OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 library dart2js.ir_builder_task; | 5 library dart2js.ir_builder_task; |
6 | 6 |
7 import '../closure.dart' as closurelib; | 7 import '../closure.dart' as closurelib; |
8 import '../closure.dart' hide ClosureScope; | 8 import '../closure.dart' hide ClosureScope; |
9 import '../constants/expressions.dart'; | 9 import '../constants/expressions.dart'; |
10 import '../dart_types.dart'; | 10 import '../dart_types.dart'; |
(...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
483 // | 483 // |
484 // Return without a subexpression is translated as if it were return null. | 484 // Return without a subexpression is translated as if it were return null. |
485 ir.Primitive visitReturn(ast.Return node) { | 485 ir.Primitive visitReturn(ast.Return node) { |
486 assert(irBuilder.isOpen); | 486 assert(irBuilder.isOpen); |
487 assert(invariant(node, node.beginToken.value != 'native')); | 487 assert(invariant(node, node.beginToken.value != 'native')); |
488 irBuilder.buildReturn(build(node.expression)); | 488 irBuilder.buildReturn(build(node.expression)); |
489 return null; | 489 return null; |
490 } | 490 } |
491 | 491 |
492 visitTryStatement(ast.TryStatement node) { | 492 visitTryStatement(ast.TryStatement node) { |
493 // Try/catch is not yet implemented in the JS backend. | |
494 if (tryStatements == null) { | |
495 return giveup(node, 'try/catch in the JS backend'); | |
496 } | |
497 // Multiple catch blocks are not yet implemented. | 493 // Multiple catch blocks are not yet implemented. |
498 if (node.catchBlocks.isEmpty || | 494 if (node.catchBlocks.isEmpty || |
499 node.catchBlocks.nodes.tail == null) { | 495 node.catchBlocks.nodes.tail == null) { |
500 return giveup(node, 'not exactly one catch block'); | 496 return giveup(node, 'not exactly one catch block'); |
501 } | 497 } |
502 // 'on T' catch blocks are not yet implemented. | 498 // 'on T' catch blocks are not yet implemented. |
503 if ((node.catchBlocks.nodes.head as ast.CatchBlock).onKeyword != null) { | 499 if ((node.catchBlocks.nodes.head as ast.CatchBlock).onKeyword != null) { |
504 return giveup(node, '"on T" catch block'); | 500 return giveup(node, '"on T" catch block'); |
505 } | 501 } |
506 // Finally blocks are not yet implemented. | 502 // Finally blocks are not yet implemented. |
(...skipping 2046 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2553 body.functionSignature.orderedForEachParameter((ParameterElement param) { | 2549 body.functionSignature.orderedForEachParameter((ParameterElement param) { |
2554 if (scope != null && scope.capturedVariables.containsKey(param)) { | 2550 if (scope != null && scope.capturedVariables.containsKey(param)) { |
2555 // Do not pass this parameter; the box will carry its value. | 2551 // Do not pass this parameter; the box will carry its value. |
2556 } else { | 2552 } else { |
2557 parameters.add(param); | 2553 parameters.add(param); |
2558 } | 2554 } |
2559 }); | 2555 }); |
2560 return parameters; | 2556 return parameters; |
2561 } | 2557 } |
2562 | 2558 |
| 2559 DartCapturedVariables _analyzeCapturedVariables(ast.Node node) { |
| 2560 DartCapturedVariables variables = new DartCapturedVariables(elements); |
| 2561 try { |
| 2562 variables.analyze(node); |
| 2563 } catch (e) { |
| 2564 bailoutMessage = variables.bailoutMessage; |
| 2565 rethrow; |
| 2566 } |
| 2567 return variables; |
| 2568 } |
| 2569 |
2563 /// Builds the IR for the body of a constructor. | 2570 /// Builds the IR for the body of a constructor. |
2564 /// | 2571 /// |
2565 /// This function is invoked from one or more "factory" constructors built by | 2572 /// This function is invoked from one or more "factory" constructors built by |
2566 /// [buildConstructor]. | 2573 /// [buildConstructor]. |
2567 ir.FunctionDefinition buildConstructorBody(ConstructorBodyElement body) { | 2574 ir.FunctionDefinition buildConstructorBody(ConstructorBodyElement body) { |
2568 ConstructorElement constructor = body.constructor; | 2575 ConstructorElement constructor = body.constructor; |
2569 ast.FunctionExpression node = constructor.node; | 2576 ast.FunctionExpression node = constructor.node; |
2570 closureMap = compiler.closureToClassMapper.computeClosureToClassMapping( | 2577 closureMap = compiler.closureToClassMapper.computeClosureToClassMapping( |
2571 constructor, | 2578 constructor, |
2572 node, | 2579 node, |
2573 elements); | 2580 elements); |
2574 | 2581 |
| 2582 // We compute variables boxed in mutable variables on entry to each try |
| 2583 // block, not including variables captured by a closure (which are boxed |
| 2584 // in the heap). This duplicates some of the work of closure conversion |
| 2585 // without directly using the results. This duplication is wasteful and |
| 2586 // error-prone. |
| 2587 // TODO(kmillikin): We should combine closure conversion and try/catch |
| 2588 // variable analysis in some way. |
| 2589 DartCapturedVariables variables = _analyzeCapturedVariables(node); |
| 2590 tryStatements = variables.tryStatements; |
2575 JsIrBuilder builder = getBuilderFor(body); | 2591 JsIrBuilder builder = getBuilderFor(body); |
2576 | 2592 |
2577 return withBuilder(builder, () { | 2593 return withBuilder(builder, () { |
2578 irBuilder.buildConstructorBodyHeader(getConstructorBodyParameters(body), | 2594 irBuilder.buildConstructorBodyHeader(getConstructorBodyParameters(body), |
2579 getClosureScopeForNode(node)); | 2595 getClosureScopeForNode(node)); |
2580 visit(node.body); | 2596 visit(node.body); |
2581 return irBuilder.makeFunctionDefinition([]); | 2597 return irBuilder.makeFunctionDefinition([]); |
2582 }); | 2598 }); |
2583 } | 2599 } |
2584 | 2600 |
2585 ir.FunctionDefinition buildFunction(FunctionElement element) { | 2601 ir.FunctionDefinition buildFunction(FunctionElement element) { |
2586 assert(invariant(element, element.isImplementation)); | 2602 assert(invariant(element, element.isImplementation)); |
2587 ast.FunctionExpression node = element.node; | 2603 ast.FunctionExpression node = element.node; |
2588 | 2604 |
2589 assert(!element.isSynthesized); | 2605 assert(!element.isSynthesized); |
2590 assert(node != null); | 2606 assert(node != null); |
2591 assert(elements[node] != null); | 2607 assert(elements[node] != null); |
2592 | 2608 |
2593 closureMap = compiler.closureToClassMapper.computeClosureToClassMapping( | 2609 closureMap = compiler.closureToClassMapper.computeClosureToClassMapping( |
2594 element, | 2610 element, |
2595 node, | 2611 node, |
2596 elements); | 2612 elements); |
| 2613 DartCapturedVariables variables = _analyzeCapturedVariables(node); |
| 2614 tryStatements = variables.tryStatements; |
2597 IrBuilder builder = getBuilderFor(element); | 2615 IrBuilder builder = getBuilderFor(element); |
2598 return withBuilder(builder, () => _makeFunctionBody(element, node)); | 2616 return withBuilder(builder, () => _makeFunctionBody(element, node)); |
2599 } | 2617 } |
2600 | 2618 |
2601 /// Creates a primitive for the default value of [parameter]. | 2619 /// Creates a primitive for the default value of [parameter]. |
2602 ir.Primitive translateDefaultValue(ParameterElement parameter) { | 2620 ir.Primitive translateDefaultValue(ParameterElement parameter) { |
2603 if (parameter.initializer == null) { | 2621 if (parameter.initializer == null) { |
2604 return irBuilder.buildNullLiteral(); | 2622 return irBuilder.buildNullLiteral(); |
2605 } else { | 2623 } else { |
2606 return inlineConstant(parameter.executableContext, parameter.initializer); | 2624 return inlineConstant(parameter.executableContext, parameter.initializer); |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2737 SourceInformation buildCall(ast.Node node) { | 2755 SourceInformation buildCall(ast.Node node) { |
2738 return new PositionSourceInformation( | 2756 return new PositionSourceInformation( |
2739 new TokenSourceLocation(sourceFile, node.getBeginToken(), name)); | 2757 new TokenSourceLocation(sourceFile, node.getBeginToken(), name)); |
2740 } | 2758 } |
2741 | 2759 |
2742 @override | 2760 @override |
2743 SourceInformationBuilder forContext(AstElement element) { | 2761 SourceInformationBuilder forContext(AstElement element) { |
2744 return new PositionSourceInformationBuilder(element); | 2762 return new PositionSourceInformationBuilder(element); |
2745 } | 2763 } |
2746 } | 2764 } |
OLD | NEW |