Chromium Code Reviews| Index: lib/compiler/implementation/ssa/nodes.dart |
| diff --git a/lib/compiler/implementation/ssa/nodes.dart b/lib/compiler/implementation/ssa/nodes.dart |
| index d0f265635e68290035c33e6bfd01b38d3ed85249..3a1fb32e68bc1d26ab304a0277de596ea57d6fd0 100644 |
| --- a/lib/compiler/implementation/ssa/nodes.dart |
| +++ b/lib/compiler/implementation/ssa/nodes.dart |
| @@ -666,106 +666,6 @@ class HBasicBlock extends HInstructionList implements Hashable { |
| } |
| -class HType { |
| - final int flag; |
| - const HType(int this.flag); |
| - |
| - static final int FLAG_CONFLICTING = 0; |
| - static final int FLAG_UNKNOWN = 1; |
| - static final int FLAG_BOOLEAN = FLAG_UNKNOWN << 1; |
| - static final int FLAG_INTEGER = FLAG_BOOLEAN << 1; |
| - static final int FLAG_STRING = FLAG_INTEGER << 1; |
| - static final int FLAG_READABLE_ARRAY = FLAG_STRING << 1; |
| - // FLAG_WRITABLE_ARRAY implies FLAG_READABLE_ARRAY. |
| - static final int FLAG_WRITEABLE_ARRAY = FLAG_READABLE_ARRAY << 1; |
| - static final int FLAG_DOUBLE = FLAG_WRITEABLE_ARRAY << 1; |
| - static final int FLAG_NON_PRIMITIVE = FLAG_DOUBLE << 1; |
| - |
| - static final HType CONFLICTING = const HType(FLAG_CONFLICTING); |
| - static final HType UNKNOWN = const HType(FLAG_UNKNOWN); |
| - static final HType BOOLEAN = const HType(FLAG_BOOLEAN); |
| - static final HType STRING = const HType(FLAG_STRING); |
| - static final HType READABLE_ARRAY = const HType(FLAG_READABLE_ARRAY); |
| - static final HType MUTABLE_ARRAY = |
| - const HType(FLAG_READABLE_ARRAY | FLAG_WRITEABLE_ARRAY); |
| - static final HType INTEGER = const HType(FLAG_INTEGER); |
| - static final HType DOUBLE = const HType(FLAG_DOUBLE); |
| - static final HType STRING_OR_ARRAY = |
| - const HType(FLAG_STRING | FLAG_READABLE_ARRAY | FLAG_WRITEABLE_ARRAY); |
| - static final HType NUMBER = const HType(FLAG_DOUBLE | FLAG_INTEGER); |
| - |
| - bool isConflicting() => this === CONFLICTING; |
| - bool isUnknown() => this === UNKNOWN; |
| - bool isBoolean() => this === BOOLEAN; |
| - bool isInteger() => this === INTEGER; |
| - bool isDouble() => this === DOUBLE; |
| - bool isString() => this === STRING; |
| - bool isArray() => (this.flag & FLAG_READABLE_ARRAY) != 0; |
| - bool isMutableArray() => this === MUTABLE_ARRAY; |
| - bool isNumber() => (this.flag & (FLAG_INTEGER | FLAG_DOUBLE)) != 0; |
| - bool isStringOrArray() => |
| - (this.flag & (FLAG_STRING | FLAG_READABLE_ARRAY)) != 0; |
| - bool isNonPrimitive() => this.flag === FLAG_NON_PRIMITIVE; |
| - /** A type is useful it is not unknown and not conflicting. */ |
| - bool isUseful() => this !== UNKNOWN && this !== CONFLICTING; |
| - |
| - static HType getTypeFromFlag(int flag) { |
| - if (flag === CONFLICTING.flag) return CONFLICTING; |
| - if (flag === UNKNOWN.flag) return UNKNOWN; |
| - if (flag === BOOLEAN.flag) return BOOLEAN; |
| - if (flag === INTEGER.flag) return INTEGER; |
| - if (flag === DOUBLE.flag) return DOUBLE; |
| - if (flag === STRING.flag) return STRING; |
| - if (flag === READABLE_ARRAY.flag) return READABLE_ARRAY; |
| - if (flag === MUTABLE_ARRAY.flag) return MUTABLE_ARRAY; |
| - if (flag === NUMBER.flag) return NUMBER; |
| - if (flag === STRING_OR_ARRAY.flag) return STRING_OR_ARRAY; |
| - unreachable(); |
| - } |
| - |
| - String toString() { |
| - if (isConflicting()) return 'conflicting'; |
| - if (isUnknown()) return 'unknown'; |
| - if (isBoolean()) return 'boolean'; |
| - if (isInteger()) return 'integer'; |
| - if (isDouble()) return 'double'; |
| - if (isString()) return 'string'; |
| - if (isMutableArray()) return 'mutable array'; |
| - if (isArray()) return 'array'; |
| - if (isNumber()) return 'number'; |
| - if (isStringOrArray()) return 'string or array'; |
| - unreachable(); |
| - } |
| - |
| - HType combine(HType other) { |
| - if (isUnknown()) return other; |
| - if (other.isUnknown()) return this; |
| - return getTypeFromFlag(this.flag & other.flag); |
| - } |
| -} |
| - |
| -class HNonPrimitiveType extends HType { |
| - final Type type; |
| - |
| - // TODO(ngeoffray): Add a HPrimitiveType to get rid of the flag. |
| - const HNonPrimitiveType(Type this.type) : super(HType.FLAG_NON_PRIMITIVE); |
| - |
| - HType combine(HType other) { |
| - if (other.isNonPrimitive()) { |
| - HNonPrimitiveType temp = other; |
| - if (this.type === temp.type) return this; |
| - } |
| - if (other.isUnknown()) return this; |
| - return HType.CONFLICTING; |
| - } |
| - |
| - String toString() => type.toString(); |
| - Element lookupMember(SourceString name) { |
| - ClassElement classElement = type.element; |
| - return classElement.lookupMember(name); |
| - } |
| -} |
| - |
| class HInstruction implements Hashable { |
| Element sourceElement; |
| @@ -818,14 +718,16 @@ class HInstruction implements Hashable { |
| // All isFunctions work on the propagated types. |
| bool isArray() => propagatedType.isArray(); |
| + bool isReadableArray() => propagatedType.isReadableArray(); |
| bool isMutableArray() => propagatedType.isMutableArray(); |
| + bool isExtendableArray() => propagatedType.isExtendableArray(); |
| bool isBoolean() => propagatedType.isBoolean(); |
| bool isInteger() => propagatedType.isInteger(); |
| bool isDouble() => propagatedType.isDouble(); |
| bool isNumber() => propagatedType.isNumber(); |
| bool isString() => propagatedType.isString(); |
| bool isTypeUnknown() => propagatedType.isUnknown(); |
| - bool isStringOrArray() => propagatedType.isStringOrArray(); |
| + bool isIndexablePrimitive() => propagatedType.isIndexable(); |
|
ngeoffray
2012/04/25 11:41:13
I think both should be named isIndexablePrimitive
floitsch
2012/04/25 19:52:15
Done.
|
| bool isNonPrimitive() => propagatedType.isNonPrimitive(); |
| /** |
| @@ -1215,18 +1117,17 @@ class HInvokeInterceptor extends HInvokeStatic { |
| } |
| bool isLengthGetterOnStringOrArray() { |
| - return isLengthGetter() |
| - && inputs[1].isStringOrArray(); |
| + return isLengthGetter() && inputs[1].isIndexablePrimitive(); |
| } |
| String get builtinJsName() { |
| if (isLengthGetterOnStringOrArray()) { |
| return 'length'; |
| } else if (name == const SourceString('add') |
| - && inputs[1].isMutableArray()) { |
| + && inputs[1].isExtendableArray()) { |
| return 'push'; |
| } else if (name == const SourceString('removeLast') |
| - && inputs[1].isMutableArray()) { |
| + && inputs[1].isExtendableArray()) { |
| return 'pop'; |
| } |
| return null; |
| @@ -1249,7 +1150,7 @@ class HInvokeInterceptor extends HInvokeStatic { |
| // If the first argument is a string or an array and we invoke methods |
| // on it that mutate it, then we want to restrict the incoming type to be |
| // a mutable array. |
| - if (input == inputs[1] && input.isStringOrArray()) { |
| + if (input == inputs[1] && input.isIndexablePrimitive()) { |
| if (name == const SourceString('add') |
| || name == const SourceString('removeLast')) { |
| return HType.MUTABLE_ARRAY; |
| @@ -1311,6 +1212,7 @@ class HForeign extends HInstruction { |
| static HType computeTypeFromDeclaredType(DartString declaredType) { |
| if (declaredType.slowToString() == 'bool') return HType.BOOLEAN; |
| if (declaredType.slowToString() == 'int') return HType.INTEGER; |
| + if (declaredType.slowToString() == 'double') return HType.DOUBLE; |
| if (declaredType.slowToString() == 'num') return HType.NUMBER; |
| if (declaredType.slowToString() == 'String') return HType.STRING; |
| return HType.UNKNOWN; |
| @@ -1861,7 +1763,11 @@ class HPhi extends HInstruction { |
| if (inputType.isUnknown()) { |
| seenUnknown = true; |
| } else { |
| - candidateType = candidateType.combine(inputType); |
| + // Phis need to combine the incoming types using the union operation. |
| + // For example, if one incoming edge has type integer and the other has |
| + // type double, then the phi is either an integer or double and thus has |
| + // type number. |
| + candidateType = candidateType.union(inputType); |
| if (candidateType.isConflicting()) return HType.CONFLICTING; |
| } |
| } |
| @@ -1936,7 +1842,9 @@ class HRelational extends HInvokeBinary { |
| // only. With numbers the outgoing type is a boolean. If something else |
| // is desired, then numbers are incorrect, though. |
| if (propagatedType.isUnknown() || propagatedType.isBoolean()) { |
| - if (left.isTypeUnknown() || left.isNumber()) return HType.NUMBER; |
| + if (left.isTypeUnknown() || left.isNumber()) { |
| + return HType.NUMBER; |
| + } |
| } |
| return HType.UNKNOWN; |
| } |
| @@ -1971,18 +1879,20 @@ class HEquals extends HRelational { |
| // speculatively test for all possible types. Therefore we try to match |
| // the two types. That is, if we see x == 3, then we speculatively test |
| // if x is a number and bailout if it isn't. |
| - if (right.isNumber()) return HType.NUMBER; // No need to be more precise. |
| + // If right is a number we don't need more than a number (no need to match |
| + // the exact type of right). |
| + if (right.isNumber()) return HType.NUMBER; |
| // String equality testing is much more common than array equality |
| // testing. |
| - if (right.isStringOrArray()) return HType.STRING; |
| + if (right.isIndexablePrimitive()) return HType.STRING; |
| return right.propagatedType; |
| } |
| // String equality testing is much more common than array equality testing. |
| - if (input == left && left.isStringOrArray()) { |
| + if (input == left && left.isIndexablePrimitive()) { |
| return HType.READABLE_ARRAY; |
| } |
| // String equality testing is much more common than array equality testing. |
| - if (input == right && right.isStringOrArray()) { |
| + if (input == right && right.isIndexablePrimitive()) { |
| return HType.STRING; |
| } |
| return HType.UNKNOWN; |
| @@ -2131,7 +2041,7 @@ class HIndex extends HInvokeStatic { |
| HType computeDesiredTypeForNonTargetInput(HInstruction input) { |
| if (input == receiver && (index.isTypeUnknown() || index.isNumber())) { |
| - return HType.STRING_OR_ARRAY; |
| + return HType.INDEXABLE; |
|
ngeoffray
2012/04/25 11:41:13
INDEXABLE_PRIMITIVE
floitsch
2012/04/25 19:52:15
Done.
|
| } |
| // The index should be an int when the receiver is a string or array. |
| // However it turns out that inserting an integer check in the optimized |
| @@ -2140,7 +2050,7 @@ class HIndex extends HInvokeStatic { |
| return HType.UNKNOWN; |
| } |
| - bool get builtin() => receiver.isStringOrArray() && index.isInteger(); |
| + bool get builtin() => receiver.isIndexablePrimitive() && index.isInteger(); |
| } |
| class HIndexAssign extends HInvokeStatic { |