OLD | NEW |
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 '../common.dart'; | 6 import '../common.dart'; |
7 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; | 7 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; |
8 import '../common/tasks.dart' show CompilerTask; | 8 import '../common/tasks.dart' show CompilerTask; |
9 import '../compiler.dart' show Compiler; | |
10 import '../constants/constant_system.dart'; | 9 import '../constants/constant_system.dart'; |
11 import '../constants/values.dart'; | 10 import '../constants/values.dart'; |
12 import '../common_elements.dart' show CommonElements; | 11 import '../common_elements.dart' show CommonElements; |
13 import '../elements/elements.dart' | 12 import '../elements/elements.dart' |
14 show | 13 show AsyncMarker, JumpTarget, LabelDefinition, MethodElement, ResolvedAst; |
15 AsyncMarker, | |
16 JumpTarget, | |
17 LabelDefinition, | |
18 MethodElement, | |
19 Name, | |
20 ResolvedAst; | |
21 import '../elements/entities.dart'; | 14 import '../elements/entities.dart'; |
22 import '../elements/types.dart'; | 15 import '../elements/types.dart'; |
23 import '../io/source_information.dart'; | 16 import '../io/source_information.dart'; |
24 import '../js/js.dart' as js; | 17 import '../js/js.dart' as js; |
25 import '../js_backend/backend_helpers.dart' show BackendHelpers; | 18 import '../js_backend/backend_helpers.dart' show BackendHelpers; |
| 19 import '../js_backend/interceptor_data.dart'; |
26 import '../js_backend/js_backend.dart'; | 20 import '../js_backend/js_backend.dart'; |
27 import '../js_emitter/js_emitter.dart' show NativeEmitter; | 21 import '../js_backend/native_data.dart'; |
| 22 import '../js_emitter/code_emitter_task.dart'; |
28 import '../native/native.dart' as native; | 23 import '../native/native.dart' as native; |
| 24 import '../options.dart'; |
29 import '../types/types.dart'; | 25 import '../types/types.dart'; |
30 import '../universe/call_structure.dart' show CallStructure; | 26 import '../universe/call_structure.dart' show CallStructure; |
31 import '../universe/selector.dart' show Selector; | 27 import '../universe/selector.dart' show Selector; |
32 import '../universe/use.dart' show ConstantUse, DynamicUse, StaticUse, TypeUse; | 28 import '../universe/use.dart' show ConstantUse, DynamicUse, StaticUse, TypeUse; |
33 import '../util/util.dart'; | 29 import '../util/util.dart'; |
34 import '../world.dart' show ClosedWorld; | 30 import '../world.dart' show ClosedWorld; |
35 import 'codegen_helpers.dart'; | 31 import 'codegen_helpers.dart'; |
36 import 'nodes.dart'; | 32 import 'nodes.dart'; |
37 import 'variable_allocator.dart'; | 33 import 'variable_allocator.dart'; |
38 | 34 |
39 class SsaCodeGeneratorTask extends CompilerTask { | 35 class SsaCodeGeneratorTask extends CompilerTask { |
40 final JavaScriptBackend backend; | 36 final JavaScriptBackend backend; |
41 final Compiler compiler; | |
42 final SourceInformationStrategy sourceInformationFactory; | 37 final SourceInformationStrategy sourceInformationFactory; |
43 | 38 |
44 SsaCodeGeneratorTask(JavaScriptBackend backend, this.sourceInformationFactory) | 39 SsaCodeGeneratorTask(JavaScriptBackend backend, this.sourceInformationFactory) |
45 : this.backend = backend, | 40 : this.backend = backend, |
46 this.compiler = backend.compiler, | |
47 super(backend.compiler.measurer); | 41 super(backend.compiler.measurer); |
48 | 42 |
49 String get name => 'SSA code generator'; | 43 String get name => 'SSA code generator'; |
50 NativeEmitter get nativeEmitter => backend.emitter.nativeEmitter; | |
51 | 44 |
52 js.Fun buildJavaScriptFunction( | 45 js.Fun buildJavaScriptFunction( |
53 ResolvedAst resolvedAst, List<js.Parameter> parameters, js.Block body) { | 46 ResolvedAst resolvedAst, List<js.Parameter> parameters, js.Block body) { |
54 MethodElement element = resolvedAst.element; | 47 MethodElement element = resolvedAst.element; |
55 js.AsyncModifier asyncModifier = element.asyncMarker.isAsync | 48 js.AsyncModifier asyncModifier = element.asyncMarker.isAsync |
56 ? (element.asyncMarker.isYielding | 49 ? (element.asyncMarker.isYielding |
57 ? const js.AsyncModifier.asyncStar() | 50 ? const js.AsyncModifier.asyncStar() |
58 : const js.AsyncModifier.async()) | 51 : const js.AsyncModifier.async()) |
59 : (element.asyncMarker.isYielding | 52 : (element.asyncMarker.isYielding |
60 ? const js.AsyncModifier.syncStar() | 53 ? const js.AsyncModifier.syncStar() |
(...skipping 14 matching lines...) Expand all Loading... |
75 } | 68 } |
76 } | 69 } |
77 | 70 |
78 js.Expression generateLazyInitializer( | 71 js.Expression generateLazyInitializer( |
79 CodegenWorkItem work, HGraph graph, ClosedWorld closedWorld) { | 72 CodegenWorkItem work, HGraph graph, ClosedWorld closedWorld) { |
80 return measure(() { | 73 return measure(() { |
81 backend.tracer.traceGraph("codegen", graph); | 74 backend.tracer.traceGraph("codegen", graph); |
82 SourceInformation sourceInformation = sourceInformationFactory | 75 SourceInformation sourceInformation = sourceInformationFactory |
83 .createBuilderForContext(work.resolvedAst) | 76 .createBuilderForContext(work.resolvedAst) |
84 .buildDeclaration(work.resolvedAst); | 77 .buildDeclaration(work.resolvedAst); |
85 SsaCodeGenerator codegen = | 78 SsaCodeGenerator codegen = new SsaCodeGenerator( |
86 new SsaCodeGenerator(backend, closedWorld, work); | 79 backend.compiler.options, |
| 80 backend.emitter, |
| 81 backend.nativeCodegenEnqueuer, |
| 82 backend.helpers, |
| 83 backend.checkedModeHelpers, |
| 84 backend.nativeData, |
| 85 backend.interceptorData, |
| 86 backend.oneShotInterceptorData, |
| 87 backend.rtiSubstitutions, |
| 88 backend.rtiEncoder, |
| 89 backend.namer, |
| 90 backend.superMemberData, |
| 91 closedWorld, |
| 92 work); |
87 codegen.visitGraph(graph); | 93 codegen.visitGraph(graph); |
88 return new js.Fun(codegen.parameters, codegen.body) | 94 return new js.Fun(codegen.parameters, codegen.body) |
89 .withSourceInformation(sourceInformation); | 95 .withSourceInformation(sourceInformation); |
90 }); | 96 }); |
91 } | 97 } |
92 | 98 |
93 js.Expression generateMethod( | 99 js.Expression generateMethod( |
94 CodegenWorkItem work, HGraph graph, ClosedWorld closedWorld) { | 100 CodegenWorkItem work, HGraph graph, ClosedWorld closedWorld) { |
95 return measure(() { | 101 return measure(() { |
96 MethodElement element = work.element; | 102 MethodElement element = work.element; |
97 if (element.asyncMarker != AsyncMarker.SYNC) { | 103 if (element.asyncMarker != AsyncMarker.SYNC) { |
98 work.registry.registerAsyncMarker(element); | 104 work.registry.registerAsyncMarker(element); |
99 } | 105 } |
100 SsaCodeGenerator codegen = | 106 SsaCodeGenerator codegen = new SsaCodeGenerator( |
101 new SsaCodeGenerator(backend, closedWorld, work); | 107 backend.compiler.options, |
| 108 backend.emitter, |
| 109 backend.nativeCodegenEnqueuer, |
| 110 backend.helpers, |
| 111 backend.checkedModeHelpers, |
| 112 backend.nativeData, |
| 113 backend.interceptorData, |
| 114 backend.oneShotInterceptorData, |
| 115 backend.rtiSubstitutions, |
| 116 backend.rtiEncoder, |
| 117 backend.namer, |
| 118 backend.superMemberData, |
| 119 closedWorld, |
| 120 work); |
102 codegen.visitGraph(graph); | 121 codegen.visitGraph(graph); |
103 backend.tracer.traceGraph("codegen", graph); | 122 backend.tracer.traceGraph("codegen", graph); |
104 return buildJavaScriptFunction( | 123 return buildJavaScriptFunction( |
105 work.resolvedAst, codegen.parameters, codegen.body); | 124 work.resolvedAst, codegen.parameters, codegen.body); |
106 }); | 125 }); |
107 } | 126 } |
108 } | 127 } |
109 | 128 |
110 typedef void EntityAction(Entity element); | 129 typedef void EntityAction(Entity element); |
111 | 130 |
(...skipping 13 matching lines...) Expand all Loading... |
125 static const int TYPE_STATEMENT = 0; | 144 static const int TYPE_STATEMENT = 0; |
126 static const int TYPE_EXPRESSION = 1; | 145 static const int TYPE_EXPRESSION = 1; |
127 static const int TYPE_DECLARATION = 2; | 146 static const int TYPE_DECLARATION = 2; |
128 | 147 |
129 /** | 148 /** |
130 * Whether we are currently generating expressions instead of statements. | 149 * Whether we are currently generating expressions instead of statements. |
131 * This includes declarations, which are generated as expressions. | 150 * This includes declarations, which are generated as expressions. |
132 */ | 151 */ |
133 bool isGeneratingExpression = false; | 152 bool isGeneratingExpression = false; |
134 | 153 |
135 final JavaScriptBackend backend; | 154 final CompilerOptions _options; |
136 final ClosedWorld closedWorld; | 155 final CodeEmitterTask _emitter; |
137 final CodegenWorkItem work; | 156 final native.NativeCodegenEnqueuer _nativeEnqueuer; |
| 157 final BackendHelpers _helpers; |
| 158 final CheckedModeHelpers _checkedModeHelpers; |
| 159 final NativeData _nativeData; |
| 160 final InterceptorData _interceptorData; |
| 161 final OneShotInterceptorData _oneShotInterceptorData; |
| 162 final RuntimeTypesSubstitutions _rtiSubstitutions; |
| 163 final RuntimeTypesEncoder _rtiEncoder; |
| 164 final Namer _namer; |
| 165 final SuperMemberData _superMemberData; |
| 166 final ClosedWorld _closedWorld; |
| 167 final CodegenWorkItem _work; |
138 | 168 |
139 final Set<HInstruction> generateAtUseSite; | 169 final Set<HInstruction> generateAtUseSite; |
140 final Set<HInstruction> controlFlowOperators; | 170 final Set<HInstruction> controlFlowOperators; |
141 final Map<Entity, EntityAction> breakAction; | 171 final Map<Entity, EntityAction> breakAction; |
142 final Map<Entity, EntityAction> continueAction; | 172 final Map<Entity, EntityAction> continueAction; |
143 final List<js.Parameter> parameters; | 173 final List<js.Parameter> parameters; |
144 | 174 |
145 js.Block currentContainer; | 175 js.Block currentContainer; |
146 js.Block get body => currentContainer; | 176 js.Block get body => currentContainer; |
147 List<js.Expression> expressionStack; | 177 List<js.Expression> expressionStack; |
(...skipping 21 matching lines...) Expand all Loading... |
169 | 199 |
170 HGraph currentGraph; | 200 HGraph currentGraph; |
171 | 201 |
172 // Records a block-information that is being handled specially. | 202 // Records a block-information that is being handled specially. |
173 // Used to break bad recursion. | 203 // Used to break bad recursion. |
174 HBlockInformation currentBlockInformation; | 204 HBlockInformation currentBlockInformation; |
175 // The subgraph is used to delimit traversal for some constructions, e.g., | 205 // The subgraph is used to delimit traversal for some constructions, e.g., |
176 // if branches. | 206 // if branches. |
177 SubGraph subGraph; | 207 SubGraph subGraph; |
178 | 208 |
179 SsaCodeGenerator(this.backend, this.closedWorld, CodegenWorkItem work, | 209 SsaCodeGenerator( |
| 210 this._options, |
| 211 this._emitter, |
| 212 this._nativeEnqueuer, |
| 213 this._helpers, |
| 214 this._checkedModeHelpers, |
| 215 this._nativeData, |
| 216 this._interceptorData, |
| 217 this._oneShotInterceptorData, |
| 218 this._rtiSubstitutions, |
| 219 this._rtiEncoder, |
| 220 this._namer, |
| 221 this._superMemberData, |
| 222 this._closedWorld, |
| 223 this._work, |
180 {SourceInformation sourceInformation}) | 224 {SourceInformation sourceInformation}) |
181 : this.work = work, | 225 : declaredLocals = new Set<String>(), |
182 declaredLocals = new Set<String>(), | |
183 collectedVariableDeclarations = new Set<String>(), | 226 collectedVariableDeclarations = new Set<String>(), |
184 currentContainer = new js.Block.empty(), | 227 currentContainer = new js.Block.empty(), |
185 parameters = <js.Parameter>[], | 228 parameters = <js.Parameter>[], |
186 expressionStack = <js.Expression>[], | 229 expressionStack = <js.Expression>[], |
187 oldContainerStack = <js.Block>[], | 230 oldContainerStack = <js.Block>[], |
188 generateAtUseSite = new Set<HInstruction>(), | 231 generateAtUseSite = new Set<HInstruction>(), |
189 controlFlowOperators = new Set<HInstruction>(), | 232 controlFlowOperators = new Set<HInstruction>(), |
190 breakAction = new Map<Entity, EntityAction>(), | 233 breakAction = new Map<Entity, EntityAction>(), |
191 continueAction = new Map<Entity, EntityAction>(); | 234 continueAction = new Map<Entity, EntityAction>(); |
192 | 235 |
193 Compiler get compiler => backend.compiler; | 236 CodegenRegistry get _registry => _work.registry; |
194 | 237 |
195 NativeEmitter get nativeEmitter => backend.emitter.nativeEmitter; | 238 CommonElements get _commonElements => _closedWorld.commonElements; |
196 | 239 |
197 CodegenRegistry get registry => work.registry; | 240 ConstantSystem get _constantSystem => _closedWorld.constantSystem; |
198 | |
199 BackendHelpers get helpers => backend.helpers; | |
200 | |
201 native.NativeCodegenEnqueuer get nativeEnqueuer { | |
202 return backend.nativeCodegenEnqueuer; | |
203 } | |
204 | |
205 DiagnosticReporter get reporter => compiler.reporter; | |
206 | |
207 CommonElements get commonElements => closedWorld.commonElements; | |
208 | 241 |
209 bool isGenerateAtUseSite(HInstruction instruction) { | 242 bool isGenerateAtUseSite(HInstruction instruction) { |
210 return generateAtUseSite.contains(instruction); | 243 return generateAtUseSite.contains(instruction); |
211 } | 244 } |
212 | 245 |
213 bool hasNonBitOpUser(HInstruction instruction, Set<HPhi> phiSet) { | 246 bool hasNonBitOpUser(HInstruction instruction, Set<HPhi> phiSet) { |
214 for (HInstruction user in instruction.usedBy) { | 247 for (HInstruction user in instruction.usedBy) { |
215 if (user is HPhi) { | 248 if (user is HPhi) { |
216 if (!phiSet.contains(user)) { | 249 if (!phiSet.contains(user)) { |
217 phiSet.add(user); | 250 phiSet.add(user); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 } | 301 } |
269 if (instruction is HAdd) { | 302 if (instruction is HAdd) { |
270 return math.min( | 303 return math.min( |
271 1 + math.max(bitWidth(instruction.left), bitWidth(instruction.right)), | 304 1 + math.max(bitWidth(instruction.left), bitWidth(instruction.right)), |
272 MAX); | 305 MAX); |
273 } | 306 } |
274 return MAX; | 307 return MAX; |
275 } | 308 } |
276 | 309 |
277 bool requiresUintConversion(HInstruction instruction) { | 310 bool requiresUintConversion(HInstruction instruction) { |
278 if (instruction.isUInt31(closedWorld)) return false; | 311 if (instruction.isUInt31(_closedWorld)) return false; |
279 if (bitWidth(instruction) <= 31) return false; | 312 if (bitWidth(instruction) <= 31) return false; |
280 // If the result of a bit-operation is only used by other bit | 313 // If the result of a bit-operation is only used by other bit |
281 // operations, we do not have to convert to an unsigned integer. | 314 // operations, we do not have to convert to an unsigned integer. |
282 return hasNonBitOpUser(instruction, new Set<HPhi>()); | 315 return hasNonBitOpUser(instruction, new Set<HPhi>()); |
283 } | 316 } |
284 | 317 |
285 /** | 318 /** |
286 * If the [instruction] is not `null` it will be used to attach the position | 319 * If the [instruction] is not `null` it will be used to attach the position |
287 * to the [statement]. | 320 * to the [statement]. |
288 */ | 321 */ |
(...skipping 22 matching lines...) Expand all Loading... |
311 */ | 344 */ |
312 push(js.Expression expression) { | 345 push(js.Expression expression) { |
313 expressionStack.add(expression); | 346 expressionStack.add(expression); |
314 } | 347 } |
315 | 348 |
316 js.Expression pop() { | 349 js.Expression pop() { |
317 return expressionStack.removeLast(); | 350 return expressionStack.removeLast(); |
318 } | 351 } |
319 | 352 |
320 void preGenerateMethod(HGraph graph) { | 353 void preGenerateMethod(HGraph graph) { |
321 new SsaInstructionSelection(closedWorld, backend.interceptorData) | 354 new SsaInstructionSelection(_closedWorld, _interceptorData) |
322 .visitGraph(graph); | 355 .visitGraph(graph); |
323 new SsaTypeKnownRemover().visitGraph(graph); | 356 new SsaTypeKnownRemover().visitGraph(graph); |
324 new SsaTrustedCheckRemover(compiler.options).visitGraph(graph); | 357 new SsaTrustedCheckRemover(_options).visitGraph(graph); |
325 new SsaInstructionMerger(generateAtUseSite, backend.superMemberData) | 358 new SsaInstructionMerger(generateAtUseSite, _superMemberData) |
326 .visitGraph(graph); | 359 .visitGraph(graph); |
327 new SsaConditionMerger(generateAtUseSite, controlFlowOperators) | 360 new SsaConditionMerger(generateAtUseSite, controlFlowOperators) |
328 .visitGraph(graph); | 361 .visitGraph(graph); |
329 SsaLiveIntervalBuilder intervalBuilder = | 362 SsaLiveIntervalBuilder intervalBuilder = |
330 new SsaLiveIntervalBuilder(generateAtUseSite, controlFlowOperators); | 363 new SsaLiveIntervalBuilder(generateAtUseSite, controlFlowOperators); |
331 intervalBuilder.visitGraph(graph); | 364 intervalBuilder.visitGraph(graph); |
332 SsaVariableAllocator allocator = new SsaVariableAllocator( | 365 SsaVariableAllocator allocator = new SsaVariableAllocator( |
333 backend.namer, | 366 _namer, |
334 intervalBuilder.liveInstructions, | 367 intervalBuilder.liveInstructions, |
335 intervalBuilder.liveIntervals, | 368 intervalBuilder.liveIntervals, |
336 generateAtUseSite); | 369 generateAtUseSite); |
337 allocator.visitGraph(graph); | 370 allocator.visitGraph(graph); |
338 variableNames = allocator.names; | 371 variableNames = allocator.names; |
339 shouldGroupVarDeclarations = allocator.names.numberOfVariables > 1; | 372 shouldGroupVarDeclarations = allocator.names.numberOfVariables > 1; |
340 } | 373 } |
341 | 374 |
342 void handleDelayedVariableDeclarations(SourceInformation sourceInformation) { | 375 void handleDelayedVariableDeclarations(SourceInformation sourceInformation) { |
343 // If we have only one variable declaration and the first statement is an | 376 // If we have only one variable declaration and the first statement is an |
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
687 assert(!isGeneratingExpression); | 720 assert(!isGeneratingExpression); |
688 visit(node); | 721 visit(node); |
689 if (!expressionStack.isEmpty) { | 722 if (!expressionStack.isEmpty) { |
690 assert(expressionStack.length == 1); | 723 assert(expressionStack.length == 1); |
691 js.Expression expression = pop(); | 724 js.Expression expression = pop(); |
692 pushExpressionAsStatement(expression, node.sourceInformation); | 725 pushExpressionAsStatement(expression, node.sourceInformation); |
693 } | 726 } |
694 } | 727 } |
695 | 728 |
696 void continueAsBreak(LabelDefinition target) { | 729 void continueAsBreak(LabelDefinition target) { |
697 pushStatement(new js.Break(backend.namer.continueLabelName(target))); | 730 pushStatement(new js.Break(_namer.continueLabelName(target))); |
698 } | 731 } |
699 | 732 |
700 void implicitContinueAsBreak(JumpTarget target) { | 733 void implicitContinueAsBreak(JumpTarget target) { |
701 pushStatement( | 734 pushStatement(new js.Break(_namer.implicitContinueLabelName(target))); |
702 new js.Break(backend.namer.implicitContinueLabelName(target))); | |
703 } | 735 } |
704 | 736 |
705 void implicitBreakWithLabel(JumpTarget target) { | 737 void implicitBreakWithLabel(JumpTarget target) { |
706 pushStatement(new js.Break(backend.namer.implicitBreakLabelName(target))); | 738 pushStatement(new js.Break(_namer.implicitBreakLabelName(target))); |
707 } | 739 } |
708 | 740 |
709 js.Statement wrapIntoLabels( | 741 js.Statement wrapIntoLabels( |
710 js.Statement result, List<LabelDefinition> labels) { | 742 js.Statement result, List<LabelDefinition> labels) { |
711 for (LabelDefinition label in labels) { | 743 for (LabelDefinition label in labels) { |
712 if (label.isTarget) { | 744 if (label.isTarget) { |
713 String breakLabelString = backend.namer.breakLabelName(label); | 745 String breakLabelString = _namer.breakLabelName(label); |
714 result = new js.LabeledStatement(breakLabelString, result); | 746 result = new js.LabeledStatement(breakLabelString, result); |
715 } | 747 } |
716 } | 748 } |
717 return result; | 749 return result; |
718 } | 750 } |
719 | 751 |
720 // The regular [visitIf] method implements the needed logic. | 752 // The regular [visitIf] method implements the needed logic. |
721 bool visitIfInfo(HIfBlockInformation info) => false; | 753 bool visitIfInfo(HIfBlockInformation info) => false; |
722 | 754 |
723 bool visitSwitchInfo(HSwitchBlockInformation info) { | 755 bool visitSwitchInfo(HSwitchBlockInformation info) { |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
798 return false; | 830 return false; |
799 } | 831 } |
800 | 832 |
801 bool visitTryInfo(HTryBlockInformation info) { | 833 bool visitTryInfo(HTryBlockInformation info) { |
802 js.Block body = generateStatementsInNewBlock(info.body); | 834 js.Block body = generateStatementsInNewBlock(info.body); |
803 js.Catch catchPart = null; | 835 js.Catch catchPart = null; |
804 js.Block finallyPart = null; | 836 js.Block finallyPart = null; |
805 if (info.catchBlock != null) { | 837 if (info.catchBlock != null) { |
806 void register(ClassEntity classElement) { | 838 void register(ClassEntity classElement) { |
807 if (classElement != null) { | 839 if (classElement != null) { |
808 registry.registerInstantiatedClass(classElement); | 840 _registry.registerInstantiatedClass(classElement); |
809 } | 841 } |
810 } | 842 } |
811 | 843 |
812 register(helpers.jsPlainJavaScriptObjectClass); | 844 register(_helpers.jsPlainJavaScriptObjectClass); |
813 register(helpers.jsUnknownJavaScriptObjectClass); | 845 register(_helpers.jsUnknownJavaScriptObjectClass); |
814 | 846 |
815 HLocalValue exception = info.catchVariable; | 847 HLocalValue exception = info.catchVariable; |
816 String name = variableNames.getName(exception); | 848 String name = variableNames.getName(exception); |
817 js.VariableDeclaration decl = new js.VariableDeclaration(name); | 849 js.VariableDeclaration decl = new js.VariableDeclaration(name); |
818 js.Block catchBlock = generateStatementsInNewBlock(info.catchBlock); | 850 js.Block catchBlock = generateStatementsInNewBlock(info.catchBlock); |
819 catchPart = new js.Catch(decl, catchBlock); | 851 catchPart = new js.Catch(decl, catchBlock); |
820 } | 852 } |
821 if (info.finallyBlock != null) { | 853 if (info.finallyBlock != null) { |
822 finallyPart = generateStatementsInNewBlock(info.finallyBlock); | 854 finallyPart = generateStatementsInNewBlock(info.finallyBlock); |
823 } | 855 } |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1036 } | 1068 } |
1037 body.statements.add(new js.If(jsCondition, updateBody, exitLoop)); | 1069 body.statements.add(new js.If(jsCondition, updateBody, exitLoop)); |
1038 jsCondition = newLiteralBool(true, info.sourceInformation); | 1070 jsCondition = newLiteralBool(true, info.sourceInformation); |
1039 } | 1071 } |
1040 loop = new js.Do(unwrapStatement(body), jsCondition) | 1072 loop = new js.Do(unwrapStatement(body), jsCondition) |
1041 .withSourceInformation(info.sourceInformation); | 1073 .withSourceInformation(info.sourceInformation); |
1042 } | 1074 } |
1043 currentContainer = oldContainer; | 1075 currentContainer = oldContainer; |
1044 break; | 1076 break; |
1045 default: | 1077 default: |
1046 reporter.internalError(condition.conditionExpression, | 1078 throw new SpannableAssertionFailure(condition.conditionExpression, |
1047 'Unexpected loop kind: ${info.kind}.'); | 1079 'Unexpected loop kind: ${info.kind}.'); |
1048 } | 1080 } |
1049 js.Statement result = loop; | 1081 js.Statement result = loop; |
1050 if (info.kind == HLoopBlockInformation.SWITCH_CONTINUE_LOOP) { | 1082 if (info.kind == HLoopBlockInformation.SWITCH_CONTINUE_LOOP) { |
1051 String continueLabelString = | 1083 String continueLabelString = |
1052 backend.namer.implicitContinueLabelName(info.target); | 1084 _namer.implicitContinueLabelName(info.target); |
1053 result = new js.LabeledStatement(continueLabelString, result); | 1085 result = new js.LabeledStatement(continueLabelString, result); |
1054 } | 1086 } |
1055 pushStatement(wrapIntoLabels(result, info.labels)); | 1087 pushStatement(wrapIntoLabels(result, info.labels)); |
1056 return true; | 1088 return true; |
1057 } | 1089 } |
1058 | 1090 |
1059 bool visitLabeledBlockInfo(HLabeledBlockInformation labeledBlockInfo) { | 1091 bool visitLabeledBlockInfo(HLabeledBlockInformation labeledBlockInfo) { |
1060 Link<Entity> continueOverrides = const Link<Entity>(); | 1092 Link<Entity> continueOverrides = const Link<Entity>(); |
1061 | 1093 |
1062 js.Block oldContainer = currentContainer; | 1094 js.Block oldContainer = currentContainer; |
1063 js.Block body = new js.Block.empty(); | 1095 js.Block body = new js.Block.empty(); |
1064 js.Statement result = body; | 1096 js.Statement result = body; |
1065 | 1097 |
1066 currentContainer = body; | 1098 currentContainer = body; |
1067 | 1099 |
1068 // If [labeledBlockInfo.isContinue], the block is an artificial | 1100 // If [labeledBlockInfo.isContinue], the block is an artificial |
1069 // block around the body of a loop with an update block, so that | 1101 // block around the body of a loop with an update block, so that |
1070 // continues of the loop can be written as breaks of the body | 1102 // continues of the loop can be written as breaks of the body |
1071 // block. | 1103 // block. |
1072 if (labeledBlockInfo.isContinue) { | 1104 if (labeledBlockInfo.isContinue) { |
1073 for (LabelDefinition label in labeledBlockInfo.labels) { | 1105 for (LabelDefinition label in labeledBlockInfo.labels) { |
1074 if (label.isContinueTarget) { | 1106 if (label.isContinueTarget) { |
1075 String labelName = backend.namer.continueLabelName(label); | 1107 String labelName = _namer.continueLabelName(label); |
1076 result = new js.LabeledStatement(labelName, result); | 1108 result = new js.LabeledStatement(labelName, result); |
1077 continueAction[label] = continueAsBreak; | 1109 continueAction[label] = continueAsBreak; |
1078 continueOverrides = continueOverrides.prepend(label); | 1110 continueOverrides = continueOverrides.prepend(label); |
1079 } | 1111 } |
1080 } | 1112 } |
1081 // For handling unlabeled continues from the body of a loop. | 1113 // For handling unlabeled continues from the body of a loop. |
1082 // TODO(lrn): Consider recording whether the target is in fact | 1114 // TODO(lrn): Consider recording whether the target is in fact |
1083 // a target of an unlabeled continue, and not generate this if it isn't. | 1115 // a target of an unlabeled continue, and not generate this if it isn't. |
1084 JumpTarget target = labeledBlockInfo.target; | 1116 JumpTarget target = labeledBlockInfo.target; |
1085 String labelName = backend.namer.implicitContinueLabelName(target); | 1117 String labelName = _namer.implicitContinueLabelName(target); |
1086 result = new js.LabeledStatement(labelName, result); | 1118 result = new js.LabeledStatement(labelName, result); |
1087 continueAction[target] = implicitContinueAsBreak; | 1119 continueAction[target] = implicitContinueAsBreak; |
1088 continueOverrides = continueOverrides.prepend(target); | 1120 continueOverrides = continueOverrides.prepend(target); |
1089 } else { | 1121 } else { |
1090 for (LabelDefinition label in labeledBlockInfo.labels) { | 1122 for (LabelDefinition label in labeledBlockInfo.labels) { |
1091 if (label.isBreakTarget) { | 1123 if (label.isBreakTarget) { |
1092 String labelName = backend.namer.breakLabelName(label); | 1124 String labelName = _namer.breakLabelName(label); |
1093 result = new js.LabeledStatement(labelName, result); | 1125 result = new js.LabeledStatement(labelName, result); |
1094 } | 1126 } |
1095 } | 1127 } |
1096 } | 1128 } |
1097 JumpTarget target = labeledBlockInfo.target; | 1129 JumpTarget target = labeledBlockInfo.target; |
1098 if (target.isSwitch) { | 1130 if (target.isSwitch) { |
1099 // This is an extra block around a switch that is generated | 1131 // This is an extra block around a switch that is generated |
1100 // as a nested if/else chain. We add an extra break target | 1132 // as a nested if/else chain. We add an extra break target |
1101 // so that case code can break. | 1133 // so that case code can break. |
1102 String labelName = backend.namer.implicitBreakLabelName(target); | 1134 String labelName = _namer.implicitBreakLabelName(target); |
1103 result = new js.LabeledStatement(labelName, result); | 1135 result = new js.LabeledStatement(labelName, result); |
1104 breakAction[target] = implicitBreakWithLabel; | 1136 breakAction[target] = implicitBreakWithLabel; |
1105 } | 1137 } |
1106 | 1138 |
1107 currentContainer = body; | 1139 currentContainer = body; |
1108 generateStatements(labeledBlockInfo.body); | 1140 generateStatements(labeledBlockInfo.body); |
1109 | 1141 |
1110 if (labeledBlockInfo.isContinue) { | 1142 if (labeledBlockInfo.isContinue) { |
1111 while (!continueOverrides.isEmpty) { | 1143 while (!continueOverrides.isEmpty) { |
1112 continueAction.remove(continueOverrides.head); | 1144 continueAction.remove(continueOverrides.head); |
(...skipping 12 matching lines...) Expand all Loading... |
1125 // to (if necessary). | 1157 // to (if necessary). |
1126 void wrapLoopBodyForContinue(HLoopBlockInformation info) { | 1158 void wrapLoopBodyForContinue(HLoopBlockInformation info) { |
1127 JumpTarget target = info.target; | 1159 JumpTarget target = info.target; |
1128 if (target != null && target.isContinueTarget) { | 1160 if (target != null && target.isContinueTarget) { |
1129 js.Block oldContainer = currentContainer; | 1161 js.Block oldContainer = currentContainer; |
1130 js.Block body = new js.Block.empty(); | 1162 js.Block body = new js.Block.empty(); |
1131 currentContainer = body; | 1163 currentContainer = body; |
1132 js.Statement result = body; | 1164 js.Statement result = body; |
1133 for (LabelDefinition label in info.labels) { | 1165 for (LabelDefinition label in info.labels) { |
1134 if (label.isContinueTarget) { | 1166 if (label.isContinueTarget) { |
1135 String labelName = backend.namer.continueLabelName(label); | 1167 String labelName = _namer.continueLabelName(label); |
1136 result = new js.LabeledStatement(labelName, result); | 1168 result = new js.LabeledStatement(labelName, result); |
1137 continueAction[label] = continueAsBreak; | 1169 continueAction[label] = continueAsBreak; |
1138 } | 1170 } |
1139 } | 1171 } |
1140 String labelName = backend.namer.implicitContinueLabelName(target); | 1172 String labelName = _namer.implicitContinueLabelName(target); |
1141 result = new js.LabeledStatement(labelName, result); | 1173 result = new js.LabeledStatement(labelName, result); |
1142 continueAction[info.target] = implicitContinueAsBreak; | 1174 continueAction[info.target] = implicitContinueAsBreak; |
1143 visitBodyIgnoreLabels(info); | 1175 visitBodyIgnoreLabels(info); |
1144 continueAction.remove(info.target); | 1176 continueAction.remove(info.target); |
1145 for (LabelDefinition label in info.labels) { | 1177 for (LabelDefinition label in info.labels) { |
1146 if (label.isContinueTarget) { | 1178 if (label.isContinueTarget) { |
1147 continueAction.remove(label); | 1179 continueAction.remove(label); |
1148 } | 1180 } |
1149 } | 1181 } |
1150 currentContainer = oldContainer; | 1182 currentContainer = oldContainer; |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1389 visitMultiply(HMultiply node) => visitInvokeBinary(node, '*'); | 1421 visitMultiply(HMultiply node) => visitInvokeBinary(node, '*'); |
1390 visitSubtract(HSubtract node) => visitInvokeBinary(node, '-'); | 1422 visitSubtract(HSubtract node) => visitInvokeBinary(node, '-'); |
1391 visitBitAnd(HBitAnd node) => visitBitInvokeBinary(node, '&'); | 1423 visitBitAnd(HBitAnd node) => visitBitInvokeBinary(node, '&'); |
1392 visitBitNot(HBitNot node) => visitBitInvokeUnary(node, '~'); | 1424 visitBitNot(HBitNot node) => visitBitInvokeUnary(node, '~'); |
1393 visitBitOr(HBitOr node) => visitBitInvokeBinary(node, '|'); | 1425 visitBitOr(HBitOr node) => visitBitInvokeBinary(node, '|'); |
1394 visitBitXor(HBitXor node) => visitBitInvokeBinary(node, '^'); | 1426 visitBitXor(HBitXor node) => visitBitInvokeBinary(node, '^'); |
1395 visitShiftLeft(HShiftLeft node) => visitBitInvokeBinary(node, '<<'); | 1427 visitShiftLeft(HShiftLeft node) => visitBitInvokeBinary(node, '<<'); |
1396 visitShiftRight(HShiftRight node) => visitBitInvokeBinary(node, '>>>'); | 1428 visitShiftRight(HShiftRight node) => visitBitInvokeBinary(node, '>>>'); |
1397 | 1429 |
1398 visitTruncatingDivide(HTruncatingDivide node) { | 1430 visitTruncatingDivide(HTruncatingDivide node) { |
1399 assert(node.isUInt31(closedWorld)); | 1431 assert(node.isUInt31(_closedWorld)); |
1400 // TODO(karlklose): Enable this assertion again when type propagation is | 1432 // TODO(karlklose): Enable this assertion again when type propagation is |
1401 // fixed. Issue 23555. | 1433 // fixed. Issue 23555. |
1402 // assert(node.left.isUInt32(compiler)); | 1434 // assert(node.left.isUInt32(compiler)); |
1403 assert(node.right.isPositiveInteger(closedWorld)); | 1435 assert(node.right.isPositiveInteger(_closedWorld)); |
1404 use(node.left); | 1436 use(node.left); |
1405 js.Expression jsLeft = pop(); | 1437 js.Expression jsLeft = pop(); |
1406 use(node.right); | 1438 use(node.right); |
1407 push(new js.Binary('/', jsLeft, pop()) | 1439 push(new js.Binary('/', jsLeft, pop()) |
1408 .withSourceInformation(node.sourceInformation)); | 1440 .withSourceInformation(node.sourceInformation)); |
1409 push(new js.Binary('|', pop(), new js.LiteralNumber("0")) | 1441 push(new js.Binary('|', pop(), new js.LiteralNumber("0")) |
1410 .withSourceInformation(node.sourceInformation)); | 1442 .withSourceInformation(node.sourceInformation)); |
1411 } | 1443 } |
1412 | 1444 |
1413 visitRemainder(HRemainder node) { | 1445 visitRemainder(HRemainder node) { |
(...skipping 23 matching lines...) Expand all Loading... |
1437 HBasicBlock block = node.block; | 1469 HBasicBlock block = node.block; |
1438 assert(block.successors.length == 1); | 1470 assert(block.successors.length == 1); |
1439 List<HBasicBlock> dominated = block.dominatedBlocks; | 1471 List<HBasicBlock> dominated = block.dominatedBlocks; |
1440 // With the exception of the entry-node which dominates its successor | 1472 // With the exception of the entry-node which dominates its successor |
1441 // and the exit node, no block finishing with a 'goto' can have more than | 1473 // and the exit node, no block finishing with a 'goto' can have more than |
1442 // one dominated block (since it has only one successor). | 1474 // one dominated block (since it has only one successor). |
1443 // If the successor is dominated by another block, then the other block | 1475 // If the successor is dominated by another block, then the other block |
1444 // is responsible for visiting the successor. | 1476 // is responsible for visiting the successor. |
1445 if (dominated.isEmpty) return; | 1477 if (dominated.isEmpty) return; |
1446 if (dominated.length > 2) { | 1478 if (dominated.length > 2) { |
1447 reporter.internalError(node, 'dominated.length = ${dominated.length}'); | 1479 throw new SpannableAssertionFailure( |
| 1480 node, 'dominated.length = ${dominated.length}'); |
1448 } | 1481 } |
1449 if (dominated.length == 2 && block != currentGraph.entry) { | 1482 if (dominated.length == 2 && block != currentGraph.entry) { |
1450 reporter.internalError(node, 'node.block != currentGraph.entry'); | 1483 throw new SpannableAssertionFailure( |
| 1484 node, 'node.block != currentGraph.entry'); |
1451 } | 1485 } |
1452 assert(dominated[0] == block.successors[0]); | 1486 assert(dominated[0] == block.successors[0]); |
1453 visitBasicBlock(dominated[0]); | 1487 visitBasicBlock(dominated[0]); |
1454 } | 1488 } |
1455 | 1489 |
1456 visitLoopBranch(HLoopBranch node) { | 1490 visitLoopBranch(HLoopBranch node) { |
1457 assert(node.block == subGraph.end); | 1491 assert(node.block == subGraph.end); |
1458 // We are generating code for a loop condition. | 1492 // We are generating code for a loop condition. |
1459 // If we are generating the subgraph as an expression, the | 1493 // If we are generating the subgraph as an expression, the |
1460 // condition will be generated as the expression. | 1494 // condition will be generated as the expression. |
(...skipping 14 matching lines...) Expand all Loading... |
1475 if (action == null) return false; | 1509 if (action == null) return false; |
1476 action(entity); | 1510 action(entity); |
1477 return true; | 1511 return true; |
1478 } | 1512 } |
1479 | 1513 |
1480 visitBreak(HBreak node) { | 1514 visitBreak(HBreak node) { |
1481 assert(node.block.successors.length == 1); | 1515 assert(node.block.successors.length == 1); |
1482 if (node.label != null) { | 1516 if (node.label != null) { |
1483 LabelDefinition label = node.label; | 1517 LabelDefinition label = node.label; |
1484 if (!tryCallAction(breakAction, label)) { | 1518 if (!tryCallAction(breakAction, label)) { |
1485 pushStatement(new js.Break(backend.namer.breakLabelName(label)) | 1519 pushStatement(new js.Break(_namer.breakLabelName(label)) |
1486 .withSourceInformation(node.sourceInformation)); | 1520 .withSourceInformation(node.sourceInformation)); |
1487 } | 1521 } |
1488 } else { | 1522 } else { |
1489 JumpTarget target = node.target; | 1523 JumpTarget target = node.target; |
1490 if (!tryCallAction(breakAction, target)) { | 1524 if (!tryCallAction(breakAction, target)) { |
1491 if (node.breakSwitchContinueLoop) { | 1525 if (node.breakSwitchContinueLoop) { |
1492 pushStatement( | 1526 pushStatement(new js.Break(_namer.implicitContinueLabelName(target)) |
1493 new js.Break(backend.namer.implicitContinueLabelName(target)) | 1527 .withSourceInformation(node.sourceInformation)); |
1494 .withSourceInformation(node.sourceInformation)); | |
1495 } else { | 1528 } else { |
1496 pushStatement( | 1529 pushStatement( |
1497 new js.Break(null).withSourceInformation(node.sourceInformation)); | 1530 new js.Break(null).withSourceInformation(node.sourceInformation)); |
1498 } | 1531 } |
1499 } | 1532 } |
1500 } | 1533 } |
1501 } | 1534 } |
1502 | 1535 |
1503 visitContinue(HContinue node) { | 1536 visitContinue(HContinue node) { |
1504 assert(node.block.successors.length == 1); | 1537 assert(node.block.successors.length == 1); |
1505 if (node.label != null) { | 1538 if (node.label != null) { |
1506 LabelDefinition label = node.label; | 1539 LabelDefinition label = node.label; |
1507 if (!tryCallAction(continueAction, label)) { | 1540 if (!tryCallAction(continueAction, label)) { |
1508 // TODO(floitsch): should this really be the breakLabelName? | 1541 // TODO(floitsch): should this really be the breakLabelName? |
1509 pushStatement(new js.Continue(backend.namer.breakLabelName(label)) | 1542 pushStatement(new js.Continue(_namer.breakLabelName(label)) |
1510 .withSourceInformation(node.sourceInformation)); | 1543 .withSourceInformation(node.sourceInformation)); |
1511 } | 1544 } |
1512 } else { | 1545 } else { |
1513 JumpTarget target = node.target; | 1546 JumpTarget target = node.target; |
1514 if (!tryCallAction(continueAction, target)) { | 1547 if (!tryCallAction(continueAction, target)) { |
1515 if (target.isSwitch) { | 1548 if (target.isSwitch) { |
1516 pushStatement( | 1549 pushStatement( |
1517 new js.Continue(backend.namer.implicitContinueLabelName(target)) | 1550 new js.Continue(_namer.implicitContinueLabelName(target)) |
1518 .withSourceInformation(node.sourceInformation)); | 1551 .withSourceInformation(node.sourceInformation)); |
1519 } else { | 1552 } else { |
1520 pushStatement(new js.Continue(null) | 1553 pushStatement(new js.Continue(null) |
1521 .withSourceInformation(node.sourceInformation)); | 1554 .withSourceInformation(node.sourceInformation)); |
1522 } | 1555 } |
1523 } | 1556 } |
1524 } | 1557 } |
1525 } | 1558 } |
1526 | 1559 |
1527 visitExitTry(HExitTry node) { | 1560 visitExitTry(HExitTry node) { |
1528 // An [HExitTry] is used to represent the control flow graph of a | 1561 // An [HExitTry] is used to represent the control flow graph of a |
1529 // try/catch block, ie the try body is always a predecessor | 1562 // try/catch block, ie the try body is always a predecessor |
1530 // of the catch and finally. Here, we continue visiting the try | 1563 // of the catch and finally. Here, we continue visiting the try |
1531 // body by visiting the block that contains the user-level control | 1564 // body by visiting the block that contains the user-level control |
1532 // flow instruction. | 1565 // flow instruction. |
1533 visitBasicBlock(node.bodyTrySuccessor); | 1566 visitBasicBlock(node.bodyTrySuccessor); |
1534 } | 1567 } |
1535 | 1568 |
1536 visitTry(HTry node) { | 1569 visitTry(HTry node) { |
1537 // We should never get here. Try/catch/finally is always handled using block | 1570 // We should never get here. Try/catch/finally is always handled using block |
1538 // information in [visitTryInfo]. | 1571 // information in [visitTryInfo]. |
1539 reporter.internalError(node, 'visitTry should not be called.'); | 1572 throw new SpannableAssertionFailure(node, 'visitTry should not be called.'); |
1540 } | 1573 } |
1541 | 1574 |
1542 bool tryControlFlowOperation(HIf node) { | 1575 bool tryControlFlowOperation(HIf node) { |
1543 if (!controlFlowOperators.contains(node)) return false; | 1576 if (!controlFlowOperators.contains(node)) return false; |
1544 HPhi phi = node.joinBlock.phis.first; | 1577 HPhi phi = node.joinBlock.phis.first; |
1545 bool atUseSite = isGenerateAtUseSite(phi); | 1578 bool atUseSite = isGenerateAtUseSite(phi); |
1546 // Don't generate a conditional operator in this situation: | 1579 // Don't generate a conditional operator in this situation: |
1547 // i = condition ? bar() : i; | 1580 // i = condition ? bar() : i; |
1548 // But generate this instead: | 1581 // But generate this instead: |
1549 // if (condition) i = bar(); | 1582 // if (condition) i = bar(); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1628 void visitInterceptor(HInterceptor node) { | 1661 void visitInterceptor(HInterceptor node) { |
1629 if (node.isConditionalConstantInterceptor) { | 1662 if (node.isConditionalConstantInterceptor) { |
1630 assert(node.inputs.length == 2); | 1663 assert(node.inputs.length == 2); |
1631 use(node.receiver); | 1664 use(node.receiver); |
1632 js.Expression receiverExpression = pop(); | 1665 js.Expression receiverExpression = pop(); |
1633 use(node.conditionalConstantInterceptor); | 1666 use(node.conditionalConstantInterceptor); |
1634 js.Expression constant = pop(); | 1667 js.Expression constant = pop(); |
1635 push(js.js('# && #', [receiverExpression, constant])); | 1668 push(js.js('# && #', [receiverExpression, constant])); |
1636 } else { | 1669 } else { |
1637 assert(node.inputs.length == 1); | 1670 assert(node.inputs.length == 1); |
1638 registry.registerSpecializedGetInterceptor(node.interceptedClasses); | 1671 _registry.registerSpecializedGetInterceptor(node.interceptedClasses); |
1639 js.Name name = | 1672 js.Name name = _namer.nameForGetInterceptor(node.interceptedClasses); |
1640 backend.namer.nameForGetInterceptor(node.interceptedClasses); | |
1641 var isolate = new js.VariableUse( | 1673 var isolate = new js.VariableUse( |
1642 backend.namer.globalObjectForLibrary(helpers.interceptorsLibrary)); | 1674 _namer.globalObjectForLibrary(_helpers.interceptorsLibrary)); |
1643 use(node.receiver); | 1675 use(node.receiver); |
1644 List<js.Expression> arguments = <js.Expression>[pop()]; | 1676 List<js.Expression> arguments = <js.Expression>[pop()]; |
1645 push(js | 1677 push(js |
1646 .propertyCall(isolate, name, arguments) | 1678 .propertyCall(isolate, name, arguments) |
1647 .withSourceInformation(node.sourceInformation)); | 1679 .withSourceInformation(node.sourceInformation)); |
1648 registry.registerUseInterceptor(); | 1680 _registry.registerUseInterceptor(); |
1649 } | 1681 } |
1650 } | 1682 } |
1651 | 1683 |
1652 visitInvokeDynamicMethod(HInvokeDynamicMethod node) { | 1684 visitInvokeDynamicMethod(HInvokeDynamicMethod node) { |
1653 use(node.receiver); | 1685 use(node.receiver); |
1654 js.Expression object = pop(); | 1686 js.Expression object = pop(); |
1655 String methodName; | 1687 String methodName; |
1656 List<js.Expression> arguments = visitArguments(node.inputs); | 1688 List<js.Expression> arguments = visitArguments(node.inputs); |
1657 MemberEntity target = node.element; | 1689 MemberEntity target = node.element; |
1658 | 1690 |
1659 // TODO(herhut): The namer should return the appropriate backendname here. | 1691 // TODO(herhut): The namer should return the appropriate backendname here. |
1660 if (target != null && !node.isInterceptedCall) { | 1692 if (target != null && !node.isInterceptedCall) { |
1661 if (target == helpers.jsArrayAdd) { | 1693 if (target == _helpers.jsArrayAdd) { |
1662 methodName = 'push'; | 1694 methodName = 'push'; |
1663 } else if (target == helpers.jsArrayRemoveLast) { | 1695 } else if (target == _helpers.jsArrayRemoveLast) { |
1664 methodName = 'pop'; | 1696 methodName = 'pop'; |
1665 } else if (target == helpers.jsStringSplit) { | 1697 } else if (target == _helpers.jsStringSplit) { |
1666 methodName = 'split'; | 1698 methodName = 'split'; |
1667 // Split returns a List, so we make sure the backend knows the | 1699 // Split returns a List, so we make sure the backend knows the |
1668 // list class is instantiated. | 1700 // list class is instantiated. |
1669 registry.registerInstantiatedClass(commonElements.listClass); | 1701 _registry.registerInstantiatedClass(_commonElements.listClass); |
1670 } else if (backend.nativeData.isNativeMember(target) && | 1702 } else if (_nativeData.isNativeMember(target) && |
1671 target.isFunction && | 1703 target.isFunction && |
1672 !node.isInterceptedCall) { | 1704 !node.isInterceptedCall) { |
1673 // A direct (i.e. non-interceptor) native call is the result of | 1705 // A direct (i.e. non-interceptor) native call is the result of |
1674 // optimization. The optimization ensures any type checks or | 1706 // optimization. The optimization ensures any type checks or |
1675 // conversions have been satisified. | 1707 // conversions have been satisified. |
1676 methodName = backend.nativeData.getFixedBackendName(target); | 1708 methodName = _nativeData.getFixedBackendName(target); |
1677 } | 1709 } |
1678 } | 1710 } |
1679 | 1711 |
1680 js.Name methodLiteral; | 1712 js.Name methodLiteral; |
1681 if (methodName == null) { | 1713 if (methodName == null) { |
1682 methodLiteral = backend.namer.invocationName(node.selector); | 1714 methodLiteral = _namer.invocationName(node.selector); |
1683 registerMethodInvoke(node); | 1715 registerMethodInvoke(node); |
1684 } else { | 1716 } else { |
1685 methodLiteral = backend.namer.asName(methodName); | 1717 methodLiteral = _namer.asName(methodName); |
1686 } | 1718 } |
1687 push(js | 1719 push(js |
1688 .propertyCall(object, methodLiteral, arguments) | 1720 .propertyCall(object, methodLiteral, arguments) |
1689 .withSourceInformation(node.sourceInformation)); | 1721 .withSourceInformation(node.sourceInformation)); |
1690 } | 1722 } |
1691 | 1723 |
1692 void visitInvokeConstructorBody(HInvokeConstructorBody node) { | 1724 void visitInvokeConstructorBody(HInvokeConstructorBody node) { |
1693 use(node.inputs[0]); | 1725 use(node.inputs[0]); |
1694 js.Expression object = pop(); | 1726 js.Expression object = pop(); |
1695 js.Name methodName = backend.namer.instanceMethodName(node.element); | 1727 js.Name methodName = _namer.instanceMethodName(node.element); |
1696 List<js.Expression> arguments = visitArguments(node.inputs); | 1728 List<js.Expression> arguments = visitArguments(node.inputs); |
1697 push(js | 1729 push(js |
1698 .propertyCall(object, methodName, arguments) | 1730 .propertyCall(object, methodName, arguments) |
1699 .withSourceInformation(node.sourceInformation)); | 1731 .withSourceInformation(node.sourceInformation)); |
1700 registry.registerStaticUse(new StaticUse.constructorBodyInvoke( | 1732 _registry.registerStaticUse(new StaticUse.constructorBodyInvoke( |
1701 node.element, new CallStructure.unnamed(arguments.length))); | 1733 node.element, new CallStructure.unnamed(arguments.length))); |
1702 } | 1734 } |
1703 | 1735 |
1704 void visitOneShotInterceptor(HOneShotInterceptor node) { | 1736 void visitOneShotInterceptor(HOneShotInterceptor node) { |
1705 List<js.Expression> arguments = visitArguments(node.inputs); | 1737 List<js.Expression> arguments = visitArguments(node.inputs); |
1706 var isolate = new js.VariableUse( | 1738 var isolate = new js.VariableUse( |
1707 backend.namer.globalObjectForLibrary(helpers.interceptorsLibrary)); | 1739 _namer.globalObjectForLibrary(_helpers.interceptorsLibrary)); |
1708 Selector selector = node.selector; | 1740 Selector selector = node.selector; |
1709 js.Name methodName = backend.oneShotInterceptorData | 1741 js.Name methodName = |
1710 .registerOneShotInterceptor(selector, backend.namer); | 1742 _oneShotInterceptorData.registerOneShotInterceptor(selector, _namer); |
1711 push(js | 1743 push(js |
1712 .propertyCall(isolate, methodName, arguments) | 1744 .propertyCall(isolate, methodName, arguments) |
1713 .withSourceInformation(node.sourceInformation)); | 1745 .withSourceInformation(node.sourceInformation)); |
1714 if (selector.isGetter) { | 1746 if (selector.isGetter) { |
1715 registerGetter(node); | 1747 registerGetter(node); |
1716 } else if (selector.isSetter) { | 1748 } else if (selector.isSetter) { |
1717 registerSetter(node); | 1749 registerSetter(node); |
1718 } else { | 1750 } else { |
1719 registerMethodInvoke(node); | 1751 registerMethodInvoke(node); |
1720 } | 1752 } |
1721 registry.registerUseInterceptor(); | 1753 _registry.registerUseInterceptor(); |
1722 } | 1754 } |
1723 | 1755 |
1724 TypeMask getOptimizedSelectorFor( | 1756 TypeMask getOptimizedSelectorFor( |
1725 HInvokeDynamic node, Selector selector, TypeMask mask) { | 1757 HInvokeDynamic node, Selector selector, TypeMask mask) { |
1726 if (node.element != null) { | 1758 if (node.element != null) { |
1727 // Create an artificial type mask to make sure only | 1759 // Create an artificial type mask to make sure only |
1728 // [node.element] will be enqueued. We're not using the receiver | 1760 // [node.element] will be enqueued. We're not using the receiver |
1729 // type because our optimizations might end up in a state where the | 1761 // type because our optimizations might end up in a state where the |
1730 // invoke dynamic knows more than the receiver. | 1762 // invoke dynamic knows more than the receiver. |
1731 ClassEntity enclosing = node.element.enclosingClass; | 1763 ClassEntity enclosing = node.element.enclosingClass; |
1732 if (closedWorld.isInstantiated(enclosing)) { | 1764 if (_closedWorld.isInstantiated(enclosing)) { |
1733 return closedWorld.commonMasks.createNonNullExact(enclosing); | 1765 return _closedWorld.commonMasks.createNonNullExact(enclosing); |
1734 } else { | 1766 } else { |
1735 // The element is mixed in so a non-null subtype mask is the most | 1767 // The element is mixed in so a non-null subtype mask is the most |
1736 // precise we have. | 1768 // precise we have. |
1737 assert(invariant(node, closedWorld.isUsedAsMixin(enclosing), | 1769 assert(invariant(node, _closedWorld.isUsedAsMixin(enclosing), |
1738 message: "Element ${node.element} from $enclosing expected " | 1770 message: "Element ${node.element} from $enclosing expected " |
1739 "to be mixed in.")); | 1771 "to be mixed in.")); |
1740 return closedWorld.commonMasks.createNonNullSubtype(enclosing); | 1772 return _closedWorld.commonMasks.createNonNullSubtype(enclosing); |
1741 } | 1773 } |
1742 } | 1774 } |
1743 // If [JSInvocationMirror._invokeOn] is enabled, and this call | 1775 // If [JSInvocationMirror._invokeOn] is enabled, and this call |
1744 // might hit a `noSuchMethod`, we register an untyped selector. | 1776 // might hit a `noSuchMethod`, we register an untyped selector. |
1745 return closedWorld.extendMaskIfReachesAll(selector, mask); | 1777 return _closedWorld.extendMaskIfReachesAll(selector, mask); |
1746 } | 1778 } |
1747 | 1779 |
1748 void registerMethodInvoke(HInvokeDynamic node) { | 1780 void registerMethodInvoke(HInvokeDynamic node) { |
1749 Selector selector = node.selector; | 1781 Selector selector = node.selector; |
1750 | 1782 |
1751 // If we don't know what we're calling or if we are calling a getter, | 1783 // If we don't know what we're calling or if we are calling a getter, |
1752 // we need to register that fact that we may be calling a closure | 1784 // we need to register that fact that we may be calling a closure |
1753 // with the same arguments. | 1785 // with the same arguments. |
1754 MemberEntity target = node.element; | 1786 MemberEntity target = node.element; |
1755 if (target == null || target.isGetter) { | 1787 if (target == null || target.isGetter) { |
1756 // TODO(kasperl): If we have a typed selector for the call, we | 1788 // TODO(kasperl): If we have a typed selector for the call, we |
1757 // may know something about the types of closures that need | 1789 // may know something about the types of closures that need |
1758 // the specific closure call method. | 1790 // the specific closure call method. |
1759 Selector call = new Selector.callClosureFrom(selector); | 1791 Selector call = new Selector.callClosureFrom(selector); |
1760 registry.registerDynamicUse(new DynamicUse(call, null)); | 1792 _registry.registerDynamicUse(new DynamicUse(call, null)); |
1761 } | 1793 } |
1762 if (target != null) { | 1794 if (target != null) { |
1763 // This is a dynamic invocation which we have found to have a single | 1795 // This is a dynamic invocation which we have found to have a single |
1764 // target but for some reason haven't inlined. We are _still_ accessing | 1796 // target but for some reason haven't inlined. We are _still_ accessing |
1765 // the target dynamically but we don't need to enqueue more than target | 1797 // the target dynamically but we don't need to enqueue more than target |
1766 // for this to work. | 1798 // for this to work. |
1767 assert(invariant(node, selector.applies(target), | 1799 assert(invariant(node, selector.applies(target), |
1768 message: '$selector does not apply to $target')); | 1800 message: '$selector does not apply to $target')); |
1769 registry.registerStaticUse( | 1801 _registry.registerStaticUse( |
1770 new StaticUse.directInvoke(target, selector.callStructure)); | 1802 new StaticUse.directInvoke(target, selector.callStructure)); |
1771 } else { | 1803 } else { |
1772 TypeMask mask = getOptimizedSelectorFor(node, selector, node.mask); | 1804 TypeMask mask = getOptimizedSelectorFor(node, selector, node.mask); |
1773 registry.registerDynamicUse(new DynamicUse(selector, mask)); | 1805 _registry.registerDynamicUse(new DynamicUse(selector, mask)); |
1774 } | 1806 } |
1775 } | 1807 } |
1776 | 1808 |
1777 void registerSetter(HInvokeDynamic node) { | 1809 void registerSetter(HInvokeDynamic node) { |
1778 if (node.element != null) { | 1810 if (node.element != null) { |
1779 // This is a dynamic update which we have found to have a single | 1811 // This is a dynamic update which we have found to have a single |
1780 // target but for some reason haven't inlined. We are _still_ accessing | 1812 // target but for some reason haven't inlined. We are _still_ accessing |
1781 // the target dynamically but we don't need to enqueue more than target | 1813 // the target dynamically but we don't need to enqueue more than target |
1782 // for this to work. | 1814 // for this to work. |
1783 registry.registerStaticUse(new StaticUse.directSet(node.element)); | 1815 _registry.registerStaticUse(new StaticUse.directSet(node.element)); |
1784 } else { | 1816 } else { |
1785 Selector selector = node.selector; | 1817 Selector selector = node.selector; |
1786 TypeMask mask = getOptimizedSelectorFor(node, selector, node.mask); | 1818 TypeMask mask = getOptimizedSelectorFor(node, selector, node.mask); |
1787 registry.registerDynamicUse(new DynamicUse(selector, mask)); | 1819 _registry.registerDynamicUse(new DynamicUse(selector, mask)); |
1788 } | 1820 } |
1789 } | 1821 } |
1790 | 1822 |
1791 void registerGetter(HInvokeDynamic node) { | 1823 void registerGetter(HInvokeDynamic node) { |
1792 if (node.element != null && | 1824 if (node.element != null && |
1793 (node.element.isGetter || node.element.isField)) { | 1825 (node.element.isGetter || node.element.isField)) { |
1794 // This is a dynamic read which we have found to have a single target but | 1826 // This is a dynamic read which we have found to have a single target but |
1795 // for some reason haven't inlined. We are _still_ accessing the target | 1827 // for some reason haven't inlined. We are _still_ accessing the target |
1796 // dynamically but we don't need to enqueue more than target for this to | 1828 // dynamically but we don't need to enqueue more than target for this to |
1797 // work. The test above excludes non-getter functions since the element | 1829 // work. The test above excludes non-getter functions since the element |
1798 // represents two targets - a tearoff getter and the torn-off method. | 1830 // represents two targets - a tearoff getter and the torn-off method. |
1799 registry.registerStaticUse(new StaticUse.directGet(node.element)); | 1831 _registry.registerStaticUse(new StaticUse.directGet(node.element)); |
1800 } else { | 1832 } else { |
1801 Selector selector = node.selector; | 1833 Selector selector = node.selector; |
1802 TypeMask mask = getOptimizedSelectorFor(node, selector, node.mask); | 1834 TypeMask mask = getOptimizedSelectorFor(node, selector, node.mask); |
1803 registry.registerDynamicUse(new DynamicUse(selector, mask)); | 1835 _registry.registerDynamicUse(new DynamicUse(selector, mask)); |
1804 } | 1836 } |
1805 } | 1837 } |
1806 | 1838 |
1807 visitInvokeDynamicSetter(HInvokeDynamicSetter node) { | 1839 visitInvokeDynamicSetter(HInvokeDynamicSetter node) { |
1808 use(node.receiver); | 1840 use(node.receiver); |
1809 js.Name name = backend.namer.invocationName(node.selector); | 1841 js.Name name = _namer.invocationName(node.selector); |
1810 push(js | 1842 push(js |
1811 .propertyCall(pop(), name, visitArguments(node.inputs)) | 1843 .propertyCall(pop(), name, visitArguments(node.inputs)) |
1812 .withSourceInformation(node.sourceInformation)); | 1844 .withSourceInformation(node.sourceInformation)); |
1813 registerSetter(node); | 1845 registerSetter(node); |
1814 } | 1846 } |
1815 | 1847 |
1816 visitInvokeDynamicGetter(HInvokeDynamicGetter node) { | 1848 visitInvokeDynamicGetter(HInvokeDynamicGetter node) { |
1817 use(node.receiver); | 1849 use(node.receiver); |
1818 js.Name name = backend.namer.invocationName(node.selector); | 1850 js.Name name = _namer.invocationName(node.selector); |
1819 push(js | 1851 push(js |
1820 .propertyCall(pop(), name, visitArguments(node.inputs)) | 1852 .propertyCall(pop(), name, visitArguments(node.inputs)) |
1821 .withSourceInformation(node.sourceInformation)); | 1853 .withSourceInformation(node.sourceInformation)); |
1822 registerGetter(node); | 1854 registerGetter(node); |
1823 } | 1855 } |
1824 | 1856 |
1825 visitInvokeClosure(HInvokeClosure node) { | 1857 visitInvokeClosure(HInvokeClosure node) { |
1826 Selector call = new Selector.callClosureFrom(node.selector); | 1858 Selector call = new Selector.callClosureFrom(node.selector); |
1827 use(node.receiver); | 1859 use(node.receiver); |
1828 push(js | 1860 push(js |
1829 .propertyCall(pop(), backend.namer.invocationName(call), | 1861 .propertyCall( |
1830 visitArguments(node.inputs)) | 1862 pop(), _namer.invocationName(call), visitArguments(node.inputs)) |
1831 .withSourceInformation(node.sourceInformation)); | 1863 .withSourceInformation(node.sourceInformation)); |
1832 registry.registerDynamicUse(new DynamicUse(call, null)); | 1864 _registry.registerDynamicUse(new DynamicUse(call, null)); |
1833 } | 1865 } |
1834 | 1866 |
1835 visitInvokeStatic(HInvokeStatic node) { | 1867 visitInvokeStatic(HInvokeStatic node) { |
1836 MemberEntity element = node.element; | 1868 MemberEntity element = node.element; |
1837 List<DartType> instantiatedTypes = node.instantiatedTypes; | 1869 List<DartType> instantiatedTypes = node.instantiatedTypes; |
1838 | 1870 |
1839 if (instantiatedTypes != null && !instantiatedTypes.isEmpty) { | 1871 if (instantiatedTypes != null && !instantiatedTypes.isEmpty) { |
1840 instantiatedTypes.forEach((type) { | 1872 instantiatedTypes.forEach((type) { |
1841 registry.registerInstantiation(type); | 1873 _registry.registerInstantiation(type); |
1842 }); | 1874 }); |
1843 } | 1875 } |
1844 | 1876 |
1845 List<js.Expression> arguments = visitArguments(node.inputs, start: 0); | 1877 List<js.Expression> arguments = visitArguments(node.inputs, start: 0); |
1846 | 1878 |
1847 if (element == backend.helpers.checkConcurrentModificationError) { | 1879 if (element == _helpers.checkConcurrentModificationError) { |
1848 // Manually inline the [checkConcurrentModificationError] function. This | 1880 // Manually inline the [checkConcurrentModificationError] function. This |
1849 // function is only called from a for-loop update. Ideally we would just | 1881 // function is only called from a for-loop update. Ideally we would just |
1850 // generate the conditionalcontrol flow in the builder but it adds basic | 1882 // generate the conditionalcontrol flow in the builder but it adds basic |
1851 // blocks in the loop update that interfere with other optimizations and | 1883 // blocks in the loop update that interfere with other optimizations and |
1852 // confuses loop recognition. | 1884 // confuses loop recognition. |
1853 | 1885 |
1854 assert(arguments.length == 2); | 1886 assert(arguments.length == 2); |
1855 FunctionEntity throwFunction = | 1887 FunctionEntity throwFunction = _helpers.throwConcurrentModificationError; |
1856 backend.helpers.throwConcurrentModificationError; | 1888 _registry.registerStaticUse( |
1857 registry.registerStaticUse( | |
1858 new StaticUse.staticInvoke(throwFunction, CallStructure.ONE_ARG)); | 1889 new StaticUse.staticInvoke(throwFunction, CallStructure.ONE_ARG)); |
1859 | 1890 |
1860 // Calling using `(0, #)(#)` instead of `#(#)` separates the property load | 1891 // Calling using `(0, #)(#)` instead of `#(#)` separates the property load |
1861 // of the static function access from the call. For some reason this | 1892 // of the static function access from the call. For some reason this |
1862 // helps V8 see that the call never happens so V8 makes the call a | 1893 // helps V8 see that the call never happens so V8 makes the call a |
1863 // deoptimization. This removes the call from the optimized loop, making | 1894 // deoptimization. This removes the call from the optimized loop, making |
1864 // more optimizations available to the loop. This form is 50% faster on | 1895 // more optimizations available to the loop. This form is 50% faster on |
1865 // some small loop, almost as fast as loops with no concurrent | 1896 // some small loop, almost as fast as loops with no concurrent |
1866 // modification check. | 1897 // modification check. |
1867 push(js.js('# || (0, #)(#)', [ | 1898 push(js.js('# || (0, #)(#)', [ |
1868 arguments[0], | 1899 arguments[0], |
1869 backend.emitter.staticFunctionAccess(throwFunction), | 1900 _emitter.staticFunctionAccess(throwFunction), |
1870 arguments[1] | 1901 arguments[1] |
1871 ])); | 1902 ])); |
1872 } else { | 1903 } else { |
1873 CallStructure callStructure = new CallStructure.unnamed(arguments.length); | 1904 CallStructure callStructure = new CallStructure.unnamed(arguments.length); |
1874 registry.registerStaticUse(element.isConstructor | 1905 _registry.registerStaticUse(element.isConstructor |
1875 ? new StaticUse.constructorInvoke(element, callStructure) | 1906 ? new StaticUse.constructorInvoke(element, callStructure) |
1876 : new StaticUse.staticInvoke(element, callStructure)); | 1907 : new StaticUse.staticInvoke(element, callStructure)); |
1877 push(backend.emitter.staticFunctionAccess(element)); | 1908 push(_emitter.staticFunctionAccess(element)); |
1878 push(new js.Call(pop(), arguments, | 1909 push(new js.Call(pop(), arguments, |
1879 sourceInformation: node.sourceInformation)); | 1910 sourceInformation: node.sourceInformation)); |
1880 } | 1911 } |
1881 } | 1912 } |
1882 | 1913 |
1883 visitInvokeSuper(HInvokeSuper node) { | 1914 visitInvokeSuper(HInvokeSuper node) { |
1884 MemberEntity superElement = node.element; | 1915 MemberEntity superElement = node.element; |
1885 ClassEntity superClass = superElement.enclosingClass; | 1916 ClassEntity superClass = superElement.enclosingClass; |
1886 if (superElement.isField) { | 1917 if (superElement.isField) { |
1887 js.Name fieldName = backend.namer.instanceFieldPropertyName(superElement); | 1918 js.Name fieldName = _namer.instanceFieldPropertyName(superElement); |
1888 use(node.inputs[0]); | 1919 use(node.inputs[0]); |
1889 js.PropertyAccess access = new js.PropertyAccess(pop(), fieldName) | 1920 js.PropertyAccess access = new js.PropertyAccess(pop(), fieldName) |
1890 .withSourceInformation(node.sourceInformation); | 1921 .withSourceInformation(node.sourceInformation); |
1891 if (node.isSetter) { | 1922 if (node.isSetter) { |
1892 registry.registerStaticUse(superElement.isSetter | 1923 _registry.registerStaticUse(superElement.isSetter |
1893 ? new StaticUse.superSetterSet(superElement) | 1924 ? new StaticUse.superSetterSet(superElement) |
1894 : new StaticUse.superFieldSet(superElement)); | 1925 : new StaticUse.superFieldSet(superElement)); |
1895 use(node.value); | 1926 use(node.value); |
1896 push(new js.Assignment(access, pop()) | 1927 push(new js.Assignment(access, pop()) |
1897 .withSourceInformation(node.sourceInformation)); | 1928 .withSourceInformation(node.sourceInformation)); |
1898 } else { | 1929 } else { |
1899 registry.registerStaticUse(new StaticUse.superGet(superElement)); | 1930 _registry.registerStaticUse(new StaticUse.superGet(superElement)); |
1900 push(access); | 1931 push(access); |
1901 } | 1932 } |
1902 } else { | 1933 } else { |
1903 Selector selector = node.selector; | 1934 Selector selector = node.selector; |
1904 if (!backend.superMemberData | 1935 if (!_superMemberData.maybeRegisterAliasedSuperMember( |
1905 .maybeRegisterAliasedSuperMember(superElement, selector)) { | 1936 superElement, selector)) { |
1906 js.Name methodName; | 1937 js.Name methodName; |
1907 if (selector.isGetter && !superElement.isGetter) { | 1938 if (selector.isGetter && !superElement.isGetter) { |
1908 // If this is a tear-off, register the fact that a tear-off closure | 1939 // If this is a tear-off, register the fact that a tear-off closure |
1909 // will be created, and that this tear-off must bypass ordinary | 1940 // will be created, and that this tear-off must bypass ordinary |
1910 // dispatch to ensure the super method is invoked. | 1941 // dispatch to ensure the super method is invoked. |
1911 FunctionEntity helper = backend.helpers.closureFromTearOff; | 1942 FunctionEntity helper = _helpers.closureFromTearOff; |
1912 registry.registerStaticUse(new StaticUse.staticInvoke( | 1943 _registry.registerStaticUse(new StaticUse.staticInvoke( |
1913 helper, new CallStructure.unnamed(node.inputs.length))); | 1944 helper, new CallStructure.unnamed(node.inputs.length))); |
1914 registry.registerStaticUse(new StaticUse.superTearOff(node.element)); | 1945 _registry.registerStaticUse(new StaticUse.superTearOff(node.element)); |
1915 methodName = backend.namer.invocationName(selector); | 1946 methodName = _namer.invocationName(selector); |
1916 } else { | 1947 } else { |
1917 methodName = backend.namer.instanceMethodName(superElement); | 1948 methodName = _namer.instanceMethodName(superElement); |
1918 } | 1949 } |
1919 registry.registerStaticUse(new StaticUse.superInvoke( | 1950 _registry.registerStaticUse(new StaticUse.superInvoke( |
1920 superElement, new CallStructure.unnamed(node.inputs.length))); | 1951 superElement, new CallStructure.unnamed(node.inputs.length))); |
1921 push(js.js('#.#.call(#)', [ | 1952 push(js.js('#.#.call(#)', [ |
1922 backend.emitter | 1953 _emitter.prototypeAccess(superClass, hasBeenInstantiated: true), |
1923 .prototypeAccess(superClass, hasBeenInstantiated: true), | |
1924 methodName, | 1954 methodName, |
1925 visitArguments(node.inputs, start: 0) | 1955 visitArguments(node.inputs, start: 0) |
1926 ]).withSourceInformation(node.sourceInformation)); | 1956 ]).withSourceInformation(node.sourceInformation)); |
1927 } else { | 1957 } else { |
1928 use(node.receiver); | 1958 use(node.receiver); |
1929 registry.registerStaticUse(new StaticUse.superInvoke( | 1959 _registry.registerStaticUse(new StaticUse.superInvoke( |
1930 superElement, new CallStructure.unnamed(node.inputs.length - 1))); | 1960 superElement, new CallStructure.unnamed(node.inputs.length - 1))); |
1931 push(js.js('#.#(#)', [ | 1961 push(js.js('#.#(#)', [ |
1932 pop(), | 1962 pop(), |
1933 backend.namer.aliasedSuperMemberPropertyName(superElement), | 1963 _namer.aliasedSuperMemberPropertyName(superElement), |
1934 visitArguments(node.inputs, start: 1) | 1964 visitArguments(node.inputs, start: 1) |
1935 ]) // Skip receiver argument. | 1965 ]) // Skip receiver argument. |
1936 .withSourceInformation(node.sourceInformation)); | 1966 .withSourceInformation(node.sourceInformation)); |
1937 } | 1967 } |
1938 } | 1968 } |
1939 } | 1969 } |
1940 | 1970 |
1941 visitFieldGet(HFieldGet node) { | 1971 visitFieldGet(HFieldGet node) { |
1942 use(node.receiver); | 1972 use(node.receiver); |
1943 if (node.isNullCheck) { | 1973 if (node.isNullCheck) { |
1944 // We access a JavaScript member we know all objects besides | 1974 // We access a JavaScript member we know all objects besides |
1945 // null and undefined have: V8 does not like accessing a member | 1975 // null and undefined have: V8 does not like accessing a member |
1946 // that does not exist. | 1976 // that does not exist. |
1947 push(new js.PropertyAccess.field(pop(), 'toString') | 1977 push(new js.PropertyAccess.field(pop(), 'toString') |
1948 .withSourceInformation(node.sourceInformation)); | 1978 .withSourceInformation(node.sourceInformation)); |
1949 } else { | 1979 } else { |
1950 FieldEntity field = node.element; | 1980 FieldEntity field = node.element; |
1951 js.Name name = backend.namer.instanceFieldPropertyName(field); | 1981 js.Name name = _namer.instanceFieldPropertyName(field); |
1952 push(new js.PropertyAccess(pop(), name) | 1982 push(new js.PropertyAccess(pop(), name) |
1953 .withSourceInformation(node.sourceInformation)); | 1983 .withSourceInformation(node.sourceInformation)); |
1954 registry.registerStaticUse(new StaticUse.fieldGet(field)); | 1984 _registry.registerStaticUse(new StaticUse.fieldGet(field)); |
1955 } | 1985 } |
1956 } | 1986 } |
1957 | 1987 |
1958 visitFieldSet(HFieldSet node) { | 1988 visitFieldSet(HFieldSet node) { |
1959 FieldEntity element = node.element; | 1989 FieldEntity element = node.element; |
1960 registry.registerStaticUse(new StaticUse.fieldSet(element)); | 1990 _registry.registerStaticUse(new StaticUse.fieldSet(element)); |
1961 js.Name name = backend.namer.instanceFieldPropertyName(element); | 1991 js.Name name = _namer.instanceFieldPropertyName(element); |
1962 use(node.receiver); | 1992 use(node.receiver); |
1963 js.Expression receiver = pop(); | 1993 js.Expression receiver = pop(); |
1964 use(node.value); | 1994 use(node.value); |
1965 push(new js.Assignment(new js.PropertyAccess(receiver, name), pop()) | 1995 push(new js.Assignment(new js.PropertyAccess(receiver, name), pop()) |
1966 .withSourceInformation(node.sourceInformation)); | 1996 .withSourceInformation(node.sourceInformation)); |
1967 } | 1997 } |
1968 | 1998 |
1969 visitGetLength(HGetLength node) { | 1999 visitGetLength(HGetLength node) { |
1970 use(node.receiver); | 2000 use(node.receiver); |
1971 push(new js.PropertyAccess.field(pop(), 'length') | 2001 push(new js.PropertyAccess.field(pop(), 'length') |
1972 .withSourceInformation(node.sourceInformation)); | 2002 .withSourceInformation(node.sourceInformation)); |
1973 } | 2003 } |
1974 | 2004 |
1975 visitReadModifyWrite(HReadModifyWrite node) { | 2005 visitReadModifyWrite(HReadModifyWrite node) { |
1976 FieldEntity element = node.element; | 2006 FieldEntity element = node.element; |
1977 registry.registerStaticUse(new StaticUse.fieldGet(element)); | 2007 _registry.registerStaticUse(new StaticUse.fieldGet(element)); |
1978 registry.registerStaticUse(new StaticUse.fieldSet(element)); | 2008 _registry.registerStaticUse(new StaticUse.fieldSet(element)); |
1979 js.Name name = backend.namer.instanceFieldPropertyName(element); | 2009 js.Name name = _namer.instanceFieldPropertyName(element); |
1980 use(node.receiver); | 2010 use(node.receiver); |
1981 js.Expression fieldReference = new js.PropertyAccess(pop(), name); | 2011 js.Expression fieldReference = new js.PropertyAccess(pop(), name); |
1982 if (node.isPreOp) { | 2012 if (node.isPreOp) { |
1983 push(new js.Prefix(node.jsOp, fieldReference) | 2013 push(new js.Prefix(node.jsOp, fieldReference) |
1984 .withSourceInformation(node.sourceInformation)); | 2014 .withSourceInformation(node.sourceInformation)); |
1985 } else if (node.isPostOp) { | 2015 } else if (node.isPostOp) { |
1986 push(new js.Postfix(node.jsOp, fieldReference) | 2016 push(new js.Postfix(node.jsOp, fieldReference) |
1987 .withSourceInformation(node.sourceInformation)); | 2017 .withSourceInformation(node.sourceInformation)); |
1988 } else { | 2018 } else { |
1989 use(node.value); | 2019 use(node.value); |
1990 push(new js.Assignment.compound(fieldReference, node.jsOp, pop()) | 2020 push(new js.Assignment.compound(fieldReference, node.jsOp, pop()) |
1991 .withSourceInformation(node.sourceInformation)); | 2021 .withSourceInformation(node.sourceInformation)); |
1992 } | 2022 } |
1993 } | 2023 } |
1994 | 2024 |
1995 visitLocalGet(HLocalGet node) { | 2025 visitLocalGet(HLocalGet node) { |
1996 use(node.receiver); | 2026 use(node.receiver); |
1997 } | 2027 } |
1998 | 2028 |
1999 visitLocalSet(HLocalSet node) { | 2029 visitLocalSet(HLocalSet node) { |
2000 use(node.value); | 2030 use(node.value); |
2001 assignVariable( | 2031 assignVariable( |
2002 variableNames.getName(node.receiver), pop(), node.sourceInformation); | 2032 variableNames.getName(node.receiver), pop(), node.sourceInformation); |
2003 } | 2033 } |
2004 | 2034 |
2005 void registerForeignTypes(HForeign node) { | 2035 void registerForeignTypes(HForeign node) { |
2006 native.NativeBehavior nativeBehavior = node.nativeBehavior; | 2036 native.NativeBehavior nativeBehavior = node.nativeBehavior; |
2007 if (nativeBehavior == null) return; | 2037 if (nativeBehavior == null) return; |
2008 nativeEnqueuer.registerNativeBehavior( | 2038 _nativeEnqueuer.registerNativeBehavior( |
2009 registry.worldImpact, nativeBehavior, node); | 2039 _registry.worldImpact, nativeBehavior, node); |
2010 } | 2040 } |
2011 | 2041 |
2012 visitForeignCode(HForeignCode node) { | 2042 visitForeignCode(HForeignCode node) { |
2013 List<HInstruction> inputs = node.inputs; | 2043 List<HInstruction> inputs = node.inputs; |
2014 if (node.isJsStatement()) { | 2044 if (node.isJsStatement()) { |
2015 List<js.Expression> interpolatedExpressions = <js.Expression>[]; | 2045 List<js.Expression> interpolatedExpressions = <js.Expression>[]; |
2016 for (int i = 0; i < inputs.length; i++) { | 2046 for (int i = 0; i < inputs.length; i++) { |
2017 use(inputs[i]); | 2047 use(inputs[i]); |
2018 interpolatedExpressions.add(pop()); | 2048 interpolatedExpressions.add(pop()); |
2019 } | 2049 } |
2020 pushStatement(node.codeTemplate | 2050 pushStatement(node.codeTemplate |
2021 .instantiate(interpolatedExpressions) | 2051 .instantiate(interpolatedExpressions) |
2022 .withSourceInformation(node.sourceInformation)); | 2052 .withSourceInformation(node.sourceInformation)); |
2023 } else { | 2053 } else { |
2024 List<js.Expression> interpolatedExpressions = <js.Expression>[]; | 2054 List<js.Expression> interpolatedExpressions = <js.Expression>[]; |
2025 for (int i = 0; i < inputs.length; i++) { | 2055 for (int i = 0; i < inputs.length; i++) { |
2026 use(inputs[i]); | 2056 use(inputs[i]); |
2027 interpolatedExpressions.add(pop()); | 2057 interpolatedExpressions.add(pop()); |
2028 } | 2058 } |
2029 push(node.codeTemplate | 2059 push(node.codeTemplate |
2030 .instantiate(interpolatedExpressions) | 2060 .instantiate(interpolatedExpressions) |
2031 .withSourceInformation(node.sourceInformation)); | 2061 .withSourceInformation(node.sourceInformation)); |
2032 } | 2062 } |
2033 | 2063 |
2034 // TODO(sra): Tell world.nativeEnqueuer about the types created here. | 2064 // TODO(sra): Tell world.nativeEnqueuer about the types created here. |
2035 registerForeignTypes(node); | 2065 registerForeignTypes(node); |
2036 | 2066 |
2037 if (node.foreignFunction != null) { | 2067 if (node.foreignFunction != null) { |
2038 registry?.registerStaticUse( | 2068 _registry?.registerStaticUse( |
2039 new StaticUse.implicitInvoke(node.foreignFunction)); | 2069 new StaticUse.implicitInvoke(node.foreignFunction)); |
2040 } | 2070 } |
2041 } | 2071 } |
2042 | 2072 |
2043 visitCreate(HCreate node) { | 2073 visitCreate(HCreate node) { |
2044 js.Expression jsClassReference = | 2074 js.Expression jsClassReference = _emitter.constructorAccess(node.element); |
2045 backend.emitter.constructorAccess(node.element); | |
2046 List<js.Expression> arguments = visitArguments(node.inputs, start: 0); | 2075 List<js.Expression> arguments = visitArguments(node.inputs, start: 0); |
2047 push(new js.New(jsClassReference, arguments) | 2076 push(new js.New(jsClassReference, arguments) |
2048 .withSourceInformation(node.sourceInformation)); | 2077 .withSourceInformation(node.sourceInformation)); |
2049 // We also use HCreate to instantiate closure classes that belong to | 2078 // We also use HCreate to instantiate closure classes that belong to |
2050 // function expressions. We have to register their use here, as otherwise | 2079 // function expressions. We have to register their use here, as otherwise |
2051 // code for them might not be emitted. | 2080 // code for them might not be emitted. |
2052 if (node.element.isClosure) { | 2081 if (node.element.isClosure) { |
2053 registry.registerInstantiatedClass(node.element); | 2082 _registry.registerInstantiatedClass(node.element); |
2054 } | 2083 } |
2055 node.instantiatedTypes?.forEach(registry.registerInstantiation); | 2084 node.instantiatedTypes?.forEach(_registry.registerInstantiation); |
2056 if (node.callMethod != null) { | 2085 if (node.callMethod != null) { |
2057 registry | 2086 _registry |
2058 ?.registerStaticUse(new StaticUse.implicitInvoke(node.callMethod)); | 2087 ?.registerStaticUse(new StaticUse.implicitInvoke(node.callMethod)); |
2059 } | 2088 } |
2060 if (node.localFunction != null) { | 2089 if (node.localFunction != null) { |
2061 registry?.registerInstantiatedClosure(node.localFunction); | 2090 _registry?.registerInstantiatedClosure(node.localFunction); |
2062 } | 2091 } |
2063 } | 2092 } |
2064 | 2093 |
2065 js.Expression newLiteralBool( | 2094 js.Expression newLiteralBool( |
2066 bool value, SourceInformation sourceInformation) { | 2095 bool value, SourceInformation sourceInformation) { |
2067 if (compiler.options.enableMinification) { | 2096 if (_options.enableMinification) { |
2068 // Use !0 for true, !1 for false. | 2097 // Use !0 for true, !1 for false. |
2069 return new js.Prefix("!", new js.LiteralNumber(value ? "0" : "1")) | 2098 return new js.Prefix("!", new js.LiteralNumber(value ? "0" : "1")) |
2070 .withSourceInformation(sourceInformation); | 2099 .withSourceInformation(sourceInformation); |
2071 } else { | 2100 } else { |
2072 return new js.LiteralBool(value).withSourceInformation(sourceInformation); | 2101 return new js.LiteralBool(value).withSourceInformation(sourceInformation); |
2073 } | 2102 } |
2074 } | 2103 } |
2075 | 2104 |
2076 void generateConstant( | 2105 void generateConstant( |
2077 ConstantValue constant, SourceInformation sourceInformation) { | 2106 ConstantValue constant, SourceInformation sourceInformation) { |
2078 js.Expression expression = backend.emitter.constantReference(constant); | 2107 js.Expression expression = _emitter.constantReference(constant); |
2079 if (!constant.isDummy) { | 2108 if (!constant.isDummy) { |
2080 // TODO(johnniwinther): Support source information on synthetic constants. | 2109 // TODO(johnniwinther): Support source information on synthetic constants. |
2081 expression = expression.withSourceInformation(sourceInformation); | 2110 expression = expression.withSourceInformation(sourceInformation); |
2082 } | 2111 } |
2083 push(expression); | 2112 push(expression); |
2084 } | 2113 } |
2085 | 2114 |
2086 visitConstant(HConstant node) { | 2115 visitConstant(HConstant node) { |
2087 assert(isGenerateAtUseSite(node)); | 2116 assert(isGenerateAtUseSite(node)); |
2088 generateConstant(node.constant, node.sourceInformation); | 2117 generateConstant(node.constant, node.sourceInformation); |
2089 | 2118 |
2090 registry.registerConstantUse(new ConstantUse.literal(node.constant)); | 2119 _registry.registerConstantUse(new ConstantUse.literal(node.constant)); |
2091 } | 2120 } |
2092 | 2121 |
2093 visitNot(HNot node) { | 2122 visitNot(HNot node) { |
2094 assert(node.inputs.length == 1); | 2123 assert(node.inputs.length == 1); |
2095 generateNot(node.inputs[0], node.sourceInformation); | 2124 generateNot(node.inputs[0], node.sourceInformation); |
2096 } | 2125 } |
2097 | 2126 |
2098 static String mapRelationalOperator(String op, bool inverse) { | 2127 static String mapRelationalOperator(String op, bool inverse) { |
2099 Map<String, String> inverseOperator = const <String, String>{ | 2128 Map<String, String> inverseOperator = const <String, String>{ |
2100 "==": "!=", | 2129 "==": "!=", |
2101 "!=": "==", | 2130 "!=": "==", |
2102 "===": "!==", | 2131 "===": "!==", |
2103 "!==": "===", | 2132 "!==": "===", |
2104 "<": ">=", | 2133 "<": ">=", |
2105 "<=": ">", | 2134 "<=": ">", |
2106 ">": "<=", | 2135 ">": "<=", |
2107 ">=": "<" | 2136 ">=": "<" |
2108 }; | 2137 }; |
2109 return inverse ? inverseOperator[op] : op; | 2138 return inverse ? inverseOperator[op] : op; |
2110 } | 2139 } |
2111 | 2140 |
2112 void generateNot(HInstruction input, SourceInformation sourceInformation) { | 2141 void generateNot(HInstruction input, SourceInformation sourceInformation) { |
2113 bool canGenerateOptimizedComparison(HInstruction instruction) { | 2142 bool canGenerateOptimizedComparison(HInstruction instruction) { |
2114 if (instruction is! HRelational) return false; | 2143 if (instruction is! HRelational) return false; |
2115 | 2144 |
2116 HRelational relational = instruction; | 2145 HRelational relational = instruction; |
2117 | 2146 |
2118 HInstruction left = relational.left; | 2147 HInstruction left = relational.left; |
2119 HInstruction right = relational.right; | 2148 HInstruction right = relational.right; |
2120 if (left.isStringOrNull(closedWorld) && | 2149 if (left.isStringOrNull(_closedWorld) && |
2121 right.isStringOrNull(closedWorld)) { | 2150 right.isStringOrNull(_closedWorld)) { |
2122 return true; | 2151 return true; |
2123 } | 2152 } |
2124 | 2153 |
2125 // This optimization doesn't work for NaN, so we only do it if the | 2154 // This optimization doesn't work for NaN, so we only do it if the |
2126 // type is known to be an integer. | 2155 // type is known to be an integer. |
2127 return left.isInteger(closedWorld) && right.isInteger(closedWorld); | 2156 return left.isInteger(_closedWorld) && right.isInteger(_closedWorld); |
2128 } | 2157 } |
2129 | 2158 |
2130 bool handledBySpecialCase = false; | 2159 bool handledBySpecialCase = false; |
2131 if (isGenerateAtUseSite(input)) { | 2160 if (isGenerateAtUseSite(input)) { |
2132 handledBySpecialCase = true; | 2161 handledBySpecialCase = true; |
2133 if (input is HIs) { | 2162 if (input is HIs) { |
2134 emitIs(input, '!==', sourceInformation); | 2163 emitIs(input, '!==', sourceInformation); |
2135 } else if (input is HIsViaInterceptor) { | 2164 } else if (input is HIsViaInterceptor) { |
2136 emitIsViaInterceptor(input, sourceInformation, negative: true); | 2165 emitIsViaInterceptor(input, sourceInformation, negative: true); |
2137 } else if (input is HNot) { | 2166 } else if (input is HNot) { |
2138 use(input.inputs[0]); | 2167 use(input.inputs[0]); |
2139 } else if (input is HIdentity) { | 2168 } else if (input is HIdentity) { |
2140 emitIdentityComparison(input, sourceInformation, inverse: true); | 2169 emitIdentityComparison(input, sourceInformation, inverse: true); |
2141 } else if (input is HBoolify) { | 2170 } else if (input is HBoolify) { |
2142 use(input.inputs[0]); | 2171 use(input.inputs[0]); |
2143 push(new js.Binary( | 2172 push(new js.Binary( |
2144 "!==", pop(), newLiteralBool(true, input.sourceInformation)) | 2173 "!==", pop(), newLiteralBool(true, input.sourceInformation)) |
2145 .withSourceInformation(sourceInformation)); | 2174 .withSourceInformation(sourceInformation)); |
2146 } else if (canGenerateOptimizedComparison(input)) { | 2175 } else if (canGenerateOptimizedComparison(input)) { |
2147 HRelational relational = input; | 2176 HRelational relational = input; |
2148 BinaryOperation operation = | 2177 BinaryOperation operation = relational.operation(_constantSystem); |
2149 relational.operation(backend.constantSystem); | |
2150 String op = mapRelationalOperator(operation.name, true); | 2178 String op = mapRelationalOperator(operation.name, true); |
2151 handleInvokeBinary(input, op, sourceInformation); | 2179 handleInvokeBinary(input, op, sourceInformation); |
2152 } else { | 2180 } else { |
2153 handledBySpecialCase = false; | 2181 handledBySpecialCase = false; |
2154 } | 2182 } |
2155 } | 2183 } |
2156 if (!handledBySpecialCase) { | 2184 if (!handledBySpecialCase) { |
2157 use(input); | 2185 use(input); |
2158 push(new js.Prefix("!", pop()).withSourceInformation(sourceInformation)); | 2186 push(new js.Prefix("!", pop()).withSourceInformation(sourceInformation)); |
2159 } | 2187 } |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2219 visitThis(HThis node) { | 2247 visitThis(HThis node) { |
2220 push(new js.This()); | 2248 push(new js.This()); |
2221 } | 2249 } |
2222 | 2250 |
2223 visitThrow(HThrow node) { | 2251 visitThrow(HThrow node) { |
2224 if (node.isRethrow) { | 2252 if (node.isRethrow) { |
2225 use(node.inputs[0]); | 2253 use(node.inputs[0]); |
2226 pushStatement( | 2254 pushStatement( |
2227 new js.Throw(pop()).withSourceInformation(node.sourceInformation)); | 2255 new js.Throw(pop()).withSourceInformation(node.sourceInformation)); |
2228 } else { | 2256 } else { |
2229 generateThrowWithHelper(helpers.wrapExceptionHelper, node.inputs[0], | 2257 generateThrowWithHelper(_helpers.wrapExceptionHelper, node.inputs[0], |
2230 sourceInformation: node.sourceInformation); | 2258 sourceInformation: node.sourceInformation); |
2231 } | 2259 } |
2232 } | 2260 } |
2233 | 2261 |
2234 visitAwait(HAwait node) { | 2262 visitAwait(HAwait node) { |
2235 use(node.inputs[0]); | 2263 use(node.inputs[0]); |
2236 push(new js.Await(pop()).withSourceInformation(node.sourceInformation)); | 2264 push(new js.Await(pop()).withSourceInformation(node.sourceInformation)); |
2237 } | 2265 } |
2238 | 2266 |
2239 visitYield(HYield node) { | 2267 visitYield(HYield node) { |
(...skipping 13 matching lines...) Expand all Loading... |
2253 // e.g., the zero checks can be shared if possible. | 2281 // e.g., the zero checks can be shared if possible. |
2254 | 2282 |
2255 // If the checks always succeeds, we would have removed the bounds check | 2283 // If the checks always succeeds, we would have removed the bounds check |
2256 // completely. | 2284 // completely. |
2257 assert(node.staticChecks != HBoundsCheck.ALWAYS_TRUE); | 2285 assert(node.staticChecks != HBoundsCheck.ALWAYS_TRUE); |
2258 if (node.staticChecks != HBoundsCheck.ALWAYS_FALSE) { | 2286 if (node.staticChecks != HBoundsCheck.ALWAYS_FALSE) { |
2259 js.Expression under; | 2287 js.Expression under; |
2260 js.Expression over; | 2288 js.Expression over; |
2261 if (node.staticChecks != HBoundsCheck.ALWAYS_ABOVE_ZERO) { | 2289 if (node.staticChecks != HBoundsCheck.ALWAYS_ABOVE_ZERO) { |
2262 use(node.index); | 2290 use(node.index); |
2263 if (node.index.isInteger(closedWorld)) { | 2291 if (node.index.isInteger(_closedWorld)) { |
2264 under = js.js("# < 0", pop()); | 2292 under = js.js("# < 0", pop()); |
2265 } else { | 2293 } else { |
2266 js.Expression jsIndex = pop(); | 2294 js.Expression jsIndex = pop(); |
2267 under = js.js("# >>> 0 !== #", [jsIndex, jsIndex]); | 2295 under = js.js("# >>> 0 !== #", [jsIndex, jsIndex]); |
2268 } | 2296 } |
2269 } else if (!node.index.isInteger(closedWorld)) { | 2297 } else if (!node.index.isInteger(_closedWorld)) { |
2270 checkInt(node.index, '!=='); | 2298 checkInt(node.index, '!=='); |
2271 under = pop(); | 2299 under = pop(); |
2272 } | 2300 } |
2273 if (node.staticChecks != HBoundsCheck.ALWAYS_BELOW_LENGTH) { | 2301 if (node.staticChecks != HBoundsCheck.ALWAYS_BELOW_LENGTH) { |
2274 var index = node.index; | 2302 var index = node.index; |
2275 use(index); | 2303 use(index); |
2276 js.Expression jsIndex = pop(); | 2304 js.Expression jsIndex = pop(); |
2277 use(node.length); | 2305 use(node.length); |
2278 over = new js.Binary(">=", jsIndex, pop()); | 2306 over = new js.Binary(">=", jsIndex, pop()); |
2279 } | 2307 } |
2280 assert(over != null || under != null); | 2308 assert(over != null || under != null); |
2281 js.Expression underOver = under == null | 2309 js.Expression underOver = under == null |
2282 ? over | 2310 ? over |
2283 : over == null ? under : new js.Binary("||", under, over); | 2311 : over == null ? under : new js.Binary("||", under, over); |
2284 js.Statement thenBody = new js.Block.empty(); | 2312 js.Statement thenBody = new js.Block.empty(); |
2285 js.Block oldContainer = currentContainer; | 2313 js.Block oldContainer = currentContainer; |
2286 currentContainer = thenBody; | 2314 currentContainer = thenBody; |
2287 generateThrowWithHelper(helpers.throwIndexOutOfRangeException, | 2315 generateThrowWithHelper(_helpers.throwIndexOutOfRangeException, |
2288 [node.array, node.reportedIndex]); | 2316 [node.array, node.reportedIndex]); |
2289 currentContainer = oldContainer; | 2317 currentContainer = oldContainer; |
2290 thenBody = unwrapStatement(thenBody); | 2318 thenBody = unwrapStatement(thenBody); |
2291 pushStatement(new js.If.noElse(underOver, thenBody) | 2319 pushStatement(new js.If.noElse(underOver, thenBody) |
2292 .withSourceInformation(node.sourceInformation)); | 2320 .withSourceInformation(node.sourceInformation)); |
2293 } else { | 2321 } else { |
2294 generateThrowWithHelper( | 2322 generateThrowWithHelper( |
2295 helpers.throwIndexOutOfRangeException, [node.array, node.index]); | 2323 _helpers.throwIndexOutOfRangeException, [node.array, node.index]); |
2296 } | 2324 } |
2297 } | 2325 } |
2298 | 2326 |
2299 void generateThrowWithHelper(FunctionEntity helper, argument, | 2327 void generateThrowWithHelper(FunctionEntity helper, argument, |
2300 {SourceInformation sourceInformation}) { | 2328 {SourceInformation sourceInformation}) { |
2301 js.Expression jsHelper = backend.emitter.staticFunctionAccess(helper); | 2329 js.Expression jsHelper = _emitter.staticFunctionAccess(helper); |
2302 List arguments = []; | 2330 List arguments = []; |
2303 if (argument is List) { | 2331 if (argument is List) { |
2304 argument.forEach((instruction) { | 2332 argument.forEach((instruction) { |
2305 use(instruction); | 2333 use(instruction); |
2306 arguments.add(pop()); | 2334 arguments.add(pop()); |
2307 }); | 2335 }); |
2308 } else { | 2336 } else { |
2309 use(argument); | 2337 use(argument); |
2310 arguments.add(pop()); | 2338 arguments.add(pop()); |
2311 } | 2339 } |
2312 registry.registerStaticUse(new StaticUse.staticInvoke( | 2340 _registry.registerStaticUse(new StaticUse.staticInvoke( |
2313 helper, new CallStructure.unnamed(arguments.length))); | 2341 helper, new CallStructure.unnamed(arguments.length))); |
2314 js.Call value = new js.Call(jsHelper, arguments.toList(growable: false), | 2342 js.Call value = new js.Call(jsHelper, arguments.toList(growable: false), |
2315 sourceInformation: sourceInformation); | 2343 sourceInformation: sourceInformation); |
2316 // BUG(4906): Using throw/return here adds to the size of the generated code | 2344 // BUG(4906): Using throw/return here adds to the size of the generated code |
2317 // but it has the advantage of explicitly telling the JS engine that | 2345 // but it has the advantage of explicitly telling the JS engine that |
2318 // this code path will terminate abruptly. Needs more work. | 2346 // this code path will terminate abruptly. Needs more work. |
2319 if (helper == helpers.wrapExceptionHelper) { | 2347 if (helper == _helpers.wrapExceptionHelper) { |
2320 pushStatement( | 2348 pushStatement( |
2321 new js.Throw(value).withSourceInformation(sourceInformation)); | 2349 new js.Throw(value).withSourceInformation(sourceInformation)); |
2322 } else { | 2350 } else { |
2323 Entity element = work.element; | 2351 Entity element = _work.element; |
2324 if (element is MethodElement && element.asyncMarker.isYielding) { | 2352 if (element is MethodElement && element.asyncMarker.isYielding) { |
2325 // `return <expr>;` is illegal in a sync* or async* function. | 2353 // `return <expr>;` is illegal in a sync* or async* function. |
2326 // To have the async-translator working, we avoid introducing | 2354 // To have the async-translator working, we avoid introducing |
2327 // `return` nodes. | 2355 // `return` nodes. |
2328 pushStatement(new js.ExpressionStatement(value) | 2356 pushStatement(new js.ExpressionStatement(value) |
2329 .withSourceInformation(sourceInformation)); | 2357 .withSourceInformation(sourceInformation)); |
2330 } else { | 2358 } else { |
2331 pushStatement( | 2359 pushStatement( |
2332 new js.Return(value).withSourceInformation(sourceInformation)); | 2360 new js.Return(value).withSourceInformation(sourceInformation)); |
2333 } | 2361 } |
2334 } | 2362 } |
2335 } | 2363 } |
2336 | 2364 |
2337 visitThrowExpression(HThrowExpression node) { | 2365 visitThrowExpression(HThrowExpression node) { |
2338 HInstruction argument = node.inputs[0]; | 2366 HInstruction argument = node.inputs[0]; |
2339 use(argument); | 2367 use(argument); |
2340 | 2368 |
2341 FunctionEntity helper = helpers.throwExpressionHelper; | 2369 FunctionEntity helper = _helpers.throwExpressionHelper; |
2342 registry.registerStaticUse( | 2370 _registry.registerStaticUse( |
2343 new StaticUse.staticInvoke(helper, CallStructure.ONE_ARG)); | 2371 new StaticUse.staticInvoke(helper, CallStructure.ONE_ARG)); |
2344 | 2372 |
2345 js.Expression jsHelper = backend.emitter.staticFunctionAccess(helper); | 2373 js.Expression jsHelper = _emitter.staticFunctionAccess(helper); |
2346 js.Call value = new js.Call(jsHelper, [pop()]) | 2374 js.Call value = new js.Call(jsHelper, [pop()]) |
2347 .withSourceInformation(node.sourceInformation); | 2375 .withSourceInformation(node.sourceInformation); |
2348 push(value); | 2376 push(value); |
2349 } | 2377 } |
2350 | 2378 |
2351 void visitSwitch(HSwitch node) { | 2379 void visitSwitch(HSwitch node) { |
2352 // Switches are handled using [visitSwitchInfo]. | 2380 // Switches are handled using [visitSwitchInfo]. |
2353 } | 2381 } |
2354 | 2382 |
2355 void visitStatic(HStatic node) { | 2383 void visitStatic(HStatic node) { |
2356 MemberEntity element = node.element; | 2384 MemberEntity element = node.element; |
2357 assert(element.isFunction || element.isField); | 2385 assert(element.isFunction || element.isField); |
2358 if (element.isFunction) { | 2386 if (element.isFunction) { |
2359 push(backend.emitter | 2387 push(_emitter |
2360 .isolateStaticClosureAccess(element) | 2388 .isolateStaticClosureAccess(element) |
2361 .withSourceInformation(node.sourceInformation)); | 2389 .withSourceInformation(node.sourceInformation)); |
2362 registry.registerStaticUse(new StaticUse.staticTearOff(element)); | 2390 _registry.registerStaticUse(new StaticUse.staticTearOff(element)); |
2363 } else { | 2391 } else { |
2364 push(backend.emitter | 2392 push(_emitter |
2365 .staticFieldAccess(element) | 2393 .staticFieldAccess(element) |
2366 .withSourceInformation(node.sourceInformation)); | 2394 .withSourceInformation(node.sourceInformation)); |
2367 registry.registerStaticUse(new StaticUse.staticGet(element)); | 2395 _registry.registerStaticUse(new StaticUse.staticGet(element)); |
2368 } | 2396 } |
2369 } | 2397 } |
2370 | 2398 |
2371 void visitLazyStatic(HLazyStatic node) { | 2399 void visitLazyStatic(HLazyStatic node) { |
2372 FieldEntity element = node.element; | 2400 FieldEntity element = node.element; |
2373 registry.registerStaticUse(new StaticUse.staticInit(element)); | 2401 _registry.registerStaticUse(new StaticUse.staticInit(element)); |
2374 js.Expression lazyGetter = | 2402 js.Expression lazyGetter = _emitter.isolateLazyInitializerAccess(element); |
2375 backend.emitter.isolateLazyInitializerAccess(element); | |
2376 js.Call call = new js.Call(lazyGetter, <js.Expression>[], | 2403 js.Call call = new js.Call(lazyGetter, <js.Expression>[], |
2377 sourceInformation: node.sourceInformation); | 2404 sourceInformation: node.sourceInformation); |
2378 push(call); | 2405 push(call); |
2379 } | 2406 } |
2380 | 2407 |
2381 void visitStaticStore(HStaticStore node) { | 2408 void visitStaticStore(HStaticStore node) { |
2382 registry.registerStaticUse(new StaticUse.staticSet(node.element)); | 2409 _registry.registerStaticUse(new StaticUse.staticSet(node.element)); |
2383 js.Node variable = backend.emitter.staticFieldAccess(node.element); | 2410 js.Node variable = _emitter.staticFieldAccess(node.element); |
2384 use(node.inputs[0]); | 2411 use(node.inputs[0]); |
2385 push(new js.Assignment(variable, pop()) | 2412 push(new js.Assignment(variable, pop()) |
2386 .withSourceInformation(node.sourceInformation)); | 2413 .withSourceInformation(node.sourceInformation)); |
2387 } | 2414 } |
2388 | 2415 |
2389 void visitStringConcat(HStringConcat node) { | 2416 void visitStringConcat(HStringConcat node) { |
2390 use(node.left); | 2417 use(node.left); |
2391 js.Expression jsLeft = pop(); | 2418 js.Expression jsLeft = pop(); |
2392 use(node.right); | 2419 use(node.right); |
2393 push(new js.Binary('+', jsLeft, pop()) | 2420 push(new js.Binary('+', jsLeft, pop()) |
2394 .withSourceInformation(node.sourceInformation)); | 2421 .withSourceInformation(node.sourceInformation)); |
2395 } | 2422 } |
2396 | 2423 |
2397 void visitStringify(HStringify node) { | 2424 void visitStringify(HStringify node) { |
2398 HInstruction input = node.inputs.first; | 2425 HInstruction input = node.inputs.first; |
2399 if (input.isString(closedWorld)) { | 2426 if (input.isString(_closedWorld)) { |
2400 use(input); | 2427 use(input); |
2401 } else if (input.isInteger(closedWorld) || input.isBoolean(closedWorld)) { | 2428 } else if (input.isInteger(_closedWorld) || input.isBoolean(_closedWorld)) { |
2402 // JavaScript's + operator with a string for the left operand will convert | 2429 // JavaScript's + operator with a string for the left operand will convert |
2403 // the right operand to a string, and the conversion result is correct. | 2430 // the right operand to a string, and the conversion result is correct. |
2404 use(input); | 2431 use(input); |
2405 if (node.usedBy.length == 1 && | 2432 if (node.usedBy.length == 1 && |
2406 node.usedBy[0] is HStringConcat && | 2433 node.usedBy[0] is HStringConcat && |
2407 node.usedBy[0].inputs[1] == node) { | 2434 node.usedBy[0].inputs[1] == node) { |
2408 // The context is already <string> + value. | 2435 // The context is already <string> + value. |
2409 } else { | 2436 } else { |
2410 // Force an empty string for the first operand. | 2437 // Force an empty string for the first operand. |
2411 push(new js.Binary('+', js.string(""), pop()) | 2438 push(new js.Binary('+', js.string(""), pop()) |
2412 .withSourceInformation(node.sourceInformation)); | 2439 .withSourceInformation(node.sourceInformation)); |
2413 } | 2440 } |
2414 } else { | 2441 } else { |
2415 FunctionEntity convertToString = | 2442 FunctionEntity convertToString = _helpers.stringInterpolationHelper; |
2416 backend.helpers.stringInterpolationHelper; | 2443 _registry.registerStaticUse( |
2417 registry.registerStaticUse( | |
2418 new StaticUse.staticInvoke(convertToString, CallStructure.ONE_ARG)); | 2444 new StaticUse.staticInvoke(convertToString, CallStructure.ONE_ARG)); |
2419 js.Expression jsHelper = | 2445 js.Expression jsHelper = _emitter.staticFunctionAccess(convertToString); |
2420 backend.emitter.staticFunctionAccess(convertToString); | |
2421 use(input); | 2446 use(input); |
2422 push(new js.Call(jsHelper, <js.Expression>[pop()], | 2447 push(new js.Call(jsHelper, <js.Expression>[pop()], |
2423 sourceInformation: node.sourceInformation)); | 2448 sourceInformation: node.sourceInformation)); |
2424 } | 2449 } |
2425 } | 2450 } |
2426 | 2451 |
2427 void visitLiteralList(HLiteralList node) { | 2452 void visitLiteralList(HLiteralList node) { |
2428 registry.registerInstantiatedClass(commonElements.listClass); | 2453 _registry.registerInstantiatedClass(_commonElements.listClass); |
2429 generateArrayLiteral(node); | 2454 generateArrayLiteral(node); |
2430 } | 2455 } |
2431 | 2456 |
2432 void generateArrayLiteral(HLiteralList node) { | 2457 void generateArrayLiteral(HLiteralList node) { |
2433 List<js.Expression> elements = node.inputs.map((HInstruction input) { | 2458 List<js.Expression> elements = node.inputs.map((HInstruction input) { |
2434 use(input); | 2459 use(input); |
2435 return pop(); | 2460 return pop(); |
2436 }).toList(); | 2461 }).toList(); |
2437 push(new js.ArrayInitializer(elements) | 2462 push(new js.ArrayInitializer(elements) |
2438 .withSourceInformation(node.sourceInformation)); | 2463 .withSourceInformation(node.sourceInformation)); |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2568 use(input); | 2593 use(input); |
2569 push(new js.Binary('!=', pop(), new js.LiteralNull())); | 2594 push(new js.Binary('!=', pop(), new js.LiteralNull())); |
2570 } | 2595 } |
2571 | 2596 |
2572 void checkType(HInstruction input, HInstruction interceptor, DartType type, | 2597 void checkType(HInstruction input, HInstruction interceptor, DartType type, |
2573 SourceInformation sourceInformation, | 2598 SourceInformation sourceInformation, |
2574 {bool negative: false}) { | 2599 {bool negative: false}) { |
2575 if (type.isInterfaceType) { | 2600 if (type.isInterfaceType) { |
2576 InterfaceType interfaceType = type; | 2601 InterfaceType interfaceType = type; |
2577 ClassEntity element = interfaceType.element; | 2602 ClassEntity element = interfaceType.element; |
2578 if (element == helpers.jsArrayClass) { | 2603 if (element == _helpers.jsArrayClass) { |
2579 checkArray(input, negative ? '!==' : '==='); | 2604 checkArray(input, negative ? '!==' : '==='); |
2580 return; | 2605 return; |
2581 } else if (element == helpers.jsMutableArrayClass) { | 2606 } else if (element == _helpers.jsMutableArrayClass) { |
2582 if (negative) { | 2607 if (negative) { |
2583 checkImmutableArray(input); | 2608 checkImmutableArray(input); |
2584 } else { | 2609 } else { |
2585 checkMutableArray(input); | 2610 checkMutableArray(input); |
2586 } | 2611 } |
2587 return; | 2612 return; |
2588 } else if (element == helpers.jsExtendableArrayClass) { | 2613 } else if (element == _helpers.jsExtendableArrayClass) { |
2589 if (negative) { | 2614 if (negative) { |
2590 checkFixedArray(input); | 2615 checkFixedArray(input); |
2591 } else { | 2616 } else { |
2592 checkExtendableArray(input); | 2617 checkExtendableArray(input); |
2593 } | 2618 } |
2594 return; | 2619 return; |
2595 } else if (element == helpers.jsFixedArrayClass) { | 2620 } else if (element == _helpers.jsFixedArrayClass) { |
2596 if (negative) { | 2621 if (negative) { |
2597 checkExtendableArray(input); | 2622 checkExtendableArray(input); |
2598 } else { | 2623 } else { |
2599 checkFixedArray(input); | 2624 checkFixedArray(input); |
2600 } | 2625 } |
2601 return; | 2626 return; |
2602 } else if (element == helpers.jsUnmodifiableArrayClass) { | 2627 } else if (element == _helpers.jsUnmodifiableArrayClass) { |
2603 if (negative) { | 2628 if (negative) { |
2604 checkMutableArray(input); | 2629 checkMutableArray(input); |
2605 } else { | 2630 } else { |
2606 checkImmutableArray(input); | 2631 checkImmutableArray(input); |
2607 } | 2632 } |
2608 return; | 2633 return; |
2609 } | 2634 } |
2610 } | 2635 } |
2611 if (interceptor != null) { | 2636 if (interceptor != null) { |
2612 checkTypeViaProperty(interceptor, type, sourceInformation, | 2637 checkTypeViaProperty(interceptor, type, sourceInformation, |
2613 negative: negative); | 2638 negative: negative); |
2614 } else { | 2639 } else { |
2615 checkTypeViaProperty(input, type, sourceInformation, negative: negative); | 2640 checkTypeViaProperty(input, type, sourceInformation, negative: negative); |
2616 } | 2641 } |
2617 } | 2642 } |
2618 | 2643 |
2619 void checkTypeViaProperty( | 2644 void checkTypeViaProperty( |
2620 HInstruction input, DartType type, SourceInformation sourceInformation, | 2645 HInstruction input, DartType type, SourceInformation sourceInformation, |
2621 {bool negative: false}) { | 2646 {bool negative: false}) { |
2622 registry.registerTypeUse(new TypeUse.isCheck(type)); | 2647 _registry.registerTypeUse(new TypeUse.isCheck(type)); |
2623 | 2648 |
2624 use(input); | 2649 use(input); |
2625 | 2650 |
2626 js.PropertyAccess field = | 2651 js.PropertyAccess field = |
2627 new js.PropertyAccess(pop(), backend.namer.operatorIsType(type)) | 2652 new js.PropertyAccess(pop(), _namer.operatorIsType(type)) |
2628 .withSourceInformation(sourceInformation); | 2653 .withSourceInformation(sourceInformation); |
2629 // We always negate at least once so that the result is boolified. | 2654 // We always negate at least once so that the result is boolified. |
2630 push(new js.Prefix('!', field).withSourceInformation(sourceInformation)); | 2655 push(new js.Prefix('!', field).withSourceInformation(sourceInformation)); |
2631 // If the result is not negated, put another '!' in front. | 2656 // If the result is not negated, put another '!' in front. |
2632 if (!negative) { | 2657 if (!negative) { |
2633 push(new js.Prefix('!', pop()).withSourceInformation(sourceInformation)); | 2658 push(new js.Prefix('!', pop()).withSourceInformation(sourceInformation)); |
2634 } | 2659 } |
2635 } | 2660 } |
2636 | 2661 |
2637 void checkTypeViaInstanceof(HInstruction input, InterfaceType type, | 2662 void checkTypeViaInstanceof(HInstruction input, InterfaceType type, |
2638 SourceInformation sourceInformation, | 2663 SourceInformation sourceInformation, |
2639 {bool negative: false}) { | 2664 {bool negative: false}) { |
2640 registry.registerTypeUse(new TypeUse.isCheck(type)); | 2665 _registry.registerTypeUse(new TypeUse.isCheck(type)); |
2641 | 2666 |
2642 use(input); | 2667 use(input); |
2643 | 2668 |
2644 js.Expression jsClassReference = | 2669 js.Expression jsClassReference = _emitter.constructorAccess(type.element); |
2645 backend.emitter.constructorAccess(type.element); | |
2646 push(js.js('# instanceof #', | 2670 push(js.js('# instanceof #', |
2647 [pop(), jsClassReference]).withSourceInformation(sourceInformation)); | 2671 [pop(), jsClassReference]).withSourceInformation(sourceInformation)); |
2648 if (negative) { | 2672 if (negative) { |
2649 push(new js.Prefix('!', pop()).withSourceInformation(sourceInformation)); | 2673 push(new js.Prefix('!', pop()).withSourceInformation(sourceInformation)); |
2650 } | 2674 } |
2651 registry.registerInstantiation(type); | 2675 _registry.registerInstantiation(type); |
2652 } | 2676 } |
2653 | 2677 |
2654 void handleNumberOrStringSupertypeCheck( | 2678 void handleNumberOrStringSupertypeCheck( |
2655 HInstruction input, | 2679 HInstruction input, |
2656 HInstruction interceptor, | 2680 HInstruction interceptor, |
2657 InterfaceType type, | 2681 InterfaceType type, |
2658 SourceInformation sourceInformation, | 2682 SourceInformation sourceInformation, |
2659 {bool negative: false}) { | 2683 {bool negative: false}) { |
2660 assert(!identical(type.element, commonElements.listClass) && | 2684 assert(!identical(type.element, _commonElements.listClass) && |
2661 !commonElements.isListSupertype(type.element) && | 2685 !_commonElements.isListSupertype(type.element) && |
2662 !commonElements.isStringOnlySupertype(type.element)); | 2686 !_commonElements.isStringOnlySupertype(type.element)); |
2663 String relation = negative ? '!==' : '==='; | 2687 String relation = negative ? '!==' : '==='; |
2664 checkNum(input, relation, sourceInformation); | 2688 checkNum(input, relation, sourceInformation); |
2665 js.Expression numberTest = pop(); | 2689 js.Expression numberTest = pop(); |
2666 checkString(input, relation, sourceInformation); | 2690 checkString(input, relation, sourceInformation); |
2667 js.Expression stringTest = pop(); | 2691 js.Expression stringTest = pop(); |
2668 checkObject(input, relation, sourceInformation); | 2692 checkObject(input, relation, sourceInformation); |
2669 js.Expression objectTest = pop(); | 2693 js.Expression objectTest = pop(); |
2670 checkType(input, interceptor, type, sourceInformation, negative: negative); | 2694 checkType(input, interceptor, type, sourceInformation, negative: negative); |
2671 String combiner = negative ? '&&' : '||'; | 2695 String combiner = negative ? '&&' : '||'; |
2672 String combiner2 = negative ? '||' : '&&'; | 2696 String combiner2 = negative ? '||' : '&&'; |
2673 push(new js.Binary( | 2697 push(new js.Binary( |
2674 combiner, | 2698 combiner, |
2675 new js.Binary(combiner, numberTest, stringTest) | 2699 new js.Binary(combiner, numberTest, stringTest) |
2676 .withSourceInformation(sourceInformation), | 2700 .withSourceInformation(sourceInformation), |
2677 new js.Binary(combiner2, objectTest, pop()) | 2701 new js.Binary(combiner2, objectTest, pop()) |
2678 .withSourceInformation(sourceInformation)) | 2702 .withSourceInformation(sourceInformation)) |
2679 .withSourceInformation(sourceInformation)); | 2703 .withSourceInformation(sourceInformation)); |
2680 } | 2704 } |
2681 | 2705 |
2682 void handleStringSupertypeCheck(HInstruction input, HInstruction interceptor, | 2706 void handleStringSupertypeCheck(HInstruction input, HInstruction interceptor, |
2683 InterfaceType type, SourceInformation sourceInformation, | 2707 InterfaceType type, SourceInformation sourceInformation, |
2684 {bool negative: false}) { | 2708 {bool negative: false}) { |
2685 assert(!identical(type.element, commonElements.listClass) && | 2709 assert(!identical(type.element, _commonElements.listClass) && |
2686 !commonElements.isListSupertype(type.element) && | 2710 !_commonElements.isListSupertype(type.element) && |
2687 !commonElements.isNumberOrStringSupertype(type.element)); | 2711 !_commonElements.isNumberOrStringSupertype(type.element)); |
2688 String relation = negative ? '!==' : '==='; | 2712 String relation = negative ? '!==' : '==='; |
2689 checkString(input, relation, sourceInformation); | 2713 checkString(input, relation, sourceInformation); |
2690 js.Expression stringTest = pop(); | 2714 js.Expression stringTest = pop(); |
2691 checkObject(input, relation, sourceInformation); | 2715 checkObject(input, relation, sourceInformation); |
2692 js.Expression objectTest = pop(); | 2716 js.Expression objectTest = pop(); |
2693 checkType(input, interceptor, type, sourceInformation, negative: negative); | 2717 checkType(input, interceptor, type, sourceInformation, negative: negative); |
2694 String combiner = negative ? '||' : '&&'; | 2718 String combiner = negative ? '||' : '&&'; |
2695 push(new js.Binary(negative ? '&&' : '||', stringTest, | 2719 push(new js.Binary(negative ? '&&' : '||', stringTest, |
2696 new js.Binary(combiner, objectTest, pop()))); | 2720 new js.Binary(combiner, objectTest, pop()))); |
2697 } | 2721 } |
2698 | 2722 |
2699 void handleListOrSupertypeCheck(HInstruction input, HInstruction interceptor, | 2723 void handleListOrSupertypeCheck(HInstruction input, HInstruction interceptor, |
2700 InterfaceType type, SourceInformation sourceInformation, | 2724 InterfaceType type, SourceInformation sourceInformation, |
2701 {bool negative: false}) { | 2725 {bool negative: false}) { |
2702 assert(!identical(type.element, commonElements.stringClass) && | 2726 assert(!identical(type.element, _commonElements.stringClass) && |
2703 !commonElements.isStringOnlySupertype(type.element) && | 2727 !_commonElements.isStringOnlySupertype(type.element) && |
2704 !commonElements.isNumberOrStringSupertype(type.element)); | 2728 !_commonElements.isNumberOrStringSupertype(type.element)); |
2705 String relation = negative ? '!==' : '==='; | 2729 String relation = negative ? '!==' : '==='; |
2706 checkObject(input, relation, sourceInformation); | 2730 checkObject(input, relation, sourceInformation); |
2707 js.Expression objectTest = pop(); | 2731 js.Expression objectTest = pop(); |
2708 checkArray(input, relation); | 2732 checkArray(input, relation); |
2709 js.Expression arrayTest = pop(); | 2733 js.Expression arrayTest = pop(); |
2710 checkType(input, interceptor, type, sourceInformation, negative: negative); | 2734 checkType(input, interceptor, type, sourceInformation, negative: negative); |
2711 String combiner = negative ? '&&' : '||'; | 2735 String combiner = negative ? '&&' : '||'; |
2712 push(new js.Binary(negative ? '||' : '&&', objectTest, | 2736 push(new js.Binary(negative ? '||' : '&&', objectTest, |
2713 new js.Binary(combiner, arrayTest, pop())) | 2737 new js.Binary(combiner, arrayTest, pop())) |
2714 .withSourceInformation(sourceInformation)); | 2738 .withSourceInformation(sourceInformation)); |
2715 } | 2739 } |
2716 | 2740 |
2717 void visitIs(HIs node) { | 2741 void visitIs(HIs node) { |
2718 emitIs(node, "===", node.sourceInformation); | 2742 emitIs(node, "===", node.sourceInformation); |
2719 } | 2743 } |
2720 | 2744 |
2721 void visitIsViaInterceptor(HIsViaInterceptor node) { | 2745 void visitIsViaInterceptor(HIsViaInterceptor node) { |
2722 emitIsViaInterceptor(node, node.sourceInformation, negative: false); | 2746 emitIsViaInterceptor(node, node.sourceInformation, negative: false); |
2723 } | 2747 } |
2724 | 2748 |
2725 void emitIs(HIs node, String relation, SourceInformation sourceInformation) { | 2749 void emitIs(HIs node, String relation, SourceInformation sourceInformation) { |
2726 DartType type = node.typeExpression; | 2750 DartType type = node.typeExpression; |
2727 registry.registerTypeUse(new TypeUse.isCheck(type)); | 2751 _registry.registerTypeUse(new TypeUse.isCheck(type)); |
2728 HInstruction input = node.expression; | 2752 HInstruction input = node.expression; |
2729 | 2753 |
2730 // If this is changed to single == there are several places below that must | 2754 // If this is changed to single == there are several places below that must |
2731 // be changed to match. | 2755 // be changed to match. |
2732 assert(relation == '===' || relation == '!=='); | 2756 assert(relation == '===' || relation == '!=='); |
2733 bool negative = relation == '!=='; | 2757 bool negative = relation == '!=='; |
2734 | 2758 |
2735 if (node.isVariableCheck || node.isCompoundCheck) { | 2759 if (node.isVariableCheck || node.isCompoundCheck) { |
2736 use(node.checkCall); | 2760 use(node.checkCall); |
2737 if (negative) push(new js.Prefix('!', pop())); | 2761 if (negative) push(new js.Prefix('!', pop())); |
2738 } else { | 2762 } else { |
2739 assert(node.isRawCheck); | 2763 assert(node.isRawCheck); |
2740 HInstruction interceptor = node.interceptor; | 2764 HInstruction interceptor = node.interceptor; |
2741 InterfaceType interfaceType = type; | 2765 InterfaceType interfaceType = type; |
2742 ClassEntity element = interfaceType.element; | 2766 ClassEntity element = interfaceType.element; |
2743 if (element == commonElements.nullClass) { | 2767 if (element == _commonElements.nullClass) { |
2744 if (negative) { | 2768 if (negative) { |
2745 checkNonNull(input); | 2769 checkNonNull(input); |
2746 } else { | 2770 } else { |
2747 checkNull(input); | 2771 checkNull(input); |
2748 } | 2772 } |
2749 } else if (element == | 2773 } else if (element == |
2750 commonElements.objectClass /* || type.treatAsDynamic*/) { | 2774 _commonElements.objectClass /* || type.treatAsDynamic*/) { |
2751 // The constant folder also does this optimization, but we make | 2775 // The constant folder also does this optimization, but we make |
2752 // it safe by assuming it may have not run. | 2776 // it safe by assuming it may have not run. |
2753 push(newLiteralBool(!negative, sourceInformation)); | 2777 push(newLiteralBool(!negative, sourceInformation)); |
2754 } else if (element == commonElements.stringClass) { | 2778 } else if (element == _commonElements.stringClass) { |
2755 checkString(input, relation, sourceInformation); | 2779 checkString(input, relation, sourceInformation); |
2756 } else if (element == commonElements.doubleClass) { | 2780 } else if (element == _commonElements.doubleClass) { |
2757 checkDouble(input, relation, sourceInformation); | 2781 checkDouble(input, relation, sourceInformation); |
2758 } else if (element == commonElements.numClass) { | 2782 } else if (element == _commonElements.numClass) { |
2759 checkNum(input, relation, sourceInformation); | 2783 checkNum(input, relation, sourceInformation); |
2760 } else if (element == commonElements.boolClass) { | 2784 } else if (element == _commonElements.boolClass) { |
2761 checkBool(input, relation, sourceInformation); | 2785 checkBool(input, relation, sourceInformation); |
2762 } else if (element == commonElements.intClass) { | 2786 } else if (element == _commonElements.intClass) { |
2763 // The is check in the code tells us that it might not be an | 2787 // The is check in the code tells us that it might not be an |
2764 // int. So we do a typeof first to avoid possible | 2788 // int. So we do a typeof first to avoid possible |
2765 // deoptimizations on the JS engine due to the Math.floor check. | 2789 // deoptimizations on the JS engine due to the Math.floor check. |
2766 checkNum(input, relation, sourceInformation); | 2790 checkNum(input, relation, sourceInformation); |
2767 js.Expression numTest = pop(); | 2791 js.Expression numTest = pop(); |
2768 checkBigInt(input, relation, sourceInformation); | 2792 checkBigInt(input, relation, sourceInformation); |
2769 push(new js.Binary(negative ? '||' : '&&', numTest, pop()) | 2793 push(new js.Binary(negative ? '||' : '&&', numTest, pop()) |
2770 .withSourceInformation(sourceInformation)); | 2794 .withSourceInformation(sourceInformation)); |
2771 } else if (node.useInstanceOf) { | 2795 } else if (node.useInstanceOf) { |
2772 assert(interceptor == null); | 2796 assert(interceptor == null); |
2773 checkTypeViaInstanceof(input, type, sourceInformation, | 2797 checkTypeViaInstanceof(input, type, sourceInformation, |
2774 negative: negative); | 2798 negative: negative); |
2775 } else if (commonElements.isNumberOrStringSupertype(element)) { | 2799 } else if (_commonElements.isNumberOrStringSupertype(element)) { |
2776 handleNumberOrStringSupertypeCheck( | 2800 handleNumberOrStringSupertypeCheck( |
2777 input, interceptor, type, sourceInformation, | 2801 input, interceptor, type, sourceInformation, |
2778 negative: negative); | 2802 negative: negative); |
2779 } else if (commonElements.isStringOnlySupertype(element)) { | 2803 } else if (_commonElements.isStringOnlySupertype(element)) { |
2780 handleStringSupertypeCheck(input, interceptor, type, sourceInformation, | 2804 handleStringSupertypeCheck(input, interceptor, type, sourceInformation, |
2781 negative: negative); | 2805 negative: negative); |
2782 } else if (element == commonElements.listClass || | 2806 } else if (element == _commonElements.listClass || |
2783 commonElements.isListSupertype(element)) { | 2807 _commonElements.isListSupertype(element)) { |
2784 handleListOrSupertypeCheck(input, interceptor, type, sourceInformation, | 2808 handleListOrSupertypeCheck(input, interceptor, type, sourceInformation, |
2785 negative: negative); | 2809 negative: negative); |
2786 } else if (type.isFunctionType) { | 2810 } else if (type.isFunctionType) { |
2787 checkType(input, interceptor, type, sourceInformation, | 2811 checkType(input, interceptor, type, sourceInformation, |
2788 negative: negative); | 2812 negative: negative); |
2789 } else if ((input.canBePrimitive(closedWorld) && | 2813 } else if ((input.canBePrimitive(_closedWorld) && |
2790 !input.canBePrimitiveArray(closedWorld)) || | 2814 !input.canBePrimitiveArray(_closedWorld)) || |
2791 input.canBeNull()) { | 2815 input.canBeNull()) { |
2792 checkObject(input, relation, node.sourceInformation); | 2816 checkObject(input, relation, node.sourceInformation); |
2793 js.Expression objectTest = pop(); | 2817 js.Expression objectTest = pop(); |
2794 checkType(input, interceptor, type, sourceInformation, | 2818 checkType(input, interceptor, type, sourceInformation, |
2795 negative: negative); | 2819 negative: negative); |
2796 push(new js.Binary(negative ? '||' : '&&', objectTest, pop()) | 2820 push(new js.Binary(negative ? '||' : '&&', objectTest, pop()) |
2797 .withSourceInformation(sourceInformation)); | 2821 .withSourceInformation(sourceInformation)); |
2798 } else { | 2822 } else { |
2799 checkType(input, interceptor, type, sourceInformation, | 2823 checkType(input, interceptor, type, sourceInformation, |
2800 negative: negative); | 2824 negative: negative); |
(...skipping 10 matching lines...) Expand all Loading... |
2811 } | 2835 } |
2812 | 2836 |
2813 js.Expression generateReceiverOrArgumentTypeTest(HTypeConversion node) { | 2837 js.Expression generateReceiverOrArgumentTypeTest(HTypeConversion node) { |
2814 HInstruction input = node.checkedInput; | 2838 HInstruction input = node.checkedInput; |
2815 TypeMask inputType = node.inputType ?? input.instructionType; | 2839 TypeMask inputType = node.inputType ?? input.instructionType; |
2816 TypeMask checkedType = node.checkedType; | 2840 TypeMask checkedType = node.checkedType; |
2817 // Figure out if it is beneficial to turn this into a null check. | 2841 // Figure out if it is beneficial to turn this into a null check. |
2818 // V8 generally prefers 'typeof' checks, but for integers and | 2842 // V8 generally prefers 'typeof' checks, but for integers and |
2819 // indexable primitives we cannot compile this test into a single | 2843 // indexable primitives we cannot compile this test into a single |
2820 // typeof check so the null check is cheaper. | 2844 // typeof check so the null check is cheaper. |
2821 bool isIntCheck = checkedType.containsOnlyInt(closedWorld); | 2845 bool isIntCheck = checkedType.containsOnlyInt(_closedWorld); |
2822 bool turnIntoNumCheck = | 2846 bool turnIntoNumCheck = |
2823 isIntCheck && inputType.containsOnlyInt(closedWorld); | 2847 isIntCheck && inputType.containsOnlyInt(_closedWorld); |
2824 bool turnIntoNullCheck = !turnIntoNumCheck && | 2848 bool turnIntoNullCheck = !turnIntoNumCheck && |
2825 (checkedType.nullable() == inputType) && | 2849 (checkedType.nullable() == inputType) && |
2826 (isIntCheck || | 2850 (isIntCheck || |
2827 checkedType.satisfies(helpers.jsIndexableClass, closedWorld)); | 2851 checkedType.satisfies(_helpers.jsIndexableClass, _closedWorld)); |
2828 | 2852 |
2829 if (turnIntoNullCheck) { | 2853 if (turnIntoNullCheck) { |
2830 use(input); | 2854 use(input); |
2831 return new js.Binary("==", pop(), new js.LiteralNull()) | 2855 return new js.Binary("==", pop(), new js.LiteralNull()) |
2832 .withSourceInformation(input.sourceInformation); | 2856 .withSourceInformation(input.sourceInformation); |
2833 } else if (isIntCheck && !turnIntoNumCheck) { | 2857 } else if (isIntCheck && !turnIntoNumCheck) { |
2834 // input is !int | 2858 // input is !int |
2835 checkBigInt(input, '!==', input.sourceInformation); | 2859 checkBigInt(input, '!==', input.sourceInformation); |
2836 return pop(); | 2860 return pop(); |
2837 } else if (turnIntoNumCheck || checkedType.containsOnlyNum(closedWorld)) { | 2861 } else if (turnIntoNumCheck || checkedType.containsOnlyNum(_closedWorld)) { |
2838 // input is !num | 2862 // input is !num |
2839 checkNum(input, '!==', input.sourceInformation); | 2863 checkNum(input, '!==', input.sourceInformation); |
2840 return pop(); | 2864 return pop(); |
2841 } else if (checkedType.containsOnlyBool(closedWorld)) { | 2865 } else if (checkedType.containsOnlyBool(_closedWorld)) { |
2842 // input is !bool | 2866 // input is !bool |
2843 checkBool(input, '!==', input.sourceInformation); | 2867 checkBool(input, '!==', input.sourceInformation); |
2844 return pop(); | 2868 return pop(); |
2845 } else if (checkedType.containsOnlyString(closedWorld)) { | 2869 } else if (checkedType.containsOnlyString(_closedWorld)) { |
2846 // input is !string | 2870 // input is !string |
2847 checkString(input, '!==', input.sourceInformation); | 2871 checkString(input, '!==', input.sourceInformation); |
2848 return pop(); | 2872 return pop(); |
2849 } | 2873 } |
2850 reporter.internalError(input, 'Unexpected check: $checkedType.'); | 2874 throw new SpannableAssertionFailure( |
2851 return null; | 2875 input, 'Unexpected check: $checkedType.'); |
2852 } | 2876 } |
2853 | 2877 |
2854 void visitTypeConversion(HTypeConversion node) { | 2878 void visitTypeConversion(HTypeConversion node) { |
2855 if (node.isArgumentTypeCheck || node.isReceiverTypeCheck) { | 2879 if (node.isArgumentTypeCheck || node.isReceiverTypeCheck) { |
2856 js.Expression test = generateReceiverOrArgumentTypeTest(node); | 2880 js.Expression test = generateReceiverOrArgumentTypeTest(node); |
2857 js.Block oldContainer = currentContainer; | 2881 js.Block oldContainer = currentContainer; |
2858 js.Statement body = new js.Block.empty(); | 2882 js.Statement body = new js.Block.empty(); |
2859 currentContainer = body; | 2883 currentContainer = body; |
2860 if (node.isArgumentTypeCheck) { | 2884 if (node.isArgumentTypeCheck) { |
2861 generateThrowWithHelper( | 2885 generateThrowWithHelper( |
2862 helpers.throwIllegalArgumentException, node.checkedInput, | 2886 _helpers.throwIllegalArgumentException, node.checkedInput, |
2863 sourceInformation: node.sourceInformation); | 2887 sourceInformation: node.sourceInformation); |
2864 } else if (node.isReceiverTypeCheck) { | 2888 } else if (node.isReceiverTypeCheck) { |
2865 use(node.checkedInput); | 2889 use(node.checkedInput); |
2866 js.Name methodName = | 2890 js.Name methodName = |
2867 backend.namer.invocationName(node.receiverTypeCheckSelector); | 2891 _namer.invocationName(node.receiverTypeCheckSelector); |
2868 js.Expression call = js.propertyCall(pop(), methodName, []); | 2892 js.Expression call = js.propertyCall(pop(), methodName, []); |
2869 pushStatement(new js.Return(call)); | 2893 pushStatement(new js.Return(call)); |
2870 } | 2894 } |
2871 currentContainer = oldContainer; | 2895 currentContainer = oldContainer; |
2872 body = unwrapStatement(body); | 2896 body = unwrapStatement(body); |
2873 pushStatement(new js.If.noElse(test, body) | 2897 pushStatement(new js.If.noElse(test, body) |
2874 .withSourceInformation(node.sourceInformation)); | 2898 .withSourceInformation(node.sourceInformation)); |
2875 return; | 2899 return; |
2876 } | 2900 } |
2877 | 2901 |
2878 assert(node.isCheckedModeCheck || node.isCastTypeCheck); | 2902 assert(node.isCheckedModeCheck || node.isCastTypeCheck); |
2879 DartType type = node.typeExpression; | 2903 DartType type = node.typeExpression; |
2880 assert(!type.isTypedef); | 2904 assert(!type.isTypedef); |
2881 assert(!type.isDynamic); | 2905 assert(!type.isDynamic); |
2882 if (type.isFunctionType) { | 2906 if (type.isFunctionType) { |
2883 // TODO(5022): We currently generate $isFunction checks for | 2907 // TODO(5022): We currently generate $isFunction checks for |
2884 // function types. | 2908 // function types. |
2885 registry.registerTypeUse( | 2909 _registry |
2886 new TypeUse.isCheck(compiler.commonElements.functionType)); | 2910 .registerTypeUse(new TypeUse.isCheck(_commonElements.functionType)); |
2887 } | 2911 } |
2888 registry.registerTypeUse(new TypeUse.isCheck(type)); | 2912 _registry.registerTypeUse(new TypeUse.isCheck(type)); |
2889 | 2913 |
2890 CheckedModeHelper helper; | 2914 CheckedModeHelper helper; |
2891 if (node.isBooleanConversionCheck) { | 2915 if (node.isBooleanConversionCheck) { |
2892 helper = const CheckedModeHelper('boolConversionCheck'); | 2916 helper = const CheckedModeHelper('boolConversionCheck'); |
2893 } else { | 2917 } else { |
2894 helper = backend.checkedModeHelpers | 2918 helper = _checkedModeHelpers.getCheckedModeHelper(type, |
2895 .getCheckedModeHelper(type, typeCast: node.isCastTypeCheck); | 2919 typeCast: node.isCastTypeCheck); |
2896 } | 2920 } |
2897 | 2921 |
2898 push(helper.generateCall(this, node)); | 2922 StaticUse staticUse = helper.getStaticUse(_helpers); |
| 2923 _registry.registerStaticUse(staticUse); |
| 2924 List<js.Expression> arguments = <js.Expression>[]; |
| 2925 use(node.checkedInput); |
| 2926 arguments.add(pop()); |
| 2927 helper.generateAdditionalArguments(this, _namer, node, arguments); |
| 2928 push(new js.Call( |
| 2929 _emitter.staticFunctionAccess(staticUse.element), arguments)); |
2899 } | 2930 } |
2900 | 2931 |
2901 void visitTypeKnown(HTypeKnown node) { | 2932 void visitTypeKnown(HTypeKnown node) { |
2902 // [HTypeKnown] instructions are removed before generating code. | 2933 // [HTypeKnown] instructions are removed before generating code. |
2903 assert(false); | 2934 assert(false); |
2904 } | 2935 } |
2905 | 2936 |
2906 void visitTypeInfoReadRaw(HTypeInfoReadRaw node) { | 2937 void visitTypeInfoReadRaw(HTypeInfoReadRaw node) { |
2907 use(node.inputs[0]); | 2938 use(node.inputs[0]); |
2908 js.Expression receiver = pop(); | 2939 js.Expression receiver = pop(); |
2909 push(js.js(r'#.#', [receiver, backend.namer.rtiFieldJsName])); | 2940 push(js.js(r'#.#', [receiver, _namer.rtiFieldJsName])); |
2910 } | 2941 } |
2911 | 2942 |
2912 void visitTypeInfoReadVariable(HTypeInfoReadVariable node) { | 2943 void visitTypeInfoReadVariable(HTypeInfoReadVariable node) { |
2913 TypeVariableEntity element = node.variable.element; | 2944 TypeVariableEntity element = node.variable.element; |
2914 | 2945 |
2915 int index = element.index; | 2946 int index = element.index; |
2916 HInstruction object = node.object; | 2947 HInstruction object = node.object; |
2917 use(object); | 2948 use(object); |
2918 js.Expression receiver = pop(); | 2949 js.Expression receiver = pop(); |
2919 | 2950 |
2920 if (typeVariableAccessNeedsSubstitution(element, object.instructionType)) { | 2951 if (typeVariableAccessNeedsSubstitution(element, object.instructionType)) { |
2921 js.Expression typeName = | 2952 js.Expression typeName = |
2922 js.quoteName(backend.namer.runtimeTypeName(element.typeDeclaration)); | 2953 js.quoteName(_namer.runtimeTypeName(element.typeDeclaration)); |
2923 FunctionEntity helperElement = helpers.getRuntimeTypeArgument; | 2954 FunctionEntity helperElement = _helpers.getRuntimeTypeArgument; |
2924 registry.registerStaticUse( | 2955 _registry.registerStaticUse( |
2925 new StaticUse.staticInvoke(helperElement, CallStructure.THREE_ARGS)); | 2956 new StaticUse.staticInvoke(helperElement, CallStructure.THREE_ARGS)); |
2926 js.Expression helper = | 2957 js.Expression helper = _emitter.staticFunctionAccess(helperElement); |
2927 backend.emitter.staticFunctionAccess(helperElement); | |
2928 push(js.js( | 2958 push(js.js( |
2929 r'#(#, #, #)', [helper, receiver, typeName, js.js.number(index)])); | 2959 r'#(#, #, #)', [helper, receiver, typeName, js.js.number(index)])); |
2930 } else { | 2960 } else { |
2931 FunctionEntity helperElement = helpers.getTypeArgumentByIndex; | 2961 FunctionEntity helperElement = _helpers.getTypeArgumentByIndex; |
2932 registry.registerStaticUse( | 2962 _registry.registerStaticUse( |
2933 new StaticUse.staticInvoke(helperElement, CallStructure.TWO_ARGS)); | 2963 new StaticUse.staticInvoke(helperElement, CallStructure.TWO_ARGS)); |
2934 js.Expression helper = | 2964 js.Expression helper = _emitter.staticFunctionAccess(helperElement); |
2935 backend.emitter.staticFunctionAccess(helperElement); | |
2936 push(js.js(r'#(#, #)', [helper, receiver, js.js.number(index)])); | 2965 push(js.js(r'#(#, #)', [helper, receiver, js.js.number(index)])); |
2937 } | 2966 } |
2938 } | 2967 } |
2939 | 2968 |
2940 void visitTypeInfoExpression(HTypeInfoExpression node) { | 2969 void visitTypeInfoExpression(HTypeInfoExpression node) { |
2941 List<js.Expression> arguments = <js.Expression>[]; | 2970 List<js.Expression> arguments = <js.Expression>[]; |
2942 for (HInstruction input in node.inputs) { | 2971 for (HInstruction input in node.inputs) { |
2943 use(input); | 2972 use(input); |
2944 arguments.add(pop()); | 2973 arguments.add(pop()); |
2945 } | 2974 } |
2946 | 2975 |
2947 switch (node.kind) { | 2976 switch (node.kind) { |
2948 case TypeInfoExpressionKind.COMPLETE: | 2977 case TypeInfoExpressionKind.COMPLETE: |
2949 int index = 0; | 2978 int index = 0; |
2950 js.Expression result = backend.rtiEncoder.getTypeRepresentation( | 2979 js.Expression result = _rtiEncoder.getTypeRepresentation( |
2951 node.dartType, (TypeVariableType variable) => arguments[index++]); | 2980 node.dartType, (TypeVariableType variable) => arguments[index++]); |
2952 assert(index == node.inputs.length); | 2981 assert(index == node.inputs.length); |
2953 push(result); | 2982 push(result); |
2954 return; | 2983 return; |
2955 | 2984 |
2956 case TypeInfoExpressionKind.INSTANCE: | 2985 case TypeInfoExpressionKind.INSTANCE: |
2957 // We expect only flat types for the INSTANCE representation. | 2986 // We expect only flat types for the INSTANCE representation. |
2958 assert((node.dartType as InterfaceType).typeArguments.length == | 2987 assert((node.dartType as InterfaceType).typeArguments.length == |
2959 arguments.length); | 2988 arguments.length); |
2960 registry.registerInstantiatedClass(commonElements.listClass); | 2989 _registry.registerInstantiatedClass(_commonElements.listClass); |
2961 push(new js.ArrayInitializer(arguments) | 2990 push(new js.ArrayInitializer(arguments) |
2962 .withSourceInformation(node.sourceInformation)); | 2991 .withSourceInformation(node.sourceInformation)); |
2963 } | 2992 } |
2964 } | 2993 } |
2965 | 2994 |
2966 bool typeVariableAccessNeedsSubstitution( | 2995 bool typeVariableAccessNeedsSubstitution( |
2967 TypeVariableEntity element, TypeMask receiverMask) { | 2996 TypeVariableEntity element, TypeMask receiverMask) { |
2968 ClassEntity cls = element.typeDeclaration; | 2997 ClassEntity cls = element.typeDeclaration; |
2969 | 2998 |
2970 // See if the receiver type narrows the set of classes to ones that can be | 2999 // See if the receiver type narrows the set of classes to ones that can be |
2971 // indexed. | 3000 // indexed. |
2972 // TODO(sra): Currently the only convenient query is [singleClass]. We | 3001 // TODO(sra): Currently the only convenient query is [singleClass]. We |
2973 // should iterate over all the concrete classes in [receiverMask]. | 3002 // should iterate over all the concrete classes in [receiverMask]. |
2974 ClassEntity receiverClass = receiverMask.singleClass(closedWorld); | 3003 ClassEntity receiverClass = receiverMask.singleClass(_closedWorld); |
2975 if (receiverClass != null) { | 3004 if (receiverClass != null) { |
2976 if (backend.rtiSubstitutions.isTrivialSubstitution(receiverClass, cls)) { | 3005 if (_rtiSubstitutions.isTrivialSubstitution(receiverClass, cls)) { |
2977 return false; | 3006 return false; |
2978 } | 3007 } |
2979 } | 3008 } |
2980 | 3009 |
2981 if (closedWorld.isUsedAsMixin(cls)) return true; | 3010 if (_closedWorld.isUsedAsMixin(cls)) return true; |
2982 | 3011 |
2983 return closedWorld.anyStrictSubclassOf(cls, (ClassEntity subclass) { | 3012 return _closedWorld.anyStrictSubclassOf(cls, (ClassEntity subclass) { |
2984 return !backend.rtiSubstitutions.isTrivialSubstitution(subclass, cls); | 3013 return !_rtiSubstitutions.isTrivialSubstitution(subclass, cls); |
2985 }); | 3014 }); |
2986 } | 3015 } |
2987 | 3016 |
2988 @override | 3017 @override |
2989 void visitRef(HRef node) { | 3018 void visitRef(HRef node) { |
2990 visit(node.value); | 3019 visit(node.value); |
2991 } | 3020 } |
2992 } | 3021 } |
OLD | NEW |