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 1302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1313 visit(node.receiver); | 1313 visit(node.receiver); |
| 1314 HNot not = new HNot(popBoolified()); | 1314 HNot not = new HNot(popBoolified()); |
| 1315 push(not); | 1315 push(not); |
| 1316 } | 1316 } |
| 1317 | 1317 |
| 1318 void visitUnary(Send node, Operator op) { | 1318 void visitUnary(Send node, Operator op) { |
| 1319 assert(node.argumentsNode is Prefix); | 1319 assert(node.argumentsNode is Prefix); |
| 1320 visit(node.receiver); | 1320 visit(node.receiver); |
| 1321 assert(op.token.kind !== PLUS_TOKEN); | 1321 assert(op.token.kind !== PLUS_TOKEN); |
| 1322 HInstruction operand = pop(); | 1322 HInstruction operand = pop(); |
| 1323 | |
| 1323 HInstruction target = | 1324 HInstruction target = |
| 1324 new HStatic(interceptors.getPrefixOperatorInterceptor(op)); | 1325 new HStatic(interceptors.getPrefixOperatorInterceptor(op)); |
| 1325 add(target); | 1326 add(target); |
| 1326 HInvokeUnary result; | 1327 HInvokeUnary result; |
| 1327 switch (op.source.stringValue) { | 1328 switch (op.source.stringValue) { |
| 1328 case "-": result = new HNegate(target, operand); break; | 1329 case "-": result = new HNegate(target, operand); break; |
| 1329 case "~": result = new HBitNot(target, operand); break; | 1330 case "~": result = new HBitNot(target, operand); break; |
| 1330 default: unreachable(); | 1331 default: unreachable(); |
| 1331 } | 1332 } |
| 1332 // See if we can constant-fold right away. This avoids rewrites later on. | 1333 // See if we can constant-fold right away. This avoids rewrites later on. |
| (...skipping 623 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1956 } | 1957 } |
| 1957 | 1958 |
| 1958 void visitLiteralBool(LiteralBool node) { | 1959 void visitLiteralBool(LiteralBool node) { |
| 1959 stack.add(graph.addConstantBool(node.value)); | 1960 stack.add(graph.addConstantBool(node.value)); |
| 1960 } | 1961 } |
| 1961 | 1962 |
| 1962 void visitLiteralString(LiteralString node) { | 1963 void visitLiteralString(LiteralString node) { |
| 1963 stack.add(graph.addConstantString(node.dartString)); | 1964 stack.add(graph.addConstantString(node.dartString)); |
| 1964 } | 1965 } |
| 1965 | 1966 |
| 1966 void visitLiteralStringJuxtaposition(LiteralStringJuxtaposition node) { | 1967 void visitStringJuxtaposition(StringJuxtaposition node) { |
| 1967 visitLiteralString(node); | 1968 if (node.dartString !== null) { |
|
ngeoffray
2012/03/14 12:29:58
!node.isInterpolation
Lasse Reichstein Nielsen
2012/03/14 13:04:49
Done.
At this point, we know that things are eithe
| |
| 1969 // This is a simple string with no interpolations. | |
| 1970 stack.add(graph.addConstantString(node.dartString)); | |
| 1971 return; | |
| 1972 } | |
| 1973 int offset = node.getBeginToken().charOffset; | |
| 1974 StringBuilderVisitor stringBuilder = | |
| 1975 new StringBuilderVisitor(this, offset); | |
| 1976 stringBuilder.visit(node); | |
| 1977 stack.add(stringBuilder.result()); | |
| 1968 } | 1978 } |
| 1969 | 1979 |
| 1970 void visitLiteralNull(LiteralNull node) { | 1980 void visitLiteralNull(LiteralNull node) { |
| 1971 stack.add(graph.addConstantNull()); | 1981 stack.add(graph.addConstantNull()); |
| 1972 } | 1982 } |
| 1973 | 1983 |
| 1974 visitNodeList(NodeList node) { | 1984 visitNodeList(NodeList node) { |
| 1975 for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) { | 1985 for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) { |
| 1976 if (isAborted()) { | 1986 if (isAborted()) { |
| 1977 compiler.reportWarning(link.head, 'dead code'); | 1987 compiler.reportWarning(link.head, 'dead code'); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2080 open(joinBlock); | 2090 open(joinBlock); |
| 2081 | 2091 |
| 2082 localsHandler.mergeWith(thenLocals, joinBlock); | 2092 localsHandler.mergeWith(thenLocals, joinBlock); |
| 2083 HPhi phi = new HPhi.manyInputs(null, [thenInstruction, elseInstruction]); | 2093 HPhi phi = new HPhi.manyInputs(null, [thenInstruction, elseInstruction]); |
| 2084 joinBlock.addPhi(phi); | 2094 joinBlock.addPhi(phi); |
| 2085 stack.add(phi); | 2095 stack.add(phi); |
| 2086 } | 2096 } |
| 2087 | 2097 |
| 2088 visitStringInterpolation(StringInterpolation node) { | 2098 visitStringInterpolation(StringInterpolation node) { |
| 2089 int offset = node.getBeginToken().charOffset; | 2099 int offset = node.getBeginToken().charOffset; |
| 2090 Operator op = new Operator(new StringToken(PLUS_INFO, "+", offset)); | 2100 StringBuilderVisitor stringBuilder = |
| 2091 HInstruction target = new HStatic(interceptors.getOperatorInterceptor(op)); | 2101 new StringBuilderVisitor(this, offset); |
| 2092 add(target); | 2102 stringBuilder.visit(node); |
| 2093 visit(node.string); | 2103 stack.add(stringBuilder.result()); |
| 2094 // Handle the parts here, to avoid recreating [target]. | |
| 2095 for (StringInterpolationPart part in node.parts) { | |
| 2096 HInstruction prefix = pop(); | |
| 2097 visit(part.expression); | |
| 2098 push(new HAdd(target, prefix, pop())); | |
| 2099 prefix = pop(); | |
| 2100 visit(part.string); | |
| 2101 push(new HAdd(target, prefix, pop())); | |
| 2102 } | |
| 2103 } | 2104 } |
| 2104 | 2105 |
| 2105 visitStringInterpolationPart(StringInterpolationPart node) { | 2106 visitStringInterpolationPart(StringInterpolationPart node) { |
| 2106 // The parts are iterated in visitStringInterpolation. | 2107 // The parts are iterated in visitStringInterpolation. |
| 2107 unreachable(); | 2108 unreachable(); |
| 2108 } | 2109 } |
| 2109 | 2110 |
| 2110 visitEmptyStatement(EmptyStatement node) { | 2111 visitEmptyStatement(EmptyStatement node) { |
| 2111 // Do nothing, empty statement. | 2112 // Do nothing, empty statement. |
| 2112 } | 2113 } |
| (...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2561 buildBody() { | 2562 buildBody() { |
| 2562 // TODO(lrn): Make sure to take continue into account. | 2563 // TODO(lrn): Make sure to take continue into account. |
| 2563 visit(body); | 2564 visit(body); |
| 2564 if (isAborted()) { | 2565 if (isAborted()) { |
| 2565 compiler.reportWarning(body, "aborting loop body"); | 2566 compiler.reportWarning(body, "aborting loop body"); |
| 2566 } | 2567 } |
| 2567 } | 2568 } |
| 2568 handleIf(buildBody, null); | 2569 handleIf(buildBody, null); |
| 2569 } | 2570 } |
| 2570 } | 2571 } |
| 2572 | |
| 2573 /** | |
| 2574 * Visitor that handles generation of string literals (LiteralString, | |
| 2575 * StringInterpolation), and otherwise delegates to the given visitor for | |
| 2576 * non-literal subexpressions. | |
| 2577 * TODO(lrn): Consider whether to handle compile time constant int/boolan | |
|
ngeoffray
2012/03/14 12:29:58
boolan -> boolean
Lasse Reichstein Nielsen
2012/03/14 13:04:49
Done.
| |
| 2578 * expressions as well. | |
| 2579 */ | |
| 2580 class StringBuilderVisitor extends AbstractVisitor { | |
| 2581 final SsaBuilder builder; | |
| 2582 // Offset used for the synthetic operator token used by concat. | |
| 2583 // Can probably be removed when we stop using String.operator+. | |
| 2584 final int offset; | |
| 2585 // Used to collect concatenated string literals into a single literal | |
| 2586 // instead of introducing unnecessary concatenations. | |
| 2587 DartString accumulator = const LiteralDartString(""); | |
| 2588 // The string value generated so far (not including that which is still | |
| 2589 // in [accumulator]). | |
| 2590 HInstruction prefix = null; | |
|
ngeoffray
2012/03/14 12:29:58
IMO 'current' would be better than 'prefix'. But t
Lasse Reichstein Nielsen
2012/03/14 13:04:49
Yes, it's really an "instruction accumulator" (as
| |
| 2591 | |
| 2592 StringBuilderVisitor(this.builder, this.offset); | |
| 2593 | |
| 2594 void visit(Node node) { | |
| 2595 node.accept(this); | |
| 2596 } | |
| 2597 | |
| 2598 void visitNode() { | |
| 2599 unreachable(); | |
| 2600 } | |
| 2601 | |
| 2602 void visitExpression(Node node) { | |
| 2603 flushAccumulator(); | |
| 2604 node.accept(builder); | |
| 2605 prefix = concat(prefix, builder.pop()); | |
| 2606 } | |
| 2607 | |
| 2608 void visitStringInterpolation(StringInterpolation node) { | |
| 2609 node.visitChildren(this); | |
| 2610 } | |
| 2611 | |
| 2612 void visitStringInterpolationPart(StringInterpolationPart node) { | |
| 2613 visit(node.expression); | |
| 2614 visit(node.string); | |
| 2615 } | |
| 2616 | |
| 2617 void visitLiteralString(LiteralString node) { | |
| 2618 accumulator = new DartString.concat(accumulator, node.dartString); | |
| 2619 } | |
| 2620 | |
| 2621 void visitStringJuxtaposition(StringJuxtaposition node) { | |
| 2622 node.visitChildren(this); | |
| 2623 } | |
| 2624 | |
| 2625 void visitNodeList(NodeList node) { | |
| 2626 node.visitChildren(this); | |
| 2627 } | |
| 2628 | |
| 2629 /** | |
| 2630 * Combine the strings in [accumulator] into the prefix instruction. | |
| 2631 * After this, the [accumulator] is empty and [prefix] is non-null. | |
| 2632 */ | |
| 2633 void flushAccumulator() { | |
| 2634 if (accumulator.isEmpty()) { | |
| 2635 if (prefix === null) { | |
| 2636 prefix = builder.graph.addConstantString(accumulator); | |
| 2637 } | |
| 2638 return; | |
| 2639 } | |
| 2640 HInstruction string = builder.graph.addConstantString(accumulator); | |
| 2641 accumulator = new DartString.empty(); | |
| 2642 if (prefix !== null) { | |
| 2643 prefix = concat(prefix, string); | |
| 2644 } else { | |
| 2645 prefix = string; | |
| 2646 } | |
| 2647 } | |
| 2648 | |
| 2649 HInstruction concat(HInstruction left, HInstruction right) { | |
| 2650 Operator op = new Operator(new StringToken(PLUS_INFO, "+", offset)); | |
| 2651 HStatic target = | |
| 2652 new HStatic(builder.interceptors.getOperatorInterceptor(op)); | |
| 2653 builder.add(target); | |
| 2654 HInstruction concat = new HAdd(target, left, right); | |
| 2655 builder.add(concat); | |
| 2656 return concat; | |
| 2657 } | |
| 2658 | |
| 2659 HInstruction result() { | |
| 2660 flushAccumulator(); | |
| 2661 return prefix; | |
| 2662 } | |
| 2663 } | |
| OLD | NEW |