| OLD | NEW | 
|---|
| 1 // Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file | 
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a | 
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. | 
| 4 | 4 | 
| 5 import '../common/codegen.dart' show CodegenWorkItem; | 5 import '../common/codegen.dart' show CodegenWorkItem; | 
| 6 import '../compiler.dart' show Compiler; | 6 import '../compiler.dart' show Compiler; | 
| 7 import '../constants/constant_system.dart'; | 7 import '../constants/constant_system.dart'; | 
| 8 import '../constants/values.dart'; | 8 import '../constants/values.dart'; | 
| 9 import '../elements/elements.dart'; | 9 import '../elements/elements.dart'; | 
| 10 import '../js_backend/backend_helpers.dart' show BackendHelpers; | 10 import '../js_backend/backend_helpers.dart' show BackendHelpers; | 
| 11 import '../js_backend/js_backend.dart'; | 11 import '../js_backend/js_backend.dart'; | 
| 12 import '../types/types.dart'; | 12 import '../types/types.dart'; | 
| 13 import '../universe/selector.dart' show Selector; | 13 import '../universe/selector.dart' show Selector; | 
| 14 import '../world.dart' show ClassWorld; | 14 import '../world.dart' show ClosedWorld; | 
| 15 import 'nodes.dart'; | 15 import 'nodes.dart'; | 
| 16 import 'optimize.dart'; | 16 import 'optimize.dart'; | 
| 17 | 17 | 
| 18 /** | 18 /** | 
| 19  * This phase simplifies interceptors in multiple ways: | 19  * This phase simplifies interceptors in multiple ways: | 
| 20  * | 20  * | 
| 21  * 1) If the interceptor is for an object whose type is known, it | 21  * 1) If the interceptor is for an object whose type is known, it | 
| 22  * tries to use a constant interceptor instead. | 22  * tries to use a constant interceptor instead. | 
| 23  * | 23  * | 
| 24  * 2) Interceptors are specialized based on the selector it is used with. | 24  * 2) Interceptors are specialized based on the selector it is used with. | 
| (...skipping 17 matching lines...) Expand all  Loading... | 
| 42   final Compiler compiler; | 42   final Compiler compiler; | 
| 43   final Element element; | 43   final Element element; | 
| 44   HGraph graph; | 44   HGraph graph; | 
| 45 | 45 | 
| 46   SsaSimplifyInterceptors(this.compiler, this.constantSystem, this.element); | 46   SsaSimplifyInterceptors(this.compiler, this.constantSystem, this.element); | 
| 47 | 47 | 
| 48   JavaScriptBackend get backend => compiler.backend; | 48   JavaScriptBackend get backend => compiler.backend; | 
| 49 | 49 | 
| 50   BackendHelpers get helpers => backend.helpers; | 50   BackendHelpers get helpers => backend.helpers; | 
| 51 | 51 | 
| 52   ClassWorld get classWorld => compiler.closedWorld; | 52   ClosedWorld get closedWorld => compiler.closedWorld; | 
| 53 | 53 | 
| 54   void visitGraph(HGraph graph) { | 54   void visitGraph(HGraph graph) { | 
| 55     this.graph = graph; | 55     this.graph = graph; | 
| 56     visitDominatorTree(graph); | 56     visitDominatorTree(graph); | 
| 57   } | 57   } | 
| 58 | 58 | 
| 59   void visitBasicBlock(HBasicBlock node) { | 59   void visitBasicBlock(HBasicBlock node) { | 
| 60     currentBlock = node; | 60     currentBlock = node; | 
| 61 | 61 | 
| 62     HInstruction instruction = node.first; | 62     HInstruction instruction = node.first; | 
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 102       return false; | 102       return false; | 
| 103     } | 103     } | 
| 104     if (receiver.canBeNull() && | 104     if (receiver.canBeNull() && | 
| 105         interceptedClasses.contains(helpers.jsNullClass)) { | 105         interceptedClasses.contains(helpers.jsNullClass)) { | 
| 106       // Need the JSNull interceptor. | 106       // Need the JSNull interceptor. | 
| 107       return false; | 107       return false; | 
| 108     } | 108     } | 
| 109 | 109 | 
| 110     // All intercepted classes extend `Interceptor`, so if the receiver can't be | 110     // All intercepted classes extend `Interceptor`, so if the receiver can't be | 
| 111     // a class extending `Interceptor` then it can be called directly. | 111     // a class extending `Interceptor` then it can be called directly. | 
| 112     return new TypeMask.nonNullSubclass(helpers.jsInterceptorClass, classWorld) | 112     return new TypeMask.nonNullSubclass(helpers.jsInterceptorClass, closedWorld) | 
| 113         .isDisjoint(receiver.instructionType, classWorld); | 113         .isDisjoint(receiver.instructionType, closedWorld); | 
| 114   } | 114   } | 
| 115 | 115 | 
| 116   HInstruction tryComputeConstantInterceptor( | 116   HInstruction tryComputeConstantInterceptor( | 
| 117       HInstruction input, Set<ClassElement> interceptedClasses) { | 117       HInstruction input, Set<ClassElement> interceptedClasses) { | 
| 118     if (input == graph.explicitReceiverParameter) { | 118     if (input == graph.explicitReceiverParameter) { | 
| 119       // If `explicitReceiverParameter` is set it means the current method is an | 119       // If `explicitReceiverParameter` is set it means the current method is an | 
| 120       // interceptor method, and `this` is the interceptor.  The caller just did | 120       // interceptor method, and `this` is the interceptor.  The caller just did | 
| 121       // `getInterceptor(foo).currentMethod(foo)` to enter the current method. | 121       // `getInterceptor(foo).currentMethod(foo)` to enter the current method. | 
| 122       return graph.thisInstruction; | 122       return graph.thisInstruction; | 
| 123     } | 123     } | 
| (...skipping 14 matching lines...) Expand all  Loading... | 
| 138         new InterceptorConstantValue(constantInterceptor.thisType); | 138         new InterceptorConstantValue(constantInterceptor.thisType); | 
| 139     return graph.addConstant(constant, compiler); | 139     return graph.addConstant(constant, compiler); | 
| 140   } | 140   } | 
| 141 | 141 | 
| 142   ClassElement tryComputeConstantInterceptorFromType( | 142   ClassElement tryComputeConstantInterceptorFromType( | 
| 143       TypeMask type, Set<ClassElement> interceptedClasses) { | 143       TypeMask type, Set<ClassElement> interceptedClasses) { | 
| 144     if (type.isNullable) { | 144     if (type.isNullable) { | 
| 145       if (type.isNull) { | 145       if (type.isNull) { | 
| 146         return helpers.jsNullClass; | 146         return helpers.jsNullClass; | 
| 147       } | 147       } | 
| 148     } else if (type.containsOnlyInt(classWorld)) { | 148     } else if (type.containsOnlyInt(closedWorld)) { | 
| 149       return helpers.jsIntClass; | 149       return helpers.jsIntClass; | 
| 150     } else if (type.containsOnlyDouble(classWorld)) { | 150     } else if (type.containsOnlyDouble(closedWorld)) { | 
| 151       return helpers.jsDoubleClass; | 151       return helpers.jsDoubleClass; | 
| 152     } else if (type.containsOnlyBool(classWorld)) { | 152     } else if (type.containsOnlyBool(closedWorld)) { | 
| 153       return helpers.jsBoolClass; | 153       return helpers.jsBoolClass; | 
| 154     } else if (type.containsOnlyString(classWorld)) { | 154     } else if (type.containsOnlyString(closedWorld)) { | 
| 155       return helpers.jsStringClass; | 155       return helpers.jsStringClass; | 
| 156     } else if (type.satisfies(helpers.jsArrayClass, classWorld)) { | 156     } else if (type.satisfies(helpers.jsArrayClass, closedWorld)) { | 
| 157       return helpers.jsArrayClass; | 157       return helpers.jsArrayClass; | 
| 158     } else if (type.containsOnlyNum(classWorld) && | 158     } else if (type.containsOnlyNum(closedWorld) && | 
| 159         !interceptedClasses.contains(helpers.jsIntClass) && | 159         !interceptedClasses.contains(helpers.jsIntClass) && | 
| 160         !interceptedClasses.contains(helpers.jsDoubleClass)) { | 160         !interceptedClasses.contains(helpers.jsDoubleClass)) { | 
| 161       // If the method being intercepted is not defined in [int] or [double] we | 161       // If the method being intercepted is not defined in [int] or [double] we | 
| 162       // can safely use the number interceptor.  This is because none of the | 162       // can safely use the number interceptor.  This is because none of the | 
| 163       // [int] or [double] methods are called from a method defined on [num]. | 163       // [int] or [double] methods are called from a method defined on [num]. | 
| 164       return helpers.jsNumberClass; | 164       return helpers.jsNumberClass; | 
| 165     } else { | 165     } else { | 
| 166       // Try to find constant interceptor for a native class.  If the receiver | 166       // Try to find constant interceptor for a native class.  If the receiver | 
| 167       // is constrained to a leaf native class, we can use the class's | 167       // is constrained to a leaf native class, we can use the class's | 
| 168       // interceptor directly. | 168       // interceptor directly. | 
| 169 | 169 | 
| 170       // TODO(sra): Key DOM classes like Node, Element and Event are not leaf | 170       // TODO(sra): Key DOM classes like Node, Element and Event are not leaf | 
| 171       // classes.  When the receiver type is not a leaf class, we might still be | 171       // classes.  When the receiver type is not a leaf class, we might still be | 
| 172       // able to use the receiver class as a constant interceptor.  It is | 172       // able to use the receiver class as a constant interceptor.  It is | 
| 173       // usually the case that methods defined on a non-leaf class don't test | 173       // usually the case that methods defined on a non-leaf class don't test | 
| 174       // for a subclass or call methods defined on a subclass.  Provided the | 174       // for a subclass or call methods defined on a subclass.  Provided the | 
| 175       // code is completely insensitive to the specific instance subclasses, we | 175       // code is completely insensitive to the specific instance subclasses, we | 
| 176       // can use the non-leaf class directly. | 176       // can use the non-leaf class directly. | 
| 177       ClassElement element = type.singleClass(classWorld); | 177       ClassElement element = type.singleClass(closedWorld); | 
| 178       if (element != null && backend.isNative(element)) { | 178       if (element != null && backend.isNative(element)) { | 
| 179         return element; | 179         return element; | 
| 180       } | 180       } | 
| 181     } | 181     } | 
| 182 | 182 | 
| 183     return null; | 183     return null; | 
| 184   } | 184   } | 
| 185 | 185 | 
| 186   HInstruction findDominator(Iterable<HInstruction> instructions) { | 186   HInstruction findDominator(Iterable<HInstruction> instructions) { | 
| 187     HInstruction result; | 187     HInstruction result; | 
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 419       instruction = new HInvokeDynamicMethod( | 419       instruction = new HInvokeDynamicMethod( | 
| 420           selector, mask, inputs, node.instructionType, true); | 420           selector, mask, inputs, node.instructionType, true); | 
| 421     } | 421     } | 
| 422 | 422 | 
| 423     HBasicBlock block = node.block; | 423     HBasicBlock block = node.block; | 
| 424     block.addAfter(node, instruction); | 424     block.addAfter(node, instruction); | 
| 425     block.rewrite(node, instruction); | 425     block.rewrite(node, instruction); | 
| 426     return true; | 426     return true; | 
| 427   } | 427   } | 
| 428 } | 428 } | 
| OLD | NEW | 
|---|