Chromium Code Reviews| 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); |
| 694 return addPrimitive( | 696 if (program.isJsInterop(element)) { |
| 695 new ir.InvokeStatic(element, selector, arguments, sourceInformation)); | 697 return buildInvokeJsInteropMember(element, arguments); |
| 698 } else { | |
|
Jacob
2016/02/11 17:54:33
style not: remove else.
Siggi Cherem (dart-lang)
2016/02/11 21:16:53
Done.
| |
| 699 return addPrimitive( | |
| 700 new ir.InvokeStatic(element, selector, arguments, sourceInformation)); | |
| 701 } | |
| 696 } | 702 } |
| 697 | 703 |
| 698 ir.Primitive _buildInvokeSuper(Element target, | 704 ir.Primitive _buildInvokeSuper(Element target, |
| 699 Selector selector, | 705 Selector selector, |
| 700 List<ir.Primitive> arguments, | 706 List<ir.Primitive> arguments, |
| 701 SourceInformation sourceInformation) { | 707 SourceInformation sourceInformation) { |
| 702 assert(target.isInstanceMember); | 708 assert(target.isInstanceMember); |
| 703 assert(isOpen); | 709 assert(isOpen); |
| 704 return addPrimitive(new ir.InvokeMethodDirectly( | 710 return addPrimitive(new ir.InvokeMethodDirectly( |
| 705 buildThis(), target, selector, arguments, sourceInformation)); | 711 buildThis(), target, selector, arguments, sourceInformation)); |
| (...skipping 1353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2059 // Generate the [ForeignCode] expression and a return statement to return | 2065 // Generate the [ForeignCode] expression and a return statement to return |
| 2060 // its value. | 2066 // its value. |
| 2061 ir.Primitive value = buildForeignCode( | 2067 ir.Primitive value = buildForeignCode( |
| 2062 js.js.uncachedExpressionTemplate(code), | 2068 js.js.uncachedExpressionTemplate(code), |
| 2063 arguments, | 2069 arguments, |
| 2064 behavior, | 2070 behavior, |
| 2065 type: program.getTypeMaskForNativeFunction(function)); | 2071 type: program.getTypeMaskForNativeFunction(function)); |
| 2066 buildReturn(value: value, sourceInformation: source); | 2072 buildReturn(value: value, sourceInformation: source); |
| 2067 } | 2073 } |
| 2068 | 2074 |
| 2075 static _isNotNull(ir.Primitive value) => | |
| 2076 value is! ir.Constant || !value.value.isNull; | |
| 2077 | |
| 2078 /// Builds a call to a resolved js-interop element. | |
| 2079 ir.Primitive buildInvokeJsInteropMember(FunctionElement element, | |
|
Siggi Cherem (dart-lang)
2016/02/11 03:13:30
most of this code logic is line-per-line as it was
Jacob
2016/02/11 17:54:33
Acknowledged.
| |
| 2080 List<ir.Primitive> arguments) { | |
| 2081 program.addNativeMethod(element); | |
| 2082 String target = program.getJsInteropTargetPath(element); | |
| 2083 // Strip off trailing arguments that were not specified. | |
| 2084 // TODO(jacobr): assert that the trailing arguments are all null. | |
|
Jacob
2016/02/11 17:54:33
hey now... shouldn't this be
TODO(sigmund)?
:)
Siggi Cherem (dart-lang)
2016/02/11 21:16:53
The comment was there before, I just made it a TOD
| |
| 2085 // TODO(jacobr): rewrite named arguments to an object literal matching | |
| 2086 // the factory constructor case. | |
| 2087 var inputs = arguments.where(_isNotNull).toList(); | |
| 2088 | |
| 2089 var behavior = new NativeBehavior()..sideEffects.setAllSideEffects(); | |
| 2090 DartType type = element.isConstructor ? | |
| 2091 element.enclosingClass.thisType : element.type.returnType; | |
| 2092 // Native behavior effects here are similar to native/behavior.dart. | |
| 2093 // The return type is dynamic if we don't trust js-interop type | |
| 2094 // declarations. | |
| 2095 behavior.typesReturned.add( | |
| 2096 program.trustJSInteropTypeAnnotations ? type : const DynamicType()); | |
| 2097 | |
| 2098 // The allocation effects include the declared type if it is native (which | |
| 2099 // includes js interop types). | |
| 2100 if (type.element != null && program.isNative(type.element)) { | |
| 2101 behavior.typesInstantiated.add(type); | |
| 2102 } | |
| 2103 | |
| 2104 // It also includes any other JS interop type if we don't trust the | |
| 2105 // annotation or if is declared too broad. | |
| 2106 if (!program.trustJSInteropTypeAnnotations || type.isObject || | |
| 2107 type.isDynamic) { | |
| 2108 behavior.typesInstantiated.add(program.jsJavascriptObjectType); | |
| 2109 } | |
| 2110 | |
| 2111 String code; | |
| 2112 if (element.isGetter) { | |
| 2113 code = target; | |
|
Siggi Cherem (dart-lang)
2016/02/11 03:13:30
difference 1: I use `target` directly here, SSA cr
Jacob
2016/02/11 17:54:33
Acknowledged.
| |
| 2114 } else if (element.isSetter) { | |
| 2115 code = "$target = #"; | |
| 2116 } else { | |
| 2117 var args = new List.filled(inputs.length, '#').join(','); | |
| 2118 code = element.isConstructor ? "new $target($args)" : "$target($args)"; | |
| 2119 } | |
| 2120 return buildForeignCode(js.js.parseForeignJS(code), inputs, behavior); | |
|
Siggi Cherem (dart-lang)
2016/02/11 03:13:31
difference 2: I no longer attach the code to the b
| |
| 2121 // TODO(sigmund): should we record the source-information here? | |
|
Siggi Cherem (dart-lang)
2016/02/11 03:13:31
difference 3: I have no place to store source-info
Jacob
2016/02/11 17:54:33
Will that result in a good source maps exerience u
Siggi Cherem (dart-lang)
2016/02/11 21:16:53
Yeah, I think that is likely to be an issue here a
| |
| 2122 } | |
| 2123 | |
| 2124 /// Builds an object literal that results from invoking a factory constructor | |
| 2125 /// of a js-interop anonymous type. | |
| 2126 ir.Primitive buildJsInteropObjectLiteral(ConstructorElement constructor, | |
| 2127 List<ir.Primitive> arguments, {SourceInformation source}) { | |
| 2128 assert(program.isJsInteropAnonymous(constructor)); | |
| 2129 program.addNativeMethod(constructor); | |
| 2130 FunctionSignature params = constructor.functionSignature; | |
| 2131 int i = 0; | |
| 2132 var filteredArguments = <ir.Primitive>[]; | |
| 2133 var entries = new Map<String, js.Expression>(); | |
| 2134 params.orderedForEachParameter((ParameterElement parameter) { | |
| 2135 // TODO(jacobr): throw if parameter names do not match names of property | |
| 2136 // names in the class. | |
| 2137 assert (parameter.isNamed); | |
| 2138 ir.Primitive argument = arguments[i++]; | |
| 2139 if (_isNotNull(argument)) { | |
| 2140 filteredArguments.add(argument); | |
| 2141 entries[parameter.name] = | |
| 2142 new js.InterpolatedExpression(filteredArguments.length - 1); | |
| 2143 } | |
| 2144 }); | |
| 2145 var code = new js.Template(null, js.objectLiteral(entries)); | |
| 2146 var behavior = new NativeBehavior(); | |
| 2147 if (program.trustJSInteropTypeAnnotations) { | |
| 2148 behavior.typesReturned.add(constructor.enclosingClass.thisType); | |
| 2149 } | |
| 2150 | |
| 2151 // TODO(sigmund): should we record the source-information here? | |
| 2152 return buildForeignCode(code, filteredArguments, behavior); | |
| 2153 } | |
| 2154 | |
| 2069 /// Create a blocks of [statements] by applying [build] to all reachable | 2155 /// Create a blocks of [statements] by applying [build] to all reachable |
| 2070 /// statements. The first statement is assumed to be reachable. | 2156 /// statements. The first statement is assumed to be reachable. |
| 2071 // TODO(johnniwinther): Type [statements] as `Iterable` when `NodeList` uses | 2157 // TODO(johnniwinther): Type [statements] as `Iterable` when `NodeList` uses |
| 2072 // `List` instead of `Link`. | 2158 // `List` instead of `Link`. |
| 2073 void buildBlock(var statements, BuildFunction build) { | 2159 void buildBlock(var statements, BuildFunction build) { |
| 2074 // Build(Block(stamements), C) = C' | 2160 // Build(Block(stamements), C) = C' |
| 2075 // where C' = statements.fold(Build, C) | 2161 // where C' = statements.fold(Build, C) |
| 2076 assert(isOpen); | 2162 assert(isOpen); |
| 2077 return buildSequence(statements, build); | 2163 return buildSequence(statements, build); |
| 2078 } | 2164 } |
| (...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2544 ConstructorElement element, | 2630 ConstructorElement element, |
| 2545 CallStructure callStructure, | 2631 CallStructure callStructure, |
| 2546 DartType type, | 2632 DartType type, |
| 2547 List<ir.Primitive> arguments, | 2633 List<ir.Primitive> arguments, |
| 2548 SourceInformation sourceInformation, | 2634 SourceInformation sourceInformation, |
| 2549 {TypeMask allocationSiteType}) { | 2635 {TypeMask allocationSiteType}) { |
| 2550 assert(isOpen); | 2636 assert(isOpen); |
| 2551 Selector selector = | 2637 Selector selector = |
| 2552 new Selector(SelectorKind.CALL, element.memberName, callStructure); | 2638 new Selector(SelectorKind.CALL, element.memberName, callStructure); |
| 2553 ClassElement cls = element.enclosingClass; | 2639 ClassElement cls = element.enclosingClass; |
| 2640 if (program.isJsInterop(element)) { | |
| 2641 if (program.isJsInteropAnonymous(element)) { | |
| 2642 return buildJsInteropObjectLiteral(element, arguments, | |
| 2643 source: sourceInformation); | |
| 2644 } else { | |
|
Jacob
2016/02/11 17:54:33
sme nit about unneeded else
Siggi Cherem (dart-lang)
2016/02/11 21:16:53
Done.
| |
| 2645 return buildInvokeJsInteropMember(element, arguments); | |
| 2646 } | |
| 2647 } | |
| 2554 if (program.requiresRuntimeTypesFor(cls)) { | 2648 if (program.requiresRuntimeTypesFor(cls)) { |
| 2555 InterfaceType interface = type; | 2649 InterfaceType interface = type; |
| 2556 Iterable<ir.Primitive> typeArguments = | 2650 Iterable<ir.Primitive> typeArguments = |
| 2557 interface.typeArguments.map((DartType argument) { | 2651 interface.typeArguments.map((DartType argument) { |
| 2558 return type.treatAsRaw | 2652 return type.treatAsRaw |
| 2559 ? buildNullConstant() | 2653 ? buildNullConstant() |
| 2560 : buildTypeExpression(argument); | 2654 : buildTypeExpression(argument); |
| 2561 }); | 2655 }); |
| 2562 arguments = new List<ir.Primitive>.from(arguments) | 2656 arguments = new List<ir.Primitive>.from(arguments) |
| 2563 ..addAll(typeArguments); | 2657 ..addAll(typeArguments); |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2843 this.stackTraceVariable, | 2937 this.stackTraceVariable, |
| 2844 this.buildCatchBlock}); | 2938 this.buildCatchBlock}); |
| 2845 } | 2939 } |
| 2846 | 2940 |
| 2847 class SwitchCaseInfo { | 2941 class SwitchCaseInfo { |
| 2848 final SubbuildFunction buildCondition; | 2942 final SubbuildFunction buildCondition; |
| 2849 final SubbuildFunction buildBody; | 2943 final SubbuildFunction buildBody; |
| 2850 | 2944 |
| 2851 SwitchCaseInfo(this.buildCondition, this.buildBody); | 2945 SwitchCaseInfo(this.buildCondition, this.buildBody); |
| 2852 } | 2946 } |
| OLD | NEW |