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 '../closure.dart' as closure; | 7 import '../closure.dart' as closure; |
8 import '../common.dart'; | 8 import '../common.dart'; |
9 import '../common/names.dart' show | 9 import '../common/names.dart' show |
10 Names, | 10 Names, |
11 Selectors; | 11 Selectors; |
12 import '../compile_time_constants.dart' show | 12 import '../compile_time_constants.dart' show |
13 BackendConstantEnvironment; | 13 BackendConstantEnvironment; |
14 import '../constants/constant_system.dart'; | 14 import '../constants/constant_system.dart'; |
15 import '../constants/values.dart' show | 15 import '../constants/values.dart' show |
16 ConstantValue, | 16 ConstantValue, |
17 PrimitiveConstantValue; | 17 PrimitiveConstantValue; |
18 import '../dart_types.dart'; | 18 import '../dart_types.dart'; |
19 import '../elements/elements.dart'; | 19 import '../elements/elements.dart'; |
20 import '../io/source_information.dart'; | 20 import '../io/source_information.dart'; |
21 import '../js/js.dart' as js show | 21 import '../js/js.dart' as js show |
22 js, | 22 js, |
| 23 objectLiteral, |
23 LiteralStatement, | 24 LiteralStatement, |
24 Template, | 25 Template, |
| 26 InterpolatedExpression, |
25 isIdentityTemplate; | 27 isIdentityTemplate; |
26 import '../native/native.dart' show | 28 import '../native/native.dart' show |
27 NativeBehavior; | 29 NativeBehavior; |
28 import '../tree/tree.dart' as ast; | 30 import '../tree/tree.dart' as ast; |
29 import '../types/types.dart' show | 31 import '../types/types.dart' show |
30 TypeMask; | 32 TypeMask; |
31 import '../universe/call_structure.dart' show | 33 import '../universe/call_structure.dart' show |
32 CallStructure; | 34 CallStructure; |
33 import '../universe/selector.dart' show | 35 import '../universe/selector.dart' show |
34 Selector, | 36 Selector, |
(...skipping 649 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
684 return primitive; | 686 return primitive; |
685 } | 687 } |
686 | 688 |
687 ir.Primitive buildInvokeStatic(Element element, | 689 ir.Primitive buildInvokeStatic(Element element, |
688 Selector selector, | 690 Selector selector, |
689 List<ir.Primitive> arguments, | 691 List<ir.Primitive> arguments, |
690 SourceInformation sourceInformation) { | 692 SourceInformation sourceInformation) { |
691 assert(!element.isLocal); | 693 assert(!element.isLocal); |
692 assert(!element.isInstanceMember); | 694 assert(!element.isInstanceMember); |
693 assert(isOpen); | 695 assert(isOpen); |
| 696 if (program.isJsInterop(element)) { |
| 697 return buildInvokeJsInteropMember(element, arguments); |
| 698 } |
694 return addPrimitive( | 699 return addPrimitive( |
695 new ir.InvokeStatic(element, selector, arguments, sourceInformation)); | 700 new ir.InvokeStatic(element, selector, arguments, sourceInformation)); |
696 } | 701 } |
697 | 702 |
698 ir.Primitive _buildInvokeSuper(Element target, | 703 ir.Primitive _buildInvokeSuper(Element target, |
699 Selector selector, | 704 Selector selector, |
700 List<ir.Primitive> arguments, | 705 List<ir.Primitive> arguments, |
701 SourceInformation sourceInformation) { | 706 SourceInformation sourceInformation) { |
702 assert(target.isInstanceMember); | 707 assert(target.isInstanceMember); |
703 assert(isOpen); | 708 assert(isOpen); |
(...skipping 1355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2059 // Generate the [ForeignCode] expression and a return statement to return | 2064 // Generate the [ForeignCode] expression and a return statement to return |
2060 // its value. | 2065 // its value. |
2061 ir.Primitive value = buildForeignCode( | 2066 ir.Primitive value = buildForeignCode( |
2062 js.js.uncachedExpressionTemplate(code), | 2067 js.js.uncachedExpressionTemplate(code), |
2063 arguments, | 2068 arguments, |
2064 behavior, | 2069 behavior, |
2065 type: program.getTypeMaskForNativeFunction(function)); | 2070 type: program.getTypeMaskForNativeFunction(function)); |
2066 buildReturn(value: value, sourceInformation: source); | 2071 buildReturn(value: value, sourceInformation: source); |
2067 } | 2072 } |
2068 | 2073 |
| 2074 static _isNotNull(ir.Primitive value) => |
| 2075 value is! ir.Constant || !value.value.isNull; |
| 2076 |
| 2077 /// Builds a call to a resolved js-interop element. |
| 2078 ir.Primitive buildInvokeJsInteropMember(FunctionElement element, |
| 2079 List<ir.Primitive> arguments) { |
| 2080 program.addNativeMethod(element); |
| 2081 String target = program.getJsInteropTargetPath(element); |
| 2082 // Strip off trailing arguments that were not specified. |
| 2083 // TODO(jacobr,sigmund): assert that the trailing arguments are all null. |
| 2084 // TODO(jacobr): rewrite named arguments to an object literal matching |
| 2085 // the factory constructor case. |
| 2086 var inputs = arguments.where(_isNotNull).toList(); |
| 2087 |
| 2088 var behavior = new NativeBehavior()..sideEffects.setAllSideEffects(); |
| 2089 DartType type = element.isConstructor ? |
| 2090 element.enclosingClass.thisType : element.type.returnType; |
| 2091 // Native behavior effects here are similar to native/behavior.dart. |
| 2092 // The return type is dynamic if we don't trust js-interop type |
| 2093 // declarations. |
| 2094 behavior.typesReturned.add( |
| 2095 program.trustJSInteropTypeAnnotations ? type : const DynamicType()); |
| 2096 |
| 2097 // The allocation effects include the declared type if it is native (which |
| 2098 // includes js interop types). |
| 2099 if (type.element != null && program.isNative(type.element)) { |
| 2100 behavior.typesInstantiated.add(type); |
| 2101 } |
| 2102 |
| 2103 // It also includes any other JS interop type if we don't trust the |
| 2104 // annotation or if is declared too broad. |
| 2105 if (!program.trustJSInteropTypeAnnotations || type.isObject || |
| 2106 type.isDynamic) { |
| 2107 behavior.typesInstantiated.add(program.jsJavascriptObjectType); |
| 2108 } |
| 2109 |
| 2110 String code; |
| 2111 if (element.isGetter) { |
| 2112 code = target; |
| 2113 } else if (element.isSetter) { |
| 2114 code = "$target = #"; |
| 2115 } else { |
| 2116 var args = new List.filled(inputs.length, '#').join(','); |
| 2117 code = element.isConstructor ? "new $target($args)" : "$target($args)"; |
| 2118 } |
| 2119 return buildForeignCode(js.js.parseForeignJS(code), inputs, behavior); |
| 2120 // TODO(sigmund): should we record the source-information here? |
| 2121 } |
| 2122 |
| 2123 /// Builds an object literal that results from invoking a factory constructor |
| 2124 /// of a js-interop anonymous type. |
| 2125 ir.Primitive buildJsInteropObjectLiteral(ConstructorElement constructor, |
| 2126 List<ir.Primitive> arguments, {SourceInformation source}) { |
| 2127 assert(program.isJsInteropAnonymous(constructor)); |
| 2128 program.addNativeMethod(constructor); |
| 2129 FunctionSignature params = constructor.functionSignature; |
| 2130 int i = 0; |
| 2131 var filteredArguments = <ir.Primitive>[]; |
| 2132 var entries = new Map<String, js.Expression>(); |
| 2133 params.orderedForEachParameter((ParameterElement parameter) { |
| 2134 // TODO(jacobr): throw if parameter names do not match names of property |
| 2135 // names in the class. |
| 2136 assert (parameter.isNamed); |
| 2137 ir.Primitive argument = arguments[i++]; |
| 2138 if (_isNotNull(argument)) { |
| 2139 filteredArguments.add(argument); |
| 2140 entries[parameter.name] = |
| 2141 new js.InterpolatedExpression(filteredArguments.length - 1); |
| 2142 } |
| 2143 }); |
| 2144 var code = new js.Template(null, js.objectLiteral(entries)); |
| 2145 var behavior = new NativeBehavior(); |
| 2146 if (program.trustJSInteropTypeAnnotations) { |
| 2147 behavior.typesReturned.add(constructor.enclosingClass.thisType); |
| 2148 } |
| 2149 |
| 2150 // TODO(sigmund): should we record the source-information here? |
| 2151 return buildForeignCode(code, filteredArguments, behavior); |
| 2152 } |
| 2153 |
2069 /// Create a blocks of [statements] by applying [build] to all reachable | 2154 /// Create a blocks of [statements] by applying [build] to all reachable |
2070 /// statements. The first statement is assumed to be reachable. | 2155 /// statements. The first statement is assumed to be reachable. |
2071 // TODO(johnniwinther): Type [statements] as `Iterable` when `NodeList` uses | 2156 // TODO(johnniwinther): Type [statements] as `Iterable` when `NodeList` uses |
2072 // `List` instead of `Link`. | 2157 // `List` instead of `Link`. |
2073 void buildBlock(var statements, BuildFunction build) { | 2158 void buildBlock(var statements, BuildFunction build) { |
2074 // Build(Block(stamements), C) = C' | 2159 // Build(Block(stamements), C) = C' |
2075 // where C' = statements.fold(Build, C) | 2160 // where C' = statements.fold(Build, C) |
2076 assert(isOpen); | 2161 assert(isOpen); |
2077 return buildSequence(statements, build); | 2162 return buildSequence(statements, build); |
2078 } | 2163 } |
(...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2544 ConstructorElement element, | 2629 ConstructorElement element, |
2545 CallStructure callStructure, | 2630 CallStructure callStructure, |
2546 DartType type, | 2631 DartType type, |
2547 List<ir.Primitive> arguments, | 2632 List<ir.Primitive> arguments, |
2548 SourceInformation sourceInformation, | 2633 SourceInformation sourceInformation, |
2549 {TypeMask allocationSiteType}) { | 2634 {TypeMask allocationSiteType}) { |
2550 assert(isOpen); | 2635 assert(isOpen); |
2551 Selector selector = | 2636 Selector selector = |
2552 new Selector(SelectorKind.CALL, element.memberName, callStructure); | 2637 new Selector(SelectorKind.CALL, element.memberName, callStructure); |
2553 ClassElement cls = element.enclosingClass; | 2638 ClassElement cls = element.enclosingClass; |
| 2639 if (program.isJsInterop(element)) { |
| 2640 if (program.isJsInteropAnonymous(element)) { |
| 2641 return buildJsInteropObjectLiteral(element, arguments, |
| 2642 source: sourceInformation); |
| 2643 } |
| 2644 return buildInvokeJsInteropMember(element, arguments); |
| 2645 } |
2554 if (program.requiresRuntimeTypesFor(cls)) { | 2646 if (program.requiresRuntimeTypesFor(cls)) { |
2555 InterfaceType interface = type; | 2647 InterfaceType interface = type; |
2556 Iterable<ir.Primitive> typeArguments = | 2648 Iterable<ir.Primitive> typeArguments = |
2557 interface.typeArguments.map((DartType argument) { | 2649 interface.typeArguments.map((DartType argument) { |
2558 return type.treatAsRaw | 2650 return type.treatAsRaw |
2559 ? buildNullConstant() | 2651 ? buildNullConstant() |
2560 : buildTypeExpression(argument); | 2652 : buildTypeExpression(argument); |
2561 }); | 2653 }); |
2562 arguments = new List<ir.Primitive>.from(arguments) | 2654 arguments = new List<ir.Primitive>.from(arguments) |
2563 ..addAll(typeArguments); | 2655 ..addAll(typeArguments); |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2843 this.stackTraceVariable, | 2935 this.stackTraceVariable, |
2844 this.buildCatchBlock}); | 2936 this.buildCatchBlock}); |
2845 } | 2937 } |
2846 | 2938 |
2847 class SwitchCaseInfo { | 2939 class SwitchCaseInfo { |
2848 final SubbuildFunction buildCondition; | 2940 final SubbuildFunction buildCondition; |
2849 final SubbuildFunction buildBody; | 2941 final SubbuildFunction buildBody; |
2850 | 2942 |
2851 SwitchCaseInfo(this.buildCondition, this.buildBody); | 2943 SwitchCaseInfo(this.buildCondition, this.buildBody); |
2852 } | 2944 } |
OLD | NEW |