| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 class Interceptors { | 5 class Interceptors { |
| 6 Compiler compiler; | 6 Compiler compiler; |
| 7 Interceptors(Compiler this.compiler); | 7 Interceptors(Compiler this.compiler); |
| 8 | 8 |
| 9 SourceString mapOperatorToMethodName(Operator op) { | 9 SourceString mapOperatorToMethodName(Operator op) { |
| 10 String name = op.source.stringValue; | 10 String name = op.source.stringValue; |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 emitter = backend.emitter, | 150 emitter = backend.emitter, |
| 151 functionsCalledInLoop = new Set<FunctionElement>(), | 151 functionsCalledInLoop = new Set<FunctionElement>(), |
| 152 selectorsCalledInLoop = new Map<SourceString, Selector>(), | 152 selectorsCalledInLoop = new Map<SourceString, Selector>(), |
| 153 backend = backend, | 153 backend = backend, |
| 154 super(backend.compiler); | 154 super(backend.compiler); |
| 155 | 155 |
| 156 HGraph build(WorkItem work) { | 156 HGraph build(WorkItem work) { |
| 157 return measure(() { | 157 return measure(() { |
| 158 Element element = work.element; | 158 Element element = work.element; |
| 159 HInstruction.idCounter = 0; | 159 HInstruction.idCounter = 0; |
| 160 SsaBuilder builder = new SsaBuilder(this, work); | 160 ConstantSystem constantSystem = compiler.backend.constantSystem; |
| 161 SsaBuilder builder = new SsaBuilder(constantSystem, this, work); |
| 161 HGraph graph; | 162 HGraph graph; |
| 162 ElementKind kind = element.kind; | 163 ElementKind kind = element.kind; |
| 163 if (kind === ElementKind.GENERATIVE_CONSTRUCTOR) { | 164 if (kind === ElementKind.GENERATIVE_CONSTRUCTOR) { |
| 164 graph = compileConstructor(builder, work); | 165 graph = compileConstructor(builder, work); |
| 165 } else if (kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY || | 166 } else if (kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY || |
| 166 kind === ElementKind.FUNCTION || | 167 kind === ElementKind.FUNCTION || |
| 167 kind === ElementKind.GETTER || | 168 kind === ElementKind.GETTER || |
| 168 kind === ElementKind.SETTER) { | 169 kind === ElementKind.SETTER) { |
| 169 graph = builder.buildMethod(work.element); | 170 graph = builder.buildMethod(work.element); |
| 170 } else if (kind === ElementKind.FIELD) { | 171 } else if (kind === ElementKind.FIELD) { |
| (...skipping 629 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 800 result.add(element); | 801 result.add(element); |
| 801 } | 802 } |
| 802 return (result === null) ? const <LabelElement>[] : result; | 803 return (result === null) ? const <LabelElement>[] : result; |
| 803 } | 804 } |
| 804 } | 805 } |
| 805 | 806 |
| 806 class SsaBuilder extends ResolvedVisitor implements Visitor { | 807 class SsaBuilder extends ResolvedVisitor implements Visitor { |
| 807 final SsaBuilderTask builder; | 808 final SsaBuilderTask builder; |
| 808 final Interceptors interceptors; | 809 final Interceptors interceptors; |
| 809 final WorkItem work; | 810 final WorkItem work; |
| 811 final ConstantSystem constantSystem; |
| 810 bool methodInterceptionEnabled; | 812 bool methodInterceptionEnabled; |
| 811 HGraph graph; | 813 HGraph graph; |
| 812 LocalsHandler localsHandler; | 814 LocalsHandler localsHandler; |
| 813 HInstruction rethrowableException; | 815 HInstruction rethrowableException; |
| 814 Map<Element, HParameterValue> parameters; | 816 Map<Element, HParameterValue> parameters; |
| 815 | 817 |
| 816 Map<TargetElement, JumpHandler> jumpTargets; | 818 Map<TargetElement, JumpHandler> jumpTargets; |
| 817 | 819 |
| 818 /** | 820 /** |
| 819 * Variables stored in the current activation. These variables are | 821 * Variables stored in the current activation. These variables are |
| (...skipping 11 matching lines...) Expand all Loading... |
| 831 // The most recently opened block. Has the same value as [current] while | 833 // The most recently opened block. Has the same value as [current] while |
| 832 // the block is open, but unlike [current], it isn't cleared when the current | 834 // the block is open, but unlike [current], it isn't cleared when the current |
| 833 // block is closed. | 835 // block is closed. |
| 834 HBasicBlock lastOpenedBlock; | 836 HBasicBlock lastOpenedBlock; |
| 835 | 837 |
| 836 LibraryElement get currentLibrary => work.element.getLibrary(); | 838 LibraryElement get currentLibrary => work.element.getLibrary(); |
| 837 Element get currentElement => work.element; | 839 Element get currentElement => work.element; |
| 838 Compiler get compiler => builder.compiler; | 840 Compiler get compiler => builder.compiler; |
| 839 CodeEmitterTask get emitter => builder.emitter; | 841 CodeEmitterTask get emitter => builder.emitter; |
| 840 | 842 |
| 841 SsaBuilder(SsaBuilderTask builder, WorkItem work) | 843 SsaBuilder(this.constantSystem, SsaBuilderTask builder, WorkItem work) |
| 842 : this.builder = builder, | 844 : this.builder = builder, |
| 843 this.work = work, | 845 this.work = work, |
| 844 interceptors = builder.interceptors, | 846 interceptors = builder.interceptors, |
| 845 methodInterceptionEnabled = true, | 847 methodInterceptionEnabled = true, |
| 846 graph = new HGraph(), | 848 graph = new HGraph(), |
| 847 stack = new List<HInstruction>(), | 849 stack = new List<HInstruction>(), |
| 848 activationVariables = new Map<Element, HLocalValue>(), | 850 activationVariables = new Map<Element, HLocalValue>(), |
| 849 jumpTargets = new Map<TargetElement, JumpHandler>(), | 851 jumpTargets = new Map<TargetElement, JumpHandler>(), |
| 850 parameters = new Map<Element, HParameterValue>(), | 852 parameters = new Map<Element, HParameterValue>(), |
| 851 inliningStack = <InliningState>[], | 853 inliningStack = <InliningState>[], |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 943 compiledArguments); | 945 compiledArguments); |
| 944 assert(succeeded); | 946 assert(succeeded); |
| 945 | 947 |
| 946 InliningState state = | 948 InliningState state = |
| 947 new InliningState(function, returnElement, elements, stack); | 949 new InliningState(function, returnElement, elements, stack); |
| 948 inliningStack.add(state); | 950 inliningStack.add(state); |
| 949 stack = <HInstruction>[]; | 951 stack = <HInstruction>[]; |
| 950 returnElement = new Element(const SourceString("result"), | 952 returnElement = new Element(const SourceString("result"), |
| 951 ElementKind.VARIABLE, | 953 ElementKind.VARIABLE, |
| 952 function); | 954 function); |
| 953 localsHandler.updateLocal(returnElement, graph.addConstantNull()); | 955 localsHandler.updateLocal(returnElement, |
| 956 graph.addConstantNull(constantSystem)); |
| 954 elements = compiler.enqueuer.resolution.getCachedElements(function); | 957 elements = compiler.enqueuer.resolution.getCachedElements(function); |
| 955 FunctionSignature signature = function.computeSignature(compiler); | 958 FunctionSignature signature = function.computeSignature(compiler); |
| 956 int index = 0; | 959 int index = 0; |
| 957 signature.forEachParameter((Element parameter) { | 960 signature.forEachParameter((Element parameter) { |
| 958 HInstruction argument = compiledArguments[index++]; | 961 HInstruction argument = compiledArguments[index++]; |
| 959 localsHandler.updateLocal(parameter, argument); | 962 localsHandler.updateLocal(parameter, argument); |
| 960 potentiallyCheckType(argument, parameter); | 963 potentiallyCheckType(argument, parameter); |
| 961 }); | 964 }); |
| 962 return state; | 965 return state; |
| 963 } | 966 } |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1129 Map<Element, HInstruction> fieldValues) { | 1132 Map<Element, HInstruction> fieldValues) { |
| 1130 classElement.forEachInstanceField( | 1133 classElement.forEachInstanceField( |
| 1131 includeBackendMembers: true, | 1134 includeBackendMembers: true, |
| 1132 includeSuperMembers: false, | 1135 includeSuperMembers: false, |
| 1133 f: (ClassElement enclosingClass, Element member) { | 1136 f: (ClassElement enclosingClass, Element member) { |
| 1134 TreeElements definitions = compiler.analyzeElement(member); | 1137 TreeElements definitions = compiler.analyzeElement(member); |
| 1135 Node node = member.parseNode(compiler); | 1138 Node node = member.parseNode(compiler); |
| 1136 SendSet assignment = node.asSendSet(); | 1139 SendSet assignment = node.asSendSet(); |
| 1137 HInstruction value; | 1140 HInstruction value; |
| 1138 if (assignment === null) { | 1141 if (assignment === null) { |
| 1139 value = graph.addConstantNull(); | 1142 value = graph.addConstantNull(constantSystem); |
| 1140 } else { | 1143 } else { |
| 1141 Node right = assignment.arguments.head; | 1144 Node right = assignment.arguments.head; |
| 1142 TreeElements savedElements = elements; | 1145 TreeElements savedElements = elements; |
| 1143 elements = definitions; | 1146 elements = definitions; |
| 1144 right.accept(this); | 1147 right.accept(this); |
| 1145 elements = savedElements; | 1148 elements = savedElements; |
| 1146 value = pop(); | 1149 value = pop(); |
| 1147 } | 1150 } |
| 1148 fieldValues[member] = value; | 1151 fieldValues[member] = value; |
| 1149 }); | 1152 }); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1262 // foo([a = 42]) { | 1265 // foo([a = 42]) { |
| 1263 // var t1 = a === sentinel; | 1266 // var t1 = a === sentinel; |
| 1264 // if (t1) a = 42; | 1267 // if (t1) a = 42; |
| 1265 // if (!t1) print('parameter passed ' + a); | 1268 // if (!t1) print('parameter passed ' + a); |
| 1266 // } | 1269 // } |
| 1267 | 1270 |
| 1268 // Fetch the original default value of [element]; | 1271 // Fetch the original default value of [element]; |
| 1269 ConstantHandler handler = compiler.constantHandler; | 1272 ConstantHandler handler = compiler.constantHandler; |
| 1270 Constant constant = handler.compileVariable(element); | 1273 Constant constant = handler.compileVariable(element); |
| 1271 HConstant defaultValue = constant == null | 1274 HConstant defaultValue = constant == null |
| 1272 ? graph.addConstantNull() | 1275 ? graph.addConstantNull(constantSystem) |
| 1273 : graph.addConstant(constant); | 1276 : graph.addConstant(constant); |
| 1274 | 1277 |
| 1275 // Emit the equality check with the sentinel. | 1278 // Emit the equality check with the sentinel. |
| 1276 HConstant sentinel = graph.addConstant(SentinelConstant.SENTINEL); | 1279 HConstant sentinel = graph.addConstant(SentinelConstant.SENTINEL); |
| 1277 Element equalsHelper = interceptors.getTripleEqualsInterceptor(); | 1280 Element equalsHelper = interceptors.getTripleEqualsInterceptor(); |
| 1278 HInstruction target = new HStatic(equalsHelper); | 1281 HInstruction target = new HStatic(equalsHelper); |
| 1279 add(target); | 1282 add(target); |
| 1280 HInstruction operand = parameters[element]; | 1283 HInstruction operand = parameters[element]; |
| 1281 HInstruction check = new HIdentity(target, sentinel, operand); | 1284 HInstruction check = new HIdentity(target, sentinel, operand); |
| 1282 add(check); | 1285 add(check); |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1663 Node initializer = node.initializer; | 1666 Node initializer = node.initializer; |
| 1664 if (initializer !== null) { | 1667 if (initializer !== null) { |
| 1665 visit(initializer); | 1668 visit(initializer); |
| 1666 if (initializer.asExpression() !== null) { | 1669 if (initializer.asExpression() !== null) { |
| 1667 pop(); | 1670 pop(); |
| 1668 } | 1671 } |
| 1669 } | 1672 } |
| 1670 } | 1673 } |
| 1671 HInstruction buildCondition() { | 1674 HInstruction buildCondition() { |
| 1672 if (node.condition === null) { | 1675 if (node.condition === null) { |
| 1673 return graph.addConstantBool(true); | 1676 return graph.addConstantBool(true, constantSystem); |
| 1674 } | 1677 } |
| 1675 visit(node.condition); | 1678 visit(node.condition); |
| 1676 return popBoolified(); | 1679 return popBoolified(); |
| 1677 } | 1680 } |
| 1678 void buildUpdate() { | 1681 void buildUpdate() { |
| 1679 for (Expression expression in node.update) { | 1682 for (Expression expression in node.update) { |
| 1680 visit(expression); | 1683 visit(expression); |
| 1681 assert(!isAborted()); | 1684 assert(!isAborted()); |
| 1682 // The result of the update instruction isn't used, and can just | 1685 // The result of the update instruction isn't used, and can just |
| 1683 // be dropped. | 1686 // be dropped. |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1878 switch (value) { | 1881 switch (value) { |
| 1879 case "-": result = new HNegate(target, operand); break; | 1882 case "-": result = new HNegate(target, operand); break; |
| 1880 case "~": result = new HBitNot(target, operand); break; | 1883 case "~": result = new HBitNot(target, operand); break; |
| 1881 default: | 1884 default: |
| 1882 compiler.internalError('Unexpected unary operator: $value.', node: op); | 1885 compiler.internalError('Unexpected unary operator: $value.', node: op); |
| 1883 break; | 1886 break; |
| 1884 } | 1887 } |
| 1885 // See if we can constant-fold right away. This avoids rewrites later on. | 1888 // See if we can constant-fold right away. This avoids rewrites later on. |
| 1886 if (operand is HConstant) { | 1889 if (operand is HConstant) { |
| 1887 HConstant constant = operand; | 1890 HConstant constant = operand; |
| 1888 Constant folded = result.operation.fold(constant.constant); | 1891 Constant folded = |
| 1892 result.operation(constantSystem).fold(constant.constant); |
| 1889 if (folded !== null) { | 1893 if (folded !== null) { |
| 1890 stack.add(graph.addConstant(folded)); | 1894 stack.add(graph.addConstant(folded)); |
| 1891 return; | 1895 return; |
| 1892 } | 1896 } |
| 1893 } | 1897 } |
| 1894 pushWithPosition(result, node); | 1898 pushWithPosition(result, node); |
| 1895 } | 1899 } |
| 1896 | 1900 |
| 1897 void visitBinary(HInstruction left, Operator op, HInstruction right) { | 1901 void visitBinary(HInstruction left, Operator op, HInstruction right) { |
| 1898 Element element = interceptors.getOperatorInterceptor(op); | 1902 Element element = interceptors.getOperatorInterceptor(op); |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2167 HInstruction typeInfo = null; | 2171 HInstruction typeInfo = null; |
| 2168 if (compiler.codegenWorld.rti.hasTypeArguments(type)) { | 2172 if (compiler.codegenWorld.rti.hasTypeArguments(type)) { |
| 2169 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), expression); | 2173 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), expression); |
| 2170 typeInfo = pop(); | 2174 typeInfo = pop(); |
| 2171 } | 2175 } |
| 2172 if (type.element.isTypeVariable()) { | 2176 if (type.element.isTypeVariable()) { |
| 2173 // TODO(karlklose): We emulate the behavior of the old frog | 2177 // TODO(karlklose): We emulate the behavior of the old frog |
| 2174 // compiler and answer true to any is check involving a type variable | 2178 // compiler and answer true to any is check involving a type variable |
| 2175 // -- both is T and is !T -- until we have a proper implementation of | 2179 // -- both is T and is !T -- until we have a proper implementation of |
| 2176 // reified generics. | 2180 // reified generics. |
| 2177 stack.add(graph.addConstantBool(true)); | 2181 stack.add(graph.addConstantBool(true, constantSystem)); |
| 2178 } else { | 2182 } else { |
| 2179 HInstruction instruction; | 2183 HInstruction instruction; |
| 2180 if (typeInfo !== null) { | 2184 if (typeInfo !== null) { |
| 2181 instruction = new HIs.withTypeInfoCall(type, expression, typeInfo); | 2185 instruction = new HIs.withTypeInfoCall(type, expression, typeInfo); |
| 2182 } else { | 2186 } else { |
| 2183 instruction = new HIs(type, expression); | 2187 instruction = new HIs(type, expression); |
| 2184 } | 2188 } |
| 2185 if (isNot) { | 2189 if (isNot) { |
| 2186 add(instruction); | 2190 add(instruction); |
| 2187 instruction = new HNot(instruction); | 2191 instruction = new HNot(instruction); |
| (...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2503 generateSuperNoSuchMethodSend(Send node) { | 2507 generateSuperNoSuchMethodSend(Send node) { |
| 2504 ClassElement cls = work.element.getEnclosingClass(); | 2508 ClassElement cls = work.element.getEnclosingClass(); |
| 2505 Element element = cls.lookupSuperMember(Compiler.NO_SUCH_METHOD); | 2509 Element element = cls.lookupSuperMember(Compiler.NO_SUCH_METHOD); |
| 2506 HStatic target = new HStatic(element); | 2510 HStatic target = new HStatic(element); |
| 2507 add(target); | 2511 add(target); |
| 2508 HInstruction self = localsHandler.readThis(); | 2512 HInstruction self = localsHandler.readThis(); |
| 2509 Identifier identifier = node.selector.asIdentifier(); | 2513 Identifier identifier = node.selector.asIdentifier(); |
| 2510 String name = identifier.source.slowToString(); | 2514 String name = identifier.source.slowToString(); |
| 2511 // TODO(ahe): Add the arguments to this list. | 2515 // TODO(ahe): Add the arguments to this list. |
| 2512 push(new HLiteralList([])); | 2516 push(new HLiteralList([])); |
| 2517 Constant nameConstant = |
| 2518 constantSystem.createString(new DartString.literal(name), node); |
| 2513 var inputs = <HInstruction>[ | 2519 var inputs = <HInstruction>[ |
| 2514 target, | 2520 target, |
| 2515 self, | 2521 self, |
| 2516 graph.addConstantString(new DartString.literal(name), node), | 2522 graph.addConstant(nameConstant), |
| 2517 pop()]; | 2523 pop()]; |
| 2518 push(new HInvokeSuper(inputs)); | 2524 push(new HInvokeSuper(inputs)); |
| 2519 } | 2525 } |
| 2520 | 2526 |
| 2521 visitSend(Send node) { | 2527 visitSend(Send node) { |
| 2522 Element element = elements[node]; | 2528 Element element = elements[node]; |
| 2523 if (element !== null && element === work.element) { | 2529 if (element !== null && element === work.element) { |
| 2524 graph.isRecursiveMethod = true; | 2530 graph.isRecursiveMethod = true; |
| 2525 } | 2531 } |
| 2526 super.visitSend(node); | 2532 super.visitSend(node); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2574 return foreign; | 2580 return foreign; |
| 2575 } else { | 2581 } else { |
| 2576 // TODO(ngeoffray): Match the VM behavior and throw an | 2582 // TODO(ngeoffray): Match the VM behavior and throw an |
| 2577 // exception at runtime. | 2583 // exception at runtime. |
| 2578 compiler.cancel('Unimplemented unresolved type variable', | 2584 compiler.cancel('Unimplemented unresolved type variable', |
| 2579 node: currentNode); | 2585 node: currentNode); |
| 2580 } | 2586 } |
| 2581 } else { | 2587 } else { |
| 2582 // The type variable is a type (e.g. int). | 2588 // The type variable is a type (e.g. int). |
| 2583 return graph.addConstantString( | 2589 return graph.addConstantString( |
| 2584 new LiteralDartString('$argument'), currentNode); | 2590 new LiteralDartString('$argument'), currentNode, constantSystem); |
| 2585 } | 2591 } |
| 2586 } | 2592 } |
| 2587 | 2593 |
| 2588 visitNewSend(Send node) { | 2594 visitNewSend(Send node) { |
| 2589 computeType(element) { | 2595 computeType(element) { |
| 2590 Element originalElement = elements[node]; | 2596 Element originalElement = elements[node]; |
| 2591 if (originalElement.getEnclosingClass() === compiler.listClass) { | 2597 if (originalElement.getEnclosingClass() === compiler.listClass) { |
| 2592 if (node.arguments.isEmpty()) { | 2598 if (node.arguments.isEmpty()) { |
| 2593 return HType.EXTENDABLE_ARRAY; | 2599 return HType.EXTENDABLE_ARRAY; |
| 2594 } else { | 2600 } else { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2632 | 2638 |
| 2633 HType elementType = computeType(constructor); | 2639 HType elementType = computeType(constructor); |
| 2634 HInstruction newInstance = new HInvokeStatic(inputs, elementType); | 2640 HInstruction newInstance = new HInvokeStatic(inputs, elementType); |
| 2635 pushWithPosition(newInstance, node); | 2641 pushWithPosition(newInstance, node); |
| 2636 } | 2642 } |
| 2637 | 2643 |
| 2638 visitStaticSend(Send node) { | 2644 visitStaticSend(Send node) { |
| 2639 Selector selector = elements.getSelector(node); | 2645 Selector selector = elements.getSelector(node); |
| 2640 Element element = elements[node]; | 2646 Element element = elements[node]; |
| 2641 if (element === compiler.assertMethod && !compiler.enableUserAssertions) { | 2647 if (element === compiler.assertMethod && !compiler.enableUserAssertions) { |
| 2642 stack.add(graph.addConstantNull()); | 2648 stack.add(graph.addConstantNull(constantSystem)); |
| 2643 return; | 2649 return; |
| 2644 } | 2650 } |
| 2645 compiler.ensure(!element.isGenerativeConstructor()); | 2651 compiler.ensure(!element.isGenerativeConstructor()); |
| 2646 if (element.isFunction()) { | 2652 if (element.isFunction()) { |
| 2647 if (tryInlineMethod(element, selector, node.arguments)) return; | 2653 if (tryInlineMethod(element, selector, node.arguments)) return; |
| 2648 | 2654 |
| 2649 HInstruction target = new HStatic(element); | 2655 HInstruction target = new HStatic(element); |
| 2650 add(target); | 2656 add(target); |
| 2651 var inputs = <HInstruction>[target]; | 2657 var inputs = <HInstruction>[target]; |
| 2652 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, | 2658 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2676 generateGetter(node, elements[node]); | 2682 generateGetter(node, elements[node]); |
| 2677 } | 2683 } |
| 2678 | 2684 |
| 2679 // TODO(antonm): migrate rest of SsaBuilder to internalError. | 2685 // TODO(antonm): migrate rest of SsaBuilder to internalError. |
| 2680 internalError(String reason, [Node node]) { | 2686 internalError(String reason, [Node node]) { |
| 2681 compiler.internalError(reason, node: node); | 2687 compiler.internalError(reason, node: node); |
| 2682 } | 2688 } |
| 2683 | 2689 |
| 2684 void generateRuntimeError(Node node, String message) { | 2690 void generateRuntimeError(Node node, String message) { |
| 2685 DartString messageObject = new DartString.literal(message); | 2691 DartString messageObject = new DartString.literal(message); |
| 2686 HInstruction errorMessage = graph.addConstantString(messageObject, node); | 2692 Constant messageConstant = |
| 2693 constantSystem.createString(messageObject, node); |
| 2694 HInstruction errorMessage = graph.addConstant(messageConstant); |
| 2687 Element helper = interceptors.getThrowRuntimeError(); | 2695 Element helper = interceptors.getThrowRuntimeError(); |
| 2688 pushInvokeHelper1(helper, errorMessage); | 2696 pushInvokeHelper1(helper, errorMessage); |
| 2689 } | 2697 } |
| 2690 | 2698 |
| 2691 visitNewExpression(NewExpression node) { | 2699 visitNewExpression(NewExpression node) { |
| 2692 Element element = elements[node.send]; | 2700 Element element = elements[node.send]; |
| 2693 if (element != null && element.isErroneous()) { | 2701 if (element != null && element.isErroneous()) { |
| 2694 ErroneousElement error = element; | 2702 ErroneousElement error = element; |
| 2695 Message message = error.errorMessage; | 2703 Message message = error.errorMessage; |
| 2696 if (message.kind === MessageKind.CANNOT_FIND_CONSTRUCTOR) { | 2704 if (message.kind === MessageKind.CANNOT_FIND_CONSTRUCTOR) { |
| 2697 Element helper = | 2705 Element helper = |
| 2698 compiler.findHelper(const SourceString('throwNoSuchMethod')); | 2706 compiler.findHelper(const SourceString('throwNoSuchMethod')); |
| 2699 DartString receiverLiteral = new DartString.literal(''); | 2707 DartString receiverLiteral = new DartString.literal(''); |
| 2700 HInstruction receiver = graph.addConstantString(receiverLiteral, node); | 2708 Constant receiverConstant = |
| 2709 constantSystem.createString(receiverLiteral, node); |
| 2710 HInstruction receiver = graph.addConstant(receiverConstant); |
| 2701 String constructorName = 'constructor ${message.arguments[0]}'; | 2711 String constructorName = 'constructor ${message.arguments[0]}'; |
| 2702 DartString nameLiteral = new DartString.literal(constructorName); | 2712 DartString nameLiteral = new DartString.literal(constructorName); |
| 2703 HInstruction name = graph.addConstantString(nameLiteral, node.send); | 2713 Constant nameConstant = |
| 2714 constantSystem.createString(nameLiteral, node.send); |
| 2715 HInstruction name = graph.addConstant(nameConstant); |
| 2704 List<HInstruction> inputs = <HInstruction>[]; | 2716 List<HInstruction> inputs = <HInstruction>[]; |
| 2705 node.send.arguments.forEach((argumentNode) { | 2717 node.send.arguments.forEach((argumentNode) { |
| 2706 visit(argumentNode); | 2718 visit(argumentNode); |
| 2707 HInstruction value = pop(); | 2719 HInstruction value = pop(); |
| 2708 inputs.add(value); | 2720 inputs.add(value); |
| 2709 }); | 2721 }); |
| 2710 HInstruction arguments = new HLiteralList(inputs); | 2722 HInstruction arguments = new HLiteralList(inputs); |
| 2711 add(arguments); | 2723 add(arguments); |
| 2712 pushInvokeHelper3(helper, receiver, name, arguments); | 2724 pushInvokeHelper3(helper, receiver, name, arguments); |
| 2713 } else if (message.kind === MessageKind.CANNOT_RESOLVE) { | 2725 } else if (message.kind === MessageKind.CANNOT_RESOLVE) { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2762 HInstruction index; | 2774 HInstruction index; |
| 2763 bool isCompoundAssignment = op.source.stringValue.endsWith('='); | 2775 bool isCompoundAssignment = op.source.stringValue.endsWith('='); |
| 2764 // Compound assignments are considered as being prefix. | 2776 // Compound assignments are considered as being prefix. |
| 2765 bool isPrefix = !node.isPostfix; | 2777 bool isPrefix = !node.isPostfix; |
| 2766 Element getter = elements[node.selector]; | 2778 Element getter = elements[node.selector]; |
| 2767 if (isCompoundAssignment) { | 2779 if (isCompoundAssignment) { |
| 2768 value = pop(); | 2780 value = pop(); |
| 2769 index = pop(); | 2781 index = pop(); |
| 2770 } else { | 2782 } else { |
| 2771 index = pop(); | 2783 index = pop(); |
| 2772 value = graph.addConstantInt(1); | 2784 value = graph.addConstantInt(1, constantSystem); |
| 2773 } | 2785 } |
| 2774 HStatic indexMethod = new HStatic(interceptors.getIndexInterceptor()); | 2786 HStatic indexMethod = new HStatic(interceptors.getIndexInterceptor()); |
| 2775 add(indexMethod); | 2787 add(indexMethod); |
| 2776 HInstruction left = new HIndex(indexMethod, receiver, index); | 2788 HInstruction left = new HIndex(indexMethod, receiver, index); |
| 2777 add(left); | 2789 add(left); |
| 2778 Element opElement = elements[op]; | 2790 Element opElement = elements[op]; |
| 2779 visitBinary(left, op, value); | 2791 visitBinary(left, op, value); |
| 2780 value = pop(); | 2792 value = pop(); |
| 2781 HInstruction assign = new HIndexAssign( | 2793 HInstruction assign = new HIndexAssign( |
| 2782 target, receiver, index, value); | 2794 target, receiver, index, value); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 2812 generateInstanceGetterWithCompiledReceiver(node, receiver); | 2824 generateInstanceGetterWithCompiledReceiver(node, receiver); |
| 2813 } else { | 2825 } else { |
| 2814 generateGetter(node, elements[node.selector]); | 2826 generateGetter(node, elements[node.selector]); |
| 2815 } | 2827 } |
| 2816 HInstruction left = pop(); | 2828 HInstruction left = pop(); |
| 2817 HInstruction right; | 2829 HInstruction right; |
| 2818 if (isCompoundAssignment) { | 2830 if (isCompoundAssignment) { |
| 2819 visit(node.argumentsNode); | 2831 visit(node.argumentsNode); |
| 2820 right = pop(); | 2832 right = pop(); |
| 2821 } else { | 2833 } else { |
| 2822 right = graph.addConstantInt(1); | 2834 right = graph.addConstantInt(1, constantSystem); |
| 2823 } | 2835 } |
| 2824 visitBinary(left, op, right); | 2836 visitBinary(left, op, right); |
| 2825 HInstruction operation = pop(); | 2837 HInstruction operation = pop(); |
| 2826 assert(operation !== null); | 2838 assert(operation !== null); |
| 2827 if (Elements.isInstanceSend(node, elements)) { | 2839 if (Elements.isInstanceSend(node, elements)) { |
| 2828 assert(receiver !== null); | 2840 assert(receiver !== null); |
| 2829 generateInstanceSetterWithCompiledReceiver(node, receiver, operation); | 2841 generateInstanceSetterWithCompiledReceiver(node, receiver, operation); |
| 2830 } else { | 2842 } else { |
| 2831 assert(receiver === null); | 2843 assert(receiver === null); |
| 2832 generateSetter(node, element, operation); | 2844 generateSetter(node, element, operation); |
| 2833 } | 2845 } |
| 2834 if (!isPrefix) { | 2846 if (!isPrefix) { |
| 2835 pop(); | 2847 pop(); |
| 2836 stack.add(left); | 2848 stack.add(left); |
| 2837 } | 2849 } |
| 2838 } | 2850 } |
| 2839 } | 2851 } |
| 2840 | 2852 |
| 2841 void visitLiteralInt(LiteralInt node) { | 2853 void visitLiteralInt(LiteralInt node) { |
| 2842 stack.add(graph.addConstantInt(node.value)); | 2854 stack.add(graph.addConstantInt(node.value, constantSystem)); |
| 2843 } | 2855 } |
| 2844 | 2856 |
| 2845 void visitLiteralDouble(LiteralDouble node) { | 2857 void visitLiteralDouble(LiteralDouble node) { |
| 2846 stack.add(graph.addConstantDouble(node.value)); | 2858 stack.add(graph.addConstantDouble(node.value, constantSystem)); |
| 2847 } | 2859 } |
| 2848 | 2860 |
| 2849 void visitLiteralBool(LiteralBool node) { | 2861 void visitLiteralBool(LiteralBool node) { |
| 2850 stack.add(graph.addConstantBool(node.value)); | 2862 stack.add(graph.addConstantBool(node.value, constantSystem)); |
| 2851 } | 2863 } |
| 2852 | 2864 |
| 2853 void visitLiteralString(LiteralString node) { | 2865 void visitLiteralString(LiteralString node) { |
| 2854 stack.add(graph.addConstantString(node.dartString, node)); | 2866 stack.add(graph.addConstantString(node.dartString, node, constantSystem)); |
| 2855 } | 2867 } |
| 2856 | 2868 |
| 2857 void visitStringJuxtaposition(StringJuxtaposition node) { | 2869 void visitStringJuxtaposition(StringJuxtaposition node) { |
| 2858 if (!node.isInterpolation) { | 2870 if (!node.isInterpolation) { |
| 2859 // This is a simple string with no interpolations. | 2871 // This is a simple string with no interpolations. |
| 2860 stack.add(graph.addConstantString(node.dartString, node)); | 2872 stack.add(graph.addConstantString(node.dartString, node, constantSystem)); |
| 2861 return; | 2873 return; |
| 2862 } | 2874 } |
| 2863 StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this, node); | 2875 StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this, node); |
| 2864 stringBuilder.visit(node); | 2876 stringBuilder.visit(node); |
| 2865 stack.add(stringBuilder.result); | 2877 stack.add(stringBuilder.result); |
| 2866 } | 2878 } |
| 2867 | 2879 |
| 2868 void visitLiteralNull(LiteralNull node) { | 2880 void visitLiteralNull(LiteralNull node) { |
| 2869 stack.add(graph.addConstantNull()); | 2881 stack.add(graph.addConstantNull(constantSystem)); |
| 2870 } | 2882 } |
| 2871 | 2883 |
| 2872 visitNodeList(NodeList node) { | 2884 visitNodeList(NodeList node) { |
| 2873 for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) { | 2885 for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) { |
| 2874 if (isAborted()) { | 2886 if (isAborted()) { |
| 2875 compiler.reportWarning(link.head, 'dead code'); | 2887 compiler.reportWarning(link.head, 'dead code'); |
| 2876 } else { | 2888 } else { |
| 2877 visit(link.head); | 2889 visit(link.head); |
| 2878 } | 2890 } |
| 2879 } | 2891 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2899 dup(); | 2911 dup(); |
| 2900 } | 2912 } |
| 2901 | 2913 |
| 2902 visitReturn(Return node) { | 2914 visitReturn(Return node) { |
| 2903 if (node.getBeginToken().stringValue === 'native') { | 2915 if (node.getBeginToken().stringValue === 'native') { |
| 2904 native.handleSsaNative(this, node.expression); | 2916 native.handleSsaNative(this, node.expression); |
| 2905 return; | 2917 return; |
| 2906 } | 2918 } |
| 2907 HInstruction value; | 2919 HInstruction value; |
| 2908 if (node.expression === null) { | 2920 if (node.expression === null) { |
| 2909 value = graph.addConstantNull(); | 2921 value = graph.addConstantNull(constantSystem); |
| 2910 } else { | 2922 } else { |
| 2911 visit(node.expression); | 2923 visit(node.expression); |
| 2912 value = pop(); | 2924 value = pop(); |
| 2913 } | 2925 } |
| 2914 if (!inliningStack.isEmpty()) { | 2926 if (!inliningStack.isEmpty()) { |
| 2915 localsHandler.updateLocal(returnElement, value); | 2927 localsHandler.updateLocal(returnElement, value); |
| 2916 } else { | 2928 } else { |
| 2917 close(attachPosition(new HReturn(value), node)).addSuccessor(graph.exit); | 2929 close(attachPosition(new HReturn(value), node)).addSuccessor(graph.exit); |
| 2918 } | 2930 } |
| 2919 } | 2931 } |
| 2920 | 2932 |
| 2921 visitThrow(Throw node) { | 2933 visitThrow(Throw node) { |
| 2922 if (node.expression === null) { | 2934 if (node.expression === null) { |
| 2923 HInstruction exception = rethrowableException; | 2935 HInstruction exception = rethrowableException; |
| 2924 if (exception === null) { | 2936 if (exception === null) { |
| 2925 exception = graph.addConstantNull(); | 2937 exception = graph.addConstantNull(constantSystem); |
| 2926 compiler.reportError(node, | 2938 compiler.reportError(node, |
| 2927 'throw without expression outside catch block'); | 2939 'throw without expression outside catch block'); |
| 2928 } | 2940 } |
| 2929 close(new HThrow(exception, isRethrow: true)); | 2941 close(new HThrow(exception, isRethrow: true)); |
| 2930 } else { | 2942 } else { |
| 2931 visit(node.expression); | 2943 visit(node.expression); |
| 2932 close(new HThrow(pop())); | 2944 close(new HThrow(pop())); |
| 2933 } | 2945 } |
| 2934 } | 2946 } |
| 2935 | 2947 |
| 2936 visitTypeAnnotation(TypeAnnotation node) { | 2948 visitTypeAnnotation(TypeAnnotation node) { |
| 2937 compiler.internalError('visiting type annotation in SSA builder', | 2949 compiler.internalError('visiting type annotation in SSA builder', |
| 2938 node: node); | 2950 node: node); |
| 2939 } | 2951 } |
| 2940 | 2952 |
| 2941 visitVariableDefinitions(VariableDefinitions node) { | 2953 visitVariableDefinitions(VariableDefinitions node) { |
| 2942 for (Link<Node> link = node.definitions.nodes; | 2954 for (Link<Node> link = node.definitions.nodes; |
| 2943 !link.isEmpty(); | 2955 !link.isEmpty(); |
| 2944 link = link.tail) { | 2956 link = link.tail) { |
| 2945 Node definition = link.head; | 2957 Node definition = link.head; |
| 2946 if (definition is Identifier) { | 2958 if (definition is Identifier) { |
| 2947 HInstruction initialValue = graph.addConstantNull(); | 2959 HInstruction initialValue = graph.addConstantNull(constantSystem); |
| 2948 localsHandler.updateLocal(elements[definition], initialValue); | 2960 localsHandler.updateLocal(elements[definition], initialValue); |
| 2949 } else { | 2961 } else { |
| 2950 assert(definition is SendSet); | 2962 assert(definition is SendSet); |
| 2951 visitSendSet(definition); | 2963 visitSendSet(definition); |
| 2952 pop(); // Discard value. | 2964 pop(); // Discard value. |
| 2953 } | 2965 } |
| 2954 } | 2966 } |
| 2955 } | 2967 } |
| 2956 | 2968 |
| 2957 visitLiteralList(LiteralList node) { | 2969 visitLiteralList(LiteralList node) { |
| (...skipping 577 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3535 compiler.cancel('On with unresolved type', | 3547 compiler.cancel('On with unresolved type', |
| 3536 node: catchBlock.type); | 3548 node: catchBlock.type); |
| 3537 } | 3549 } |
| 3538 HInstruction condition = new HIs(type, unwrappedException); | 3550 HInstruction condition = new HIs(type, unwrappedException); |
| 3539 push(condition); | 3551 push(condition); |
| 3540 } | 3552 } |
| 3541 else { | 3553 else { |
| 3542 VariableDefinitions declaration = catchBlock.formals.nodes.head; | 3554 VariableDefinitions declaration = catchBlock.formals.nodes.head; |
| 3543 HInstruction condition = null; | 3555 HInstruction condition = null; |
| 3544 if (declaration.type == null) { | 3556 if (declaration.type == null) { |
| 3545 condition = graph.addConstantBool(true); | 3557 condition = graph.addConstantBool(true, constantSystem); |
| 3546 stack.add(condition); | 3558 stack.add(condition); |
| 3547 } else { | 3559 } else { |
| 3548 // TODO(aprelev@gmail.com): Once old catch syntax is removed | 3560 // TODO(aprelev@gmail.com): Once old catch syntax is removed |
| 3549 // "if" condition above and this "else" branch should be deleted as | 3561 // "if" condition above and this "else" branch should be deleted as |
| 3550 // type of declared variable won't matter for the catch | 3562 // type of declared variable won't matter for the catch |
| 3551 // condition. | 3563 // condition. |
| 3552 DartType type = elements.getType(declaration.type); | 3564 DartType type = elements.getType(declaration.type); |
| 3553 if (type == null) { | 3565 if (type == null) { |
| 3554 compiler.cancel('Catch with unresolved type', node: catchBlock); | 3566 compiler.cancel('Catch with unresolved type', node: catchBlock); |
| 3555 } | 3567 } |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3646 if (element === builder.compiler.intClass) return HType.INTEGER; | 3658 if (element === builder.compiler.intClass) return HType.INTEGER; |
| 3647 if (element === builder.compiler.listClass) return HType.READABLE_ARRAY; | 3659 if (element === builder.compiler.listClass) return HType.READABLE_ARRAY; |
| 3648 if (element === builder.compiler.nullClass) return HType.NULL; | 3660 if (element === builder.compiler.nullClass) return HType.NULL; |
| 3649 if (element === builder.compiler.stringClass) return HType.STRING; | 3661 if (element === builder.compiler.stringClass) return HType.STRING; |
| 3650 return HType.UNKNOWN; | 3662 return HType.UNKNOWN; |
| 3651 } | 3663 } |
| 3652 | 3664 |
| 3653 /** HACK HACK HACK */ | 3665 /** HACK HACK HACK */ |
| 3654 void hackAroundPossiblyAbortingBody(Node statement, void body()) { | 3666 void hackAroundPossiblyAbortingBody(Node statement, void body()) { |
| 3655 visitCondition() { | 3667 visitCondition() { |
| 3656 stack.add(graph.addConstantBool(true)); | 3668 stack.add(graph.addConstantBool(true, constantSystem)); |
| 3657 } | 3669 } |
| 3658 buildBody() { | 3670 buildBody() { |
| 3659 // TODO(lrn): Make sure to take continue into account. | 3671 // TODO(lrn): Make sure to take continue into account. |
| 3660 body(); | 3672 body(); |
| 3661 } | 3673 } |
| 3662 handleIf(statement, visitCondition, buildBody, null); | 3674 handleIf(statement, visitCondition, buildBody, null); |
| 3663 } | 3675 } |
| 3664 } | 3676 } |
| 3665 | 3677 |
| 3666 /** | 3678 /** |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3938 builder.push(new HNot(builder.pop())); | 3950 builder.push(new HNot(builder.pop())); |
| 3939 } | 3951 } |
| 3940 } | 3952 } |
| 3941 | 3953 |
| 3942 void visitThen() { | 3954 void visitThen() { |
| 3943 right(); | 3955 right(); |
| 3944 boolifiedRight = builder.popBoolified(); | 3956 boolifiedRight = builder.popBoolified(); |
| 3945 } | 3957 } |
| 3946 | 3958 |
| 3947 handleIf(visitCondition, visitThen, null); | 3959 handleIf(visitCondition, visitThen, null); |
| 3960 HConstant notIsAnd = |
| 3961 builder.graph.addConstantBool(!isAnd, builder.constantSystem); |
| 3948 HPhi result = new HPhi.manyInputs(null, | 3962 HPhi result = new HPhi.manyInputs(null, |
| 3949 <HInstruction>[boolifiedRight, builder.graph.addConstantBool(!isAnd)]); | 3963 <HInstruction>[boolifiedRight, notIsAnd]); |
| 3950 builder.current.addPhi(result); | 3964 builder.current.addPhi(result); |
| 3951 builder.stack.add(result); | 3965 builder.stack.add(result); |
| 3952 } | 3966 } |
| 3953 | 3967 |
| 3954 void handleLogicalAndOrWithLeftNode(Node left, | 3968 void handleLogicalAndOrWithLeftNode(Node left, |
| 3955 void visitRight(), | 3969 void visitRight(), |
| 3956 [bool isAnd]) { | 3970 [bool isAnd]) { |
| 3957 // This method is similar to [handleLogicalAndOr] but optimizes the case | 3971 // This method is similar to [handleLogicalAndOr] but optimizes the case |
| 3958 // where left is a logical "and" or logical "or". | 3972 // where left is a logical "and" or logical "or". |
| 3959 // | 3973 // |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4026 new HSubGraphBlockInformation(elseBranch.graph)); | 4040 new HSubGraphBlockInformation(elseBranch.graph)); |
| 4027 | 4041 |
| 4028 HBasicBlock conditionStartBlock = conditionBranch.block; | 4042 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 4029 conditionStartBlock.setBlockFlow(info, joinBlock); | 4043 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 4030 SubGraph conditionGraph = conditionBranch.graph; | 4044 SubGraph conditionGraph = conditionBranch.graph; |
| 4031 HIf branch = conditionGraph.end.last; | 4045 HIf branch = conditionGraph.end.last; |
| 4032 assert(branch is HIf); | 4046 assert(branch is HIf); |
| 4033 branch.blockInformation = conditionStartBlock.blockFlow; | 4047 branch.blockInformation = conditionStartBlock.blockFlow; |
| 4034 } | 4048 } |
| 4035 } | 4049 } |
| OLD | NEW |