Chromium Code Reviews| Index: sdk/lib/_internal/compiler/implementation/ssa/nodes.dart |
| =================================================================== |
| --- sdk/lib/_internal/compiler/implementation/ssa/nodes.dart (revision 17466) |
| +++ sdk/lib/_internal/compiler/implementation/ssa/nodes.dart (working copy) |
| @@ -50,6 +50,7 @@ |
| R visitMultiply(HMultiply node); |
| R visitNegate(HNegate node); |
| R visitNot(HNot node); |
| + R visitOneShotInterceptor(HOneShotInterceptor); |
| R visitParameterValue(HParameterValue node); |
| R visitPhi(HPhi node); |
| R visitRangeConversion(HRangeConversion node); |
| @@ -313,6 +314,8 @@ |
| visitLoopBranch(HLoopBranch node) => visitConditionalBranch(node); |
| visitNegate(HNegate node) => visitInvokeUnary(node); |
| visitNot(HNot node) => visitInstruction(node); |
| + visitOneShotInterceptor(HOneShotInterceptor node) |
| + => visitInvokeDynamic(node); |
| visitPhi(HPhi node) => visitInstruction(node); |
| visitMultiply(HMultiply node) => visitBinaryArithmetic(node); |
| visitParameterValue(HParameterValue node) => visitLocalValue(node); |
| @@ -1156,6 +1159,14 @@ |
| return new HTypeConversion(convertedType, this, kind); |
| } |
| + |
| + /** |
| + * Return whether the instructions do not belong to a loop or |
| + * belong to the same loop. |
| + */ |
| + bool bothNotInLoopOrInSameLoop(HInstruction other) { |
|
kasperl
2013/01/24 09:03:51
hasSameLoopHeaderAs
ngeoffray
2013/01/24 10:41:30
Done.
|
| + return block.enclosingLoopHeader == other.block.enclosingLoopHeader; |
| + } |
| } |
| class HBoolify extends HInstruction { |
| @@ -1314,11 +1325,19 @@ |
| } |
| abstract class HInvokeDynamic extends HInvoke { |
| + final InvokeDynamicSpecializer specializer; |
| final Selector selector; |
| Element element; |
| - HInvokeDynamic(this.selector, this.element, List<HInstruction> inputs) |
| - : super(inputs); |
| + HInvokeDynamic(Selector selector, |
| + this.element, |
| + List<HInstruction> inputs, |
| + [bool isIntercepted = false]) |
| + : super(inputs), |
| + this.selector = selector, |
| + specializer = isIntercepted |
| + ? InvokeDynamicSpecializer.lookupSpecializer(selector) |
| + : const InvokeDynamicSpecializer(); |
| toString() => 'invoke dynamic: $selector'; |
| HInstruction get receiver => inputs[0]; |
| @@ -1335,6 +1354,16 @@ |
| return selector == other.selector |
| && element == other.element; |
| } |
| + |
| + HType computeDesiredTypeForInput(HInstruction input, |
| + HTypeMap types, |
| + Compiler compiler) { |
| + return specializer.computeDesiredTypeForInput(this, input, types, compiler); |
| + } |
| + |
| + HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) { |
| + return specializer.computeTypeFromInputTypes(this, types, compiler); |
| + } |
| } |
| class HInvokeClosure extends HInvokeDynamic { |
| @@ -1346,14 +1375,11 @@ |
| } |
| class HInvokeDynamicMethod extends HInvokeDynamic { |
| - final InvokeDynamicSpecializer specializer; |
| HInvokeDynamicMethod(Selector selector, |
| List<HInstruction> inputs, |
| [bool isIntercepted = false]) |
| - : super(selector, null, inputs), |
| - specializer = isIntercepted |
| - ? InvokeDynamicSpecializer.lookupSpecializer(selector) |
| - : const InvokeDynamicSpecializer(); |
| + : super(selector, null, inputs, isIntercepted); |
| + |
| String toString() => 'invoke dynamic method: $selector'; |
| accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this); |
| @@ -1363,16 +1389,6 @@ |
| && selector.name == const SourceString('[]') |
| && inputs[1].isIndexablePrimitive(types); |
| } |
| - |
| - HType computeDesiredTypeForInput(HInstruction input, |
| - HTypeMap types, |
| - Compiler compiler) { |
| - return specializer.computeDesiredTypeForInput(this, input, types, compiler); |
| - } |
| - |
| - HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) { |
| - return specializer.computeTypeFromInputTypes(this, types, compiler); |
| - } |
| } |
| abstract class HInvokeDynamicField extends HInvokeDynamic { |
| @@ -2135,6 +2151,29 @@ |
| } |
| } |
| +/** |
| + * A "one-shot" interceptor is a call to a synthetized method that |
| + * will fetch the interceptor of its first parameter, and make a call |
| + * on a given selector with the remaining parameters. |
| + * |
| + * In order to share the same optimizations with regular interceptor |
| + * calls, this class extends [HInvokeDynamic] and also has the null |
| + * constant as the first input. |
| + */ |
| +class HOneShotInterceptor extends HInvokeDynamic { |
| + Set<ClassElement> interceptedClasses; |
| + HOneShotInterceptor(Selector selector, |
| + List<HInstruction> inputs, |
| + this.interceptedClasses) |
| + : super(selector, null, inputs, true) { |
| + assert(inputs[0] is HConstant); |
| + assert(inputs[0].guaranteedType == HType.NULL); |
| + } |
| + |
| + String toString() => 'one shot interceptor on $selector'; |
| + accept(HVisitor visitor) => visitor.visitOneShotInterceptor(this); |
| +} |
| + |
| /** An [HLazyStatic] is a static that is initialized lazily at first read. */ |
| class HLazyStatic extends HInstruction { |
| final Element element; |