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