Chromium Code Reviews| Index: lib/compiler/implementation/ssa/nodes.dart |
| =================================================================== |
| --- lib/compiler/implementation/ssa/nodes.dart (revision 6686) |
| +++ lib/compiler/implementation/ssa/nodes.dart (working copy) |
| @@ -154,6 +154,10 @@ |
| if (constant.isDouble()) return HType.DOUBLE; |
| if (constant.isString()) return HType.STRING; |
| if (constant.isList()) return HType.READABLE_ARRAY; |
| + if (constant.isMap()) { |
| + MapConstant map = constant; |
| + return new HNonPrimitiveType(map.type); |
| + } |
| return HType.UNKNOWN; |
| } |
| @@ -670,6 +674,7 @@ |
| // 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); |
| @@ -695,6 +700,7 @@ |
| 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; |
| @@ -709,7 +715,7 @@ |
| if (flag === MUTABLE_ARRAY.flag) return MUTABLE_ARRAY; |
| if (flag === NUMBER.flag) return NUMBER; |
| if (flag === STRING_OR_ARRAY.flag) return STRING_OR_ARRAY; |
| - assert(false); |
| + unreachable(); |
| } |
| String toString() { |
| @@ -733,6 +739,21 @@ |
| } |
| } |
| +class HNonPrimitiveType extends HType { |
|
kasperl
2012/04/19 06:46:19
Would it make sense to have a HPrimitiveType too s
ngeoffray
2012/04/19 08:09:33
Yes, added a TODO.
|
| + final Type type; |
| + |
| + const HNonPrimitiveType(Type this.type) : super(FLAG_NON_PRIMITIVE); |
| + |
| + HType combine(HType other) { |
| + if (this === other) return this; |
|
floitsch
2012/04/18 19:18:48
Why do you not look at the type?
We could even hav
ngeoffray
2012/04/19 08:09:33
Well spotted. We don;t need to think about canonic
|
| + if (other.isUnknown()) return this; |
| + return CONFLICTING; |
| + } |
| + |
| + String toString() => type.toString(); |
| + Element lookupMember(SourceString name) => type.element.lookupMember(name); |
| +} |
| + |
| class HInstruction implements Hashable { |
| final int id; |
| static int idCounter; |
| @@ -791,6 +812,7 @@ |
| bool isString() => propagatedType.isString(); |
| bool isTypeUnknown() => propagatedType.isUnknown(); |
| bool isStringOrArray() => propagatedType.isStringOrArray(); |
| + bool isNonPrimitive() => propagatedType.isNonPrimitive(); |
| /** |
| * This is the type the instruction is guaranteed to have. It does not |
| @@ -933,6 +955,8 @@ |
| bool isConstantNull() => false; |
| bool isConstantNumber() => false; |
| bool isConstantString() => false; |
| + bool isConstantList() => false; |
| + bool isConstantMap() => false; |
| bool isValid() { |
| HValidator validator = new HValidator(); |
| @@ -1058,6 +1082,7 @@ |
| } |
| class HInvokeDynamic extends HInvoke { |
| + Element element; |
| SourceString name; |
| HInvokeDynamic(Selector selector, this.name, List<HInstruction> inputs) |
| : super(selector, inputs); |
| @@ -1069,7 +1094,6 @@ |
| } |
| class HInvokeClosure extends HInvokeDynamic { |
| - Element element; |
| HInvokeClosure(Selector selector, List<HInstruction> inputs) |
| : super(selector, const SourceString('call'), inputs); |
| accept(HVisitor visitor) => visitor.visitInvokeClosure(this); |
| @@ -1085,12 +1109,13 @@ |
| } |
| class HInvokeDynamicField extends HInvokeDynamic { |
| - Element element; |
| HInvokeDynamicField(Selector selector, |
| - Element this.element, |
| + Element element, |
| SourceString name, |
| List<HInstruction>inputs) |
| - : super(selector, name, inputs); |
| + : super(selector, name, inputs) { |
| + this.element = element; |
|
floitsch
2012/04/18 19:18:48
I would prefer passing the element in the super ca
ngeoffray
2012/04/19 08:09:33
Done.
|
| + } |
| toString() => 'invoke dynamic field: $name'; |
| // TODO(floitsch): make class abstract instead of adding an abstract method. |
| @@ -1112,27 +1137,17 @@ |
| } |
| class HInvokeStatic extends HInvoke { |
| + final HType concreteType; |
| /** The first input must be the target. */ |
| - HInvokeStatic(selector, inputs) : super(selector, inputs); |
| + HInvokeStatic(selector, inputs, [this.concreteType = HType.UNKNOWN]) |
| + : super(selector, inputs); |
| toString() => 'invoke static: ${element.name}'; |
| accept(HVisitor visitor) => visitor.visitInvokeStatic(this); |
| Element get element() => target.element; |
| HStatic get target() => inputs[0]; |
| - bool isArrayConstructor() { |
| - // TODO(ngeoffray): This is not the right way to do the check, |
| - // nor the right place. We need to move it to a phase. |
| - return (element.isFactoryConstructor() |
| - && element.enclosingElement.name.slowToString() == 'List'); |
| - } |
| + HType get guaranteedType() => concreteType; |
| - HType get guaranteedType() { |
| - if (isArrayConstructor()) { |
| - return HType.MUTABLE_ARRAY; |
| - } |
| - return HType.UNKNOWN; |
| - } |
| - |
| HType computeDesiredTypeForInput(HInstruction input) { |
| // TODO(floitsch): we want the target to be a function. |
| if (input == target) return HType.UNKNOWN; |
| @@ -1164,9 +1179,13 @@ |
| toString() => 'invoke interceptor: ${element.name}'; |
| accept(HVisitor visitor) => visitor.visitInvokeInterceptor(this); |
| + bool isLengthGetter() { |
| + return getter |
|
floitsch
2012/04/18 19:18:48
one line.
kasperl
2012/04/19 06:46:19
Fits on one line?
ngeoffray
2012/04/19 08:09:33
Done.
|
| + && name == const SourceString('length'); |
| + } |
| + |
| bool isLengthGetterOnStringOrArray() { |
| - return getter |
| - && name == const SourceString('length') |
| + return isLengthGetter() |
| && inputs[1].isStringOrArray(); |
| } |
| @@ -1722,6 +1741,8 @@ |
| bool isConstantNull() => constant.isNull(); |
| bool isConstantNumber() => constant.isNum(); |
| bool isConstantString() => constant.isString(); |
| + bool isConstantList() => constant.isList(); |
| + bool isConstantMap() => constant.isMap(); |
| // Maybe avoid this if the literal is big? |
| bool isCodeMotionInvariant() => true; |