| 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 1334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1345 visit(node.receiver); | 1345 visit(node.receiver); |
| 1346 HNot not = new HNot(popBoolified()); | 1346 HNot not = new HNot(popBoolified()); |
| 1347 push(not); | 1347 push(not); |
| 1348 } | 1348 } |
| 1349 | 1349 |
| 1350 void visitUnary(Send node, Operator op) { | 1350 void visitUnary(Send node, Operator op) { |
| 1351 assert(node.argumentsNode is Prefix); | 1351 assert(node.argumentsNode is Prefix); |
| 1352 visit(node.receiver); | 1352 visit(node.receiver); |
| 1353 assert(op.token.kind !== PLUS_TOKEN); | 1353 assert(op.token.kind !== PLUS_TOKEN); |
| 1354 HInstruction operand = pop(); | 1354 HInstruction operand = pop(); |
| 1355 |
| 1355 HInstruction target = | 1356 HInstruction target = |
| 1356 new HStatic(interceptors.getPrefixOperatorInterceptor(op)); | 1357 new HStatic(interceptors.getPrefixOperatorInterceptor(op)); |
| 1357 add(target); | 1358 add(target); |
| 1358 HInvokeUnary result; | 1359 HInvokeUnary result; |
| 1359 switch (op.source.stringValue) { | 1360 switch (op.source.stringValue) { |
| 1360 case "-": result = new HNegate(target, operand); break; | 1361 case "-": result = new HNegate(target, operand); break; |
| 1361 case "~": result = new HBitNot(target, operand); break; | 1362 case "~": result = new HBitNot(target, operand); break; |
| 1362 default: unreachable(); | 1363 default: unreachable(); |
| 1363 } | 1364 } |
| 1364 // See if we can constant-fold right away. This avoids rewrites later on. | 1365 // See if we can constant-fold right away. This avoids rewrites later on. |
| (...skipping 584 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1949 } | 1950 } |
| 1950 | 1951 |
| 1951 void visitLiteralBool(LiteralBool node) { | 1952 void visitLiteralBool(LiteralBool node) { |
| 1952 stack.add(graph.addConstantBool(node.value)); | 1953 stack.add(graph.addConstantBool(node.value)); |
| 1953 } | 1954 } |
| 1954 | 1955 |
| 1955 void visitLiteralString(LiteralString node) { | 1956 void visitLiteralString(LiteralString node) { |
| 1956 stack.add(graph.addConstantString(node.dartString)); | 1957 stack.add(graph.addConstantString(node.dartString)); |
| 1957 } | 1958 } |
| 1958 | 1959 |
| 1959 void visitLiteralStringJuxtaposition(LiteralStringJuxtaposition node) { | 1960 void visitStringJuxtaposition(StringJuxtaposition node) { |
| 1960 visitLiteralString(node); | 1961 if (!node.isInterpolation) { |
| 1962 // This is a simple string with no interpolations. |
| 1963 stack.add(graph.addConstantString(node.dartString)); |
| 1964 return; |
| 1965 } |
| 1966 int offset = node.getBeginToken().charOffset; |
| 1967 StringBuilderVisitor stringBuilder = |
| 1968 new StringBuilderVisitor(this, offset); |
| 1969 stringBuilder.visit(node); |
| 1970 stack.add(stringBuilder.result()); |
| 1961 } | 1971 } |
| 1962 | 1972 |
| 1963 void visitLiteralNull(LiteralNull node) { | 1973 void visitLiteralNull(LiteralNull node) { |
| 1964 stack.add(graph.addConstantNull()); | 1974 stack.add(graph.addConstantNull()); |
| 1965 } | 1975 } |
| 1966 | 1976 |
| 1967 visitNodeList(NodeList node) { | 1977 visitNodeList(NodeList node) { |
| 1968 for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) { | 1978 for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) { |
| 1969 if (isAborted()) { | 1979 if (isAborted()) { |
| 1970 compiler.reportWarning(link.head, 'dead code'); | 1980 compiler.reportWarning(link.head, 'dead code'); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2073 open(joinBlock); | 2083 open(joinBlock); |
| 2074 | 2084 |
| 2075 localsHandler.mergeWith(thenLocals, joinBlock); | 2085 localsHandler.mergeWith(thenLocals, joinBlock); |
| 2076 HPhi phi = new HPhi.manyInputs(null, [thenInstruction, elseInstruction]); | 2086 HPhi phi = new HPhi.manyInputs(null, [thenInstruction, elseInstruction]); |
| 2077 joinBlock.addPhi(phi); | 2087 joinBlock.addPhi(phi); |
| 2078 stack.add(phi); | 2088 stack.add(phi); |
| 2079 } | 2089 } |
| 2080 | 2090 |
| 2081 visitStringInterpolation(StringInterpolation node) { | 2091 visitStringInterpolation(StringInterpolation node) { |
| 2082 int offset = node.getBeginToken().charOffset; | 2092 int offset = node.getBeginToken().charOffset; |
| 2083 Operator op = new Operator(new StringToken(PLUS_INFO, "+", offset)); | 2093 StringBuilderVisitor stringBuilder = |
| 2084 HInstruction target = new HStatic(interceptors.getOperatorInterceptor(op)); | 2094 new StringBuilderVisitor(this, offset); |
| 2085 add(target); | 2095 stringBuilder.visit(node); |
| 2086 visit(node.string); | 2096 stack.add(stringBuilder.result()); |
| 2087 // Handle the parts here, to avoid recreating [target]. | |
| 2088 for (StringInterpolationPart part in node.parts) { | |
| 2089 HInstruction prefix = pop(); | |
| 2090 visit(part.expression); | |
| 2091 push(new HAdd(target, prefix, pop())); | |
| 2092 prefix = pop(); | |
| 2093 visit(part.string); | |
| 2094 push(new HAdd(target, prefix, pop())); | |
| 2095 } | |
| 2096 } | 2097 } |
| 2097 | 2098 |
| 2098 visitStringInterpolationPart(StringInterpolationPart node) { | 2099 visitStringInterpolationPart(StringInterpolationPart node) { |
| 2099 // The parts are iterated in visitStringInterpolation. | 2100 // The parts are iterated in visitStringInterpolation. |
| 2100 unreachable(); | 2101 unreachable(); |
| 2101 } | 2102 } |
| 2102 | 2103 |
| 2103 visitEmptyStatement(EmptyStatement node) { | 2104 visitEmptyStatement(EmptyStatement node) { |
| 2104 // Do nothing, empty statement. | 2105 // Do nothing, empty statement. |
| 2105 } | 2106 } |
| (...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2557 buildBody() { | 2558 buildBody() { |
| 2558 // TODO(lrn): Make sure to take continue into account. | 2559 // TODO(lrn): Make sure to take continue into account. |
| 2559 visit(body); | 2560 visit(body); |
| 2560 if (isAborted()) { | 2561 if (isAborted()) { |
| 2561 compiler.reportWarning(body, "aborting loop body"); | 2562 compiler.reportWarning(body, "aborting loop body"); |
| 2562 } | 2563 } |
| 2563 } | 2564 } |
| 2564 handleIf(buildBody, null); | 2565 handleIf(buildBody, null); |
| 2565 } | 2566 } |
| 2566 } | 2567 } |
| 2568 |
| 2569 /** |
| 2570 * Visitor that handles generation of string literals (LiteralString, |
| 2571 * StringInterpolation), and otherwise delegates to the given visitor for |
| 2572 * non-literal subexpressions. |
| 2573 * TODO(lrn): Consider whether to handle compile time constant int/boolean |
| 2574 * expressions as well. |
| 2575 */ |
| 2576 class StringBuilderVisitor extends AbstractVisitor { |
| 2577 final SsaBuilder builder; |
| 2578 // Offset used for the synthetic operator token used by concat. |
| 2579 // Can probably be removed when we stop using String.operator+. |
| 2580 final int offset; |
| 2581 // Used to collect concatenated string literals into a single literal |
| 2582 // instead of introducing unnecessary concatenations. |
| 2583 DartString accumulator = const LiteralDartString(""); |
| 2584 // The string value generated so far (not including that which is still |
| 2585 // in [accumulator]). |
| 2586 HInstruction prefix = null; |
| 2587 |
| 2588 StringBuilderVisitor(this.builder, this.offset); |
| 2589 |
| 2590 void visit(Node node) { |
| 2591 node.accept(this); |
| 2592 } |
| 2593 |
| 2594 void visitNode() { |
| 2595 unreachable(); |
| 2596 } |
| 2597 |
| 2598 void visitExpression(Node node) { |
| 2599 flushAccumulator(); |
| 2600 node.accept(builder); |
| 2601 prefix = concat(prefix, builder.pop()); |
| 2602 } |
| 2603 |
| 2604 void visitStringInterpolation(StringInterpolation node) { |
| 2605 node.visitChildren(this); |
| 2606 } |
| 2607 |
| 2608 void visitStringInterpolationPart(StringInterpolationPart node) { |
| 2609 visit(node.expression); |
| 2610 visit(node.string); |
| 2611 } |
| 2612 |
| 2613 void visitLiteralString(LiteralString node) { |
| 2614 accumulator = new DartString.concat(accumulator, node.dartString); |
| 2615 } |
| 2616 |
| 2617 void visitStringJuxtaposition(StringJuxtaposition node) { |
| 2618 node.visitChildren(this); |
| 2619 } |
| 2620 |
| 2621 void visitNodeList(NodeList node) { |
| 2622 node.visitChildren(this); |
| 2623 } |
| 2624 |
| 2625 /** |
| 2626 * Combine the strings in [accumulator] into the prefix instruction. |
| 2627 * After this, the [accumulator] is empty and [prefix] is non-null. |
| 2628 */ |
| 2629 void flushAccumulator() { |
| 2630 if (accumulator.isEmpty()) { |
| 2631 if (prefix === null) { |
| 2632 prefix = builder.graph.addConstantString(accumulator); |
| 2633 } |
| 2634 return; |
| 2635 } |
| 2636 HInstruction string = builder.graph.addConstantString(accumulator); |
| 2637 accumulator = new DartString.empty(); |
| 2638 if (prefix !== null) { |
| 2639 prefix = concat(prefix, string); |
| 2640 } else { |
| 2641 prefix = string; |
| 2642 } |
| 2643 } |
| 2644 |
| 2645 HInstruction concat(HInstruction left, HInstruction right) { |
| 2646 Operator op = new Operator(new StringToken(PLUS_INFO, "+", offset)); |
| 2647 HStatic target = |
| 2648 new HStatic(builder.interceptors.getOperatorInterceptor(op)); |
| 2649 builder.add(target); |
| 2650 HInstruction concat = new HAdd(target, left, right); |
| 2651 builder.add(concat); |
| 2652 return concat; |
| 2653 } |
| 2654 |
| 2655 HInstruction result() { |
| 2656 flushAccumulator(); |
| 2657 return prefix; |
| 2658 } |
| 2659 } |
| OLD | NEW |