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 final RegExp nativeRedirectionRegExp = | |
2039 new RegExp(r'^[a-zA-Z][a-zA-Z_$0-9]*$'); | |
asgerf
2015/08/12 13:15:02
Make this static?
| |
2040 | |
2041 /// Generate the body for a native function. | |
2042 /// | |
2043 /// If [nativeBody] is non-null, generate a [ForeignCode] statement for the | |
2044 /// body defined in JavaScript. Otherwise, generate a call to the real | |
2045 /// target, which is given by the [FunctionElement]'s `fixedBackendName`. | |
2046 /// The target can be a function, getter, or setter. | |
2047 void buildNativeFunctionBody(ast.Node nativeBody, | |
2048 SourceInformation source) { | |
2049 FunctionElement function = state.currentElement; | |
2050 assert(function.isNative); | |
2051 String name = function.fixedBackendName; | |
2052 List<ir.Primitive> arguments = <ir.Primitive>[]; | |
2053 NativeBehavior behavior = new NativeBehavior(); | |
2054 behavior.sideEffects.setAllSideEffects(); | |
2055 | |
2056 if (nativeBody != null) { | |
asgerf
2015/08/12 13:15:02
I think it would make more sense to have this spli
| |
2057 ast.LiteralString jsCode = nativeBody.asLiteralString(); | |
2058 String code = jsCode.dartString.slowToString(); | |
2059 assert(invariant(nativeBody, !nativeRedirectionRegExp.hasMatch(code), | |
2060 message: "Deprecated syntax, use @JSName('name') instead.")); | |
2061 assert(invariant(nativeBody, | |
2062 function.functionSignature.parameterCount == 0, | |
2063 message: 'native "..." syntax is restricted to ' | |
2064 'functions with zero parameters.')); | |
2065 // Generate a [ForeignCode] statement from the given native code. | |
2066 buildForeignCode( | |
2067 js.js.statementTemplateYielding(new js.LiteralStatement(code)), | |
2068 <ir.Primitive>[], | |
2069 behavior); | |
2070 } else { | |
2071 program.addNativeMethod(function); | |
2072 // Construct the access of the target element. | |
2073 String code = function.isInstanceMember ? '#.$name' : name; | |
2074 if (function.isInstanceMember) { | |
2075 arguments.add(state.thisParameter); | |
2076 } | |
2077 // Collect all parameters of the function and templates for them to be | |
2078 // inserted into the JavaScript code. | |
2079 List<String> argumentTemplates = <String>[]; | |
2080 function.functionSignature.forEachParameter((ParameterElement parameter) { | |
2081 ir.Primitive input = environment.lookup(parameter); | |
2082 DartType type = program.unaliasType(parameter.type); | |
2083 if (type is FunctionType) { | |
2084 // The parameter type is a function type either directly or through | |
2085 // typedef(s). | |
2086 input = _convertDartClosure(input, type); | |
2087 } | |
2088 arguments.add(input); | |
2089 argumentTemplates.add('#'); | |
2090 }); | |
2091 // Construct the application of parameters for functions and setters. | |
2092 if (function.kind == ElementKind.FUNCTION) { | |
2093 code = "$code(${argumentTemplates.join(', ')})"; | |
2094 } else if (function.kind == ElementKind.SETTER) { | |
2095 code = "$code = ${argumentTemplates.single}"; | |
2096 } else { | |
2097 assert(argumentTemplates.isEmpty); | |
2098 assert(function.kind == ElementKind.GETTER); | |
2099 } | |
2100 // Generate the [ForeignCode] expression and a return statement to return | |
2101 // its value. | |
2102 ir.Primitive value = buildForeignCode( | |
2103 js.js.uncachedExpressionTemplate(code), | |
2104 arguments, | |
2105 behavior); | |
2106 buildReturn(value: value, sourceInformation: source); | |
2107 } | |
2108 } | |
2109 | |
2028 /// Create a blocks of [statements] by applying [build] to all reachable | 2110 /// Create a blocks of [statements] by applying [build] to all reachable |
2029 /// statements. The first statement is assumed to be reachable. | 2111 /// statements. The first statement is assumed to be reachable. |
2030 // TODO(johnniwinther): Type [statements] as `Iterable` when `NodeList` uses | 2112 // TODO(johnniwinther): Type [statements] as `Iterable` when `NodeList` uses |
2031 // `List` instead of `Link`. | 2113 // `List` instead of `Link`. |
2032 void buildBlock(var statements, BuildFunction build) { | 2114 void buildBlock(var statements, BuildFunction build) { |
2033 // Build(Block(stamements), C) = C' | 2115 // Build(Block(stamements), C) = C' |
2034 // where C' = statements.fold(Build, C) | 2116 // where C' = statements.fold(Build, C) |
2035 assert(isOpen); | 2117 assert(isOpen); |
2036 return buildSequence(statements, build); | 2118 return buildSequence(statements, build); |
2037 } | 2119 } |
(...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2592 | 2674 |
2593 ir.Primitive buildInvocationMirror(Selector selector, | 2675 ir.Primitive buildInvocationMirror(Selector selector, |
2594 List<ir.Primitive> arguments) { | 2676 List<ir.Primitive> arguments) { |
2595 return addPrimitive(new ir.CreateInvocationMirror(selector, arguments)); | 2677 return addPrimitive(new ir.CreateInvocationMirror(selector, arguments)); |
2596 } | 2678 } |
2597 | 2679 |
2598 ir.Primitive buildForeignCode(js.Template codeTemplate, | 2680 ir.Primitive buildForeignCode(js.Template codeTemplate, |
2599 List<ir.Primitive> arguments, | 2681 List<ir.Primitive> arguments, |
2600 NativeBehavior behavior, | 2682 NativeBehavior behavior, |
2601 {Element dependency}) { | 2683 {Element dependency}) { |
2684 assert(behavior != null); | |
2602 types.TypeMask type = program.getTypeMaskForForeign(behavior); | 2685 types.TypeMask type = program.getTypeMaskForForeign(behavior); |
2603 ir.Primitive result = _continueWithExpression((k) => new ir.ForeignCode( | 2686 ir.Primitive result = _continueWithExpression((k) => new ir.ForeignCode( |
2604 codeTemplate, | 2687 codeTemplate, |
2605 type, | 2688 type, |
2606 arguments, | 2689 arguments, |
2607 behavior, | 2690 behavior, |
2608 k, | 2691 k, |
2609 dependency: dependency)); | 2692 dependency: dependency)); |
2610 if (!codeTemplate.isExpression) { | 2693 if (!codeTemplate.isExpression) { |
2611 // Close the term if this is a "throw" expression. | 2694 // Close the term if this is a "throw" expression or native body. |
2612 add(new ir.Unreachable()); | 2695 add(new ir.Unreachable()); |
2613 _current = null; | 2696 _current = null; |
2614 } | 2697 } |
2615 return result; | 2698 return result; |
2616 } | 2699 } |
2617 | 2700 |
2618 /// Creates a type test or type cast of [value] against [type]. | 2701 /// Creates a type test or type cast of [value] against [type]. |
2619 ir.Primitive buildTypeOperator(ir.Primitive value, | 2702 ir.Primitive buildTypeOperator(ir.Primitive value, |
2620 DartType type, | 2703 DartType type, |
2621 {bool isTypeTest}) { | 2704 {bool isTypeTest}) { |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2783 } | 2866 } |
2784 | 2867 |
2785 class SwitchCaseInfo { | 2868 class SwitchCaseInfo { |
2786 final List<ir.Primitive> constants = <ir.Primitive>[]; | 2869 final List<ir.Primitive> constants = <ir.Primitive>[]; |
2787 final SubbuildFunction buildBody; | 2870 final SubbuildFunction buildBody; |
2788 | 2871 |
2789 SwitchCaseInfo(this.buildBody); | 2872 SwitchCaseInfo(this.buildBody); |
2790 | 2873 |
2791 void addConstant(ir.Primitive constant) => constants.add(constant); | 2874 void addConstant(ir.Primitive constant) => constants.add(constant); |
2792 } | 2875 } |
OLD | NEW |