Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(59)

Side by Side Diff: pkg/compiler/lib/src/ssa/codegen.dart

Issue 2814453005: Merge CommonElements and BackendHelpers! (Closed)
Patch Set: comments and re-merge, take two Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 import 'dart:math' as math; 5 import 'dart:math' as math;
6 import 'dart:collection' show Queue; 6 import 'dart:collection' show Queue;
7 import '../common.dart'; 7 import '../common.dart';
8 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; 8 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
9 import '../common/tasks.dart' show CompilerTask; 9 import '../common/tasks.dart' show CompilerTask;
10 import '../constants/constant_system.dart'; 10 import '../constants/constant_system.dart';
11 import '../constants/values.dart'; 11 import '../constants/values.dart';
12 import '../common_elements.dart' show CommonElements; 12 import '../common_elements.dart' show CommonElements;
13 import '../elements/elements.dart' 13 import '../elements/elements.dart'
14 show AsyncMarker, JumpTarget, LabelDefinition, MethodElement, ResolvedAst; 14 show AsyncMarker, JumpTarget, LabelDefinition, MethodElement, ResolvedAst;
15 import '../elements/entities.dart'; 15 import '../elements/entities.dart';
16 import '../elements/types.dart'; 16 import '../elements/types.dart';
17 import '../io/source_information.dart'; 17 import '../io/source_information.dart';
18 import '../js/js.dart' as js; 18 import '../js/js.dart' as js;
19 import '../js_backend/backend_helpers.dart' show BackendHelpers;
20 import '../js_backend/interceptor_data.dart'; 19 import '../js_backend/interceptor_data.dart';
21 import '../js_backend/js_backend.dart'; 20 import '../js_backend/js_backend.dart';
22 import '../js_backend/native_data.dart'; 21 import '../js_backend/native_data.dart';
23 import '../js_emitter/code_emitter_task.dart'; 22 import '../js_emitter/code_emitter_task.dart';
24 import '../native/native.dart' as native; 23 import '../native/native.dart' as native;
25 import '../options.dart'; 24 import '../options.dart';
26 import '../types/types.dart'; 25 import '../types/types.dart';
27 import '../universe/call_structure.dart' show CallStructure; 26 import '../universe/call_structure.dart' show CallStructure;
28 import '../universe/selector.dart' show Selector; 27 import '../universe/selector.dart' show Selector;
29 import '../universe/use.dart' show ConstantUse, DynamicUse, StaticUse, TypeUse; 28 import '../universe/use.dart' show ConstantUse, DynamicUse, StaticUse, TypeUse;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 CodegenWorkItem work, HGraph graph, ClosedWorld closedWorld) { 72 CodegenWorkItem work, HGraph graph, ClosedWorld closedWorld) {
74 return measure(() { 73 return measure(() {
75 backend.tracer.traceGraph("codegen", graph); 74 backend.tracer.traceGraph("codegen", graph);
76 SourceInformation sourceInformation = sourceInformationFactory 75 SourceInformation sourceInformation = sourceInformationFactory
77 .createBuilderForContext(work.resolvedAst) 76 .createBuilderForContext(work.resolvedAst)
78 .buildDeclaration(work.resolvedAst); 77 .buildDeclaration(work.resolvedAst);
79 SsaCodeGenerator codegen = new SsaCodeGenerator( 78 SsaCodeGenerator codegen = new SsaCodeGenerator(
80 backend.compiler.options, 79 backend.compiler.options,
81 backend.emitter, 80 backend.emitter,
82 backend.nativeCodegenEnqueuer, 81 backend.nativeCodegenEnqueuer,
83 backend.helpers,
84 backend.checkedModeHelpers, 82 backend.checkedModeHelpers,
85 backend.nativeData, 83 backend.nativeData,
86 backend.interceptorData, 84 backend.interceptorData,
87 backend.oneShotInterceptorData, 85 backend.oneShotInterceptorData,
88 backend.rtiSubstitutions, 86 backend.rtiSubstitutions,
89 backend.rtiEncoder, 87 backend.rtiEncoder,
90 backend.namer, 88 backend.namer,
91 backend.superMemberData, 89 backend.superMemberData,
92 closedWorld, 90 closedWorld,
93 work); 91 work);
94 codegen.visitGraph(graph); 92 codegen.visitGraph(graph);
95 return new js.Fun(codegen.parameters, codegen.body) 93 return new js.Fun(codegen.parameters, codegen.body)
96 .withSourceInformation(sourceInformation); 94 .withSourceInformation(sourceInformation);
97 }); 95 });
98 } 96 }
99 97
100 js.Expression generateMethod( 98 js.Expression generateMethod(
101 CodegenWorkItem work, HGraph graph, ClosedWorld closedWorld) { 99 CodegenWorkItem work, HGraph graph, ClosedWorld closedWorld) {
102 return measure(() { 100 return measure(() {
103 MethodElement element = work.element; 101 MethodElement element = work.element;
104 if (element.asyncMarker != AsyncMarker.SYNC) { 102 if (element.asyncMarker != AsyncMarker.SYNC) {
105 work.registry.registerAsyncMarker(element.asyncMarker); 103 work.registry.registerAsyncMarker(element.asyncMarker);
106 } 104 }
107 SsaCodeGenerator codegen = new SsaCodeGenerator( 105 SsaCodeGenerator codegen = new SsaCodeGenerator(
108 backend.compiler.options, 106 backend.compiler.options,
109 backend.emitter, 107 backend.emitter,
110 backend.nativeCodegenEnqueuer, 108 backend.nativeCodegenEnqueuer,
111 backend.helpers,
112 backend.checkedModeHelpers, 109 backend.checkedModeHelpers,
113 backend.nativeData, 110 backend.nativeData,
114 backend.interceptorData, 111 backend.interceptorData,
115 backend.oneShotInterceptorData, 112 backend.oneShotInterceptorData,
116 backend.rtiSubstitutions, 113 backend.rtiSubstitutions,
117 backend.rtiEncoder, 114 backend.rtiEncoder,
118 backend.namer, 115 backend.namer,
119 backend.superMemberData, 116 backend.superMemberData,
120 closedWorld, 117 closedWorld,
121 work); 118 work);
(...skipping 26 matching lines...) Expand all
148 145
149 /** 146 /**
150 * Whether we are currently generating expressions instead of statements. 147 * Whether we are currently generating expressions instead of statements.
151 * This includes declarations, which are generated as expressions. 148 * This includes declarations, which are generated as expressions.
152 */ 149 */
153 bool isGeneratingExpression = false; 150 bool isGeneratingExpression = false;
154 151
155 final CompilerOptions _options; 152 final CompilerOptions _options;
156 final CodeEmitterTask _emitter; 153 final CodeEmitterTask _emitter;
157 final native.NativeCodegenEnqueuer _nativeEnqueuer; 154 final native.NativeCodegenEnqueuer _nativeEnqueuer;
158 final BackendHelpers _helpers;
159 final CheckedModeHelpers _checkedModeHelpers; 155 final CheckedModeHelpers _checkedModeHelpers;
160 final NativeData _nativeData; 156 final NativeData _nativeData;
161 final InterceptorData _interceptorData; 157 final InterceptorData _interceptorData;
162 final OneShotInterceptorData _oneShotInterceptorData; 158 final OneShotInterceptorData _oneShotInterceptorData;
163 final RuntimeTypesSubstitutions _rtiSubstitutions; 159 final RuntimeTypesSubstitutions _rtiSubstitutions;
164 final RuntimeTypesEncoder _rtiEncoder; 160 final RuntimeTypesEncoder _rtiEncoder;
165 final Namer _namer; 161 final Namer _namer;
166 final SuperMemberData _superMemberData; 162 final SuperMemberData _superMemberData;
167 final ClosedWorld _closedWorld; 163 final ClosedWorld _closedWorld;
168 final CodegenWorkItem _work; 164 final CodegenWorkItem _work;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 // if branches. 203 // if branches.
208 SubGraph subGraph; 204 SubGraph subGraph;
209 205
210 // Pending blocks than need to be visited as part of current subgraph. 206 // Pending blocks than need to be visited as part of current subgraph.
211 Queue<HBasicBlock> blockQueue; 207 Queue<HBasicBlock> blockQueue;
212 208
213 SsaCodeGenerator( 209 SsaCodeGenerator(
214 this._options, 210 this._options,
215 this._emitter, 211 this._emitter,
216 this._nativeEnqueuer, 212 this._nativeEnqueuer,
217 this._helpers,
218 this._checkedModeHelpers, 213 this._checkedModeHelpers,
219 this._nativeData, 214 this._nativeData,
220 this._interceptorData, 215 this._interceptorData,
221 this._oneShotInterceptorData, 216 this._oneShotInterceptorData,
222 this._rtiSubstitutions, 217 this._rtiSubstitutions,
223 this._rtiEncoder, 218 this._rtiEncoder,
224 this._namer, 219 this._namer,
225 this._superMemberData, 220 this._superMemberData,
226 this._closedWorld, 221 this._closedWorld,
227 this._work, 222 this._work,
(...skipping 612 matching lines...) Expand 10 before | Expand all | Expand 10 after
840 js.Block body = generateStatementsInNewBlock(info.body); 835 js.Block body = generateStatementsInNewBlock(info.body);
841 js.Catch catchPart = null; 836 js.Catch catchPart = null;
842 js.Block finallyPart = null; 837 js.Block finallyPart = null;
843 if (info.catchBlock != null) { 838 if (info.catchBlock != null) {
844 void register(ClassEntity classElement) { 839 void register(ClassEntity classElement) {
845 if (classElement != null) { 840 if (classElement != null) {
846 _registry.registerInstantiatedClass(classElement); 841 _registry.registerInstantiatedClass(classElement);
847 } 842 }
848 } 843 }
849 844
850 register(_helpers.jsPlainJavaScriptObjectClass); 845 register(_commonElements.jsPlainJavaScriptObjectClass);
851 register(_helpers.jsUnknownJavaScriptObjectClass); 846 register(_commonElements.jsUnknownJavaScriptObjectClass);
852 847
853 HLocalValue exception = info.catchVariable; 848 HLocalValue exception = info.catchVariable;
854 String name = variableNames.getName(exception); 849 String name = variableNames.getName(exception);
855 js.VariableDeclaration decl = new js.VariableDeclaration(name); 850 js.VariableDeclaration decl = new js.VariableDeclaration(name);
856 js.Block catchBlock = generateStatementsInNewBlock(info.catchBlock); 851 js.Block catchBlock = generateStatementsInNewBlock(info.catchBlock);
857 catchPart = new js.Catch(decl, catchBlock); 852 catchPart = new js.Catch(decl, catchBlock);
858 } 853 }
859 if (info.finallyBlock != null) { 854 if (info.finallyBlock != null) {
860 finallyPart = generateStatementsInNewBlock(info.finallyBlock); 855 finallyPart = generateStatementsInNewBlock(info.finallyBlock);
861 } 856 }
(...skipping 821 matching lines...) Expand 10 before | Expand all | Expand 10 after
1683 use(node.receiver); 1678 use(node.receiver);
1684 js.Expression receiverExpression = pop(); 1679 js.Expression receiverExpression = pop();
1685 use(node.conditionalConstantInterceptor); 1680 use(node.conditionalConstantInterceptor);
1686 js.Expression constant = pop(); 1681 js.Expression constant = pop();
1687 push(js.js('# && #', [receiverExpression, constant])); 1682 push(js.js('# && #', [receiverExpression, constant]));
1688 } else { 1683 } else {
1689 assert(node.inputs.length == 1); 1684 assert(node.inputs.length == 1);
1690 _registry.registerSpecializedGetInterceptor(node.interceptedClasses); 1685 _registry.registerSpecializedGetInterceptor(node.interceptedClasses);
1691 js.Name name = _namer.nameForGetInterceptor(node.interceptedClasses); 1686 js.Name name = _namer.nameForGetInterceptor(node.interceptedClasses);
1692 var isolate = new js.VariableUse( 1687 var isolate = new js.VariableUse(
1693 _namer.globalObjectForLibrary(_helpers.interceptorsLibrary)); 1688 _namer.globalObjectForLibrary(_commonElements.interceptorsLibrary));
1694 use(node.receiver); 1689 use(node.receiver);
1695 List<js.Expression> arguments = <js.Expression>[pop()]; 1690 List<js.Expression> arguments = <js.Expression>[pop()];
1696 push(js 1691 push(js
1697 .propertyCall(isolate, name, arguments) 1692 .propertyCall(isolate, name, arguments)
1698 .withSourceInformation(node.sourceInformation)); 1693 .withSourceInformation(node.sourceInformation));
1699 _registry.registerUseInterceptor(); 1694 _registry.registerUseInterceptor();
1700 } 1695 }
1701 } 1696 }
1702 1697
1703 visitInvokeDynamicMethod(HInvokeDynamicMethod node) { 1698 visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
1704 use(node.receiver); 1699 use(node.receiver);
1705 js.Expression object = pop(); 1700 js.Expression object = pop();
1706 String methodName; 1701 String methodName;
1707 List<js.Expression> arguments = visitArguments(node.inputs); 1702 List<js.Expression> arguments = visitArguments(node.inputs);
1708 MemberEntity target = node.element; 1703 MemberEntity target = node.element;
1709 1704
1710 // TODO(herhut): The namer should return the appropriate backendname here. 1705 // TODO(herhut): The namer should return the appropriate backendname here.
1711 if (target != null && !node.isInterceptedCall) { 1706 if (target != null && !node.isInterceptedCall) {
1712 if (target == _helpers.jsArrayAdd) { 1707 if (target == _commonElements.jsArrayAdd) {
1713 methodName = 'push'; 1708 methodName = 'push';
1714 } else if (target == _helpers.jsArrayRemoveLast) { 1709 } else if (target == _commonElements.jsArrayRemoveLast) {
1715 methodName = 'pop'; 1710 methodName = 'pop';
1716 } else if (target == _helpers.jsStringSplit) { 1711 } else if (target == _commonElements.jsStringSplit) {
1717 methodName = 'split'; 1712 methodName = 'split';
1718 // Split returns a List, so we make sure the backend knows the 1713 // Split returns a List, so we make sure the backend knows the
1719 // list class is instantiated. 1714 // list class is instantiated.
1720 _registry.registerInstantiatedClass(_commonElements.listClass); 1715 _registry.registerInstantiatedClass(_commonElements.listClass);
1721 } else if (_nativeData.isNativeMember(target) && 1716 } else if (_nativeData.isNativeMember(target) &&
1722 target.isFunction && 1717 target.isFunction &&
1723 !node.isInterceptedCall) { 1718 !node.isInterceptedCall) {
1724 // A direct (i.e. non-interceptor) native call is the result of 1719 // A direct (i.e. non-interceptor) native call is the result of
1725 // optimization. The optimization ensures any type checks or 1720 // optimization. The optimization ensures any type checks or
1726 // conversions have been satisified. 1721 // conversions have been satisified.
(...skipping 21 matching lines...) Expand all
1748 push(js 1743 push(js
1749 .propertyCall(object, methodName, arguments) 1744 .propertyCall(object, methodName, arguments)
1750 .withSourceInformation(node.sourceInformation)); 1745 .withSourceInformation(node.sourceInformation));
1751 _registry.registerStaticUse(new StaticUse.constructorBodyInvoke( 1746 _registry.registerStaticUse(new StaticUse.constructorBodyInvoke(
1752 node.element, new CallStructure.unnamed(arguments.length))); 1747 node.element, new CallStructure.unnamed(arguments.length)));
1753 } 1748 }
1754 1749
1755 void visitOneShotInterceptor(HOneShotInterceptor node) { 1750 void visitOneShotInterceptor(HOneShotInterceptor node) {
1756 List<js.Expression> arguments = visitArguments(node.inputs); 1751 List<js.Expression> arguments = visitArguments(node.inputs);
1757 var isolate = new js.VariableUse( 1752 var isolate = new js.VariableUse(
1758 _namer.globalObjectForLibrary(_helpers.interceptorsLibrary)); 1753 _namer.globalObjectForLibrary(_commonElements.interceptorsLibrary));
1759 Selector selector = node.selector; 1754 Selector selector = node.selector;
1760 js.Name methodName = 1755 js.Name methodName =
1761 _oneShotInterceptorData.registerOneShotInterceptor(selector, _namer); 1756 _oneShotInterceptorData.registerOneShotInterceptor(selector, _namer);
1762 push(js 1757 push(js
1763 .propertyCall(isolate, methodName, arguments) 1758 .propertyCall(isolate, methodName, arguments)
1764 .withSourceInformation(node.sourceInformation)); 1759 .withSourceInformation(node.sourceInformation));
1765 if (selector.isGetter) { 1760 if (selector.isGetter) {
1766 registerGetter(node); 1761 registerGetter(node);
1767 } else if (selector.isSetter) { 1762 } else if (selector.isSetter) {
1768 registerSetter(node); 1763 registerSetter(node);
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
1888 List<DartType> instantiatedTypes = node.instantiatedTypes; 1883 List<DartType> instantiatedTypes = node.instantiatedTypes;
1889 1884
1890 if (instantiatedTypes != null && !instantiatedTypes.isEmpty) { 1885 if (instantiatedTypes != null && !instantiatedTypes.isEmpty) {
1891 instantiatedTypes.forEach((type) { 1886 instantiatedTypes.forEach((type) {
1892 _registry.registerInstantiation(type); 1887 _registry.registerInstantiation(type);
1893 }); 1888 });
1894 } 1889 }
1895 1890
1896 List<js.Expression> arguments = visitArguments(node.inputs, start: 0); 1891 List<js.Expression> arguments = visitArguments(node.inputs, start: 0);
1897 1892
1898 if (element == _helpers.checkConcurrentModificationError) { 1893 if (element == _commonElements.checkConcurrentModificationError) {
1899 // Manually inline the [checkConcurrentModificationError] function. This 1894 // Manually inline the [checkConcurrentModificationError] function. This
1900 // function is only called from a for-loop update. Ideally we would just 1895 // function is only called from a for-loop update. Ideally we would just
1901 // generate the conditionalcontrol flow in the builder but it adds basic 1896 // generate the conditionalcontrol flow in the builder but it adds basic
1902 // blocks in the loop update that interfere with other optimizations and 1897 // blocks in the loop update that interfere with other optimizations and
1903 // confuses loop recognition. 1898 // confuses loop recognition.
1904 1899
1905 assert(arguments.length == 2); 1900 assert(arguments.length == 2);
1906 FunctionEntity throwFunction = _helpers.throwConcurrentModificationError; 1901 FunctionEntity throwFunction =
1902 _commonElements.throwConcurrentModificationError;
1907 _registry.registerStaticUse( 1903 _registry.registerStaticUse(
1908 new StaticUse.staticInvoke(throwFunction, CallStructure.ONE_ARG)); 1904 new StaticUse.staticInvoke(throwFunction, CallStructure.ONE_ARG));
1909 1905
1910 // Calling using `(0, #)(#)` instead of `#(#)` separates the property load 1906 // Calling using `(0, #)(#)` instead of `#(#)` separates the property load
1911 // of the static function access from the call. For some reason this 1907 // of the static function access from the call. For some reason this
1912 // helps V8 see that the call never happens so V8 makes the call a 1908 // helps V8 see that the call never happens so V8 makes the call a
1913 // deoptimization. This removes the call from the optimized loop, making 1909 // deoptimization. This removes the call from the optimized loop, making
1914 // more optimizations available to the loop. This form is 50% faster on 1910 // more optimizations available to the loop. This form is 50% faster on
1915 // some small loop, almost as fast as loops with no concurrent 1911 // some small loop, almost as fast as loops with no concurrent
1916 // modification check. 1912 // modification check.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1951 } 1947 }
1952 } else { 1948 } else {
1953 Selector selector = node.selector; 1949 Selector selector = node.selector;
1954 if (!_superMemberData.maybeRegisterAliasedSuperMember( 1950 if (!_superMemberData.maybeRegisterAliasedSuperMember(
1955 superElement, selector)) { 1951 superElement, selector)) {
1956 js.Name methodName; 1952 js.Name methodName;
1957 if (selector.isGetter && !superElement.isGetter) { 1953 if (selector.isGetter && !superElement.isGetter) {
1958 // If this is a tear-off, register the fact that a tear-off closure 1954 // If this is a tear-off, register the fact that a tear-off closure
1959 // will be created, and that this tear-off must bypass ordinary 1955 // will be created, and that this tear-off must bypass ordinary
1960 // dispatch to ensure the super method is invoked. 1956 // dispatch to ensure the super method is invoked.
1961 FunctionEntity helper = _helpers.closureFromTearOff; 1957 FunctionEntity helper = _commonElements.closureFromTearOff;
1962 _registry.registerStaticUse(new StaticUse.staticInvoke( 1958 _registry.registerStaticUse(new StaticUse.staticInvoke(
1963 helper, new CallStructure.unnamed(node.inputs.length))); 1959 helper, new CallStructure.unnamed(node.inputs.length)));
1964 _registry.registerStaticUse(new StaticUse.superTearOff(node.element)); 1960 _registry.registerStaticUse(new StaticUse.superTearOff(node.element));
1965 methodName = _namer.invocationName(selector); 1961 methodName = _namer.invocationName(selector);
1966 } else { 1962 } else {
1967 methodName = _namer.instanceMethodName(superElement); 1963 methodName = _namer.instanceMethodName(superElement);
1968 } 1964 }
1969 _registry.registerStaticUse(new StaticUse.superInvoke( 1965 _registry.registerStaticUse(new StaticUse.superInvoke(
1970 superElement, new CallStructure.unnamed(node.inputs.length))); 1966 superElement, new CallStructure.unnamed(node.inputs.length)));
1971 push(js.js('#.#.call(#)', [ 1967 push(js.js('#.#.call(#)', [
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after
2266 visitThis(HThis node) { 2262 visitThis(HThis node) {
2267 push(new js.This()); 2263 push(new js.This());
2268 } 2264 }
2269 2265
2270 visitThrow(HThrow node) { 2266 visitThrow(HThrow node) {
2271 if (node.isRethrow) { 2267 if (node.isRethrow) {
2272 use(node.inputs[0]); 2268 use(node.inputs[0]);
2273 pushStatement( 2269 pushStatement(
2274 new js.Throw(pop()).withSourceInformation(node.sourceInformation)); 2270 new js.Throw(pop()).withSourceInformation(node.sourceInformation));
2275 } else { 2271 } else {
2276 generateThrowWithHelper(_helpers.wrapExceptionHelper, node.inputs[0], 2272 generateThrowWithHelper(
2273 _commonElements.wrapExceptionHelper, node.inputs[0],
2277 sourceInformation: node.sourceInformation); 2274 sourceInformation: node.sourceInformation);
2278 } 2275 }
2279 } 2276 }
2280 2277
2281 visitAwait(HAwait node) { 2278 visitAwait(HAwait node) {
2282 use(node.inputs[0]); 2279 use(node.inputs[0]);
2283 push(new js.Await(pop()).withSourceInformation(node.sourceInformation)); 2280 push(new js.Await(pop()).withSourceInformation(node.sourceInformation));
2284 } 2281 }
2285 2282
2286 visitYield(HYield node) { 2283 visitYield(HYield node) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
2324 use(node.length); 2321 use(node.length);
2325 over = new js.Binary(">=", jsIndex, pop()); 2322 over = new js.Binary(">=", jsIndex, pop());
2326 } 2323 }
2327 assert(over != null || under != null); 2324 assert(over != null || under != null);
2328 js.Expression underOver = under == null 2325 js.Expression underOver = under == null
2329 ? over 2326 ? over
2330 : over == null ? under : new js.Binary("||", under, over); 2327 : over == null ? under : new js.Binary("||", under, over);
2331 js.Statement thenBody = new js.Block.empty(); 2328 js.Statement thenBody = new js.Block.empty();
2332 js.Block oldContainer = currentContainer; 2329 js.Block oldContainer = currentContainer;
2333 currentContainer = thenBody; 2330 currentContainer = thenBody;
2334 generateThrowWithHelper(_helpers.throwIndexOutOfRangeException, 2331 generateThrowWithHelper(_commonElements.throwIndexOutOfRangeException,
2335 [node.array, node.reportedIndex]); 2332 [node.array, node.reportedIndex]);
2336 currentContainer = oldContainer; 2333 currentContainer = oldContainer;
2337 thenBody = unwrapStatement(thenBody); 2334 thenBody = unwrapStatement(thenBody);
2338 pushStatement(new js.If.noElse(underOver, thenBody) 2335 pushStatement(new js.If.noElse(underOver, thenBody)
2339 .withSourceInformation(node.sourceInformation)); 2336 .withSourceInformation(node.sourceInformation));
2340 } else { 2337 } else {
2341 generateThrowWithHelper( 2338 generateThrowWithHelper(_commonElements.throwIndexOutOfRangeException,
2342 _helpers.throwIndexOutOfRangeException, [node.array, node.index]); 2339 [node.array, node.index]);
2343 } 2340 }
2344 } 2341 }
2345 2342
2346 void generateThrowWithHelper(FunctionEntity helper, argument, 2343 void generateThrowWithHelper(FunctionEntity helper, argument,
2347 {SourceInformation sourceInformation}) { 2344 {SourceInformation sourceInformation}) {
2348 js.Expression jsHelper = _emitter.staticFunctionAccess(helper); 2345 js.Expression jsHelper = _emitter.staticFunctionAccess(helper);
2349 List arguments = []; 2346 List arguments = [];
2350 if (argument is List) { 2347 if (argument is List) {
2351 argument.forEach((instruction) { 2348 argument.forEach((instruction) {
2352 use(instruction); 2349 use(instruction);
2353 arguments.add(pop()); 2350 arguments.add(pop());
2354 }); 2351 });
2355 } else { 2352 } else {
2356 use(argument); 2353 use(argument);
2357 arguments.add(pop()); 2354 arguments.add(pop());
2358 } 2355 }
2359 _registry.registerStaticUse(new StaticUse.staticInvoke( 2356 _registry.registerStaticUse(new StaticUse.staticInvoke(
2360 helper, new CallStructure.unnamed(arguments.length))); 2357 helper, new CallStructure.unnamed(arguments.length)));
2361 js.Call value = new js.Call(jsHelper, arguments.toList(growable: false), 2358 js.Call value = new js.Call(jsHelper, arguments.toList(growable: false),
2362 sourceInformation: sourceInformation); 2359 sourceInformation: sourceInformation);
2363 // BUG(4906): Using throw/return here adds to the size of the generated code 2360 // BUG(4906): Using throw/return here adds to the size of the generated code
2364 // but it has the advantage of explicitly telling the JS engine that 2361 // but it has the advantage of explicitly telling the JS engine that
2365 // this code path will terminate abruptly. Needs more work. 2362 // this code path will terminate abruptly. Needs more work.
2366 if (helper == _helpers.wrapExceptionHelper) { 2363 if (helper == _commonElements.wrapExceptionHelper) {
2367 pushStatement( 2364 pushStatement(
2368 new js.Throw(value).withSourceInformation(sourceInformation)); 2365 new js.Throw(value).withSourceInformation(sourceInformation));
2369 } else { 2366 } else {
2370 Entity element = _work.element; 2367 Entity element = _work.element;
2371 if (element is MethodElement && element.asyncMarker.isYielding) { 2368 if (element is MethodElement && element.asyncMarker.isYielding) {
2372 // `return <expr>;` is illegal in a sync* or async* function. 2369 // `return <expr>;` is illegal in a sync* or async* function.
2373 // To have the async-translator working, we avoid introducing 2370 // To have the async-translator working, we avoid introducing
2374 // `return` nodes. 2371 // `return` nodes.
2375 pushStatement(new js.ExpressionStatement(value) 2372 pushStatement(new js.ExpressionStatement(value)
2376 .withSourceInformation(sourceInformation)); 2373 .withSourceInformation(sourceInformation));
2377 } else { 2374 } else {
2378 pushStatement( 2375 pushStatement(
2379 new js.Return(value).withSourceInformation(sourceInformation)); 2376 new js.Return(value).withSourceInformation(sourceInformation));
2380 } 2377 }
2381 } 2378 }
2382 } 2379 }
2383 2380
2384 visitThrowExpression(HThrowExpression node) { 2381 visitThrowExpression(HThrowExpression node) {
2385 HInstruction argument = node.inputs[0]; 2382 HInstruction argument = node.inputs[0];
2386 use(argument); 2383 use(argument);
2387 2384
2388 FunctionEntity helper = _helpers.throwExpressionHelper; 2385 FunctionEntity helper = _commonElements.throwExpressionHelper;
2389 _registry.registerStaticUse( 2386 _registry.registerStaticUse(
2390 new StaticUse.staticInvoke(helper, CallStructure.ONE_ARG)); 2387 new StaticUse.staticInvoke(helper, CallStructure.ONE_ARG));
2391 2388
2392 js.Expression jsHelper = _emitter.staticFunctionAccess(helper); 2389 js.Expression jsHelper = _emitter.staticFunctionAccess(helper);
2393 js.Call value = new js.Call(jsHelper, [pop()]) 2390 js.Call value = new js.Call(jsHelper, [pop()])
2394 .withSourceInformation(node.sourceInformation); 2391 .withSourceInformation(node.sourceInformation);
2395 push(value); 2392 push(value);
2396 } 2393 }
2397 2394
2398 void visitSwitch(HSwitch node) { 2395 void visitSwitch(HSwitch node) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
2451 if (node.usedBy.length == 1 && 2448 if (node.usedBy.length == 1 &&
2452 node.usedBy[0] is HStringConcat && 2449 node.usedBy[0] is HStringConcat &&
2453 node.usedBy[0].inputs[1] == node) { 2450 node.usedBy[0].inputs[1] == node) {
2454 // The context is already <string> + value. 2451 // The context is already <string> + value.
2455 } else { 2452 } else {
2456 // Force an empty string for the first operand. 2453 // Force an empty string for the first operand.
2457 push(new js.Binary('+', js.string(""), pop()) 2454 push(new js.Binary('+', js.string(""), pop())
2458 .withSourceInformation(node.sourceInformation)); 2455 .withSourceInformation(node.sourceInformation));
2459 } 2456 }
2460 } else { 2457 } else {
2461 FunctionEntity convertToString = _helpers.stringInterpolationHelper; 2458 FunctionEntity convertToString =
2459 _commonElements.stringInterpolationHelper;
2462 _registry.registerStaticUse( 2460 _registry.registerStaticUse(
2463 new StaticUse.staticInvoke(convertToString, CallStructure.ONE_ARG)); 2461 new StaticUse.staticInvoke(convertToString, CallStructure.ONE_ARG));
2464 js.Expression jsHelper = _emitter.staticFunctionAccess(convertToString); 2462 js.Expression jsHelper = _emitter.staticFunctionAccess(convertToString);
2465 use(input); 2463 use(input);
2466 push(new js.Call(jsHelper, <js.Expression>[pop()], 2464 push(new js.Call(jsHelper, <js.Expression>[pop()],
2467 sourceInformation: node.sourceInformation)); 2465 sourceInformation: node.sourceInformation));
2468 } 2466 }
2469 } 2467 }
2470 2468
2471 void visitLiteralList(HLiteralList node) { 2469 void visitLiteralList(HLiteralList node) {
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
2612 use(input); 2610 use(input);
2613 push(new js.Binary('!=', pop(), new js.LiteralNull())); 2611 push(new js.Binary('!=', pop(), new js.LiteralNull()));
2614 } 2612 }
2615 2613
2616 void checkType(HInstruction input, HInstruction interceptor, DartType type, 2614 void checkType(HInstruction input, HInstruction interceptor, DartType type,
2617 SourceInformation sourceInformation, 2615 SourceInformation sourceInformation,
2618 {bool negative: false}) { 2616 {bool negative: false}) {
2619 if (type.isInterfaceType) { 2617 if (type.isInterfaceType) {
2620 InterfaceType interfaceType = type; 2618 InterfaceType interfaceType = type;
2621 ClassEntity element = interfaceType.element; 2619 ClassEntity element = interfaceType.element;
2622 if (element == _helpers.jsArrayClass) { 2620 if (element == _commonElements.jsArrayClass) {
2623 checkArray(input, negative ? '!==' : '==='); 2621 checkArray(input, negative ? '!==' : '===');
2624 return; 2622 return;
2625 } else if (element == _helpers.jsMutableArrayClass) { 2623 } else if (element == _commonElements.jsMutableArrayClass) {
2626 if (negative) { 2624 if (negative) {
2627 checkImmutableArray(input); 2625 checkImmutableArray(input);
2628 } else { 2626 } else {
2629 checkMutableArray(input); 2627 checkMutableArray(input);
2630 } 2628 }
2631 return; 2629 return;
2632 } else if (element == _helpers.jsExtendableArrayClass) { 2630 } else if (element == _commonElements.jsExtendableArrayClass) {
2633 if (negative) { 2631 if (negative) {
2634 checkFixedArray(input); 2632 checkFixedArray(input);
2635 } else { 2633 } else {
2636 checkExtendableArray(input); 2634 checkExtendableArray(input);
2637 } 2635 }
2638 return; 2636 return;
2639 } else if (element == _helpers.jsFixedArrayClass) { 2637 } else if (element == _commonElements.jsFixedArrayClass) {
2640 if (negative) { 2638 if (negative) {
2641 checkExtendableArray(input); 2639 checkExtendableArray(input);
2642 } else { 2640 } else {
2643 checkFixedArray(input); 2641 checkFixedArray(input);
2644 } 2642 }
2645 return; 2643 return;
2646 } else if (element == _helpers.jsUnmodifiableArrayClass) { 2644 } else if (element == _commonElements.jsUnmodifiableArrayClass) {
2647 if (negative) { 2645 if (negative) {
2648 checkMutableArray(input); 2646 checkMutableArray(input);
2649 } else { 2647 } else {
2650 checkImmutableArray(input); 2648 checkImmutableArray(input);
2651 } 2649 }
2652 return; 2650 return;
2653 } 2651 }
2654 } 2652 }
2655 if (interceptor != null) { 2653 if (interceptor != null) {
2656 checkTypeViaProperty(interceptor, type, sourceInformation, 2654 checkTypeViaProperty(interceptor, type, sourceInformation,
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
2860 // Figure out if it is beneficial to turn this into a null check. 2858 // Figure out if it is beneficial to turn this into a null check.
2861 // V8 generally prefers 'typeof' checks, but for integers and 2859 // V8 generally prefers 'typeof' checks, but for integers and
2862 // indexable primitives we cannot compile this test into a single 2860 // indexable primitives we cannot compile this test into a single
2863 // typeof check so the null check is cheaper. 2861 // typeof check so the null check is cheaper.
2864 bool isIntCheck = checkedType.containsOnlyInt(_closedWorld); 2862 bool isIntCheck = checkedType.containsOnlyInt(_closedWorld);
2865 bool turnIntoNumCheck = 2863 bool turnIntoNumCheck =
2866 isIntCheck && inputType.containsOnlyInt(_closedWorld); 2864 isIntCheck && inputType.containsOnlyInt(_closedWorld);
2867 bool turnIntoNullCheck = !turnIntoNumCheck && 2865 bool turnIntoNullCheck = !turnIntoNumCheck &&
2868 (checkedType.nullable() == inputType) && 2866 (checkedType.nullable() == inputType) &&
2869 (isIntCheck || 2867 (isIntCheck ||
2870 checkedType.satisfies(_helpers.jsIndexableClass, _closedWorld)); 2868 checkedType.satisfies(
2869 _commonElements.jsIndexableClass, _closedWorld));
2871 2870
2872 if (turnIntoNullCheck) { 2871 if (turnIntoNullCheck) {
2873 use(input); 2872 use(input);
2874 return new js.Binary("==", pop(), new js.LiteralNull()) 2873 return new js.Binary("==", pop(), new js.LiteralNull())
2875 .withSourceInformation(input.sourceInformation); 2874 .withSourceInformation(input.sourceInformation);
2876 } else if (isIntCheck && !turnIntoNumCheck) { 2875 } else if (isIntCheck && !turnIntoNumCheck) {
2877 // input is !int 2876 // input is !int
2878 checkBigInt(input, '!==', input.sourceInformation); 2877 checkBigInt(input, '!==', input.sourceInformation);
2879 return pop(); 2878 return pop();
2880 } else if (turnIntoNumCheck || checkedType.containsOnlyNum(_closedWorld)) { 2879 } else if (turnIntoNumCheck || checkedType.containsOnlyNum(_closedWorld)) {
(...skipping 14 matching lines...) Expand all
2895 } 2894 }
2896 2895
2897 void visitTypeConversion(HTypeConversion node) { 2896 void visitTypeConversion(HTypeConversion node) {
2898 if (node.isArgumentTypeCheck || node.isReceiverTypeCheck) { 2897 if (node.isArgumentTypeCheck || node.isReceiverTypeCheck) {
2899 js.Expression test = generateReceiverOrArgumentTypeTest(node); 2898 js.Expression test = generateReceiverOrArgumentTypeTest(node);
2900 js.Block oldContainer = currentContainer; 2899 js.Block oldContainer = currentContainer;
2901 js.Statement body = new js.Block.empty(); 2900 js.Statement body = new js.Block.empty();
2902 currentContainer = body; 2901 currentContainer = body;
2903 if (node.isArgumentTypeCheck) { 2902 if (node.isArgumentTypeCheck) {
2904 generateThrowWithHelper( 2903 generateThrowWithHelper(
2905 _helpers.throwIllegalArgumentException, node.checkedInput, 2904 _commonElements.throwIllegalArgumentException, node.checkedInput,
2906 sourceInformation: node.sourceInformation); 2905 sourceInformation: node.sourceInformation);
2907 } else if (node.isReceiverTypeCheck) { 2906 } else if (node.isReceiverTypeCheck) {
2908 use(node.checkedInput); 2907 use(node.checkedInput);
2909 js.Name methodName = 2908 js.Name methodName =
2910 _namer.invocationName(node.receiverTypeCheckSelector); 2909 _namer.invocationName(node.receiverTypeCheckSelector);
2911 js.Expression call = js.propertyCall(pop(), methodName, []); 2910 js.Expression call = js.propertyCall(pop(), methodName, []);
2912 pushStatement(new js.Return(call)); 2911 pushStatement(new js.Return(call));
2913 } 2912 }
2914 currentContainer = oldContainer; 2913 currentContainer = oldContainer;
2915 body = unwrapStatement(body); 2914 body = unwrapStatement(body);
(...skipping 15 matching lines...) Expand all
2931 _registry.registerTypeUse(new TypeUse.isCheck(type)); 2930 _registry.registerTypeUse(new TypeUse.isCheck(type));
2932 2931
2933 CheckedModeHelper helper; 2932 CheckedModeHelper helper;
2934 if (node.isBooleanConversionCheck) { 2933 if (node.isBooleanConversionCheck) {
2935 helper = const CheckedModeHelper('boolConversionCheck'); 2934 helper = const CheckedModeHelper('boolConversionCheck');
2936 } else { 2935 } else {
2937 helper = _checkedModeHelpers.getCheckedModeHelper(type, 2936 helper = _checkedModeHelpers.getCheckedModeHelper(type,
2938 typeCast: node.isCastTypeCheck); 2937 typeCast: node.isCastTypeCheck);
2939 } 2938 }
2940 2939
2941 StaticUse staticUse = helper.getStaticUse(_helpers); 2940 StaticUse staticUse = helper.getStaticUse(_commonElements);
2942 _registry.registerStaticUse(staticUse); 2941 _registry.registerStaticUse(staticUse);
2943 List<js.Expression> arguments = <js.Expression>[]; 2942 List<js.Expression> arguments = <js.Expression>[];
2944 use(node.checkedInput); 2943 use(node.checkedInput);
2945 arguments.add(pop()); 2944 arguments.add(pop());
2946 helper.generateAdditionalArguments(this, _namer, node, arguments); 2945 helper.generateAdditionalArguments(this, _namer, node, arguments);
2947 push(new js.Call( 2946 push(new js.Call(
2948 _emitter.staticFunctionAccess(staticUse.element), arguments)); 2947 _emitter.staticFunctionAccess(staticUse.element), arguments));
2949 } 2948 }
2950 2949
2951 void visitTypeKnown(HTypeKnown node) { 2950 void visitTypeKnown(HTypeKnown node) {
(...skipping 11 matching lines...) Expand all
2963 TypeVariableEntity element = node.variable.element; 2962 TypeVariableEntity element = node.variable.element;
2964 2963
2965 int index = element.index; 2964 int index = element.index;
2966 HInstruction object = node.object; 2965 HInstruction object = node.object;
2967 use(object); 2966 use(object);
2968 js.Expression receiver = pop(); 2967 js.Expression receiver = pop();
2969 2968
2970 if (typeVariableAccessNeedsSubstitution(element, object.instructionType)) { 2969 if (typeVariableAccessNeedsSubstitution(element, object.instructionType)) {
2971 js.Expression typeName = 2970 js.Expression typeName =
2972 js.quoteName(_namer.runtimeTypeName(element.typeDeclaration)); 2971 js.quoteName(_namer.runtimeTypeName(element.typeDeclaration));
2973 FunctionEntity helperElement = _helpers.getRuntimeTypeArgument; 2972 FunctionEntity helperElement = _commonElements.getRuntimeTypeArgument;
2974 _registry.registerStaticUse( 2973 _registry.registerStaticUse(
2975 new StaticUse.staticInvoke(helperElement, CallStructure.THREE_ARGS)); 2974 new StaticUse.staticInvoke(helperElement, CallStructure.THREE_ARGS));
2976 js.Expression helper = _emitter.staticFunctionAccess(helperElement); 2975 js.Expression helper = _emitter.staticFunctionAccess(helperElement);
2977 push(js.js( 2976 push(js.js(
2978 r'#(#, #, #)', [helper, receiver, typeName, js.js.number(index)])); 2977 r'#(#, #, #)', [helper, receiver, typeName, js.js.number(index)]));
2979 } else { 2978 } else {
2980 FunctionEntity helperElement = _helpers.getTypeArgumentByIndex; 2979 FunctionEntity helperElement = _commonElements.getTypeArgumentByIndex;
2981 _registry.registerStaticUse( 2980 _registry.registerStaticUse(
2982 new StaticUse.staticInvoke(helperElement, CallStructure.TWO_ARGS)); 2981 new StaticUse.staticInvoke(helperElement, CallStructure.TWO_ARGS));
2983 js.Expression helper = _emitter.staticFunctionAccess(helperElement); 2982 js.Expression helper = _emitter.staticFunctionAccess(helperElement);
2984 push(js.js(r'#(#, #)', [helper, receiver, js.js.number(index)])); 2983 push(js.js(r'#(#, #)', [helper, receiver, js.js.number(index)]));
2985 } 2984 }
2986 } 2985 }
2987 2986
2988 void visitTypeInfoExpression(HTypeInfoExpression node) { 2987 void visitTypeInfoExpression(HTypeInfoExpression node) {
2989 List<js.Expression> arguments = <js.Expression>[]; 2988 List<js.Expression> arguments = <js.Expression>[];
2990 for (HInstruction input in node.inputs) { 2989 for (HInstruction input in node.inputs) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
3031 return _closedWorld.anyStrictSubclassOf(cls, (ClassEntity subclass) { 3030 return _closedWorld.anyStrictSubclassOf(cls, (ClassEntity subclass) {
3032 return !_rtiSubstitutions.isTrivialSubstitution(subclass, cls); 3031 return !_rtiSubstitutions.isTrivialSubstitution(subclass, cls);
3033 }); 3032 });
3034 } 3033 }
3035 3034
3036 @override 3035 @override
3037 void visitRef(HRef node) { 3036 void visitRef(HRef node) {
3038 visit(node.value); 3037 visit(node.value);
3039 } 3038 }
3040 } 3039 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/ssa/builder_kernel.dart ('k') | pkg/compiler/lib/src/ssa/graph_builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698