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 1387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1398 visit(node.receiver); | 1398 visit(node.receiver); |
| 1399 HNot not = new HNot(popBoolified()); | 1399 HNot not = new HNot(popBoolified()); |
| 1400 push(not); | 1400 push(not); |
| 1401 } | 1401 } |
| 1402 | 1402 |
| 1403 void visitUnary(Send node, Operator op) { | 1403 void visitUnary(Send node, Operator op) { |
| 1404 assert(node.argumentsNode is Prefix); | 1404 assert(node.argumentsNode is Prefix); |
| 1405 visit(node.receiver); | 1405 visit(node.receiver); |
| 1406 assert(op.token.kind !== PLUS_TOKEN); | 1406 assert(op.token.kind !== PLUS_TOKEN); |
| 1407 HInstruction operand = pop(); | 1407 HInstruction operand = pop(); |
| 1408 | |
| 1408 HInstruction target = | 1409 HInstruction target = |
| 1409 new HStatic(interceptors.getPrefixOperatorInterceptor(op)); | 1410 new HStatic(interceptors.getPrefixOperatorInterceptor(op)); |
| 1410 add(target); | 1411 add(target); |
| 1411 HInvokeUnary result; | 1412 HInvokeUnary result; |
| 1412 switch (op.source.stringValue) { | 1413 switch (op.source.stringValue) { |
| 1413 case "-": result = new HNegate(target, operand); break; | 1414 case "-": result = new HNegate(target, operand); break; |
| 1414 case "~": result = new HBitNot(target, operand); break; | 1415 case "~": result = new HBitNot(target, operand); break; |
| 1415 default: unreachable(); | 1416 default: unreachable(); |
| 1416 } | 1417 } |
| 1417 // See if we can constant-fold right away. This avoids rewrites later on. | 1418 // See if we can constant-fold right away. This avoids rewrites later on. |
| (...skipping 655 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2073 } | 2074 } |
| 2074 | 2075 |
| 2075 void visitLiteralBool(LiteralBool node) { | 2076 void visitLiteralBool(LiteralBool node) { |
| 2076 stack.add(graph.addConstantBool(node.value)); | 2077 stack.add(graph.addConstantBool(node.value)); |
| 2077 } | 2078 } |
| 2078 | 2079 |
| 2079 void visitLiteralString(LiteralString node) { | 2080 void visitLiteralString(LiteralString node) { |
| 2080 stack.add(graph.addConstantString(node.dartString)); | 2081 stack.add(graph.addConstantString(node.dartString)); |
| 2081 } | 2082 } |
| 2082 | 2083 |
| 2083 void visitLiteralStringJuxtaposition(LiteralStringJuxtaposition node) { | 2084 void visitStringJuxtaposition(StringJuxtaposition node) { |
| 2084 visitLiteralString(node); | 2085 if (!node.isInterpolation) { |
| 2086 // This is a simple string with no interpolations. | |
| 2087 stack.add(graph.addConstantString(node.dartString)); | |
| 2088 return; | |
| 2089 } | |
| 2090 int offset = node.getBeginToken().charOffset; | |
| 2091 StringBuilderVisitor stringBuilder = | |
| 2092 new StringBuilderVisitor(this, offset); | |
| 2093 stringBuilder.visit(node); | |
| 2094 stack.add(stringBuilder.result()); | |
| 2085 } | 2095 } |
| 2086 | 2096 |
| 2087 void visitLiteralNull(LiteralNull node) { | 2097 void visitLiteralNull(LiteralNull node) { |
| 2088 stack.add(graph.addConstantNull()); | 2098 stack.add(graph.addConstantNull()); |
| 2089 } | 2099 } |
| 2090 | 2100 |
| 2091 visitNodeList(NodeList node) { | 2101 visitNodeList(NodeList node) { |
| 2092 for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) { | 2102 for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) { |
| 2093 if (isAborted()) { | 2103 if (isAborted()) { |
| 2094 compiler.reportWarning(link.head, 'dead code'); | 2104 compiler.reportWarning(link.head, 'dead code'); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2197 open(joinBlock); | 2207 open(joinBlock); |
| 2198 | 2208 |
| 2199 localsHandler.mergeWith(thenLocals, joinBlock); | 2209 localsHandler.mergeWith(thenLocals, joinBlock); |
| 2200 HPhi phi = new HPhi.manyInputs(null, [thenInstruction, elseInstruction]); | 2210 HPhi phi = new HPhi.manyInputs(null, [thenInstruction, elseInstruction]); |
| 2201 joinBlock.addPhi(phi); | 2211 joinBlock.addPhi(phi); |
| 2202 stack.add(phi); | 2212 stack.add(phi); |
| 2203 } | 2213 } |
| 2204 | 2214 |
| 2205 visitStringInterpolation(StringInterpolation node) { | 2215 visitStringInterpolation(StringInterpolation node) { |
| 2206 int offset = node.getBeginToken().charOffset; | 2216 int offset = node.getBeginToken().charOffset; |
| 2207 Operator op = new Operator(new StringToken(PLUS_INFO, "+", offset)); | 2217 StringBuilderVisitor stringBuilder = |
| 2208 HInstruction target = new HStatic(interceptors.getOperatorInterceptor(op)); | 2218 new StringBuilderVisitor(this, offset); |
| 2209 add(target); | 2219 stringBuilder.visit(node); |
| 2210 visit(node.string); | 2220 stack.add(stringBuilder.result()); |
| 2211 // Handle the parts here, to avoid recreating [target]. | |
| 2212 for (StringInterpolationPart part in node.parts) { | |
| 2213 HInstruction prefix = pop(); | |
| 2214 visit(part.expression); | |
| 2215 push(new HAdd(target, prefix, pop())); | |
| 2216 prefix = pop(); | |
| 2217 visit(part.string); | |
| 2218 push(new HAdd(target, prefix, pop())); | |
| 2219 } | |
| 2220 } | 2221 } |
| 2221 | 2222 |
| 2222 visitStringInterpolationPart(StringInterpolationPart node) { | 2223 visitStringInterpolationPart(StringInterpolationPart node) { |
| 2223 // The parts are iterated in visitStringInterpolation. | 2224 // The parts are iterated in visitStringInterpolation. |
| 2224 unreachable(); | 2225 unreachable(); |
| 2225 } | 2226 } |
| 2226 | 2227 |
| 2227 visitEmptyStatement(EmptyStatement node) { | 2228 visitEmptyStatement(EmptyStatement node) { |
| 2228 // Do nothing, empty statement. | 2229 // Do nothing, empty statement. |
| 2229 } | 2230 } |
| (...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2701 buildBody() { | 2702 buildBody() { |
| 2702 // TODO(lrn): Make sure to take continue into account. | 2703 // TODO(lrn): Make sure to take continue into account. |
| 2703 visit(body); | 2704 visit(body); |
| 2704 if (isAborted()) { | 2705 if (isAborted()) { |
| 2705 compiler.reportWarning(body, "aborting loop body"); | 2706 compiler.reportWarning(body, "aborting loop body"); |
| 2706 } | 2707 } |
| 2707 } | 2708 } |
| 2708 handleIf(buildBody, null); | 2709 handleIf(buildBody, null); |
| 2709 } | 2710 } |
| 2710 } | 2711 } |
| 2712 | |
| 2713 /** | |
| 2714 * Visitor that handles generation of string literals (LiteralString, | |
| 2715 * StringInterpolation), and otherwise delegates to the given visitor for | |
| 2716 * non-literal subexpressions. | |
| 2717 * TODO(lrn): Consider whether to handle compile time constant int/boolean | |
| 2718 * expressions as well. | |
| 2719 */ | |
| 2720 class StringBuilderVisitor extends AbstractVisitor { | |
| 2721 final SsaBuilder builder; | |
| 2722 // Offset used for the synthetic operator token used by concat. | |
|
ahe
2012/03/19 15:53:06
Documentation comment.
Lasse Reichstein Nielsen
2012/03/20 09:34:33
Done.
| |
| 2723 // Can probably be removed when we stop using String.operator+. | |
| 2724 final int offset; | |
| 2725 // Used to collect concatenated string literals into a single literal | |
| 2726 // instead of introducing unnecessary concatenations. | |
|
ahe
2012/03/19 15:53:06
Ditto.
Lasse Reichstein Nielsen
2012/03/20 09:34:33
Done.
| |
| 2727 DartString accumulator = const LiteralDartString(""); | |
| 2728 // The string value generated so far (not including that which is still | |
|
ahe
2012/03/19 15:53:06
Ditto.
Lasse Reichstein Nielsen
2012/03/20 09:34:33
Done.
| |
| 2729 // in [accumulator]). | |
| 2730 HInstruction prefix = null; | |
| 2731 | |
| 2732 StringBuilderVisitor(this.builder, this.offset); | |
| 2733 | |
| 2734 void visit(Node node) { | |
| 2735 node.accept(this); | |
| 2736 } | |
| 2737 | |
| 2738 void visitNode() { | |
| 2739 unreachable(); | |
|
ahe
2012/03/19 15:53:06
There is no node argument to visitNode, and there
Lasse Reichstein Nielsen
2012/03/20 09:34:33
Good catch.
It'll most likely never get hit (requi
| |
| 2740 } | |
| 2741 | |
| 2742 void visitExpression(Node node) { | |
| 2743 flushAccumulator(); | |
| 2744 node.accept(builder); | |
| 2745 prefix = concat(prefix, builder.pop()); | |
| 2746 } | |
| 2747 | |
| 2748 void visitStringInterpolation(StringInterpolation node) { | |
| 2749 node.visitChildren(this); | |
| 2750 } | |
| 2751 | |
| 2752 void visitStringInterpolationPart(StringInterpolationPart node) { | |
| 2753 visit(node.expression); | |
| 2754 visit(node.string); | |
| 2755 } | |
| 2756 | |
| 2757 void visitLiteralString(LiteralString node) { | |
| 2758 accumulator = new DartString.concat(accumulator, node.dartString); | |
| 2759 } | |
| 2760 | |
| 2761 void visitStringJuxtaposition(StringJuxtaposition node) { | |
| 2762 node.visitChildren(this); | |
| 2763 } | |
| 2764 | |
| 2765 void visitNodeList(NodeList node) { | |
| 2766 node.visitChildren(this); | |
| 2767 } | |
| 2768 | |
| 2769 /** | |
| 2770 * Combine the strings in [accumulator] into the prefix instruction. | |
| 2771 * After this, the [accumulator] is empty and [prefix] is non-null. | |
| 2772 */ | |
| 2773 void flushAccumulator() { | |
| 2774 if (accumulator.isEmpty()) { | |
| 2775 if (prefix === null) { | |
| 2776 prefix = builder.graph.addConstantString(accumulator); | |
| 2777 } | |
| 2778 return; | |
| 2779 } | |
| 2780 HInstruction string = builder.graph.addConstantString(accumulator); | |
| 2781 accumulator = new DartString.empty(); | |
| 2782 if (prefix !== null) { | |
| 2783 prefix = concat(prefix, string); | |
| 2784 } else { | |
| 2785 prefix = string; | |
| 2786 } | |
| 2787 } | |
| 2788 | |
| 2789 HInstruction concat(HInstruction left, HInstruction right) { | |
| 2790 Operator op = new Operator(new StringToken(PLUS_INFO, "+", offset)); | |
| 2791 HStatic target = | |
| 2792 new HStatic(builder.interceptors.getOperatorInterceptor(op)); | |
| 2793 builder.add(target); | |
| 2794 HInstruction concat = new HAdd(target, left, right); | |
| 2795 builder.add(concat); | |
| 2796 return concat; | |
| 2797 } | |
| 2798 | |
| 2799 HInstruction result() { | |
| 2800 flushAccumulator(); | |
| 2801 return prefix; | |
| 2802 } | |
| 2803 } | |
| OLD | NEW |