| 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 2544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2555 void visitLiteralString(LiteralString node) { | 2555 void visitLiteralString(LiteralString node) { |
| 2556 stack.add(graph.addConstantString(node.dartString, node)); | 2556 stack.add(graph.addConstantString(node.dartString, node)); |
| 2557 } | 2557 } |
| 2558 | 2558 |
| 2559 void visitStringJuxtaposition(StringJuxtaposition node) { | 2559 void visitStringJuxtaposition(StringJuxtaposition node) { |
| 2560 if (!node.isInterpolation) { | 2560 if (!node.isInterpolation) { |
| 2561 // This is a simple string with no interpolations. | 2561 // This is a simple string with no interpolations. |
| 2562 stack.add(graph.addConstantString(node.dartString, node)); | 2562 stack.add(graph.addConstantString(node.dartString, node)); |
| 2563 return; | 2563 return; |
| 2564 } | 2564 } |
| 2565 int offset = node.getBeginToken().charOffset; | 2565 StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this); |
| 2566 StringBuilderVisitor stringBuilder = | |
| 2567 new StringBuilderVisitor(this, offset); | |
| 2568 stringBuilder.visit(node); | 2566 stringBuilder.visit(node); |
| 2569 stack.add(stringBuilder.result(node)); | 2567 stack.add(stringBuilder.result); |
| 2570 } | 2568 } |
| 2571 | 2569 |
| 2572 void visitLiteralNull(LiteralNull node) { | 2570 void visitLiteralNull(LiteralNull node) { |
| 2573 stack.add(graph.addConstantNull()); | 2571 stack.add(graph.addConstantNull()); |
| 2574 } | 2572 } |
| 2575 | 2573 |
| 2576 visitNodeList(NodeList node) { | 2574 visitNodeList(NodeList node) { |
| 2577 for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) { | 2575 for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) { |
| 2578 if (isAborted()) { | 2576 if (isAborted()) { |
| 2579 compiler.reportWarning(link.head, 'dead code'); | 2577 compiler.reportWarning(link.head, 'dead code'); |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2709 open(joinBlock); | 2707 open(joinBlock); |
| 2710 | 2708 |
| 2711 localsHandler.mergeWith(thenLocals, joinBlock); | 2709 localsHandler.mergeWith(thenLocals, joinBlock); |
| 2712 HPhi phi = new HPhi.manyInputs(null, | 2710 HPhi phi = new HPhi.manyInputs(null, |
| 2713 <HInstruction>[thenInstruction, elseInstruction]); | 2711 <HInstruction>[thenInstruction, elseInstruction]); |
| 2714 joinBlock.addPhi(phi); | 2712 joinBlock.addPhi(phi); |
| 2715 stack.add(phi); | 2713 stack.add(phi); |
| 2716 } | 2714 } |
| 2717 | 2715 |
| 2718 visitStringInterpolation(StringInterpolation node) { | 2716 visitStringInterpolation(StringInterpolation node) { |
| 2719 int offset = node.getBeginToken().charOffset; | 2717 StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this); |
| 2720 StringBuilderVisitor stringBuilder = | |
| 2721 new StringBuilderVisitor(this, offset); | |
| 2722 stringBuilder.visit(node); | 2718 stringBuilder.visit(node); |
| 2723 stack.add(stringBuilder.result(node)); | 2719 stack.add(stringBuilder.result); |
| 2724 } | 2720 } |
| 2725 | 2721 |
| 2726 visitStringInterpolationPart(StringInterpolationPart node) { | 2722 visitStringInterpolationPart(StringInterpolationPart node) { |
| 2727 // The parts are iterated in visitStringInterpolation. | 2723 // The parts are iterated in visitStringInterpolation. |
| 2728 compiler.internalError('visitStringInterpolation should not be called', | 2724 compiler.internalError('visitStringInterpolation should not be called', |
| 2729 node: node); | 2725 node: node); |
| 2730 } | 2726 } |
| 2731 | 2727 |
| 2732 visitEmptyStatement(EmptyStatement node) { | 2728 visitEmptyStatement(EmptyStatement node) { |
| 2733 // Do nothing, empty statement. | 2729 // Do nothing, empty statement. |
| (...skipping 654 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3388 | 3384 |
| 3389 /** | 3385 /** |
| 3390 * Visitor that handles generation of string literals (LiteralString, | 3386 * Visitor that handles generation of string literals (LiteralString, |
| 3391 * StringInterpolation), and otherwise delegates to the given visitor for | 3387 * StringInterpolation), and otherwise delegates to the given visitor for |
| 3392 * non-literal subexpressions. | 3388 * non-literal subexpressions. |
| 3393 * TODO(lrn): Consider whether to handle compile time constant int/boolean | 3389 * TODO(lrn): Consider whether to handle compile time constant int/boolean |
| 3394 * expressions as well. | 3390 * expressions as well. |
| 3395 */ | 3391 */ |
| 3396 class StringBuilderVisitor extends AbstractVisitor { | 3392 class StringBuilderVisitor extends AbstractVisitor { |
| 3397 final SsaBuilder builder; | 3393 final SsaBuilder builder; |
| 3398 final Element stringConcat; | |
| 3399 final Element stringToString; | |
| 3400 | 3394 |
| 3401 /** | 3395 /** |
| 3402 * Offset used for the synthetic operator token used by concat. | 3396 * The string value generated so far. |
| 3403 * Can probably be removed when we stop using String.operator+. | |
| 3404 */ | 3397 */ |
| 3405 final int offset; | 3398 HInstruction result = null; |
| 3406 | 3399 |
| 3407 /** | 3400 StringBuilderVisitor(this.builder); |
| 3408 * Used to collect concatenated string literals into a single literal | |
| 3409 * instead of introducing unnecessary concatenations. | |
| 3410 */ | |
| 3411 DartString literalAccumulator = const LiteralDartString(""); | |
| 3412 | |
| 3413 /** | |
| 3414 * The string value generated so far (not including that which is still | |
| 3415 * in [literalAccumulator]). | |
| 3416 */ | |
| 3417 HInstruction prefix = null; | |
| 3418 | |
| 3419 StringBuilderVisitor(builder, this.offset) | |
| 3420 : this.builder = builder, | |
| 3421 stringConcat = builder.compiler.findHelper( | |
| 3422 const SourceString("stringConcat")), | |
| 3423 stringToString = builder.compiler.findHelper( | |
| 3424 const SourceString("stringToString")); | |
| 3425 | 3401 |
| 3426 void visit(Node node) { | 3402 void visit(Node node) { |
| 3427 node.accept(this); | 3403 node.accept(this); |
| 3428 } | 3404 } |
| 3429 | 3405 |
| 3430 visitNode(Node node) { | 3406 visitNode(Node node) { |
| 3431 builder.compiler.internalError('unexpected node', node: node); | 3407 builder.compiler.internalError('unexpected node', node: node); |
| 3432 } | 3408 } |
| 3433 | 3409 |
| 3434 void visitExpression(Node node) { | 3410 void visitExpression(Node node) { |
| 3435 flushLiterals(node); | |
| 3436 node.accept(builder); | 3411 node.accept(builder); |
| 3437 HInstruction asString = buildToString(node, builder.pop()); | 3412 HInstruction expression = builder.pop(); |
| 3438 prefix = buildConcat(prefix, asString); | 3413 result = (result === null) ? expression : concat(result, expression); |
| 3439 } | |
| 3440 | |
| 3441 void visitLiteralNull(LiteralNull node) { | |
| 3442 addLiteral(const LiteralDartString("null")); | |
| 3443 } | |
| 3444 | |
| 3445 void visitLiteralInt(LiteralInt node) { | |
| 3446 addLiteral(new DartString.literal(node.value.toString())); | |
| 3447 } | |
| 3448 | |
| 3449 void visitLiteralDouble(LiteralDouble node) { | |
| 3450 addLiteral(new DartString.literal(node.value.toString())); | |
| 3451 } | |
| 3452 | |
| 3453 void visitLiteralBool(LiteralBool node) { | |
| 3454 addLiteral(node.value ? const LiteralDartString("true") | |
| 3455 : const LiteralDartString("false")); | |
| 3456 } | 3414 } |
| 3457 | 3415 |
| 3458 void visitStringInterpolation(StringInterpolation node) { | 3416 void visitStringInterpolation(StringInterpolation node) { |
| 3459 node.visitChildren(this); | 3417 node.visitChildren(this); |
| 3460 } | 3418 } |
| 3461 | 3419 |
| 3462 void visitStringInterpolationPart(StringInterpolationPart node) { | 3420 void visitStringInterpolationPart(StringInterpolationPart node) { |
| 3463 visit(node.expression); | 3421 visit(node.expression); |
| 3464 visit(node.string); | 3422 visit(node.string); |
| 3465 } | 3423 } |
| 3466 | 3424 |
| 3467 void visitLiteralString(LiteralString node) { | |
| 3468 addLiteral(node.dartString); | |
| 3469 } | |
| 3470 | |
| 3471 void visitStringJuxtaposition(StringJuxtaposition node) { | 3425 void visitStringJuxtaposition(StringJuxtaposition node) { |
| 3472 node.visitChildren(this); | 3426 node.visitChildren(this); |
| 3473 } | 3427 } |
| 3474 | 3428 |
| 3475 void visitNodeList(NodeList node) { | 3429 void visitNodeList(NodeList node) { |
| 3476 node.visitChildren(this); | 3430 node.visitChildren(this); |
| 3477 } | 3431 } |
| 3478 | 3432 |
| 3479 /** | 3433 HInstruction concat(HInstruction left, HInstruction right) { |
| 3480 * Add another literal string to the literalAccumulator. | 3434 HInstruction instruction = new HStringConcat(left, right); |
| 3481 */ | 3435 builder.add(instruction); |
| 3482 void addLiteral(DartString dartString) { | 3436 return instruction; |
| 3483 literalAccumulator = new DartString.concat(literalAccumulator, dartString); | |
| 3484 } | |
| 3485 | |
| 3486 /** | |
| 3487 * Combine the strings in [literalAccumulator] into the prefix instruction. | |
| 3488 * After this, the [literalAccumulator] is empty and [prefix] is non-null. | |
| 3489 */ | |
| 3490 void flushLiterals(Node node) { | |
| 3491 if (literalAccumulator.isEmpty()) { | |
| 3492 if (prefix === null) { | |
| 3493 prefix = builder.graph.addConstantString(literalAccumulator, node); | |
| 3494 } | |
| 3495 return; | |
| 3496 } | |
| 3497 HInstruction string = | |
| 3498 builder.graph.addConstantString(literalAccumulator, node); | |
| 3499 literalAccumulator = new DartString.empty(); | |
| 3500 if (prefix !== null) { | |
| 3501 prefix = buildConcat(prefix, string); | |
| 3502 } else { | |
| 3503 prefix = string; | |
| 3504 } | |
| 3505 } | |
| 3506 | |
| 3507 HInstruction buildConcat(HInstruction left, HInstruction right) { | |
| 3508 HStatic target = new HStatic(stringConcat); | |
| 3509 builder.add(target); | |
| 3510 builder.push(new HAdd(target, left, right)); | |
| 3511 return builder.pop(); | |
| 3512 } | |
| 3513 | |
| 3514 HInstruction buildToString(Node node, HInstruction input) { | |
| 3515 HStatic target = new HStatic(stringToString); | |
| 3516 builder.add(target); | |
| 3517 builder.push(new HInvokeStatic(Selector.INVOCATION_1, | |
| 3518 <HInstruction>[target, input], | |
| 3519 HType.STRING)); | |
| 3520 return builder.pop(); | |
| 3521 } | |
| 3522 | |
| 3523 HInstruction result(Node node) { | |
| 3524 flushLiterals(node); | |
| 3525 return prefix; | |
| 3526 } | 3437 } |
| 3527 } | 3438 } |
| OLD | NEW |