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

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

Issue 2777393003: Remove use JavaScriptBackend and Compiler from SsaCodeGenerator (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 import 'dart:math' as math; 5 import 'dart:math' as math;
6 import '../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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698