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 |