| 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 659 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 670 void close(); | 670 void close(); |
| 671 final TargetElement target; | 671 final TargetElement target; |
| 672 List<LabelElement> labels(); | 672 List<LabelElement> labels(); |
| 673 } | 673 } |
| 674 | 674 |
| 675 // Insert break handler used to avoid null checks when a target isn't | 675 // Insert break handler used to avoid null checks when a target isn't |
| 676 // used as the target of a break, and therefore doesn't need a break | 676 // used as the target of a break, and therefore doesn't need a break |
| 677 // handler associated with it. | 677 // handler associated with it. |
| 678 class NullJumpHandler implements JumpHandler { | 678 class NullJumpHandler implements JumpHandler { |
| 679 const NullJumpHandler(); | 679 const NullJumpHandler(); |
| 680 void generateBreak([LabelElement label]) { unreachable(); } | 680 |
| 681 void generateContinue([LabelElement label]) { unreachable(); } | 681 void generateBreak([LabelElement label]) { |
| 682 // TODO(lrn): Need a compiler object and a location. Since label |
| 683 // is optional, it may be null so we also need a position. |
| 684 compiler.internalError('generateBreak should not be called', |
| 685 missingPosition); |
| 686 } |
| 687 |
| 688 void generateContinue([LabelElement label]) { |
| 689 // TODO(lrn): Need a compiler object and a location. Since label |
| 690 // is optional, it may be null so we also need a position. |
| 691 compiler.internalError('generateContinue should not be called', |
| 692 missingPosition); |
| 693 } |
| 694 |
| 682 void forEachBreak(Function ignored) { } | 695 void forEachBreak(Function ignored) { } |
| 683 void forEachContinue(Function ignored) { } | 696 void forEachContinue(Function ignored) { } |
| 684 void close() { } | 697 void close() { } |
| 685 final TargetElement target = null; | 698 final TargetElement target = null; |
| 686 List<LabelElement> labels() => const <LabelElement>[]; | 699 List<LabelElement> labels() => const <LabelElement>[]; |
| 687 } | 700 } |
| 688 | 701 |
| 689 // Records breaks until a target block is available. | 702 // Records breaks until a target block is available. |
| 690 // Breaks are always forward jumps. | 703 // Breaks are always forward jumps. |
| 691 // Continues in loops are implemented as breaks of the body. | 704 // Continues in loops are implemented as breaks of the body. |
| (...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1143 // The block has been aborted by a return or a throw. | 1156 // The block has been aborted by a return or a throw. |
| 1144 if (!stack.isEmpty()) compiler.cancel('non-empty instruction stack'); | 1157 if (!stack.isEmpty()) compiler.cancel('non-empty instruction stack'); |
| 1145 return; | 1158 return; |
| 1146 } | 1159 } |
| 1147 } | 1160 } |
| 1148 assert(!current.isClosed()); | 1161 assert(!current.isClosed()); |
| 1149 if (!stack.isEmpty()) compiler.cancel('non-empty instruction stack'); | 1162 if (!stack.isEmpty()) compiler.cancel('non-empty instruction stack'); |
| 1150 } | 1163 } |
| 1151 | 1164 |
| 1152 visitClassNode(ClassNode node) { | 1165 visitClassNode(ClassNode node) { |
| 1153 unreachable(); | 1166 compiler.internalError('visitClassNode should not be called', node: node); |
| 1154 } | 1167 } |
| 1155 | 1168 |
| 1156 visitExpressionStatement(ExpressionStatement node) { | 1169 visitExpressionStatement(ExpressionStatement node) { |
| 1157 visit(node.expression); | 1170 visit(node.expression); |
| 1158 pop(); | 1171 pop(); |
| 1159 } | 1172 } |
| 1160 | 1173 |
| 1161 /** | 1174 /** |
| 1162 * Creates a new loop-header block. The previous [current] block | 1175 * Creates a new loop-header block. The previous [current] block |
| 1163 * is closed with an [HGoto] and replaced by the newly created block. | 1176 * is closed with an [HGoto] and replaced by the newly created block. |
| (...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1653 void visitUnary(Send node, Operator op) { | 1666 void visitUnary(Send node, Operator op) { |
| 1654 assert(node.argumentsNode is Prefix); | 1667 assert(node.argumentsNode is Prefix); |
| 1655 visit(node.receiver); | 1668 visit(node.receiver); |
| 1656 assert(op.token.kind !== PLUS_TOKEN); | 1669 assert(op.token.kind !== PLUS_TOKEN); |
| 1657 HInstruction operand = pop(); | 1670 HInstruction operand = pop(); |
| 1658 | 1671 |
| 1659 HInstruction target = | 1672 HInstruction target = |
| 1660 new HStatic(interceptors.getPrefixOperatorInterceptor(op)); | 1673 new HStatic(interceptors.getPrefixOperatorInterceptor(op)); |
| 1661 add(target); | 1674 add(target); |
| 1662 HInvokeUnary result; | 1675 HInvokeUnary result; |
| 1663 switch (op.source.stringValue) { | 1676 String value = op.source.stringValue; |
| 1677 switch (value) { |
| 1664 case "-": result = new HNegate(target, operand); break; | 1678 case "-": result = new HNegate(target, operand); break; |
| 1665 case "~": result = new HBitNot(target, operand); break; | 1679 case "~": result = new HBitNot(target, operand); break; |
| 1666 default: unreachable(); | 1680 default: |
| 1681 compiler.internalError('Unexpected unary operator: $value.', node: op); |
| 1682 break; |
| 1667 } | 1683 } |
| 1668 // See if we can constant-fold right away. This avoids rewrites later on. | 1684 // See if we can constant-fold right away. This avoids rewrites later on. |
| 1669 if (operand is HConstant) { | 1685 if (operand is HConstant) { |
| 1670 HConstant constant = operand; | 1686 HConstant constant = operand; |
| 1671 Constant folded = result.operation.fold(constant.constant); | 1687 Constant folded = result.operation.fold(constant.constant); |
| 1672 if (folded !== null) { | 1688 if (folded !== null) { |
| 1673 stack.add(graph.addConstant(folded)); | 1689 stack.add(graph.addConstant(folded)); |
| 1674 return; | 1690 return; |
| 1675 } | 1691 } |
| 1676 } | 1692 } |
| (...skipping 564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2241 HStatic target = new HStatic(element); | 2257 HStatic target = new HStatic(element); |
| 2242 add(target); | 2258 add(target); |
| 2243 HInstruction self = localsHandler.readThis(); | 2259 HInstruction self = localsHandler.readThis(); |
| 2244 Identifier identifier = node.selector.asIdentifier(); | 2260 Identifier identifier = node.selector.asIdentifier(); |
| 2245 String name = identifier.source.slowToString(); | 2261 String name = identifier.source.slowToString(); |
| 2246 // TODO(ahe): Add the arguments to this list. | 2262 // TODO(ahe): Add the arguments to this list. |
| 2247 push(new HLiteralList([])); | 2263 push(new HLiteralList([])); |
| 2248 var inputs = <HInstruction>[ | 2264 var inputs = <HInstruction>[ |
| 2249 target, | 2265 target, |
| 2250 self, | 2266 self, |
| 2251 graph.addConstantString(new DartString.literal(name)), | 2267 graph.addConstantString(new DartString.literal(name), node), |
| 2252 pop()]; | 2268 pop()]; |
| 2253 push(new HInvokeSuper(Selector.INVOCATION_2, inputs)); | 2269 push(new HInvokeSuper(Selector.INVOCATION_2, inputs)); |
| 2254 return; | 2270 return; |
| 2255 } | 2271 } |
| 2256 HInstruction target = new HStatic(element); | 2272 HInstruction target = new HStatic(element); |
| 2257 HInstruction context = localsHandler.readThis(); | 2273 HInstruction context = localsHandler.readThis(); |
| 2258 add(target); | 2274 add(target); |
| 2259 var inputs = <HInstruction>[target, context]; | 2275 var inputs = <HInstruction>[target, context]; |
| 2260 if (element.kind == ElementKind.FUNCTION || | 2276 if (element.kind == ElementKind.FUNCTION || |
| 2261 element.kind == ElementKind.GENERATIVE_CONSTRUCTOR) { | 2277 element.kind == ElementKind.GENERATIVE_CONSTRUCTOR) { |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2531 | 2547 |
| 2532 void visitLiteralDouble(LiteralDouble node) { | 2548 void visitLiteralDouble(LiteralDouble node) { |
| 2533 stack.add(graph.addConstantDouble(node.value)); | 2549 stack.add(graph.addConstantDouble(node.value)); |
| 2534 } | 2550 } |
| 2535 | 2551 |
| 2536 void visitLiteralBool(LiteralBool node) { | 2552 void visitLiteralBool(LiteralBool node) { |
| 2537 stack.add(graph.addConstantBool(node.value)); | 2553 stack.add(graph.addConstantBool(node.value)); |
| 2538 } | 2554 } |
| 2539 | 2555 |
| 2540 void visitLiteralString(LiteralString node) { | 2556 void visitLiteralString(LiteralString node) { |
| 2541 stack.add(graph.addConstantString(node.dartString)); | 2557 stack.add(graph.addConstantString(node.dartString, node)); |
| 2542 } | 2558 } |
| 2543 | 2559 |
| 2544 void visitStringJuxtaposition(StringJuxtaposition node) { | 2560 void visitStringJuxtaposition(StringJuxtaposition node) { |
| 2545 if (!node.isInterpolation) { | 2561 if (!node.isInterpolation) { |
| 2546 // This is a simple string with no interpolations. | 2562 // This is a simple string with no interpolations. |
| 2547 stack.add(graph.addConstantString(node.dartString)); | 2563 stack.add(graph.addConstantString(node.dartString, node)); |
| 2548 return; | 2564 return; |
| 2549 } | 2565 } |
| 2550 int offset = node.getBeginToken().charOffset; | 2566 int offset = node.getBeginToken().charOffset; |
| 2551 StringBuilderVisitor stringBuilder = | 2567 StringBuilderVisitor stringBuilder = |
| 2552 new StringBuilderVisitor(this, offset); | 2568 new StringBuilderVisitor(this, offset); |
| 2553 stringBuilder.visit(node); | 2569 stringBuilder.visit(node); |
| 2554 stack.add(stringBuilder.result()); | 2570 stack.add(stringBuilder.result(node)); |
| 2555 } | 2571 } |
| 2556 | 2572 |
| 2557 void visitLiteralNull(LiteralNull node) { | 2573 void visitLiteralNull(LiteralNull node) { |
| 2558 stack.add(graph.addConstantNull()); | 2574 stack.add(graph.addConstantNull()); |
| 2559 } | 2575 } |
| 2560 | 2576 |
| 2561 visitNodeList(NodeList node) { | 2577 visitNodeList(NodeList node) { |
| 2562 for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) { | 2578 for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) { |
| 2563 if (isAborted()) { | 2579 if (isAborted()) { |
| 2564 compiler.reportWarning(link.head, 'dead code'); | 2580 compiler.reportWarning(link.head, 'dead code'); |
| 2565 } else { | 2581 } else { |
| 2566 visit(link.head); | 2582 visit(link.head); |
| 2567 } | 2583 } |
| 2568 } | 2584 } |
| 2569 } | 2585 } |
| 2570 | 2586 |
| 2571 void visitParenthesizedExpression(ParenthesizedExpression node) { | 2587 void visitParenthesizedExpression(ParenthesizedExpression node) { |
| 2572 visit(node.expression); | 2588 visit(node.expression); |
| 2573 } | 2589 } |
| 2574 | 2590 |
| 2575 visitOperator(Operator node) { | 2591 visitOperator(Operator node) { |
| 2576 // Operators are intercepted in their surrounding Send nodes. | 2592 // Operators are intercepted in their surrounding Send nodes. |
| 2577 unreachable(); | 2593 compiler.internalError('visitOperator should not be called', node: node); |
| 2578 } | 2594 } |
| 2579 | 2595 |
| 2580 visitCascade(Cascade node) { | 2596 visitCascade(Cascade node) { |
| 2581 visit(node.expression); | 2597 visit(node.expression); |
| 2582 // Remove the result and reveal the duplicated receiver on the stack. | 2598 // Remove the result and reveal the duplicated receiver on the stack. |
| 2583 pop(); | 2599 pop(); |
| 2584 } | 2600 } |
| 2585 | 2601 |
| 2586 visitCascadeReceiver(CascadeReceiver node) { | 2602 visitCascadeReceiver(CascadeReceiver node) { |
| 2587 visit(node.expression); | 2603 visit(node.expression); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2698 <HInstruction>[thenInstruction, elseInstruction]); | 2714 <HInstruction>[thenInstruction, elseInstruction]); |
| 2699 joinBlock.addPhi(phi); | 2715 joinBlock.addPhi(phi); |
| 2700 stack.add(phi); | 2716 stack.add(phi); |
| 2701 } | 2717 } |
| 2702 | 2718 |
| 2703 visitStringInterpolation(StringInterpolation node) { | 2719 visitStringInterpolation(StringInterpolation node) { |
| 2704 int offset = node.getBeginToken().charOffset; | 2720 int offset = node.getBeginToken().charOffset; |
| 2705 StringBuilderVisitor stringBuilder = | 2721 StringBuilderVisitor stringBuilder = |
| 2706 new StringBuilderVisitor(this, offset); | 2722 new StringBuilderVisitor(this, offset); |
| 2707 stringBuilder.visit(node); | 2723 stringBuilder.visit(node); |
| 2708 stack.add(stringBuilder.result()); | 2724 stack.add(stringBuilder.result(node)); |
| 2709 } | 2725 } |
| 2710 | 2726 |
| 2711 visitStringInterpolationPart(StringInterpolationPart node) { | 2727 visitStringInterpolationPart(StringInterpolationPart node) { |
| 2712 // The parts are iterated in visitStringInterpolation. | 2728 // The parts are iterated in visitStringInterpolation. |
| 2713 unreachable(); | 2729 compiler.internalError('visitStringInterpolation should not be called', |
| 2730 node: node); |
| 2714 } | 2731 } |
| 2715 | 2732 |
| 2716 visitEmptyStatement(EmptyStatement node) { | 2733 visitEmptyStatement(EmptyStatement node) { |
| 2717 // Do nothing, empty statement. | 2734 // Do nothing, empty statement. |
| 2718 } | 2735 } |
| 2719 | 2736 |
| 2720 visitModifiers(Modifiers node) { | 2737 visitModifiers(Modifiers node) { |
| 2721 compiler.unimplemented('SsaBuilder.visitModifiers', node: node); | 2738 compiler.unimplemented('SsaBuilder.visitModifiers', node: node); |
| 2722 } | 2739 } |
| 2723 | 2740 |
| (...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3163 } | 3180 } |
| 3164 | 3181 |
| 3165 visitTypedef(Typedef node) { | 3182 visitTypedef(Typedef node) { |
| 3166 compiler.unimplemented('SsaBuilder.visitTypedef', node: node); | 3183 compiler.unimplemented('SsaBuilder.visitTypedef', node: node); |
| 3167 } | 3184 } |
| 3168 | 3185 |
| 3169 visitTypeVariable(TypeVariable node) { | 3186 visitTypeVariable(TypeVariable node) { |
| 3170 compiler.internalError('SsaBuilder.visitTypeVariable'); | 3187 compiler.internalError('SsaBuilder.visitTypeVariable'); |
| 3171 } | 3188 } |
| 3172 | 3189 |
| 3173 generateUnimplemented(String reason, [bool isExpression = false]) { | |
| 3174 DartString string = new DartString.literal(reason); | |
| 3175 HInstruction message = graph.addConstantString(string); | |
| 3176 | |
| 3177 // Normally, we would call [close] here. However, then we hit | |
| 3178 // another unimplemented feature: aborting loop body. Simply | |
| 3179 // calling [add] does not work as it asserts that the instruction | |
| 3180 // isn't a control flow instruction. So we inline parts of [add]. | |
| 3181 current.addAfter(current.last, new HThrow(message)); | |
| 3182 if (isExpression) { | |
| 3183 stack.add(graph.addConstantNull()); | |
| 3184 } | |
| 3185 } | |
| 3186 | |
| 3187 /** HACK HACK HACK */ | 3190 /** HACK HACK HACK */ |
| 3188 void hackAroundPossiblyAbortingBody(Node statement, void body()) { | 3191 void hackAroundPossiblyAbortingBody(Node statement, void body()) { |
| 3189 visitCondition() { | 3192 visitCondition() { |
| 3190 stack.add(graph.addConstantBool(true)); | 3193 stack.add(graph.addConstantBool(true)); |
| 3191 } | 3194 } |
| 3192 buildBody() { | 3195 buildBody() { |
| 3193 // TODO(lrn): Make sure to take continue into account. | 3196 // TODO(lrn): Make sure to take continue into account. |
| 3194 body(); | 3197 body(); |
| 3195 } | 3198 } |
| 3196 handleIf(visitCondition, buildBody, null); | 3199 handleIf(visitCondition, buildBody, null); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3236 | 3239 |
| 3237 void visit(Node node) { | 3240 void visit(Node node) { |
| 3238 node.accept(this); | 3241 node.accept(this); |
| 3239 } | 3242 } |
| 3240 | 3243 |
| 3241 visitNode(Node node) { | 3244 visitNode(Node node) { |
| 3242 builder.compiler.internalError('unexpected node', node: node); | 3245 builder.compiler.internalError('unexpected node', node: node); |
| 3243 } | 3246 } |
| 3244 | 3247 |
| 3245 void visitExpression(Node node) { | 3248 void visitExpression(Node node) { |
| 3246 flushLiterals(); | 3249 flushLiterals(node); |
| 3247 node.accept(builder); | 3250 node.accept(builder); |
| 3248 HInstruction asString = buildToString(node, builder.pop()); | 3251 HInstruction asString = buildToString(node, builder.pop()); |
| 3249 prefix = buildConcat(prefix, asString); | 3252 prefix = buildConcat(prefix, asString); |
| 3250 } | 3253 } |
| 3251 | 3254 |
| 3252 void visitLiteralNull(LiteralNull node) { | 3255 void visitLiteralNull(LiteralNull node) { |
| 3253 addLiteral(const LiteralDartString("null")); | 3256 addLiteral(const LiteralDartString("null")); |
| 3254 } | 3257 } |
| 3255 | 3258 |
| 3256 void visitLiteralInt(LiteralInt node) { | 3259 void visitLiteralInt(LiteralInt node) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3291 * Add another literal string to the literalAccumulator. | 3294 * Add another literal string to the literalAccumulator. |
| 3292 */ | 3295 */ |
| 3293 void addLiteral(DartString dartString) { | 3296 void addLiteral(DartString dartString) { |
| 3294 literalAccumulator = new DartString.concat(literalAccumulator, dartString); | 3297 literalAccumulator = new DartString.concat(literalAccumulator, dartString); |
| 3295 } | 3298 } |
| 3296 | 3299 |
| 3297 /** | 3300 /** |
| 3298 * Combine the strings in [literalAccumulator] into the prefix instruction. | 3301 * Combine the strings in [literalAccumulator] into the prefix instruction. |
| 3299 * After this, the [literalAccumulator] is empty and [prefix] is non-null. | 3302 * After this, the [literalAccumulator] is empty and [prefix] is non-null. |
| 3300 */ | 3303 */ |
| 3301 void flushLiterals() { | 3304 void flushLiterals(Node node) { |
| 3302 if (literalAccumulator.isEmpty()) { | 3305 if (literalAccumulator.isEmpty()) { |
| 3303 if (prefix === null) { | 3306 if (prefix === null) { |
| 3304 prefix = builder.graph.addConstantString(literalAccumulator); | 3307 prefix = builder.graph.addConstantString(literalAccumulator, node); |
| 3305 } | 3308 } |
| 3306 return; | 3309 return; |
| 3307 } | 3310 } |
| 3308 HInstruction string = builder.graph.addConstantString(literalAccumulator); | 3311 HInstruction string = |
| 3312 builder.graph.addConstantString(literalAccumulator, node); |
| 3309 literalAccumulator = new DartString.empty(); | 3313 literalAccumulator = new DartString.empty(); |
| 3310 if (prefix !== null) { | 3314 if (prefix !== null) { |
| 3311 prefix = buildConcat(prefix, string); | 3315 prefix = buildConcat(prefix, string); |
| 3312 } else { | 3316 } else { |
| 3313 prefix = string; | 3317 prefix = string; |
| 3314 } | 3318 } |
| 3315 } | 3319 } |
| 3316 | 3320 |
| 3317 HInstruction buildConcat(HInstruction left, HInstruction right) { | 3321 HInstruction buildConcat(HInstruction left, HInstruction right) { |
| 3318 HStatic target = new HStatic(stringConcat); | 3322 HStatic target = new HStatic(stringConcat); |
| 3319 builder.add(target); | 3323 builder.add(target); |
| 3320 builder.push(new HAdd(target, left, right)); | 3324 builder.push(new HAdd(target, left, right)); |
| 3321 return builder.pop(); | 3325 return builder.pop(); |
| 3322 } | 3326 } |
| 3323 | 3327 |
| 3324 HInstruction buildToString(Node node, HInstruction input) { | 3328 HInstruction buildToString(Node node, HInstruction input) { |
| 3325 HStatic target = new HStatic(stringToString); | 3329 HStatic target = new HStatic(stringToString); |
| 3326 builder.add(target); | 3330 builder.add(target); |
| 3327 builder.push(new HInvokeStatic(Selector.INVOCATION_1, | 3331 builder.push(new HInvokeStatic(Selector.INVOCATION_1, |
| 3328 <HInstruction>[target, input], | 3332 <HInstruction>[target, input], |
| 3329 HType.STRING)); | 3333 HType.STRING)); |
| 3330 return builder.pop(); | 3334 return builder.pop(); |
| 3331 } | 3335 } |
| 3332 | 3336 |
| 3333 HInstruction result() { | 3337 HInstruction result(Node node) { |
| 3334 flushLiterals(); | 3338 flushLiterals(node); |
| 3335 return prefix; | 3339 return prefix; |
| 3336 } | 3340 } |
| 3337 } | 3341 } |
| OLD | NEW |