| 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 582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1915 } | 1916 } |
| 1916 | 1917 |
| 1917 void visitLiteralBool(LiteralBool node) { | 1918 void visitLiteralBool(LiteralBool node) { |
| 1918 stack.add(graph.addConstantBool(node.value)); | 1919 stack.add(graph.addConstantBool(node.value)); |
| 1919 } | 1920 } |
| 1920 | 1921 |
| 1921 void visitLiteralString(LiteralString node) { | 1922 void visitLiteralString(LiteralString node) { |
| 1922 stack.add(graph.addConstantString(node.dartString)); | 1923 stack.add(graph.addConstantString(node.dartString)); |
| 1923 } | 1924 } |
| 1924 | 1925 |
| 1925 void visitLiteralStringJuxtaposition(LiteralStringJuxtaposition node) { | 1926 void visitStringJuxtaposition(StringJuxtaposition node) { |
| 1926 visitLiteralString(node); | 1927 if (!node.isInterpolation) { |
| 1928 // This is a simple string with no interpolations. |
| 1929 stack.add(graph.addConstantString(node.dartString)); |
| 1930 return; |
| 1931 } |
| 1932 int offset = node.getBeginToken().charOffset; |
| 1933 StringBuilderVisitor stringBuilder = |
| 1934 new StringBuilderVisitor(this, offset); |
| 1935 stringBuilder.visit(node); |
| 1936 stack.add(stringBuilder.result()); |
| 1927 } | 1937 } |
| 1928 | 1938 |
| 1929 void visitLiteralNull(LiteralNull node) { | 1939 void visitLiteralNull(LiteralNull node) { |
| 1930 stack.add(graph.addConstantNull()); | 1940 stack.add(graph.addConstantNull()); |
| 1931 } | 1941 } |
| 1932 | 1942 |
| 1933 visitNodeList(NodeList node) { | 1943 visitNodeList(NodeList node) { |
| 1934 for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) { | 1944 for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) { |
| 1935 if (isAborted()) { | 1945 if (isAborted()) { |
| 1936 compiler.reportWarning(link.head, 'dead code'); | 1946 compiler.reportWarning(link.head, 'dead code'); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2039 open(joinBlock); | 2049 open(joinBlock); |
| 2040 | 2050 |
| 2041 localsHandler.mergeWith(thenLocals, joinBlock); | 2051 localsHandler.mergeWith(thenLocals, joinBlock); |
| 2042 HPhi phi = new HPhi.manyInputs(null, [thenInstruction, elseInstruction]); | 2052 HPhi phi = new HPhi.manyInputs(null, [thenInstruction, elseInstruction]); |
| 2043 joinBlock.addPhi(phi); | 2053 joinBlock.addPhi(phi); |
| 2044 stack.add(phi); | 2054 stack.add(phi); |
| 2045 } | 2055 } |
| 2046 | 2056 |
| 2047 visitStringInterpolation(StringInterpolation node) { | 2057 visitStringInterpolation(StringInterpolation node) { |
| 2048 int offset = node.getBeginToken().charOffset; | 2058 int offset = node.getBeginToken().charOffset; |
| 2049 Operator op = new Operator(new StringToken(PLUS_INFO, "+", offset)); | 2059 StringBuilderVisitor stringBuilder = |
| 2050 HInstruction target = new HStatic(interceptors.getOperatorInterceptor(op)); | 2060 new StringBuilderVisitor(this, offset); |
| 2051 add(target); | 2061 stringBuilder.visit(node); |
| 2052 visit(node.string); | 2062 stack.add(stringBuilder.result()); |
| 2053 // Handle the parts here, to avoid recreating [target]. | |
| 2054 for (StringInterpolationPart part in node.parts) { | |
| 2055 HInstruction prefix = pop(); | |
| 2056 visit(part.expression); | |
| 2057 push(new HAdd(target, prefix, pop())); | |
| 2058 prefix = pop(); | |
| 2059 visit(part.string); | |
| 2060 push(new HAdd(target, prefix, pop())); | |
| 2061 } | |
| 2062 } | 2063 } |
| 2063 | 2064 |
| 2064 visitStringInterpolationPart(StringInterpolationPart node) { | 2065 visitStringInterpolationPart(StringInterpolationPart node) { |
| 2065 // The parts are iterated in visitStringInterpolation. | 2066 // The parts are iterated in visitStringInterpolation. |
| 2066 unreachable(); | 2067 unreachable(); |
| 2067 } | 2068 } |
| 2068 | 2069 |
| 2069 visitEmptyStatement(EmptyStatement node) { | 2070 visitEmptyStatement(EmptyStatement node) { |
| 2070 // Do nothing, empty statement. | 2071 // Do nothing, empty statement. |
| 2071 } | 2072 } |
| (...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2520 buildBody() { | 2521 buildBody() { |
| 2521 // TODO(lrn): Make sure to take continue into account. | 2522 // TODO(lrn): Make sure to take continue into account. |
| 2522 visit(body); | 2523 visit(body); |
| 2523 if (isAborted()) { | 2524 if (isAborted()) { |
| 2524 compiler.reportWarning(body, "aborting loop body"); | 2525 compiler.reportWarning(body, "aborting loop body"); |
| 2525 } | 2526 } |
| 2526 } | 2527 } |
| 2527 handleIf(buildBody, null); | 2528 handleIf(buildBody, null); |
| 2528 } | 2529 } |
| 2529 } | 2530 } |
| 2531 |
| 2532 /** |
| 2533 * Visitor that handles generation of string literals (LiteralString, |
| 2534 * StringInterpolation), and otherwise delegates to the given visitor for |
| 2535 * non-literal subexpressions. |
| 2536 * TODO(lrn): Consider whether to handle compile time constant int/boolean |
| 2537 * expressions as well. |
| 2538 */ |
| 2539 class StringBuilderVisitor extends AbstractVisitor { |
| 2540 final SsaBuilder builder; |
| 2541 // Offset used for the synthetic operator token used by concat. |
| 2542 // Can probably be removed when we stop using String.operator+. |
| 2543 final int offset; |
| 2544 // Used to collect concatenated string literals into a single literal |
| 2545 // instead of introducing unnecessary concatenations. |
| 2546 DartString accumulator = const LiteralDartString(""); |
| 2547 // The string value generated so far (not including that which is still |
| 2548 // in [accumulator]). |
| 2549 HInstruction prefix = null; |
| 2550 |
| 2551 StringBuilderVisitor(this.builder, this.offset); |
| 2552 |
| 2553 void visit(Node node) { |
| 2554 node.accept(this); |
| 2555 } |
| 2556 |
| 2557 void visitNode() { |
| 2558 unreachable(); |
| 2559 } |
| 2560 |
| 2561 void visitExpression(Node node) { |
| 2562 flushAccumulator(); |
| 2563 node.accept(builder); |
| 2564 prefix = concat(prefix, builder.pop()); |
| 2565 } |
| 2566 |
| 2567 void visitStringInterpolation(StringInterpolation node) { |
| 2568 node.visitChildren(this); |
| 2569 } |
| 2570 |
| 2571 void visitStringInterpolationPart(StringInterpolationPart node) { |
| 2572 visit(node.expression); |
| 2573 visit(node.string); |
| 2574 } |
| 2575 |
| 2576 void visitLiteralString(LiteralString node) { |
| 2577 accumulator = new DartString.concat(accumulator, node.dartString); |
| 2578 } |
| 2579 |
| 2580 void visitStringJuxtaposition(StringJuxtaposition node) { |
| 2581 node.visitChildren(this); |
| 2582 } |
| 2583 |
| 2584 void visitNodeList(NodeList node) { |
| 2585 node.visitChildren(this); |
| 2586 } |
| 2587 |
| 2588 /** |
| 2589 * Combine the strings in [accumulator] into the prefix instruction. |
| 2590 * After this, the [accumulator] is empty and [prefix] is non-null. |
| 2591 */ |
| 2592 void flushAccumulator() { |
| 2593 if (accumulator.isEmpty()) { |
| 2594 if (prefix === null) { |
| 2595 prefix = builder.graph.addConstantString(accumulator); |
| 2596 } |
| 2597 return; |
| 2598 } |
| 2599 HInstruction string = builder.graph.addConstantString(accumulator); |
| 2600 accumulator = new DartString.empty(); |
| 2601 if (prefix !== null) { |
| 2602 prefix = concat(prefix, string); |
| 2603 } else { |
| 2604 prefix = string; |
| 2605 } |
| 2606 } |
| 2607 |
| 2608 HInstruction concat(HInstruction left, HInstruction right) { |
| 2609 Operator op = new Operator(new StringToken(PLUS_INFO, "+", offset)); |
| 2610 HStatic target = |
| 2611 new HStatic(builder.interceptors.getOperatorInterceptor(op)); |
| 2612 builder.add(target); |
| 2613 HInstruction concat = new HAdd(target, left, right); |
| 2614 builder.add(concat); |
| 2615 return concat; |
| 2616 } |
| 2617 |
| 2618 HInstruction result() { |
| 2619 flushAccumulator(); |
| 2620 return prefix; |
| 2621 } |
| 2622 } |
| OLD | NEW |