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; | 5 library dart2js.ir_builder; |
6 | 6 |
7 import '../compile_time_constants.dart' show BackendConstantEnvironment; | 7 import '../compile_time_constants.dart' show BackendConstantEnvironment; |
8 import '../constants/constant_system.dart'; | 8 import '../constants/constant_system.dart'; |
9 import '../constants/values.dart' show ConstantValue, PrimitiveConstantValue; | 9 import '../constants/values.dart' show ConstantValue, PrimitiveConstantValue; |
10 import '../dart_types.dart'; | 10 import '../dart_types.dart'; |
11 import '../dart2jslib.dart'; | 11 import '../dart2jslib.dart'; |
12 import '../elements/elements.dart'; | 12 import '../elements/elements.dart'; |
13 import '../io/source_information.dart'; | 13 import '../io/source_information.dart'; |
14 import '../tree/tree.dart' as ast; | 14 import '../tree/tree.dart' as ast; |
15 import '../types/types.dart' show TypeMask; | 15 import '../types/types.dart' show TypeMask; |
16 import '../closure.dart' hide ClosureScope; | 16 import '../closure.dart' hide ClosureScope; |
17 import '../universe/universe.dart' show SelectorKind; | 17 import '../universe/universe.dart' show SelectorKind; |
18 import 'cps_ir_nodes.dart' as ir; | 18 import 'cps_ir_nodes.dart' as ir; |
19 import 'cps_ir_builder_task.dart' show DartCapturedVariables, | 19 import 'cps_ir_builder_task.dart' show DartCapturedVariables, |
20 GlobalProgramInformation; | 20 GlobalProgramInformation; |
21 | 21 |
22 import '../common.dart' as types show TypeMask; | 22 import '../common.dart' as types show TypeMask; |
23 import '../js/js.dart' as js show Template; | 23 import '../js/js.dart' as js show Template, js, LiteralStatement; |
24 import '../native/native.dart' show NativeBehavior; | 24 import '../native/native.dart' show NativeBehavior; |
25 | 25 |
26 /// A mapping from variable elements to their compile-time values. | 26 /// A mapping from variable elements to their compile-time values. |
27 /// | 27 /// |
28 /// Map elements denoted by parameters and local variables to the | 28 /// Map elements denoted by parameters and local variables to the |
29 /// [ir.Primitive] that is their value. Parameters and locals are | 29 /// [ir.Primitive] that is their value. Parameters and locals are |
30 /// assigned indexes which can be used to refer to them. | 30 /// assigned indexes which can be used to refer to them. |
31 class Environment { | 31 class Environment { |
32 /// A map from locals to their environment index. | 32 /// A map from locals to their environment index. |
33 final Map<Local, int> variable2index; | 33 final Map<Local, int> variable2index; |
(...skipping 1984 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2018 sourceInformation: sourceInformation)); | 2018 sourceInformation: sourceInformation)); |
2019 _current = null; | 2019 _current = null; |
2020 } else { | 2020 } else { |
2021 // Inside the try block of try/finally, all returns go to a join-point | 2021 // Inside the try block of try/finally, all returns go to a join-point |
2022 // continuation that contains the finally code. The return value is | 2022 // continuation that contains the finally code. The return value is |
2023 // passed as an extra argument. | 2023 // passed as an extra argument. |
2024 jumpTo(state.returnCollector, value); | 2024 jumpTo(state.returnCollector, value); |
2025 } | 2025 } |
2026 } | 2026 } |
2027 | 2027 |
| 2028 /// Build a call to the closure conversion helper for the [Function] typed |
| 2029 /// value in [value]. |
| 2030 ir.Primitive _convertDartClosure(ir.Primitive value, FunctionType type) { |
| 2031 ir.Constant arity = buildIntegerConstant(type.computeArity()); |
| 2032 return buildStaticFunctionInvocation( |
| 2033 program.closureConverter, |
| 2034 CallStructure.TWO_ARGS, |
| 2035 <ir.Primitive>[value, arity]); |
| 2036 } |
| 2037 |
| 2038 /// Generate the body for a native function [function] that is annotated with |
| 2039 /// an implementation in JavaScript (provided as string in [javaScriptCode]). |
| 2040 void buildNativeFunctionBody(FunctionElement function, |
| 2041 String javaScriptCode) { |
| 2042 NativeBehavior behavior = new NativeBehavior(); |
| 2043 behavior.sideEffects.setAllSideEffects(); |
| 2044 // Generate a [ForeignCode] statement from the given native code. |
| 2045 buildForeignCode( |
| 2046 js.js.statementTemplateYielding( |
| 2047 new js.LiteralStatement(javaScriptCode)), |
| 2048 <ir.Primitive>[], |
| 2049 behavior); |
| 2050 } |
| 2051 |
| 2052 /// Generate the body for a native function that redirects to a native |
| 2053 /// JavaScript function, getter, or setter. |
| 2054 /// |
| 2055 /// Generates a call to the real target, which is given by [functions]'s |
| 2056 /// `fixedBackendName`, passing all parameters as arguments. The target can |
| 2057 /// be the JavaScript implementation of a function, getter, or setter. |
| 2058 void buildRedirectingNativeFunctionBody(FunctionElement function, |
| 2059 SourceInformation source) { |
| 2060 String name = function.fixedBackendName; |
| 2061 List<ir.Primitive> arguments = <ir.Primitive>[]; |
| 2062 NativeBehavior behavior = new NativeBehavior(); |
| 2063 behavior.sideEffects.setAllSideEffects(); |
| 2064 program.addNativeMethod(function); |
| 2065 // Construct the access of the target element. |
| 2066 String code = function.isInstanceMember ? '#.$name' : name; |
| 2067 if (function.isInstanceMember) { |
| 2068 arguments.add(state.thisParameter); |
| 2069 } |
| 2070 // Collect all parameters of the function and templates for them to be |
| 2071 // inserted into the JavaScript code. |
| 2072 List<String> argumentTemplates = <String>[]; |
| 2073 function.functionSignature.forEachParameter((ParameterElement parameter) { |
| 2074 ir.Primitive input = environment.lookup(parameter); |
| 2075 DartType type = program.unaliasType(parameter.type); |
| 2076 if (type is FunctionType) { |
| 2077 // The parameter type is a function type either directly or through |
| 2078 // typedef(s). |
| 2079 input = _convertDartClosure(input, type); |
| 2080 } |
| 2081 arguments.add(input); |
| 2082 argumentTemplates.add('#'); |
| 2083 }); |
| 2084 // Construct the application of parameters for functions and setters. |
| 2085 if (function.kind == ElementKind.FUNCTION) { |
| 2086 code = "$code(${argumentTemplates.join(', ')})"; |
| 2087 } else if (function.kind == ElementKind.SETTER) { |
| 2088 code = "$code = ${argumentTemplates.single}"; |
| 2089 } else { |
| 2090 assert(argumentTemplates.isEmpty); |
| 2091 assert(function.kind == ElementKind.GETTER); |
| 2092 } |
| 2093 // Generate the [ForeignCode] expression and a return statement to return |
| 2094 // its value. |
| 2095 ir.Primitive value = buildForeignCode( |
| 2096 js.js.uncachedExpressionTemplate(code), |
| 2097 arguments, |
| 2098 behavior); |
| 2099 buildReturn(value: value, sourceInformation: source); |
| 2100 } |
| 2101 |
2028 /// Create a blocks of [statements] by applying [build] to all reachable | 2102 /// Create a blocks of [statements] by applying [build] to all reachable |
2029 /// statements. The first statement is assumed to be reachable. | 2103 /// statements. The first statement is assumed to be reachable. |
2030 // TODO(johnniwinther): Type [statements] as `Iterable` when `NodeList` uses | 2104 // TODO(johnniwinther): Type [statements] as `Iterable` when `NodeList` uses |
2031 // `List` instead of `Link`. | 2105 // `List` instead of `Link`. |
2032 void buildBlock(var statements, BuildFunction build) { | 2106 void buildBlock(var statements, BuildFunction build) { |
2033 // Build(Block(stamements), C) = C' | 2107 // Build(Block(stamements), C) = C' |
2034 // where C' = statements.fold(Build, C) | 2108 // where C' = statements.fold(Build, C) |
2035 assert(isOpen); | 2109 assert(isOpen); |
2036 return buildSequence(statements, build); | 2110 return buildSequence(statements, build); |
2037 } | 2111 } |
(...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2592 | 2666 |
2593 ir.Primitive buildInvocationMirror(Selector selector, | 2667 ir.Primitive buildInvocationMirror(Selector selector, |
2594 List<ir.Primitive> arguments) { | 2668 List<ir.Primitive> arguments) { |
2595 return addPrimitive(new ir.CreateInvocationMirror(selector, arguments)); | 2669 return addPrimitive(new ir.CreateInvocationMirror(selector, arguments)); |
2596 } | 2670 } |
2597 | 2671 |
2598 ir.Primitive buildForeignCode(js.Template codeTemplate, | 2672 ir.Primitive buildForeignCode(js.Template codeTemplate, |
2599 List<ir.Primitive> arguments, | 2673 List<ir.Primitive> arguments, |
2600 NativeBehavior behavior, | 2674 NativeBehavior behavior, |
2601 {Element dependency}) { | 2675 {Element dependency}) { |
| 2676 assert(behavior != null); |
2602 types.TypeMask type = program.getTypeMaskForForeign(behavior); | 2677 types.TypeMask type = program.getTypeMaskForForeign(behavior); |
2603 ir.Primitive result = _continueWithExpression((k) => new ir.ForeignCode( | 2678 ir.Primitive result = _continueWithExpression((k) => new ir.ForeignCode( |
2604 codeTemplate, | 2679 codeTemplate, |
2605 type, | 2680 type, |
2606 arguments, | 2681 arguments, |
2607 behavior, | 2682 behavior, |
2608 k, | 2683 k, |
2609 dependency: dependency)); | 2684 dependency: dependency)); |
2610 if (!codeTemplate.isExpression) { | 2685 if (!codeTemplate.isExpression) { |
2611 // Close the term if this is a "throw" expression. | 2686 // Close the term if this is a "throw" expression or native body. |
2612 add(new ir.Unreachable()); | 2687 add(new ir.Unreachable()); |
2613 _current = null; | 2688 _current = null; |
2614 } | 2689 } |
2615 return result; | 2690 return result; |
2616 } | 2691 } |
2617 | 2692 |
2618 /// Creates a type test or type cast of [value] against [type]. | 2693 /// Creates a type test or type cast of [value] against [type]. |
2619 ir.Primitive buildTypeOperator(ir.Primitive value, | 2694 ir.Primitive buildTypeOperator(ir.Primitive value, |
2620 DartType type, | 2695 DartType type, |
2621 {bool isTypeTest}) { | 2696 {bool isTypeTest}) { |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2783 } | 2858 } |
2784 | 2859 |
2785 class SwitchCaseInfo { | 2860 class SwitchCaseInfo { |
2786 final List<ir.Primitive> constants = <ir.Primitive>[]; | 2861 final List<ir.Primitive> constants = <ir.Primitive>[]; |
2787 final SubbuildFunction buildBody; | 2862 final SubbuildFunction buildBody; |
2788 | 2863 |
2789 SwitchCaseInfo(this.buildBody); | 2864 SwitchCaseInfo(this.buildBody); |
2790 | 2865 |
2791 void addConstant(ir.Primitive constant) => constants.add(constant); | 2866 void addConstant(ir.Primitive constant) => constants.add(constant); |
2792 } | 2867 } |
OLD | NEW |