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

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

Issue 1859343004: dartfmt pkg/compiler (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 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/source_file_provider.dart ('k') | pkg/compiler/lib/src/ssa/codegen.dart » ('j') | 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:collection'; 5 import 'dart:collection';
6 6
7 import 'package:js_runtime/shared/embedded_names.dart'; 7 import 'package:js_runtime/shared/embedded_names.dart';
8 8
9 import '../closure.dart'; 9 import '../closure.dart';
10 import '../common.dart'; 10 import '../common.dart';
11 import '../common/codegen.dart' show 11 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
12 CodegenRegistry, 12 import '../common/names.dart' show Identifiers, Selectors;
13 CodegenWorkItem; 13 import '../common/tasks.dart' show CompilerTask;
14 import '../common/names.dart' show 14 import '../compiler.dart' show Compiler;
15 Identifiers,
16 Selectors;
17 import '../common/tasks.dart' show
18 CompilerTask;
19 import '../compiler.dart' show
20 Compiler;
21 import '../constants/constant_system.dart'; 15 import '../constants/constant_system.dart';
22 import '../constants/expressions.dart'; 16 import '../constants/expressions.dart';
23 import '../constants/values.dart'; 17 import '../constants/values.dart';
24 import '../core_types.dart' show 18 import '../core_types.dart' show CoreClasses;
25 CoreClasses;
26 import '../dart_types.dart'; 19 import '../dart_types.dart';
27 import '../diagnostics/messages.dart' show 20 import '../diagnostics/messages.dart' show Message, MessageTemplate;
28 Message,
29 MessageTemplate;
30 import '../elements/elements.dart'; 21 import '../elements/elements.dart';
31 import '../elements/modelx.dart' show 22 import '../elements/modelx.dart'
32 ConstructorBodyElementX, 23 show ConstructorBodyElementX, ElementX, VariableElementX;
33 ElementX,
34 VariableElementX;
35 import '../io/source_information.dart'; 24 import '../io/source_information.dart';
36 import '../js/js.dart' as js; 25 import '../js/js.dart' as js;
37 import '../js_backend/backend_helpers.dart' show 26 import '../js_backend/backend_helpers.dart' show BackendHelpers;
38 BackendHelpers;
39 import '../js_backend/js_backend.dart'; 27 import '../js_backend/js_backend.dart';
40 import '../js_emitter/js_emitter.dart' show 28 import '../js_emitter/js_emitter.dart' show CodeEmitterTask, NativeEmitter;
41 CodeEmitterTask,
42 NativeEmitter;
43 import '../native/native.dart' as native; 29 import '../native/native.dart' as native;
44 import '../resolution/operators.dart'; 30 import '../resolution/operators.dart';
45 import '../resolution/semantic_visitor.dart'; 31 import '../resolution/semantic_visitor.dart';
46 import '../resolution/tree_elements.dart' show 32 import '../resolution/tree_elements.dart' show TreeElements;
47 TreeElements;
48 import '../tree/tree.dart' as ast; 33 import '../tree/tree.dart' as ast;
49 import '../types/types.dart'; 34 import '../types/types.dart';
50 import '../universe/call_structure.dart' show 35 import '../universe/call_structure.dart' show CallStructure;
51 CallStructure; 36 import '../universe/selector.dart' show Selector;
52 import '../universe/selector.dart' show 37 import '../universe/side_effects.dart' show SideEffects;
53 Selector; 38 import '../universe/use.dart' show DynamicUse, StaticUse, TypeUse;
54 import '../universe/side_effects.dart' show
55 SideEffects;
56 import '../universe/use.dart' show
57 DynamicUse,
58 StaticUse,
59 TypeUse;
60 import '../util/util.dart'; 39 import '../util/util.dart';
61 import '../world.dart' show 40 import '../world.dart' show ClassWorld, World;
62 ClassWorld,
63 World;
64 import '../dump_info.dart' show InfoReporter; 41 import '../dump_info.dart' show InfoReporter;
65 42
66 import 'nodes.dart'; 43 import 'nodes.dart';
67 import 'codegen.dart'; 44 import 'codegen.dart';
68 import 'optimize.dart'; 45 import 'optimize.dart';
69 import 'types.dart'; 46 import 'types.dart';
70 47
71 class SsaFunctionCompiler implements FunctionCompiler { 48 class SsaFunctionCompiler implements FunctionCompiler {
72 final SsaCodeGeneratorTask generator; 49 final SsaCodeGeneratorTask generator;
73 final SsaBuilderTask builder; 50 final SsaBuilderTask builder;
74 final SsaOptimizerTask optimizer; 51 final SsaOptimizerTask optimizer;
75 final JavaScriptBackend backend; 52 final JavaScriptBackend backend;
76 53
77 SsaFunctionCompiler(JavaScriptBackend backend, 54 SsaFunctionCompiler(JavaScriptBackend backend,
78 SourceInformationStrategy sourceInformationFactory) 55 SourceInformationStrategy sourceInformationFactory)
79 : generator = new SsaCodeGeneratorTask(backend, sourceInformationFactory), 56 : generator = new SsaCodeGeneratorTask(backend, sourceInformationFactory),
80 builder = new SsaBuilderTask(backend, sourceInformationFactory), 57 builder = new SsaBuilderTask(backend, sourceInformationFactory),
81 optimizer = new SsaOptimizerTask(backend), 58 optimizer = new SsaOptimizerTask(backend),
82 backend = backend; 59 backend = backend;
83 60
84 /// Generates JavaScript code for `work.element`. 61 /// Generates JavaScript code for `work.element`.
85 /// Using the ssa builder, optimizer and codegenerator. 62 /// Using the ssa builder, optimizer and codegenerator.
86 js.Fun compile(CodegenWorkItem work) { 63 js.Fun compile(CodegenWorkItem work) {
87 HGraph graph = builder.build(work); 64 HGraph graph = builder.build(work);
88 optimizer.optimize(work, graph); 65 optimizer.optimize(work, graph);
(...skipping 24 matching lines...) Expand all
113 } 90 }
114 91
115 class SsaBuilderTask extends CompilerTask { 92 class SsaBuilderTask extends CompilerTask {
116 final CodeEmitterTask emitter; 93 final CodeEmitterTask emitter;
117 final JavaScriptBackend backend; 94 final JavaScriptBackend backend;
118 final SourceInformationStrategy sourceInformationFactory; 95 final SourceInformationStrategy sourceInformationFactory;
119 96
120 String get name => 'SSA builder'; 97 String get name => 'SSA builder';
121 98
122 SsaBuilderTask(JavaScriptBackend backend, this.sourceInformationFactory) 99 SsaBuilderTask(JavaScriptBackend backend, this.sourceInformationFactory)
123 : emitter = backend.emitter, 100 : emitter = backend.emitter,
124 backend = backend, 101 backend = backend,
125 super(backend.compiler); 102 super(backend.compiler);
126 103
127 DiagnosticReporter get reporter => compiler.reporter; 104 DiagnosticReporter get reporter => compiler.reporter;
128 105
129 HGraph build(CodegenWorkItem work) { 106 HGraph build(CodegenWorkItem work) {
130 return measure(() { 107 return measure(() {
131 Element element = work.element.implementation; 108 Element element = work.element.implementation;
132 return reporter.withCurrentElement(element, () { 109 return reporter.withCurrentElement(element, () {
133 SsaBuilder builder = 110 SsaBuilder builder = new SsaBuilder(
134 new SsaBuilder(work.element.implementation, 111 work.element.implementation,
135 work.resolutionTree, work.compilationContext, work.registry, 112 work.resolutionTree,
136 backend, emitter.nativeEmitter, 113 work.compilationContext,
137 sourceInformationFactory); 114 work.registry,
115 backend,
116 emitter.nativeEmitter,
117 sourceInformationFactory);
138 HGraph graph = builder.build(); 118 HGraph graph = builder.build();
139 119
140 // Default arguments are handled elsewhere, but we must ensure 120 // Default arguments are handled elsewhere, but we must ensure
141 // that the default values are computed during codegen. 121 // that the default values are computed during codegen.
142 if (!identical(element.kind, ElementKind.FIELD)) { 122 if (!identical(element.kind, ElementKind.FIELD)) {
143 FunctionElement function = element; 123 FunctionElement function = element;
144 FunctionSignature signature = function.functionSignature; 124 FunctionSignature signature = function.functionSignature;
145 signature.forEachOptionalParameter((ParameterElement parameter) { 125 signature.forEachOptionalParameter((ParameterElement parameter) {
146 // This ensures the default value will be computed. 126 // This ensures the default value will be computed.
147 ConstantValue constant = 127 ConstantValue constant =
148 backend.constants.getConstantValueForVariable(parameter); 128 backend.constants.getConstantValueForVariable(parameter);
149 work.registry.registerCompileTimeConstant(constant); 129 work.registry.registerCompileTimeConstant(constant);
150 }); 130 });
151 } 131 }
152 if (compiler.tracer.isEnabled) { 132 if (compiler.tracer.isEnabled) {
153 String name; 133 String name;
154 if (element.isClassMember) { 134 if (element.isClassMember) {
155 String className = element.enclosingClass.name; 135 String className = element.enclosingClass.name;
156 String memberName = element.name; 136 String memberName = element.name;
157 name = "$className.$memberName"; 137 name = "$className.$memberName";
158 if (element.isGenerativeConstructorBody) { 138 if (element.isGenerativeConstructorBody) {
159 name = "$name (body)"; 139 name = "$name (body)";
160 } 140 }
161 } else { 141 } else {
162 name = "${element.name}"; 142 name = "${element.name}";
163 } 143 }
164 compiler.tracer.traceCompilation( 144 compiler.tracer.traceCompilation(name, work.compilationContext);
165 name, work.compilationContext);
166 compiler.tracer.traceGraph('builder', graph); 145 compiler.tracer.traceGraph('builder', graph);
167 } 146 }
168 return graph; 147 return graph;
169 }); 148 });
170 }); 149 });
171 } 150 }
172
173 } 151 }
174 152
175 /** 153 /**
176 * Keeps track of locals (including parameters and phis) when building. The 154 * Keeps track of locals (including parameters and phis) when building. The
177 * 'this' reference is treated as parameter and hence handled by this class, 155 * 'this' reference is treated as parameter and hence handled by this class,
178 * too. 156 * too.
179 */ 157 */
180 class LocalsHandler { 158 class LocalsHandler {
181 /** 159 /**
182 * The values of locals that can be directly accessed (without redirections 160 * The values of locals that can be directly accessed (without redirections
183 * to boxes or closure-fields). 161 * to boxes or closure-fields).
184 * 162 *
185 * [directLocals] is iterated, so it is "insertion ordered" to make the 163 * [directLocals] is iterated, so it is "insertion ordered" to make the
186 * iteration order a function only of insertions and not a function of 164 * iteration order a function only of insertions and not a function of
187 * e.g. Element hash codes. I'd prefer to use a SortedMap but some elements 165 * e.g. Element hash codes. I'd prefer to use a SortedMap but some elements
188 * don't have source locations for [Elements.compareByPosition]. 166 * don't have source locations for [Elements.compareByPosition].
189 */ 167 */
190 Map<Local, HInstruction> directLocals = 168 Map<Local, HInstruction> directLocals = new Map<Local, HInstruction>();
191 new Map<Local, HInstruction>();
192 Map<Local, CapturedVariable> redirectionMapping = 169 Map<Local, CapturedVariable> redirectionMapping =
193 new Map<Local, CapturedVariable>(); 170 new Map<Local, CapturedVariable>();
194 SsaBuilder builder; 171 SsaBuilder builder;
195 ClosureClassMap closureData; 172 ClosureClassMap closureData;
196 Map<TypeVariableType, TypeVariableLocal> typeVariableLocals = 173 Map<TypeVariableType, TypeVariableLocal> typeVariableLocals =
197 new Map<TypeVariableType, TypeVariableLocal>(); 174 new Map<TypeVariableType, TypeVariableLocal>();
198 final ExecutableElement executableContext; 175 final ExecutableElement executableContext;
199 176
200 /// The class that defines the current type environment or null if no type 177 /// The class that defines the current type environment or null if no type
201 /// variables are in scope. 178 /// variables are in scope.
(...skipping 14 matching lines...) Expand all
216 /// 193 ///
217 /// [instanceType] is not used if it contains type variables, since these 194 /// [instanceType] is not used if it contains type variables, since these
218 /// might not be in scope or from the current instance. 195 /// might not be in scope or from the current instance.
219 /// 196 ///
220 final InterfaceType instanceType; 197 final InterfaceType instanceType;
221 198
222 SourceInformationBuilder get sourceInformationBuilder { 199 SourceInformationBuilder get sourceInformationBuilder {
223 return builder.sourceInformationBuilder; 200 return builder.sourceInformationBuilder;
224 } 201 }
225 202
226 LocalsHandler(this.builder, this.executableContext, 203 LocalsHandler(
227 InterfaceType instanceType) 204 this.builder, this.executableContext, InterfaceType instanceType)
228 : this.instanceType = 205 : this.instanceType = instanceType == null ||
229 instanceType == null || instanceType.containsTypeVariables 206 instanceType.containsTypeVariables ? null : instanceType;
230 ? null : instanceType;
231 207
232 /// Substituted type variables occurring in [type] into the context of 208 /// Substituted type variables occurring in [type] into the context of
233 /// [contextClass]. 209 /// [contextClass].
234 DartType substInContext(DartType type) { 210 DartType substInContext(DartType type) {
235 if (contextClass != null) { 211 if (contextClass != null) {
236 ClassElement typeContext = Types.getClassContext(type); 212 ClassElement typeContext = Types.getClassContext(type);
237 if (typeContext != null) { 213 if (typeContext != null) {
238 type = type.substByContext( 214 type = type.substByContext(contextClass.asInstanceOf(typeContext));
239 contextClass.asInstanceOf(typeContext));
240 } 215 }
241 } 216 }
242 if (instanceType != null) { 217 if (instanceType != null) {
243 type = type.substByContext(instanceType); 218 type = type.substByContext(instanceType);
244 } 219 }
245 return type; 220 return type;
246 } 221 }
247 222
248 get typesTask => builder.compiler.typesTask; 223 get typesTask => builder.compiler.typesTask;
249 224
(...skipping 18 matching lines...) Expand all
268 assert(redirectionMapping[from] == null); 243 assert(redirectionMapping[from] == null);
269 redirectionMapping[from] = to; 244 redirectionMapping[from] = to;
270 assert(isStoredInClosureField(from) || isBoxed(from)); 245 assert(isStoredInClosureField(from) || isBoxed(from));
271 } 246 }
272 247
273 HInstruction createBox() { 248 HInstruction createBox() {
274 // TODO(floitsch): Clean up this hack. Should we create a box-object by 249 // TODO(floitsch): Clean up this hack. Should we create a box-object by
275 // just creating an empty object literal? 250 // just creating an empty object literal?
276 JavaScriptBackend backend = builder.backend; 251 JavaScriptBackend backend = builder.backend;
277 HInstruction box = new HForeignCode( 252 HInstruction box = new HForeignCode(
278 js.js.parseForeignJS('{}'), 253 js.js.parseForeignJS('{}'), backend.nonNullType, <HInstruction>[],
279 backend.nonNullType,
280 <HInstruction>[],
281 nativeBehavior: native.NativeBehavior.PURE_ALLOCATION); 254 nativeBehavior: native.NativeBehavior.PURE_ALLOCATION);
282 builder.add(box); 255 builder.add(box);
283 return box; 256 return box;
284 } 257 }
285 258
286 /** 259 /**
287 * If the scope (function or loop) [node] has captured variables then this 260 * If the scope (function or loop) [node] has captured variables then this
288 * method creates a box and sets up the redirections. 261 * method creates a box and sets up the redirections.
289 */ 262 */
290 void enterScope(ast.Node node, Element element) { 263 void enterScope(ast.Node node, Element element) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
324 } else { 297 } else {
325 redirectElement(from, to); 298 redirectElement(from, to);
326 } 299 }
327 }); 300 });
328 } 301 }
329 302
330 /** 303 /**
331 * Replaces the current box with a new box and copies over the given list 304 * Replaces the current box with a new box and copies over the given list
332 * of elements from the old box into the new box. 305 * of elements from the old box into the new box.
333 */ 306 */
334 void updateCaptureBox(BoxLocal boxElement, 307 void updateCaptureBox(
335 List<LocalVariableElement> toBeCopiedElements) { 308 BoxLocal boxElement, List<LocalVariableElement> toBeCopiedElements) {
336 // Create a new box and copy over the values from the old box into the 309 // Create a new box and copy over the values from the old box into the
337 // new one. 310 // new one.
338 HInstruction oldBox = readLocal(boxElement); 311 HInstruction oldBox = readLocal(boxElement);
339 HInstruction newBox = createBox(); 312 HInstruction newBox = createBox();
340 for (LocalVariableElement boxedVariable in toBeCopiedElements) { 313 for (LocalVariableElement boxedVariable in toBeCopiedElements) {
341 // [readLocal] uses the [boxElement] to find its box. By replacing it 314 // [readLocal] uses the [boxElement] to find its box. By replacing it
342 // behind its back we can still get to the old values. 315 // behind its back we can still get to the old values.
343 updateLocal(boxElement, oldBox); 316 updateLocal(boxElement, oldBox);
344 HInstruction oldValue = readLocal(boxedVariable); 317 HInstruction oldValue = readLocal(boxedVariable);
345 updateLocal(boxElement, newBox); 318 updateLocal(boxElement, newBox);
346 updateLocal(boxedVariable, oldValue); 319 updateLocal(boxedVariable, oldValue);
347 } 320 }
348 updateLocal(boxElement, newBox); 321 updateLocal(boxElement, newBox);
349 } 322 }
350 323
351 /** 324 /**
352 * Documentation wanted -- johnniwinther 325 * Documentation wanted -- johnniwinther
353 * 326 *
354 * Invariant: [function] must be an implementation element. 327 * Invariant: [function] must be an implementation element.
355 */ 328 */
356 void startFunction(Element element, ast.Node node) { 329 void startFunction(Element element, ast.Node node) {
357 assert(invariant(element, element.isImplementation)); 330 assert(invariant(element, element.isImplementation));
358 Compiler compiler = builder.compiler; 331 Compiler compiler = builder.compiler;
359 closureData = compiler.closureToClassMapper.computeClosureToClassMapping( 332 closureData = compiler.closureToClassMapper
360 element, node, builder.elements); 333 .computeClosureToClassMapping(element, node, builder.elements);
361 334
362 if (element is FunctionElement) { 335 if (element is FunctionElement) {
363 FunctionElement functionElement = element; 336 FunctionElement functionElement = element;
364 FunctionSignature params = functionElement.functionSignature; 337 FunctionSignature params = functionElement.functionSignature;
365 ClosureScope scopeData = closureData.capturingScopes[node]; 338 ClosureScope scopeData = closureData.capturingScopes[node];
366 params.orderedForEachParameter((ParameterElement parameterElement) { 339 params.orderedForEachParameter((ParameterElement parameterElement) {
367 if (element.isGenerativeConstructorBody) { 340 if (element.isGenerativeConstructorBody) {
368 if (scopeData != null && 341 if (scopeData != null &&
369 scopeData.isCapturedVariable(parameterElement)) { 342 scopeData.isCapturedVariable(parameterElement)) {
370 // The parameter will be a field in the box passed as the 343 // The parameter will be a field in the box passed as the
371 // last parameter. So no need to have it. 344 // last parameter. So no need to have it.
372 return; 345 return;
373 } 346 }
374 } 347 }
375 HInstruction parameter = builder.addParameter( 348 HInstruction parameter = builder.addParameter(parameterElement,
376 parameterElement,
377 TypeMaskFactory.inferredTypeForElement(parameterElement, compiler)); 349 TypeMaskFactory.inferredTypeForElement(parameterElement, compiler));
378 builder.parameters[parameterElement] = parameter; 350 builder.parameters[parameterElement] = parameter;
379 directLocals[parameterElement] = parameter; 351 directLocals[parameterElement] = parameter;
380 }); 352 });
381 } 353 }
382 354
383 enterScope(node, element); 355 enterScope(node, element);
384 356
385 // If the freeVariableMapping is not empty, then this function was a 357 // If the freeVariableMapping is not empty, then this function was a
386 // nested closure that captures variables. Redirect the captured 358 // nested closure that captures variables. Redirect the captured
387 // variables to fields in the closure. 359 // variables to fields in the closure.
388 closureData.forEachFreeVariable((Local from, CapturedVariable to) { 360 closureData.forEachFreeVariable((Local from, CapturedVariable to) {
389 redirectElement(from, to); 361 redirectElement(from, to);
390 }); 362 });
391 JavaScriptBackend backend = compiler.backend; 363 JavaScriptBackend backend = compiler.backend;
392 if (closureData.isClosure) { 364 if (closureData.isClosure) {
393 // Inside closure redirect references to itself to [:this:]. 365 // Inside closure redirect references to itself to [:this:].
394 HThis thisInstruction = new HThis(closureData.thisLocal, 366 HThis thisInstruction =
395 backend.nonNullType); 367 new HThis(closureData.thisLocal, backend.nonNullType);
396 builder.graph.thisInstruction = thisInstruction; 368 builder.graph.thisInstruction = thisInstruction;
397 builder.graph.entry.addAtEntry(thisInstruction); 369 builder.graph.entry.addAtEntry(thisInstruction);
398 updateLocal(closureData.closureElement, thisInstruction); 370 updateLocal(closureData.closureElement, thisInstruction);
399 } else if (element.isInstanceMember) { 371 } else if (element.isInstanceMember) {
400 // Once closures have been mapped to classes their instance members might 372 // Once closures have been mapped to classes their instance members might
401 // not have any thisElement if the closure was created inside a static 373 // not have any thisElement if the closure was created inside a static
402 // context. 374 // context.
403 HThis thisInstruction = new HThis( 375 HThis thisInstruction =
404 closureData.thisLocal, builder.getTypeOfThis()); 376 new HThis(closureData.thisLocal, builder.getTypeOfThis());
405 builder.graph.thisInstruction = thisInstruction; 377 builder.graph.thisInstruction = thisInstruction;
406 builder.graph.entry.addAtEntry(thisInstruction); 378 builder.graph.entry.addAtEntry(thisInstruction);
407 directLocals[closureData.thisLocal] = thisInstruction; 379 directLocals[closureData.thisLocal] = thisInstruction;
408 } 380 }
409 381
410 // If this method is an intercepted method, add the extra 382 // If this method is an intercepted method, add the extra
411 // parameter to it, that is the actual receiver for intercepted 383 // parameter to it, that is the actual receiver for intercepted
412 // classes, or the same as [:this:] for non-intercepted classes. 384 // classes, or the same as [:this:] for non-intercepted classes.
413 ClassElement cls = element.enclosingClass; 385 ClassElement cls = element.enclosingClass;
414 386
415 // When the class extends a native class, the instance is pre-constructed 387 // When the class extends a native class, the instance is pre-constructed
416 // and passed to the generative constructor factory function as a parameter. 388 // and passed to the generative constructor factory function as a parameter.
417 // Instead of allocating and initializing the object, the constructor 389 // Instead of allocating and initializing the object, the constructor
418 // 'upgrades' the native subclass object by initializing the Dart fields. 390 // 'upgrades' the native subclass object by initializing the Dart fields.
419 bool isNativeUpgradeFactory = element.isGenerativeConstructor 391 bool isNativeUpgradeFactory =
420 && backend.isNativeOrExtendsNative(cls); 392 element.isGenerativeConstructor && backend.isNativeOrExtendsNative(cls);
421 if (backend.isInterceptedMethod(element)) { 393 if (backend.isInterceptedMethod(element)) {
422 bool isInterceptorClass = backend.isInterceptorClass(cls.declaration); 394 bool isInterceptorClass = backend.isInterceptorClass(cls.declaration);
423 String name = isInterceptorClass ? 'receiver' : '_'; 395 String name = isInterceptorClass ? 'receiver' : '_';
424 SyntheticLocal parameter = new SyntheticLocal(name, executableContext); 396 SyntheticLocal parameter = new SyntheticLocal(name, executableContext);
425 HParameterValue value = 397 HParameterValue value =
426 new HParameterValue(parameter, builder.getTypeOfThis()); 398 new HParameterValue(parameter, builder.getTypeOfThis());
427 builder.graph.explicitReceiverParameter = value; 399 builder.graph.explicitReceiverParameter = value;
428 builder.graph.entry.addAfter(directLocals[closureData.thisLocal], value); 400 builder.graph.entry.addAfter(directLocals[closureData.thisLocal], value);
429 if (builder.lastAddedParameter == null) { 401 if (builder.lastAddedParameter == null) {
430 // If this is the first parameter inserted, make sure it stays first. 402 // If this is the first parameter inserted, make sure it stays first.
(...skipping 15 matching lines...) Expand all
446 builder.graph.entry.addAtEntry(value); 418 builder.graph.entry.addAtEntry(value);
447 } 419 }
448 } 420 }
449 421
450 /** 422 /**
451 * Returns true if the local can be accessed directly. Boxed variables or 423 * Returns true if the local can be accessed directly. Boxed variables or
452 * captured variables that are stored in the closure-field return [:false:]. 424 * captured variables that are stored in the closure-field return [:false:].
453 */ 425 */
454 bool isAccessedDirectly(Local local) { 426 bool isAccessedDirectly(Local local) {
455 assert(local != null); 427 assert(local != null);
456 return !redirectionMapping.containsKey(local) 428 return !redirectionMapping.containsKey(local) &&
457 && !closureData.variablesUsedInTryOrGenerator.contains(local); 429 !closureData.variablesUsedInTryOrGenerator.contains(local);
458 } 430 }
459 431
460 bool isStoredInClosureField(Local local) { 432 bool isStoredInClosureField(Local local) {
461 assert(local != null); 433 assert(local != null);
462 if (isAccessedDirectly(local)) return false; 434 if (isAccessedDirectly(local)) return false;
463 CapturedVariable redirectTarget = redirectionMapping[local]; 435 CapturedVariable redirectTarget = redirectionMapping[local];
464 if (redirectTarget == null) return false; 436 if (redirectTarget == null) return false;
465 return redirectTarget is ClosureFieldElement; 437 return redirectTarget is ClosureFieldElement;
466 } 438 }
467 439
468 bool isBoxed(Local local) { 440 bool isBoxed(Local local) {
469 if (isAccessedDirectly(local)) return false; 441 if (isAccessedDirectly(local)) return false;
470 if (isStoredInClosureField(local)) return false; 442 if (isStoredInClosureField(local)) return false;
471 return redirectionMapping.containsKey(local); 443 return redirectionMapping.containsKey(local);
472 } 444 }
473 445
474 bool isUsedInTryOrGenerator(Local local) { 446 bool isUsedInTryOrGenerator(Local local) {
475 return closureData.variablesUsedInTryOrGenerator.contains(local); 447 return closureData.variablesUsedInTryOrGenerator.contains(local);
476 } 448 }
477 449
478 /** 450 /**
479 * Returns an [HInstruction] for the given element. If the element is 451 * Returns an [HInstruction] for the given element. If the element is
480 * boxed or stored in a closure then the method generates code to retrieve 452 * boxed or stored in a closure then the method generates code to retrieve
481 * the value. 453 * the value.
482 */ 454 */
483 HInstruction readLocal(Local local, 455 HInstruction readLocal(Local local, {SourceInformation sourceInformation}) {
484 {SourceInformation sourceInformation}) {
485 if (isAccessedDirectly(local)) { 456 if (isAccessedDirectly(local)) {
486 if (directLocals[local] == null) { 457 if (directLocals[local] == null) {
487 if (local is TypeVariableElement) { 458 if (local is TypeVariableElement) {
488 builder.reporter.internalError(builder.compiler.currentElement, 459 builder.reporter.internalError(builder.compiler.currentElement,
489 "Runtime type information not available for $local."); 460 "Runtime type information not available for $local.");
490 } else { 461 } else {
491 builder.reporter.internalError(local, 462 builder.reporter.internalError(local, "Cannot find value $local.");
492 "Cannot find value $local.");
493 } 463 }
494 } 464 }
495 HInstruction value = directLocals[local]; 465 HInstruction value = directLocals[local];
496 if (sourceInformation != null) { 466 if (sourceInformation != null) {
497 value = new HRef(value, sourceInformation); 467 value = new HRef(value, sourceInformation);
498 builder.add(value); 468 builder.add(value);
499 } 469 }
500 return value; 470 return value;
501 } else if (isStoredInClosureField(local)) { 471 } else if (isStoredInClosureField(local)) {
502 ClosureFieldElement redirect = redirectionMapping[local]; 472 ClosureFieldElement redirect = redirectionMapping[local];
(...skipping 27 matching lines...) Expand all
530 } 500 }
531 501
532 HInstruction readThis() { 502 HInstruction readThis() {
533 HInstruction res = readLocal(closureData.thisLocal); 503 HInstruction res = readLocal(closureData.thisLocal);
534 if (res.instructionType == null) { 504 if (res.instructionType == null) {
535 res.instructionType = builder.getTypeOfThis(); 505 res.instructionType = builder.getTypeOfThis();
536 } 506 }
537 return res; 507 return res;
538 } 508 }
539 509
540 HLocalValue getLocal(Local local, 510 HLocalValue getLocal(Local local, {SourceInformation sourceInformation}) {
541 {SourceInformation sourceInformation}) {
542 // If the element is a parameter, we already have a 511 // If the element is a parameter, we already have a
543 // HParameterValue for it. We cannot create another one because 512 // HParameterValue for it. We cannot create another one because
544 // it could then have another name than the real parameter. And 513 // it could then have another name than the real parameter. And
545 // the other one would not know it is just a copy of the real 514 // the other one would not know it is just a copy of the real
546 // parameter. 515 // parameter.
547 if (local is ParameterElement) return builder.parameters[local]; 516 if (local is ParameterElement) return builder.parameters[local];
548 517
549 return builder.activationVariables.putIfAbsent(local, () { 518 return builder.activationVariables.putIfAbsent(local, () {
550 JavaScriptBackend backend = builder.backend; 519 JavaScriptBackend backend = builder.backend;
551 HLocalValue localValue = new HLocalValue(local, backend.nonNullType) 520 HLocalValue localValue = new HLocalValue(local, backend.nonNullType)
552 ..sourceInformation = sourceInformation; 521 ..sourceInformation = sourceInformation;
553 builder.graph.entry.addAtExit(localValue); 522 builder.graph.entry.addAtExit(localValue);
554 return localValue; 523 return localValue;
555 }); 524 });
556 } 525 }
557 526
558 Local getTypeVariableAsLocal(TypeVariableType type) { 527 Local getTypeVariableAsLocal(TypeVariableType type) {
559 return typeVariableLocals.putIfAbsent(type, () { 528 return typeVariableLocals.putIfAbsent(type, () {
560 return new TypeVariableLocal(type, executableContext); 529 return new TypeVariableLocal(type, executableContext);
561 }); 530 });
562 } 531 }
563 532
564 /** 533 /**
565 * Sets the [element] to [value]. If the element is boxed or stored in a 534 * Sets the [element] to [value]. If the element is boxed or stored in a
566 * closure then the method generates code to set the value. 535 * closure then the method generates code to set the value.
567 */ 536 */
568 void updateLocal(Local local, HInstruction value, 537 void updateLocal(Local local, HInstruction value,
569 {SourceInformation sourceInformation}) { 538 {SourceInformation sourceInformation}) {
570 if (value is HRef) { 539 if (value is HRef) {
571 HRef ref = value; 540 HRef ref = value;
572 value = ref.value; 541 value = ref.value;
573 } 542 }
574 assert(!isStoredInClosureField(local)); 543 assert(!isStoredInClosureField(local));
575 if (isAccessedDirectly(local)) { 544 if (isAccessedDirectly(local)) {
576 directLocals[local] = value; 545 directLocals[local] = value;
577 } else if (isBoxed(local)) { 546 } else if (isBoxed(local)) {
578 BoxFieldElement redirect = redirectionMapping[local]; 547 BoxFieldElement redirect = redirectionMapping[local];
579 // The box itself could be captured, or be local. A local variable that 548 // The box itself could be captured, or be local. A local variable that
580 // is captured will be boxed, but the box itself will be a local. 549 // is captured will be boxed, but the box itself will be a local.
581 // Inside the closure the box is stored in a closure-field and cannot 550 // Inside the closure the box is stored in a closure-field and cannot
582 // be accessed directly. 551 // be accessed directly.
583 HInstruction box = readLocal(redirect.box); 552 HInstruction box = readLocal(redirect.box);
584 builder.add(new HFieldSet(redirect, box, value) 553 builder.add(new HFieldSet(redirect, box, value)
585 ..sourceInformation = sourceInformation); 554 ..sourceInformation = sourceInformation);
586 } else { 555 } else {
587 assert(isUsedInTryOrGenerator(local)); 556 assert(isUsedInTryOrGenerator(local));
588 HLocalValue localValue = getLocal(local); 557 HLocalValue localValue = getLocal(local);
589 builder.add(new HLocalSet(local, localValue, value) 558 builder.add(new HLocalSet(local, localValue, value)
590 ..sourceInformation = sourceInformation); 559 ..sourceInformation = sourceInformation);
591 } 560 }
592 } 561 }
593 562
594 /** 563 /**
595 * This function, startLoop, must be called before visiting any children of 564 * This function, startLoop, must be called before visiting any children of
596 * the loop. In particular it needs to be called before executing the 565 * the loop. In particular it needs to be called before executing the
597 * initializers. 566 * initializers.
598 * 567 *
599 * The [LocalsHandler] will make the boxes and updates at the right moment. 568 * The [LocalsHandler] will make the boxes and updates at the right moment.
600 * The builder just needs to call [enterLoopBody] and [enterLoopUpdates] 569 * The builder just needs to call [enterLoopBody] and [enterLoopUpdates]
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
653 * Create phis at the loop entry for local variables (ready for the values 622 * Create phis at the loop entry for local variables (ready for the values
654 * from the back edge). Populate the phis with the current values. 623 * from the back edge). Populate the phis with the current values.
655 */ 624 */
656 void beginLoopHeader(HBasicBlock loopEntry) { 625 void beginLoopHeader(HBasicBlock loopEntry) {
657 // Create a copy because we modify the map while iterating over it. 626 // Create a copy because we modify the map while iterating over it.
658 Map<Local, HInstruction> savedDirectLocals = 627 Map<Local, HInstruction> savedDirectLocals =
659 new Map<Local, HInstruction>.from(directLocals); 628 new Map<Local, HInstruction>.from(directLocals);
660 629
661 JavaScriptBackend backend = builder.backend; 630 JavaScriptBackend backend = builder.backend;
662 // Create phis for all elements in the definitions environment. 631 // Create phis for all elements in the definitions environment.
663 savedDirectLocals.forEach((Local local, 632 savedDirectLocals.forEach((Local local, HInstruction instruction) {
664 HInstruction instruction) {
665 if (isAccessedDirectly(local)) { 633 if (isAccessedDirectly(local)) {
666 // We know 'this' cannot be modified. 634 // We know 'this' cannot be modified.
667 if (local != closureData.thisLocal) { 635 if (local != closureData.thisLocal) {
668 HPhi phi = new HPhi.singleInput( 636 HPhi phi =
669 local, instruction, backend.dynamicType); 637 new HPhi.singleInput(local, instruction, backend.dynamicType);
670 loopEntry.addPhi(phi); 638 loopEntry.addPhi(phi);
671 directLocals[local] = phi; 639 directLocals[local] = phi;
672 } else { 640 } else {
673 directLocals[local] = instruction; 641 directLocals[local] = instruction;
674 } 642 }
675 } 643 }
676 }); 644 });
677 } 645 }
678 646
679 void enterLoopBody(ast.Node node) { 647 void enterLoopBody(ast.Node node) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
719 * there is a conflict. 687 * there is a conflict.
720 * If a phi node is necessary, it will use this handler's instruction as the 688 * If a phi node is necessary, it will use this handler's instruction as the
721 * first input, and the otherLocals instruction as the second. 689 * first input, and the otherLocals instruction as the second.
722 */ 690 */
723 void mergeWith(LocalsHandler otherLocals, HBasicBlock joinBlock) { 691 void mergeWith(LocalsHandler otherLocals, HBasicBlock joinBlock) {
724 // If an element is in one map but not the other we can safely 692 // If an element is in one map but not the other we can safely
725 // ignore it. It means that a variable was declared in the 693 // ignore it. It means that a variable was declared in the
726 // block. Since variable declarations are scoped the declared 694 // block. Since variable declarations are scoped the declared
727 // variable cannot be alive outside the block. Note: this is only 695 // variable cannot be alive outside the block. Note: this is only
728 // true for nodes where we do joins. 696 // true for nodes where we do joins.
729 Map<Local, HInstruction> joinedLocals = 697 Map<Local, HInstruction> joinedLocals = new Map<Local, HInstruction>();
730 new Map<Local, HInstruction>();
731 JavaScriptBackend backend = builder.backend; 698 JavaScriptBackend backend = builder.backend;
732 otherLocals.directLocals.forEach((Local local, 699 otherLocals.directLocals.forEach((Local local, HInstruction instruction) {
733 HInstruction instruction) {
734 // We know 'this' cannot be modified. 700 // We know 'this' cannot be modified.
735 if (local == closureData.thisLocal) { 701 if (local == closureData.thisLocal) {
736 assert(directLocals[local] == instruction); 702 assert(directLocals[local] == instruction);
737 joinedLocals[local] = instruction; 703 joinedLocals[local] = instruction;
738 } else { 704 } else {
739 HInstruction mine = directLocals[local]; 705 HInstruction mine = directLocals[local];
740 if (mine == null) return; 706 if (mine == null) return;
741 if (identical(instruction, mine)) { 707 if (identical(instruction, mine)) {
742 joinedLocals[local] = instruction; 708 joinedLocals[local] = instruction;
743 } else { 709 } else {
744 HInstruction phi = new HPhi.manyInputs( 710 HInstruction phi = new HPhi.manyInputs(
745 local, <HInstruction>[mine, instruction], backend.dynamicType); 711 local, <HInstruction>[mine, instruction], backend.dynamicType);
746 joinBlock.addPhi(phi); 712 joinBlock.addPhi(phi);
747 joinedLocals[local] = phi; 713 joinedLocals[local] = phi;
748 } 714 }
749 } 715 }
750 }); 716 });
751 directLocals = joinedLocals; 717 directLocals = joinedLocals;
752 } 718 }
753 719
754 /** 720 /**
755 * When control flow merges, this method can be used to merge several 721 * When control flow merges, this method can be used to merge several
756 * localsHandlers into a new one using phis. The new localsHandler is 722 * localsHandlers into a new one using phis. The new localsHandler is
757 * returned. Unless it is also in the list, the current localsHandler is not 723 * returned. Unless it is also in the list, the current localsHandler is not
758 * used for its values, only for its declared variables. This is a way to 724 * used for its values, only for its declared variables. This is a way to
759 * exclude local values from the result when they are no longer in scope. 725 * exclude local values from the result when they are no longer in scope.
760 */ 726 */
761 LocalsHandler mergeMultiple(List<LocalsHandler> localsHandlers, 727 LocalsHandler mergeMultiple(
762 HBasicBlock joinBlock) { 728 List<LocalsHandler> localsHandlers, HBasicBlock joinBlock) {
763 assert(localsHandlers.length > 0); 729 assert(localsHandlers.length > 0);
764 if (localsHandlers.length == 1) return localsHandlers[0]; 730 if (localsHandlers.length == 1) return localsHandlers[0];
765 Map<Local, HInstruction> joinedLocals = 731 Map<Local, HInstruction> joinedLocals = new Map<Local, HInstruction>();
766 new Map<Local, HInstruction>();
767 HInstruction thisValue = null; 732 HInstruction thisValue = null;
768 JavaScriptBackend backend = builder.backend; 733 JavaScriptBackend backend = builder.backend;
769 directLocals.forEach((Local local, HInstruction instruction) { 734 directLocals.forEach((Local local, HInstruction instruction) {
770 if (local != closureData.thisLocal) { 735 if (local != closureData.thisLocal) {
771 HPhi phi = new HPhi.noInputs(local, backend.dynamicType); 736 HPhi phi = new HPhi.noInputs(local, backend.dynamicType);
772 joinedLocals[local] = phi; 737 joinedLocals[local] = phi;
773 joinBlock.addPhi(phi); 738 joinBlock.addPhi(phi);
774 } else { 739 } else {
775 // We know that "this" never changes, if it's there. 740 // We know that "this" never changes, if it's there.
776 // Save it for later. While merging, there is no phi for "this", 741 // Save it for later. While merging, there is no phi for "this",
777 // so we don't have to special case it in the merge loop. 742 // so we don't have to special case it in the merge loop.
778 thisValue = instruction; 743 thisValue = instruction;
779 } 744 }
780 }); 745 });
781 for (LocalsHandler handler in localsHandlers) { 746 for (LocalsHandler handler in localsHandlers) {
782 handler.directLocals.forEach((Local local, 747 handler.directLocals.forEach((Local local, HInstruction instruction) {
783 HInstruction instruction) {
784 HPhi phi = joinedLocals[local]; 748 HPhi phi = joinedLocals[local];
785 if (phi != null) { 749 if (phi != null) {
786 phi.addInput(instruction); 750 phi.addInput(instruction);
787 } 751 }
788 }); 752 });
789 } 753 }
790 if (thisValue != null) { 754 if (thisValue != null) {
791 // If there was a "this" for the scope, add it to the new locals. 755 // If there was a "this" for the scope, add it to the new locals.
792 joinedLocals[closureData.thisLocal] = thisValue; 756 joinedLocals[closureData.thisLocal] = thisValue;
793 } 757 }
794 758
795 // Remove locals that are not in all handlers. 759 // Remove locals that are not in all handlers.
796 directLocals = new Map<Local, HInstruction>(); 760 directLocals = new Map<Local, HInstruction>();
797 joinedLocals.forEach((Local local, 761 joinedLocals.forEach((Local local, HInstruction instruction) {
798 HInstruction instruction) { 762 if (local != closureData.thisLocal &&
799 if (local != closureData.thisLocal 763 instruction.inputs.length != localsHandlers.length) {
800 && instruction.inputs.length != localsHandlers.length) {
801 joinBlock.removePhi(instruction); 764 joinBlock.removePhi(instruction);
802 } else { 765 } else {
803 directLocals[local] = instruction; 766 directLocals[local] = instruction;
804 } 767 }
805 }); 768 });
806 return this; 769 return this;
807 } 770 }
808 } 771 }
809 772
810
811 // Represents a single break/continue instruction. 773 // Represents a single break/continue instruction.
812 class JumpHandlerEntry { 774 class JumpHandlerEntry {
813 final HJump jumpInstruction; 775 final HJump jumpInstruction;
814 final LocalsHandler locals; 776 final LocalsHandler locals;
815 bool isBreak() => jumpInstruction is HBreak; 777 bool isBreak() => jumpInstruction is HBreak;
816 bool isContinue() => jumpInstruction is HContinue; 778 bool isContinue() => jumpInstruction is HContinue;
817 JumpHandlerEntry(this.jumpInstruction, this.locals); 779 JumpHandlerEntry(this.jumpInstruction, this.locals);
818 } 780 }
819 781
820
821 abstract class JumpHandler { 782 abstract class JumpHandler {
822 factory JumpHandler(SsaBuilder builder, JumpTarget target) { 783 factory JumpHandler(SsaBuilder builder, JumpTarget target) {
823 return new TargetJumpHandler(builder, target); 784 return new TargetJumpHandler(builder, target);
824 } 785 }
825 void generateBreak([LabelDefinition label]); 786 void generateBreak([LabelDefinition label]);
826 void generateContinue([LabelDefinition label]); 787 void generateContinue([LabelDefinition label]);
827 void forEachBreak(void action(HBreak instruction, LocalsHandler locals)); 788 void forEachBreak(void action(HBreak instruction, LocalsHandler locals));
828 void forEachContinue(void action(HContinue instruction, 789 void forEachContinue(
829 LocalsHandler locals)); 790 void action(HContinue instruction, LocalsHandler locals));
830 bool hasAnyContinue(); 791 bool hasAnyContinue();
831 bool hasAnyBreak(); 792 bool hasAnyBreak();
832 void close(); 793 void close();
833 final JumpTarget target; 794 final JumpTarget target;
834 List<LabelDefinition> labels(); 795 List<LabelDefinition> labels();
835 } 796 }
836 797
837 // Insert break handler used to avoid null checks when a target isn't 798 // Insert break handler used to avoid null checks when a target isn't
838 // used as the target of a break, and therefore doesn't need a break 799 // used as the target of a break, and therefore doesn't need a break
839 // handler associated with it. 800 // handler associated with it.
840 class NullJumpHandler implements JumpHandler { 801 class NullJumpHandler implements JumpHandler {
841 final DiagnosticReporter reporter; 802 final DiagnosticReporter reporter;
842 803
843 NullJumpHandler(this.reporter); 804 NullJumpHandler(this.reporter);
844 805
845 void generateBreak([LabelDefinition label]) { 806 void generateBreak([LabelDefinition label]) {
846 reporter.internalError(CURRENT_ELEMENT_SPANNABLE, 807 reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
847 'NullJumpHandler.generateBreak should not be called.'); 808 'NullJumpHandler.generateBreak should not be called.');
848 } 809 }
849 810
850 void generateContinue([LabelDefinition label]) { 811 void generateContinue([LabelDefinition label]) {
851 reporter.internalError(CURRENT_ELEMENT_SPANNABLE, 812 reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
852 'NullJumpHandler.generateContinue should not be called.'); 813 'NullJumpHandler.generateContinue should not be called.');
853 } 814 }
854 815
855 void forEachBreak(Function ignored) { } 816 void forEachBreak(Function ignored) {}
856 void forEachContinue(Function ignored) { } 817 void forEachContinue(Function ignored) {}
857 void close() { } 818 void close() {}
858 bool hasAnyContinue() => false; 819 bool hasAnyContinue() => false;
859 bool hasAnyBreak() => false; 820 bool hasAnyBreak() => false;
860 821
861 List<LabelDefinition> labels() => const <LabelDefinition>[]; 822 List<LabelDefinition> labels() => const <LabelDefinition>[];
862 JumpTarget get target => null; 823 JumpTarget get target => null;
863 } 824 }
864 825
865 // Records breaks until a target block is available. 826 // Records breaks until a target block is available.
866 // Breaks are always forward jumps. 827 // Breaks are always forward jumps.
867 // Continues in loops are implemented as breaks of the body. 828 // Continues in loops are implemented as breaks of the body.
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
946 } 907 }
947 } 908 }
948 909
949 /// Special [JumpHandler] implementation used to handle continue statements 910 /// Special [JumpHandler] implementation used to handle continue statements
950 /// targeting switch cases. 911 /// targeting switch cases.
951 class SwitchCaseJumpHandler extends TargetJumpHandler { 912 class SwitchCaseJumpHandler extends TargetJumpHandler {
952 /// Map from switch case targets to indices used to encode the flow of the 913 /// Map from switch case targets to indices used to encode the flow of the
953 /// switch case loop. 914 /// switch case loop.
954 final Map<JumpTarget, int> targetIndexMap = new Map<JumpTarget, int>(); 915 final Map<JumpTarget, int> targetIndexMap = new Map<JumpTarget, int>();
955 916
956 SwitchCaseJumpHandler(SsaBuilder builder, 917 SwitchCaseJumpHandler(
957 JumpTarget target, 918 SsaBuilder builder, JumpTarget target, ast.SwitchStatement node)
958 ast.SwitchStatement node)
959 : super(builder, target) { 919 : super(builder, target) {
960 // The switch case indices must match those computed in 920 // The switch case indices must match those computed in
961 // [SsaFromAstMixin.buildSwitchCaseConstants]. 921 // [SsaFromAstMixin.buildSwitchCaseConstants].
962 // Switch indices are 1-based so we can bypass the synthetic loop when no 922 // Switch indices are 1-based so we can bypass the synthetic loop when no
963 // cases match simply by branching on the index (which defaults to null). 923 // cases match simply by branching on the index (which defaults to null).
964 int switchIndex = 1; 924 int switchIndex = 1;
965 for (ast.SwitchCase switchCase in node.cases) { 925 for (ast.SwitchCase switchCase in node.cases) {
966 for (ast.Node labelOrCase in switchCase.labelsAndCases) { 926 for (ast.Node labelOrCase in switchCase.labelsAndCases) {
967 ast.Node label = labelOrCase.asLabel(); 927 ast.Node label = labelOrCase.asLabel();
968 if (label != null) { 928 if (label != null) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1000 return label != null && targetIndexMap.containsKey(label.target); 960 return label != null && targetIndexMap.containsKey(label.target);
1001 } 961 }
1002 962
1003 void generateContinue([LabelDefinition label]) { 963 void generateContinue([LabelDefinition label]) {
1004 if (isContinueToSwitchCase(label)) { 964 if (isContinueToSwitchCase(label)) {
1005 // Creates the special instructions 'label = i; continue l;' used in 965 // Creates the special instructions 'label = i; continue l;' used in
1006 // switch statements with continue statements. See 966 // switch statements with continue statements. See
1007 // [SsaFromAstMixin.buildComplexSwitchStatement] for detail. 967 // [SsaFromAstMixin.buildComplexSwitchStatement] for detail.
1008 968
1009 assert(label != null); 969 assert(label != null);
1010 HInstruction value = builder.graph.addConstantInt( 970 HInstruction value = builder.graph
1011 targetIndexMap[label.target], 971 .addConstantInt(targetIndexMap[label.target], builder.compiler);
1012 builder.compiler);
1013 builder.localsHandler.updateLocal(target, value); 972 builder.localsHandler.updateLocal(target, value);
1014 973
1015 assert(label.target.labels.contains(label)); 974 assert(label.target.labels.contains(label));
1016 HInstruction continueInstruction = new HContinue(target); 975 HInstruction continueInstruction = new HContinue(target);
1017 LocalsHandler locals = new LocalsHandler.from(builder.localsHandler); 976 LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
1018 builder.close(continueInstruction); 977 builder.close(continueInstruction);
1019 jumps.add(new JumpHandlerEntry(continueInstruction, locals)); 978 jumps.add(new JumpHandlerEntry(continueInstruction, locals));
1020 } else { 979 } else {
1021 super.generateContinue(label); 980 super.generateContinue(label);
1022 } 981 }
1023 } 982 }
1024 983
1025 void close() { 984 void close() {
1026 // The mapping from TargetElement to JumpHandler is no longer needed. 985 // The mapping from TargetElement to JumpHandler is no longer needed.
1027 for (JumpTarget target in targetIndexMap.keys) { 986 for (JumpTarget target in targetIndexMap.keys) {
1028 builder.jumpTargets.remove(target); 987 builder.jumpTargets.remove(target);
1029 } 988 }
1030 super.close(); 989 super.close();
1031 } 990 }
1032 } 991 }
1033 992
1034 /** 993 /**
1035 * This class builds SSA nodes for functions represented in AST. 994 * This class builds SSA nodes for functions represented in AST.
1036 */ 995 */
1037 class SsaBuilder extends ast.Visitor 996 class SsaBuilder extends ast.Visitor
1038 with BaseImplementationOfCompoundsMixin, 997 with
1039 BaseImplementationOfSetIfNullsMixin, 998 BaseImplementationOfCompoundsMixin,
1040 BaseImplementationOfSuperIndexSetIfNullMixin, 999 BaseImplementationOfSetIfNullsMixin,
1041 SemanticSendResolvedMixin, 1000 BaseImplementationOfSuperIndexSetIfNullMixin,
1042 NewBulkMixin, 1001 SemanticSendResolvedMixin,
1043 ErrorBulkMixin 1002 NewBulkMixin,
1003 ErrorBulkMixin
1044 implements SemanticSendVisitor { 1004 implements SemanticSendVisitor {
1045
1046 /// The element for which this SSA builder is being used. 1005 /// The element for which this SSA builder is being used.
1047 final Element target; 1006 final Element target;
1048 1007
1049 /// Reference to resolved elements in [target]'s AST. 1008 /// Reference to resolved elements in [target]'s AST.
1050 TreeElements elements; 1009 TreeElements elements;
1051 1010
1052 /// Used to report information about inlining (which occurs while building the 1011 /// Used to report information about inlining (which occurs while building the
1053 /// SSA graph), when dump-info is enabled. 1012 /// SSA graph), when dump-info is enabled.
1054 final InfoReporter infoReporter; 1013 final InfoReporter infoReporter;
1055 1014
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1139 Map<ParameterElement, HInstruction> parameters = 1098 Map<ParameterElement, HInstruction> parameters =
1140 <ParameterElement, HInstruction>{}; 1099 <ParameterElement, HInstruction>{};
1141 1100
1142 Map<JumpTarget, JumpHandler> jumpTargets = <JumpTarget, JumpHandler>{}; 1101 Map<JumpTarget, JumpHandler> jumpTargets = <JumpTarget, JumpHandler>{};
1143 1102
1144 /** 1103 /**
1145 * Variables stored in the current activation. These variables are 1104 * Variables stored in the current activation. These variables are
1146 * being updated in try/catch blocks, and should be 1105 * being updated in try/catch blocks, and should be
1147 * accessed indirectly through [HLocalGet] and [HLocalSet]. 1106 * accessed indirectly through [HLocalGet] and [HLocalSet].
1148 */ 1107 */
1149 Map<Local, HLocalValue> activationVariables = 1108 Map<Local, HLocalValue> activationVariables = <Local, HLocalValue>{};
1150 <Local, HLocalValue>{};
1151 1109
1152 // We build the Ssa graph by simulating a stack machine. 1110 // We build the Ssa graph by simulating a stack machine.
1153 List<HInstruction> stack = <HInstruction>[]; 1111 List<HInstruction> stack = <HInstruction>[];
1154 1112
1155 /// Returns `true` if the current element is an `async` function. 1113 /// Returns `true` if the current element is an `async` function.
1156 bool get isBuildingAsyncFunction { 1114 bool get isBuildingAsyncFunction {
1157 Element element = sourceElement; 1115 Element element = sourceElement;
1158 return (element is FunctionElement && 1116 return (element is FunctionElement &&
1159 element.asyncMarker == AsyncMarker.ASYNC); 1117 element.asyncMarker == AsyncMarker.ASYNC);
1160 } 1118 }
1161 1119
1162 // TODO(sigmund): make most args optional 1120 // TODO(sigmund): make most args optional
1163 SsaBuilder(this.target, this.elements, this.context, this.registry, 1121 SsaBuilder(
1164 JavaScriptBackend backend, this.nativeEmitter, 1122 this.target,
1123 this.elements,
1124 this.context,
1125 this.registry,
1126 JavaScriptBackend backend,
1127 this.nativeEmitter,
1165 SourceInformationStrategy sourceInformationFactory) 1128 SourceInformationStrategy sourceInformationFactory)
1166 : this.compiler = backend.compiler, 1129 : this.compiler = backend.compiler,
1167 this.infoReporter = backend.compiler.dumpInfoTask, 1130 this.infoReporter = backend.compiler.dumpInfoTask,
1168 this.backend = backend, 1131 this.backend = backend,
1169 this.constantSystem = backend.constantSystem, 1132 this.constantSystem = backend.constantSystem,
1170 this.rti = backend.rti { 1133 this.rti = backend.rti {
1171 assert(target.isImplementation); 1134 assert(target.isImplementation);
1172 graph.element = target; 1135 graph.element = target;
1173 localsHandler = new LocalsHandler(this, target, null); 1136 localsHandler = new LocalsHandler(this, target, null);
1174 sourceElementStack.add(target); 1137 sourceElementStack.add(target);
1175 sourceInformationBuilder = sourceInformationFactory.createBuilderForContext( 1138 sourceInformationBuilder =
1176 target); 1139 sourceInformationFactory.createBuilderForContext(target);
1177 graph.sourceInformation = 1140 graph.sourceInformation =
1178 sourceInformationBuilder.buildVariableDeclaration(); 1141 sourceInformationBuilder.buildVariableDeclaration();
1179 } 1142 }
1180 1143
1181 BackendHelpers get helpers => backend.helpers; 1144 BackendHelpers get helpers => backend.helpers;
1182 1145
1183 RuntimeTypesEncoder get rtiEncoder => backend.rtiEncoder; 1146 RuntimeTypesEncoder get rtiEncoder => backend.rtiEncoder;
1184 1147
1185 DiagnosticReporter get reporter => compiler.reporter; 1148 DiagnosticReporter get reporter => compiler.reporter;
1186 1149
(...skipping 12 matching lines...) Expand all
1199 node.accept(this); 1162 node.accept(this);
1200 } 1163 }
1201 1164
1202 /// Returns the current source element. 1165 /// Returns the current source element.
1203 /// 1166 ///
1204 /// The returned element is a declaration element. 1167 /// The returned element is a declaration element.
1205 // TODO(johnniwinther): Check that all usages of sourceElement agree on 1168 // TODO(johnniwinther): Check that all usages of sourceElement agree on
1206 // implementation/declaration distinction. 1169 // implementation/declaration distinction.
1207 Element get sourceElement => sourceElementStack.last; 1170 Element get sourceElement => sourceElementStack.last;
1208 1171
1209 bool get _checkOrTrustTypes => compiler.options.enableTypeAssertions || 1172 bool get _checkOrTrustTypes =>
1173 compiler.options.enableTypeAssertions ||
1210 compiler.options.trustTypeAnnotations; 1174 compiler.options.trustTypeAnnotations;
1211 1175
1212 /// Build the graph for [target]. 1176 /// Build the graph for [target].
1213 HGraph build() { 1177 HGraph build() {
1214 assert(invariant(target, target.isImplementation)); 1178 assert(invariant(target, target.isImplementation));
1215 HInstruction.idCounter = 0; 1179 HInstruction.idCounter = 0;
1216 // TODO(sigmund): remove `result` and return graph directly, need to ensure 1180 // TODO(sigmund): remove `result` and return graph directly, need to ensure
1217 // that it can never be null (see result in buildFactory for instance). 1181 // that it can never be null (see result in buildFactory for instance).
1218 var result; 1182 var result;
1219 if (target.isGenerativeConstructor) { 1183 if (target.isGenerativeConstructor) {
1220 result = buildFactory(target); 1184 result = buildFactory(target);
1221 } else if (target.isGenerativeConstructorBody || 1185 } else if (target.isGenerativeConstructorBody ||
1222 target.isFactoryConstructor || 1186 target.isFactoryConstructor ||
1223 target.isFunction || 1187 target.isFunction ||
1224 target.isGetter || 1188 target.isGetter ||
1225 target.isSetter) { 1189 target.isSetter) {
1226 result = buildMethod(target); 1190 result = buildMethod(target);
1227 } else if (target.isField) { 1191 } else if (target.isField) {
1228 if (target.isInstanceMember) { 1192 if (target.isInstanceMember) {
1229 assert(compiler.options.enableTypeAssertions); 1193 assert(compiler.options.enableTypeAssertions);
1230 result = buildCheckedSetter(target); 1194 result = buildCheckedSetter(target);
1231 } else { 1195 } else {
1232 result = buildLazyInitializer(target); 1196 result = buildLazyInitializer(target);
1233 } 1197 }
1234 } else { 1198 } else {
1235 reporter.internalError(target, 'Unexpected element kind $target.'); 1199 reporter.internalError(target, 'Unexpected element kind $target.');
1236 } 1200 }
1237 assert(result.isValid()); 1201 assert(result.isValid());
1238 return result; 1202 return result;
1239 } 1203 }
1240 1204
1241
1242 HBasicBlock addNewBlock() { 1205 HBasicBlock addNewBlock() {
1243 HBasicBlock block = graph.addNewBlock(); 1206 HBasicBlock block = graph.addNewBlock();
1244 // If adding a new block during building of an expression, it is due to 1207 // If adding a new block during building of an expression, it is due to
1245 // conditional expressions or short-circuit logical operators. 1208 // conditional expressions or short-circuit logical operators.
1246 return block; 1209 return block;
1247 } 1210 }
1248 1211
1249 void open(HBasicBlock block) { 1212 void open(HBasicBlock block) {
1250 block.open(); 1213 block.open();
1251 current = block; 1214 current = block;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1302 FunctionElement function, 1265 FunctionElement function,
1303 Selector selector, 1266 Selector selector,
1304 List<HInstruction> providedArguments, 1267 List<HInstruction> providedArguments,
1305 ast.Node currentNode) { 1268 ast.Node currentNode) {
1306 assert(invariant(function, function.isImplementation)); 1269 assert(invariant(function, function.isImplementation));
1307 assert(providedArguments != null); 1270 assert(providedArguments != null);
1308 1271
1309 bool isInstanceMember = function.isInstanceMember; 1272 bool isInstanceMember = function.isInstanceMember;
1310 // For static calls, [providedArguments] is complete, default arguments 1273 // For static calls, [providedArguments] is complete, default arguments
1311 // have been included if necessary, see [makeStaticArgumentList]. 1274 // have been included if necessary, see [makeStaticArgumentList].
1312 if (!isInstanceMember 1275 if (!isInstanceMember ||
1313 || currentNode == null // In erroneous code, currentNode can be null. 1276 currentNode == null // In erroneous code, currentNode can be null.
1314 || providedArgumentsKnownToBeComplete(currentNode) 1277 ||
1315 || function.isGenerativeConstructorBody 1278 providedArgumentsKnownToBeComplete(currentNode) ||
1316 || selector.isGetter) { 1279 function.isGenerativeConstructorBody ||
1280 selector.isGetter) {
1317 // For these cases, the provided argument list is known to be complete. 1281 // For these cases, the provided argument list is known to be complete.
1318 return providedArguments; 1282 return providedArguments;
1319 } else { 1283 } else {
1320 return completeDynamicSendArgumentsList( 1284 return completeDynamicSendArgumentsList(
1321 selector, function, providedArguments); 1285 selector, function, providedArguments);
1322 } 1286 }
1323 } 1287 }
1324 1288
1325 /** 1289 /**
1326 * Returns a complete argument list for a dynamic call of [function]. The 1290 * Returns a complete argument list for a dynamic call of [function]. The
1327 * initial argument list [providedArguments], created by 1291 * initial argument list [providedArguments], created by
1328 * [addDynamicSendArgumentsToList], does not include values for default 1292 * [addDynamicSendArgumentsToList], does not include values for default
1329 * arguments used in the call. The reason is that the target function (which 1293 * arguments used in the call. The reason is that the target function (which
1330 * defines the defaults) is not known. 1294 * defines the defaults) is not known.
1331 * 1295 *
1332 * However, inlining can only be performed when the target function can be 1296 * However, inlining can only be performed when the target function can be
1333 * resolved statically. The defaults can therefore be included at this point. 1297 * resolved statically. The defaults can therefore be included at this point.
1334 * 1298 *
1335 * The [providedArguments] list contains first all positional arguments, then 1299 * The [providedArguments] list contains first all positional arguments, then
1336 * the provided named arguments (the named arguments that are defined in the 1300 * the provided named arguments (the named arguments that are defined in the
1337 * [selector]) in a specific order (see [addDynamicSendArgumentsToList]). 1301 * [selector]) in a specific order (see [addDynamicSendArgumentsToList]).
1338 */ 1302 */
1339 List<HInstruction> completeDynamicSendArgumentsList( 1303 List<HInstruction> completeDynamicSendArgumentsList(Selector selector,
1340 Selector selector, 1304 FunctionElement function, List<HInstruction> providedArguments) {
1341 FunctionElement function,
1342 List<HInstruction> providedArguments) {
1343 assert(selector.applies(function, compiler.world)); 1305 assert(selector.applies(function, compiler.world));
1344 FunctionSignature signature = function.functionSignature; 1306 FunctionSignature signature = function.functionSignature;
1345 List<HInstruction> compiledArguments = new List<HInstruction>( 1307 List<HInstruction> compiledArguments = new List<HInstruction>(
1346 signature.parameterCount + 1); // Plus one for receiver. 1308 signature.parameterCount + 1); // Plus one for receiver.
1347 1309
1348 compiledArguments[0] = providedArguments[0]; // Receiver. 1310 compiledArguments[0] = providedArguments[0]; // Receiver.
1349 int index = 1; 1311 int index = 1;
1350 for (; index <= signature.requiredParameterCount; index++) { 1312 for (; index <= signature.requiredParameterCount; index++) {
1351 compiledArguments[index] = providedArguments[index]; 1313 compiledArguments[index] = providedArguments[index];
1352 } 1314 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1389 index++; 1351 index++;
1390 }); 1352 });
1391 } 1353 }
1392 return compiledArguments; 1354 return compiledArguments;
1393 } 1355 }
1394 1356
1395 /** 1357 /**
1396 * Try to inline [element] within the currect context of the builder. The 1358 * Try to inline [element] within the currect context of the builder. The
1397 * insertion point is the state of the builder. 1359 * insertion point is the state of the builder.
1398 */ 1360 */
1399 bool tryInlineMethod(Element element, 1361 bool tryInlineMethod(Element element, Selector selector, TypeMask mask,
1400 Selector selector, 1362 List<HInstruction> providedArguments, ast.Node currentNode,
1401 TypeMask mask, 1363 {InterfaceType instanceType}) {
1402 List<HInstruction> providedArguments,
1403 ast.Node currentNode,
1404 {InterfaceType instanceType}) {
1405 // TODO(johnniwinther): Register this on the [registry]. Currently the 1364 // TODO(johnniwinther): Register this on the [registry]. Currently the
1406 // [CodegenRegistry] calls the enqueuer, but [element] should _not_ be 1365 // [CodegenRegistry] calls the enqueuer, but [element] should _not_ be
1407 // enqueued. 1366 // enqueued.
1408 backend.registerStaticUse(element, compiler.enqueuer.codegen); 1367 backend.registerStaticUse(element, compiler.enqueuer.codegen);
1409 1368
1410 if (backend.isJsInterop(element) && !element.isFactoryConstructor) { 1369 if (backend.isJsInterop(element) && !element.isFactoryConstructor) {
1411 // We only inline factory JavaScript interop constructors. 1370 // We only inline factory JavaScript interop constructors.
1412 return false; 1371 return false;
1413 } 1372 }
1414 1373
(...skipping 10 matching lines...) Expand all
1425 bool cachedCanBeInlined = 1384 bool cachedCanBeInlined =
1426 backend.inlineCache.canInline(function, insideLoop: insideLoop); 1385 backend.inlineCache.canInline(function, insideLoop: insideLoop);
1427 if (cachedCanBeInlined == false) return false; 1386 if (cachedCanBeInlined == false) return false;
1428 1387
1429 bool meetsHardConstraints() { 1388 bool meetsHardConstraints() {
1430 if (compiler.options.disableInlining) return false; 1389 if (compiler.options.disableInlining) return false;
1431 1390
1432 assert(invariant( 1391 assert(invariant(
1433 currentNode != null ? currentNode : element, 1392 currentNode != null ? currentNode : element,
1434 selector != null || 1393 selector != null ||
1435 Elements.isStaticOrTopLevel(element) || 1394 Elements.isStaticOrTopLevel(element) ||
1436 element.isGenerativeConstructorBody, 1395 element.isGenerativeConstructorBody,
1437 message: "Missing selector for inlining of $element.")); 1396 message: "Missing selector for inlining of $element."));
1438 if (selector != null) { 1397 if (selector != null) {
1439 if (!selector.applies(function, compiler.world)) return false; 1398 if (!selector.applies(function, compiler.world)) return false;
1440 if (mask != null && !mask.canHit(function, selector, compiler.world)) { 1399 if (mask != null && !mask.canHit(function, selector, compiler.world)) {
1441 return false; 1400 return false;
1442 } 1401 }
1443 } 1402 }
1444 1403
1445 if (backend.isJsInterop(element)) return false; 1404 if (backend.isJsInterop(element)) return false;
1446 1405
1447 // Don't inline operator== methods if the parameter can be null. 1406 // Don't inline operator== methods if the parameter can be null.
1448 if (element.name == '==') { 1407 if (element.name == '==') {
1449 if (element.enclosingClass != coreClasses.objectClass 1408 if (element.enclosingClass != coreClasses.objectClass &&
1450 && providedArguments[1].canBeNull()) { 1409 providedArguments[1].canBeNull()) {
1451 return false; 1410 return false;
1452 } 1411 }
1453 } 1412 }
1454 1413
1455 // Generative constructors of native classes should not be called directly 1414 // Generative constructors of native classes should not be called directly
1456 // and have an extra argument that causes problems with inlining. 1415 // and have an extra argument that causes problems with inlining.
1457 if (element.isGenerativeConstructor 1416 if (element.isGenerativeConstructor &&
1458 && backend.isNativeOrExtendsNative(element.enclosingClass)) { 1417 backend.isNativeOrExtendsNative(element.enclosingClass)) {
1459 return false; 1418 return false;
1460 } 1419 }
1461 1420
1462 // A generative constructor body is not seen by global analysis, 1421 // A generative constructor body is not seen by global analysis,
1463 // so we should not query for its type. 1422 // so we should not query for its type.
1464 if (!element.isGenerativeConstructorBody) { 1423 if (!element.isGenerativeConstructorBody) {
1465 // Don't inline if the return type was inferred to be non-null empty. 1424 // Don't inline if the return type was inferred to be non-null empty.
1466 // This means that the function always throws an exception. 1425 // This means that the function always throws an exception.
1467 TypeMask returnType = 1426 TypeMask returnType =
1468 compiler.typesTask.getGuaranteedReturnTypeOfElement(element); 1427 compiler.typesTask.getGuaranteedReturnTypeOfElement(element);
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1517 1476
1518 // Do not inline code that is rarely executed unless it reduces size. 1477 // Do not inline code that is rarely executed unless it reduces size.
1519 if (inExpressionOfThrow || inLazyInitializerExpression) { 1478 if (inExpressionOfThrow || inLazyInitializerExpression) {
1520 return reductiveHeuristic(); 1479 return reductiveHeuristic();
1521 } 1480 }
1522 1481
1523 if (cachedCanBeInlined == true) { 1482 if (cachedCanBeInlined == true) {
1524 // We may have forced the inlining of some methods. Therefore check 1483 // We may have forced the inlining of some methods. Therefore check
1525 // if we can inline this method regardless of size. 1484 // if we can inline this method regardless of size.
1526 assert(InlineWeeder.canBeInlined(function, -1, false, 1485 assert(InlineWeeder.canBeInlined(function, -1, false,
1527 allowLoops: true, 1486 allowLoops: true,
1528 enableUserAssertions: compiler.options.enableUserAssertions)); 1487 enableUserAssertions: compiler.options.enableUserAssertions));
1529 return true; 1488 return true;
1530 } 1489 }
1531 1490
1532 int numParameters = function.functionSignature.parameterCount; 1491 int numParameters = function.functionSignature.parameterCount;
1533 int maxInliningNodes; 1492 int maxInliningNodes;
1534 bool useMaxInliningNodes = true; 1493 bool useMaxInliningNodes = true;
1535 if (insideLoop) { 1494 if (insideLoop) {
1536 maxInliningNodes = InlineWeeder.INLINING_NODES_INSIDE_LOOP + 1495 maxInliningNodes = InlineWeeder.INLINING_NODES_INSIDE_LOOP +
1537 InlineWeeder.INLINING_NODES_INSIDE_LOOP_ARG_FACTOR * numParameters; 1496 InlineWeeder.INLINING_NODES_INSIDE_LOOP_ARG_FACTOR * numParameters;
1538 } else { 1497 } else {
(...skipping 21 matching lines...) Expand all
1560 1519
1561 void doInlining() { 1520 void doInlining() {
1562 // Add an explicit null check on the receiver before doing the 1521 // Add an explicit null check on the receiver before doing the
1563 // inlining. We use [element] to get the same name in the 1522 // inlining. We use [element] to get the same name in the
1564 // NoSuchMethodError message as if we had called it. 1523 // NoSuchMethodError message as if we had called it.
1565 if (element.isInstanceMember && 1524 if (element.isInstanceMember &&
1566 !element.isGenerativeConstructorBody && 1525 !element.isGenerativeConstructorBody &&
1567 (mask == null || mask.isNullable)) { 1526 (mask == null || mask.isNullable)) {
1568 addWithPosition( 1527 addWithPosition(
1569 new HFieldGet(null, providedArguments[0], backend.dynamicType, 1528 new HFieldGet(null, providedArguments[0], backend.dynamicType,
1570 isAssignable: false), 1529 isAssignable: false),
1571 currentNode); 1530 currentNode);
1572 } 1531 }
1573 List<HInstruction> compiledArguments = completeSendArgumentsList( 1532 List<HInstruction> compiledArguments = completeSendArgumentsList(
1574 function, selector, providedArguments, currentNode); 1533 function, selector, providedArguments, currentNode);
1575 enterInlinedMethod( 1534 enterInlinedMethod(function, currentNode, compiledArguments,
1576 function, currentNode, compiledArguments, instanceType: instanceType); 1535 instanceType: instanceType);
1577 inlinedFrom(function, () { 1536 inlinedFrom(function, () {
1578 if (!isReachable) { 1537 if (!isReachable) {
1579 emitReturn(graph.addConstantNull(compiler), null); 1538 emitReturn(graph.addConstantNull(compiler), null);
1580 } else { 1539 } else {
1581 doInline(function); 1540 doInline(function);
1582 } 1541 }
1583 }); 1542 });
1584 leaveInlinedMethod(); 1543 leaveInlinedMethod();
1585 } 1544 }
1586 1545
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
1721 graph.calledInLoop = compiler.world.isCalledInLoop(functionElement); 1680 graph.calledInLoop = compiler.world.isCalledInLoop(functionElement);
1722 ast.FunctionExpression function = functionElement.node; 1681 ast.FunctionExpression function = functionElement.node;
1723 assert(function != null); 1682 assert(function != null);
1724 assert(elements.getFunctionDefinition(function) != null); 1683 assert(elements.getFunctionDefinition(function) != null);
1725 openFunction(functionElement, function); 1684 openFunction(functionElement, function);
1726 String name = functionElement.name; 1685 String name = functionElement.name;
1727 if (backend.isJsInterop(functionElement)) { 1686 if (backend.isJsInterop(functionElement)) {
1728 push(invokeJsInteropFunction(functionElement, parameters.values.toList(), 1687 push(invokeJsInteropFunction(functionElement, parameters.values.toList(),
1729 sourceInformationBuilder.buildGeneric(function))); 1688 sourceInformationBuilder.buildGeneric(function)));
1730 var value = pop(); 1689 var value = pop();
1731 closeAndGotoExit(new HReturn(value, 1690 closeAndGotoExit(new HReturn(
1732 sourceInformationBuilder.buildReturn(functionElement.node))); 1691 value, sourceInformationBuilder.buildReturn(functionElement.node)));
1733 return closeFunction(); 1692 return closeFunction();
1734 } 1693 }
1735 assert(invariant(functionElement, !function.modifiers.isExternal)); 1694 assert(invariant(functionElement, !function.modifiers.isExternal));
1736 1695
1737 // If [functionElement] is `operator==` we explicitely add a null check at 1696 // If [functionElement] is `operator==` we explicitely add a null check at
1738 // the beginning of the method. This is to avoid having call sites do the 1697 // the beginning of the method. This is to avoid having call sites do the
1739 // null check. 1698 // null check.
1740 if (name == '==') { 1699 if (name == '==') {
1741 if (!backend.operatorEqHandlesNullArgument(functionElement)) { 1700 if (!backend.operatorEqHandlesNullArgument(functionElement)) {
1742 handleIf( 1701 handleIf(function, visitCondition: () {
1743 function, 1702 HParameterValue parameter = parameters.values.first;
1744 visitCondition: () { 1703 push(new HIdentity(parameter, graph.addConstantNull(compiler), null,
1745 HParameterValue parameter = parameters.values.first; 1704 backend.boolType));
1746 push(new HIdentity( 1705 }, visitThen: () {
1747 parameter, graph.addConstantNull(compiler), null, 1706 closeAndGotoExit(new HReturn(graph.addConstantBool(false, compiler),
1748 backend.boolType)); 1707 sourceInformationBuilder.buildImplicitReturn(functionElement)));
1749 }, 1708 },
1750 visitThen: () {
1751 closeAndGotoExit(new HReturn(
1752 graph.addConstantBool(false, compiler),
1753 sourceInformationBuilder
1754 .buildImplicitReturn(functionElement)));
1755 },
1756 visitElse: null, 1709 visitElse: null,
1757 sourceInformation: sourceInformationBuilder.buildIf(function.body)); 1710 sourceInformation: sourceInformationBuilder.buildIf(function.body));
1758 } 1711 }
1759 } 1712 }
1760 if (const bool.fromEnvironment('unreachable-throw') == true) { 1713 if (const bool.fromEnvironment('unreachable-throw') == true) {
1761 var emptyParameters = parameters.values 1714 var emptyParameters =
1762 .where((p) => p.instructionType.isEmpty); 1715 parameters.values.where((p) => p.instructionType.isEmpty);
1763 if (emptyParameters.length > 0) { 1716 if (emptyParameters.length > 0) {
1764 addComment('${emptyParameters} inferred as [empty]'); 1717 addComment('${emptyParameters} inferred as [empty]');
1765 pushInvokeStatic(function.body, helpers.assertUnreachableMethod, []); 1718 pushInvokeStatic(function.body, helpers.assertUnreachableMethod, []);
1766 pop(); 1719 pop();
1767 return closeFunction(); 1720 return closeFunction();
1768 } 1721 }
1769 } 1722 }
1770 function.body.accept(this); 1723 function.body.accept(this);
1771 return closeFunction(); 1724 return closeFunction();
1772 } 1725 }
1773 1726
1774 /// Adds a JavaScript comment to the output. The comment will be omitted in 1727 /// Adds a JavaScript comment to the output. The comment will be omitted in
1775 /// minified mode. Each line in [text] is preceded with `//` and indented. 1728 /// minified mode. Each line in [text] is preceded with `//` and indented.
1776 /// Use sparingly. In order for the comment to be retained it is modeled as 1729 /// Use sparingly. In order for the comment to be retained it is modeled as
1777 /// having side effects which will inhibit code motion. 1730 /// having side effects which will inhibit code motion.
1778 // TODO(sra): Figure out how to keep comment anchored without effects. 1731 // TODO(sra): Figure out how to keep comment anchored without effects.
1779 void addComment(String text) { 1732 void addComment(String text) {
1780 add(new HForeignCode( 1733 add(new HForeignCode(js.js.statementTemplateYielding(new js.Comment(text)),
1781 js.js.statementTemplateYielding(new js.Comment(text)), 1734 backend.dynamicType, <HInstruction>[],
1782 backend.dynamicType,
1783 <HInstruction>[],
1784 isStatement: true)); 1735 isStatement: true));
1785 } 1736 }
1786 1737
1787 HGraph buildCheckedSetter(VariableElement field) { 1738 HGraph buildCheckedSetter(VariableElement field) {
1788 openFunction(field, field.node); 1739 openFunction(field, field.node);
1789 HInstruction thisInstruction = localsHandler.readThis(); 1740 HInstruction thisInstruction = localsHandler.readThis();
1790 // Use dynamic type because the type computed by the inferrer is 1741 // Use dynamic type because the type computed by the inferrer is
1791 // narrowed to the type annotation. 1742 // narrowed to the type annotation.
1792 HInstruction parameter = new HParameterValue(field, backend.dynamicType); 1743 HInstruction parameter = new HParameterValue(field, backend.dynamicType);
1793 // Add the parameter as the last instruction of the entry block. 1744 // Add the parameter as the last instruction of the entry block.
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1871 1822
1872 /** 1823 /**
1873 * This method sets up the local state of the builder for inlining [function]. 1824 * This method sets up the local state of the builder for inlining [function].
1874 * The arguments of the function are inserted into the [localsHandler]. 1825 * The arguments of the function are inserted into the [localsHandler].
1875 * 1826 *
1876 * When inlining a function, [:return:] statements are not emitted as 1827 * When inlining a function, [:return:] statements are not emitted as
1877 * [HReturn] instructions. Instead, the value of a synthetic element is 1828 * [HReturn] instructions. Instead, the value of a synthetic element is
1878 * updated in the [localsHandler]. This function creates such an element and 1829 * updated in the [localsHandler]. This function creates such an element and
1879 * stores it in the [returnLocal] field. 1830 * stores it in the [returnLocal] field.
1880 */ 1831 */
1881 void setupStateForInlining(FunctionElement function, 1832 void setupStateForInlining(
1882 List<HInstruction> compiledArguments, 1833 FunctionElement function, List<HInstruction> compiledArguments,
1883 {InterfaceType instanceType}) { 1834 {InterfaceType instanceType}) {
1884 localsHandler = new LocalsHandler(this, function, instanceType); 1835 localsHandler = new LocalsHandler(this, function, instanceType);
1885 localsHandler.closureData = 1836 localsHandler.closureData = compiler.closureToClassMapper
1886 compiler.closureToClassMapper.computeClosureToClassMapping( 1837 .computeClosureToClassMapping(function, function.node, elements);
1887 function, function.node, elements);
1888 returnLocal = new SyntheticLocal("result", function); 1838 returnLocal = new SyntheticLocal("result", function);
1889 localsHandler.updateLocal(returnLocal, 1839 localsHandler.updateLocal(returnLocal, graph.addConstantNull(compiler));
1890 graph.addConstantNull(compiler));
1891 1840
1892 inTryStatement = false; // TODO(lry): why? Document. 1841 inTryStatement = false; // TODO(lry): why? Document.
1893 1842
1894 int argumentIndex = 0; 1843 int argumentIndex = 0;
1895 if (function.isInstanceMember) { 1844 if (function.isInstanceMember) {
1896 localsHandler.updateLocal(localsHandler.closureData.thisLocal, 1845 localsHandler.updateLocal(localsHandler.closureData.thisLocal,
1897 compiledArguments[argumentIndex++]); 1846 compiledArguments[argumentIndex++]);
1898 } 1847 }
1899 1848
1900 FunctionSignature signature = function.functionSignature; 1849 FunctionSignature signature = function.functionSignature;
1901 signature.orderedForEachParameter((ParameterElement parameter) { 1850 signature.orderedForEachParameter((ParameterElement parameter) {
1902 HInstruction argument = compiledArguments[argumentIndex++]; 1851 HInstruction argument = compiledArguments[argumentIndex++];
1903 localsHandler.updateLocal(parameter, argument); 1852 localsHandler.updateLocal(parameter, argument);
1904 }); 1853 });
1905 1854
1906 ClassElement enclosing = function.enclosingClass; 1855 ClassElement enclosing = function.enclosingClass;
1907 if ((function.isConstructor || function.isGenerativeConstructorBody) 1856 if ((function.isConstructor || function.isGenerativeConstructorBody) &&
1908 && backend.classNeedsRti(enclosing)) { 1857 backend.classNeedsRti(enclosing)) {
1909 enclosing.typeVariables.forEach((TypeVariableType typeVariable) { 1858 enclosing.typeVariables.forEach((TypeVariableType typeVariable) {
1910 HInstruction argument = compiledArguments[argumentIndex++]; 1859 HInstruction argument = compiledArguments[argumentIndex++];
1911 localsHandler.updateLocal( 1860 localsHandler.updateLocal(
1912 localsHandler.getTypeVariableAsLocal(typeVariable), argument); 1861 localsHandler.getTypeVariableAsLocal(typeVariable), argument);
1913 }); 1862 });
1914 } 1863 }
1915 assert(argumentIndex == compiledArguments.length); 1864 assert(argumentIndex == compiledArguments.length);
1916 1865
1917 elements = function.resolvedAst.elements; 1866 elements = function.resolvedAst.elements;
1918 assert(elements != null); 1867 assert(elements != null);
(...skipping 21 matching lines...) Expand all
1940 potentiallyCheckInlinedParameterTypes(function); 1889 potentiallyCheckInlinedParameterTypes(function);
1941 1890
1942 if (function.isGenerativeConstructor) { 1891 if (function.isGenerativeConstructor) {
1943 buildFactory(function); 1892 buildFactory(function);
1944 } else { 1893 } else {
1945 ast.FunctionExpression functionNode = function.node; 1894 ast.FunctionExpression functionNode = function.node;
1946 functionNode.body.accept(this); 1895 functionNode.body.accept(this);
1947 } 1896 }
1948 } 1897 }
1949 1898
1950
1951 addInlinedInstantiation(DartType type) { 1899 addInlinedInstantiation(DartType type) {
1952 if (type != null) { 1900 if (type != null) {
1953 currentInlinedInstantiations.add(type); 1901 currentInlinedInstantiations.add(type);
1954 } 1902 }
1955 } 1903 }
1956 1904
1957 removeInlinedInstantiation(DartType type) { 1905 removeInlinedInstantiation(DartType type) {
1958 if (type != null) { 1906 if (type != null) {
1959 currentInlinedInstantiations.removeLast(); 1907 currentInlinedInstantiations.removeLast();
1960 } 1908 }
(...skipping 21 matching lines...) Expand all
1982 HInstruction argument = localsHandler.readLocal(parameter); 1930 HInstruction argument = localsHandler.readLocal(parameter);
1983 potentiallyCheckOrTrustType(argument, parameter.type); 1931 potentiallyCheckOrTrustType(argument, parameter.type);
1984 }); 1932 });
1985 } 1933 }
1986 1934
1987 /** 1935 /**
1988 * Documentation wanted -- johnniwinther 1936 * Documentation wanted -- johnniwinther
1989 * 1937 *
1990 * Invariant: [constructors] must contain only implementation elements. 1938 * Invariant: [constructors] must contain only implementation elements.
1991 */ 1939 */
1992 void inlineSuperOrRedirect(ConstructorElement callee, 1940 void inlineSuperOrRedirect(
1993 List<HInstruction> compiledArguments, 1941 ConstructorElement callee,
1994 List<FunctionElement> constructors, 1942 List<HInstruction> compiledArguments,
1995 Map<Element, HInstruction> fieldValues, 1943 List<FunctionElement> constructors,
1996 FunctionElement caller) { 1944 Map<Element, HInstruction> fieldValues,
1945 FunctionElement caller) {
1997 callee = callee.implementation; 1946 callee = callee.implementation;
1998 reporter.withCurrentElement(callee, () { 1947 reporter.withCurrentElement(callee, () {
1999 constructors.add(callee); 1948 constructors.add(callee);
2000 ClassElement enclosingClass = callee.enclosingClass; 1949 ClassElement enclosingClass = callee.enclosingClass;
2001 if (backend.classNeedsRti(enclosingClass)) { 1950 if (backend.classNeedsRti(enclosingClass)) {
2002 // If [enclosingClass] needs RTI, we have to give a value to its 1951 // If [enclosingClass] needs RTI, we have to give a value to its
2003 // type parameters. 1952 // type parameters.
2004 ClassElement currentClass = caller.enclosingClass; 1953 ClassElement currentClass = caller.enclosingClass;
2005 // For a super constructor call, the type is the supertype of 1954 // For a super constructor call, the type is the supertype of
2006 // [currentClass]. For a redirecting constructor, the type is 1955 // [currentClass]. For a redirecting constructor, the type is
(...skipping 21 matching lines...) Expand all
2028 localsHandler.getTypeVariableAsLocal(variable), 1977 localsHandler.getTypeVariableAsLocal(variable),
2029 graph.addConstantNull(compiler)); 1978 graph.addConstantNull(compiler));
2030 } 1979 }
2031 } 1980 }
2032 } 1981 }
2033 1982
2034 // For redirecting constructors, the fields will be initialized later 1983 // For redirecting constructors, the fields will be initialized later
2035 // by the effective target. 1984 // by the effective target.
2036 if (!callee.isRedirectingGenerative) { 1985 if (!callee.isRedirectingGenerative) {
2037 inlinedFrom(callee, () { 1986 inlinedFrom(callee, () {
2038 buildFieldInitializers(callee.enclosingClass.implementation, 1987 buildFieldInitializers(
2039 fieldValues); 1988 callee.enclosingClass.implementation, fieldValues);
2040 }); 1989 });
2041 } 1990 }
2042 1991
2043 int index = 0; 1992 int index = 0;
2044 FunctionSignature params = callee.functionSignature; 1993 FunctionSignature params = callee.functionSignature;
2045 params.orderedForEachParameter((ParameterElement parameter) { 1994 params.orderedForEachParameter((ParameterElement parameter) {
2046 HInstruction argument = compiledArguments[index++]; 1995 HInstruction argument = compiledArguments[index++];
2047 // Because we are inlining the initializer, we must update 1996 // Because we are inlining the initializer, we must update
2048 // what was given as parameter. This will be used in case 1997 // what was given as parameter. This will be used in case
2049 // there is a parameter check expression in the initializer. 1998 // there is a parameter check expression in the initializer.
2050 parameters[parameter] = argument; 1999 parameters[parameter] = argument;
2051 localsHandler.updateLocal(parameter, argument); 2000 localsHandler.updateLocal(parameter, argument);
2052 // Don't forget to update the field, if the parameter is of the 2001 // Don't forget to update the field, if the parameter is of the
2053 // form [:this.x:]. 2002 // form [:this.x:].
2054 if (parameter.isInitializingFormal) { 2003 if (parameter.isInitializingFormal) {
2055 InitializingFormalElement fieldParameterElement = parameter; 2004 InitializingFormalElement fieldParameterElement = parameter;
2056 fieldValues[fieldParameterElement.fieldElement] = argument; 2005 fieldValues[fieldParameterElement.fieldElement] = argument;
2057 } 2006 }
2058 }); 2007 });
2059 2008
2060 // Build the initializers in the context of the new constructor. 2009 // Build the initializers in the context of the new constructor.
2061 TreeElements oldElements = elements; 2010 TreeElements oldElements = elements;
2062 ResolvedAst resolvedAst = callee.resolvedAst; 2011 ResolvedAst resolvedAst = callee.resolvedAst;
2063 elements = resolvedAst.elements; 2012 elements = resolvedAst.elements;
2064 ClosureClassMap oldClosureData = localsHandler.closureData; 2013 ClosureClassMap oldClosureData = localsHandler.closureData;
2065 ast.Node node = resolvedAst.node; 2014 ast.Node node = resolvedAst.node;
2066 ClosureClassMap newClosureData = 2015 ClosureClassMap newClosureData = compiler.closureToClassMapper
2067 compiler.closureToClassMapper.computeClosureToClassMapping( 2016 .computeClosureToClassMapping(callee, node, elements);
2068 callee, node, elements);
2069 localsHandler.closureData = newClosureData; 2017 localsHandler.closureData = newClosureData;
2070 localsHandler.enterScope(node, callee); 2018 localsHandler.enterScope(node, callee);
2071 buildInitializers(callee, constructors, fieldValues); 2019 buildInitializers(callee, constructors, fieldValues);
2072 localsHandler.closureData = oldClosureData; 2020 localsHandler.closureData = oldClosureData;
2073 elements = oldElements; 2021 elements = oldElements;
2074 }); 2022 });
2075 } 2023 }
2076 2024
2077 /** 2025 /**
2078 * Run through the initializers and inline all field initializers. Recursively 2026 * Run through the initializers and inline all field initializers. Recursively
2079 * inlines super initializers. 2027 * inlines super initializers.
2080 * 2028 *
2081 * The constructors of the inlined initializers is added to [constructors] 2029 * The constructors of the inlined initializers is added to [constructors]
2082 * with sub constructors having a lower index than super constructors. 2030 * with sub constructors having a lower index than super constructors.
2083 * 2031 *
2084 * Invariant: The [constructor] and elements in [constructors] must all be 2032 * Invariant: The [constructor] and elements in [constructors] must all be
2085 * implementation elements. 2033 * implementation elements.
2086 */ 2034 */
2087 void buildInitializers(ConstructorElement constructor, 2035 void buildInitializers(
2088 List<FunctionElement> constructors, 2036 ConstructorElement constructor,
2089 Map<Element, HInstruction> fieldValues) { 2037 List<FunctionElement> constructors,
2038 Map<Element, HInstruction> fieldValues) {
2090 assert(invariant(constructor, constructor.isImplementation)); 2039 assert(invariant(constructor, constructor.isImplementation));
2091 if (constructor.isSynthesized) { 2040 if (constructor.isSynthesized) {
2092 List<HInstruction> arguments = <HInstruction>[]; 2041 List<HInstruction> arguments = <HInstruction>[];
2093 HInstruction compileArgument(ParameterElement parameter) { 2042 HInstruction compileArgument(ParameterElement parameter) {
2094 return localsHandler.readLocal(parameter); 2043 return localsHandler.readLocal(parameter);
2095 } 2044 }
2096 2045
2097 Element target = constructor.definingConstructor.implementation; 2046 Element target = constructor.definingConstructor.implementation;
2098 bool match = !target.isMalformed && 2047 bool match = !target.isMalformed &&
2099 CallStructure.addForwardingElementArgumentsToList( 2048 CallStructure.addForwardingElementArgumentsToList(
2100 constructor, 2049 constructor,
2101 arguments, 2050 arguments,
2102 target, 2051 target,
2103 compileArgument, 2052 compileArgument,
2104 handleConstantForOptionalParameter); 2053 handleConstantForOptionalParameter);
2105 if (!match) { 2054 if (!match) {
2106 if (compiler.elementHasCompileTimeError(constructor)) { 2055 if (compiler.elementHasCompileTimeError(constructor)) {
2107 return; 2056 return;
2108 } 2057 }
2109 // If this fails, the selector we constructed for the call to a 2058 // If this fails, the selector we constructed for the call to a
2110 // forwarding constructor in a mixin application did not match the 2059 // forwarding constructor in a mixin application did not match the
2111 // constructor (which, for example, may happen when the libraries are 2060 // constructor (which, for example, may happen when the libraries are
2112 // not compatible for private names, see issue 20394). 2061 // not compatible for private names, see issue 20394).
2113 reporter.internalError(constructor, 2062 reporter.internalError(
2114 'forwarding constructor call does not match'); 2063 constructor, 'forwarding constructor call does not match');
2115 } 2064 }
2116 inlineSuperOrRedirect( 2065 inlineSuperOrRedirect(
2117 target, 2066 target, arguments, constructors, fieldValues, constructor);
2118 arguments,
2119 constructors,
2120 fieldValues,
2121 constructor);
2122 return; 2067 return;
2123 } 2068 }
2124 ast.FunctionExpression functionNode = constructor.node; 2069 ast.FunctionExpression functionNode = constructor.node;
2125 2070
2126 bool foundSuperOrRedirect = false; 2071 bool foundSuperOrRedirect = false;
2127 if (functionNode.initializers != null) { 2072 if (functionNode.initializers != null) {
2128 Link<ast.Node> initializers = functionNode.initializers.nodes; 2073 Link<ast.Node> initializers = functionNode.initializers.nodes;
2129 for (Link<ast.Node> link = initializers; !link.isEmpty; link = link.tail) { 2074 for (Link<ast.Node> link = initializers;
2075 !link.isEmpty;
2076 link = link.tail) {
2130 assert(link.head is ast.Send); 2077 assert(link.head is ast.Send);
2131 if (link.head is !ast.SendSet) { 2078 if (link.head is! ast.SendSet) {
2132 // A super initializer or constructor redirection. 2079 // A super initializer or constructor redirection.
2133 foundSuperOrRedirect = true; 2080 foundSuperOrRedirect = true;
2134 ast.Send call = link.head; 2081 ast.Send call = link.head;
2135 assert(ast.Initializers.isSuperConstructorCall(call) || 2082 assert(ast.Initializers.isSuperConstructorCall(call) ||
2136 ast.Initializers.isConstructorRedirect(call)); 2083 ast.Initializers.isConstructorRedirect(call));
2137 FunctionElement target = elements[call].implementation; 2084 FunctionElement target = elements[call].implementation;
2138 CallStructure callStructure = 2085 CallStructure callStructure =
2139 elements.getSelector(call).callStructure; 2086 elements.getSelector(call).callStructure;
2140 Link<ast.Node> arguments = call.arguments; 2087 Link<ast.Node> arguments = call.arguments;
2141 List<HInstruction> compiledArguments; 2088 List<HInstruction> compiledArguments;
2142 inlinedFrom(constructor, () { 2089 inlinedFrom(constructor, () {
2143 compiledArguments = 2090 compiledArguments =
2144 makeStaticArgumentList(callStructure, arguments, target); 2091 makeStaticArgumentList(callStructure, arguments, target);
2145 }); 2092 });
2146 inlineSuperOrRedirect(target, 2093 inlineSuperOrRedirect(target, compiledArguments, constructors,
2147 compiledArguments, 2094 fieldValues, constructor);
2148 constructors,
2149 fieldValues,
2150 constructor);
2151 } else { 2095 } else {
2152 // A field initializer. 2096 // A field initializer.
2153 ast.SendSet init = link.head; 2097 ast.SendSet init = link.head;
2154 Link<ast.Node> arguments = init.arguments; 2098 Link<ast.Node> arguments = init.arguments;
2155 assert(!arguments.isEmpty && arguments.tail.isEmpty); 2099 assert(!arguments.isEmpty && arguments.tail.isEmpty);
2156 inlinedFrom(constructor, () { 2100 inlinedFrom(constructor, () {
2157 visit(arguments.head); 2101 visit(arguments.head);
2158 }); 2102 });
2159 fieldValues[elements[init]] = pop(); 2103 fieldValues[elements[init]] = pop();
2160 } 2104 }
2161 } 2105 }
2162 } 2106 }
2163 2107
2164 if (!foundSuperOrRedirect) { 2108 if (!foundSuperOrRedirect) {
2165 // No super initializer found. Try to find the default constructor if 2109 // No super initializer found. Try to find the default constructor if
2166 // the class is not Object. 2110 // the class is not Object.
2167 ClassElement enclosingClass = constructor.enclosingClass; 2111 ClassElement enclosingClass = constructor.enclosingClass;
2168 ClassElement superClass = enclosingClass.superclass; 2112 ClassElement superClass = enclosingClass.superclass;
2169 if (!enclosingClass.isObject) { 2113 if (!enclosingClass.isObject) {
2170 assert(superClass != null); 2114 assert(superClass != null);
2171 assert(superClass.isResolved); 2115 assert(superClass.isResolved);
2172 // TODO(johnniwinther): Should we find injected constructors as well? 2116 // TODO(johnniwinther): Should we find injected constructors as well?
2173 FunctionElement target = superClass.lookupDefaultConstructor(); 2117 FunctionElement target = superClass.lookupDefaultConstructor();
2174 if (target == null) { 2118 if (target == null) {
2175 reporter.internalError(superClass, 2119 reporter.internalError(
2176 "No default constructor available."); 2120 superClass, "No default constructor available.");
2177 } 2121 }
2178 List<HInstruction> arguments = 2122 List<HInstruction> arguments = CallStructure.NO_ARGS.makeArgumentsList(
2179 CallStructure.NO_ARGS.makeArgumentsList( 2123 const Link<ast.Node>(),
2180 const Link<ast.Node>(), 2124 target.implementation,
2181 target.implementation, 2125 null,
2182 null, 2126 handleConstantForOptionalParameter);
2183 handleConstantForOptionalParameter); 2127 inlineSuperOrRedirect(
2184 inlineSuperOrRedirect(target, 2128 target, arguments, constructors, fieldValues, constructor);
2185 arguments,
2186 constructors,
2187 fieldValues,
2188 constructor);
2189 } 2129 }
2190 } 2130 }
2191 } 2131 }
2192 2132
2193 /** 2133 /**
2194 * Run through the fields of [cls] and add their potential 2134 * Run through the fields of [cls] and add their potential
2195 * initializers. 2135 * initializers.
2196 * 2136 *
2197 * Invariant: [classElement] must be an implementation element. 2137 * Invariant: [classElement] must be an implementation element.
2198 */ 2138 */
2199 void buildFieldInitializers(ClassElement classElement, 2139 void buildFieldInitializers(
2200 Map<Element, HInstruction> fieldValues) { 2140 ClassElement classElement, Map<Element, HInstruction> fieldValues) {
2201 assert(invariant(classElement, classElement.isImplementation)); 2141 assert(invariant(classElement, classElement.isImplementation));
2202 classElement.forEachInstanceField( 2142 classElement.forEachInstanceField(
2203 (ClassElement enclosingClass, VariableElement member) { 2143 (ClassElement enclosingClass, VariableElement member) {
2204 if (compiler.elementHasCompileTimeError(member)) return; 2144 if (compiler.elementHasCompileTimeError(member)) return;
2205 reporter.withCurrentElement(member, () { 2145 reporter.withCurrentElement(member, () {
2206 TreeElements definitions = member.treeElements; 2146 TreeElements definitions = member.treeElements;
2207 ast.Node node = member.node; 2147 ast.Node node = member.node;
2208 ast.Expression initializer = member.initializer; 2148 ast.Expression initializer = member.initializer;
2209 if (initializer == null) { 2149 if (initializer == null) {
2210 // Unassigned fields of native classes are not initialized to 2150 // Unassigned fields of native classes are not initialized to
2211 // prevent overwriting pre-initialized native properties. 2151 // prevent overwriting pre-initialized native properties.
2212 if (!backend.isNativeOrExtendsNative(classElement)) { 2152 if (!backend.isNativeOrExtendsNative(classElement)) {
2213 fieldValues[member] = graph.addConstantNull(compiler); 2153 fieldValues[member] = graph.addConstantNull(compiler);
2214 } 2154 }
2215 } else { 2155 } else {
2216 ast.Node right = initializer; 2156 ast.Node right = initializer;
2217 TreeElements savedElements = elements; 2157 TreeElements savedElements = elements;
2218 elements = definitions; 2158 elements = definitions;
2219 // In case the field initializer uses closures, run the 2159 // In case the field initializer uses closures, run the
2220 // closure to class mapper. 2160 // closure to class mapper.
2221 compiler.closureToClassMapper.computeClosureToClassMapping( 2161 compiler.closureToClassMapper
2222 member, node, elements); 2162 .computeClosureToClassMapping(member, node, elements);
2223 inlinedFrom(member, () => right.accept(this)); 2163 inlinedFrom(member, () => right.accept(this));
2224 elements = savedElements; 2164 elements = savedElements;
2225 fieldValues[member] = pop(); 2165 fieldValues[member] = pop();
2226 } 2166 }
2227 }); 2167 });
2228 }); 2168 });
2229 } 2169 }
2230 2170
2231 /** 2171 /**
2232 * Build the factory function corresponding to the constructor 2172 * Build the factory function corresponding to the constructor
2233 * [functionElement]: 2173 * [functionElement]:
2234 * - Initialize fields with the values of the field initializers of the 2174 * - Initialize fields with the values of the field initializers of the
2235 * current constructor and super constructors or constructors redirected 2175 * current constructor and super constructors or constructors redirected
2236 * to, starting from the current constructor. 2176 * to, starting from the current constructor.
2237 * - Call the constructor bodies, starting from the constructor(s) in the 2177 * - Call the constructor bodies, starting from the constructor(s) in the
2238 * super class(es). 2178 * super class(es).
2239 */ 2179 */
2240 HGraph buildFactory(ConstructorElement functionElement) { 2180 HGraph buildFactory(ConstructorElement functionElement) {
2241 functionElement = functionElement.implementation; 2181 functionElement = functionElement.implementation;
2242 ClassElement classElement = 2182 ClassElement classElement = functionElement.enclosingClass.implementation;
2243 functionElement.enclosingClass.implementation;
2244 bool isNativeUpgradeFactory = 2183 bool isNativeUpgradeFactory =
2245 backend.isNativeOrExtendsNative(classElement) 2184 backend.isNativeOrExtendsNative(classElement) &&
2246 && !backend.isJsInterop(classElement); 2185 !backend.isJsInterop(classElement);
2247 ast.FunctionExpression function = functionElement.node; 2186 ast.FunctionExpression function = functionElement.node;
2248 // Note that constructors (like any other static function) do not need 2187 // Note that constructors (like any other static function) do not need
2249 // to deal with optional arguments. It is the callers job to provide all 2188 // to deal with optional arguments. It is the callers job to provide all
2250 // arguments as if they were positional. 2189 // arguments as if they were positional.
2251 2190
2252 if (inliningStack.isEmpty) { 2191 if (inliningStack.isEmpty) {
2253 // The initializer list could contain closures. 2192 // The initializer list could contain closures.
2254 openFunction(functionElement, function); 2193 openFunction(functionElement, function);
2255 } 2194 }
2256 2195
2257 Map<Element, HInstruction> fieldValues = new Map<Element, HInstruction>(); 2196 Map<Element, HInstruction> fieldValues = new Map<Element, HInstruction>();
2258 2197
2259 // Compile the possible initialization code for local fields and 2198 // Compile the possible initialization code for local fields and
2260 // super fields, unless this is a redirecting constructor, in which case 2199 // super fields, unless this is a redirecting constructor, in which case
2261 // the effective target will initialize these. 2200 // the effective target will initialize these.
2262 if (!functionElement.isRedirectingGenerative) { 2201 if (!functionElement.isRedirectingGenerative) {
2263 buildFieldInitializers(classElement, fieldValues); 2202 buildFieldInitializers(classElement, fieldValues);
2264 } 2203 }
2265 2204
2266 // Compile field-parameters such as [:this.x:]. 2205 // Compile field-parameters such as [:this.x:].
2267 FunctionSignature params = functionElement.functionSignature; 2206 FunctionSignature params = functionElement.functionSignature;
2268 params.orderedForEachParameter((ParameterElement parameter) { 2207 params.orderedForEachParameter((ParameterElement parameter) {
2269 if (parameter.isInitializingFormal) { 2208 if (parameter.isInitializingFormal) {
2270 // If the [element] is a field-parameter then 2209 // If the [element] is a field-parameter then
2271 // initialize the field element with its value. 2210 // initialize the field element with its value.
2272 InitializingFormalElement fieldParameter = parameter; 2211 InitializingFormalElement fieldParameter = parameter;
2273 HInstruction parameterValue = 2212 HInstruction parameterValue = localsHandler.readLocal(fieldParameter);
2274 localsHandler.readLocal(fieldParameter);
2275 fieldValues[fieldParameter.fieldElement] = parameterValue; 2213 fieldValues[fieldParameter.fieldElement] = parameterValue;
2276 } 2214 }
2277 }); 2215 });
2278 2216
2279 // Analyze the constructor and all referenced constructors and collect 2217 // Analyze the constructor and all referenced constructors and collect
2280 // initializers and constructor bodies. 2218 // initializers and constructor bodies.
2281 List<FunctionElement> constructors = <FunctionElement>[functionElement]; 2219 List<FunctionElement> constructors = <FunctionElement>[functionElement];
2282 buildInitializers(functionElement, constructors, fieldValues); 2220 buildInitializers(functionElement, constructors, fieldValues);
2283 2221
2284 // Call the JavaScript constructor with the fields as argument. 2222 // Call the JavaScript constructor with the fields as argument.
2285 List<HInstruction> constructorArguments = <HInstruction>[]; 2223 List<HInstruction> constructorArguments = <HInstruction>[];
2286 List<Element> fields = <Element>[]; 2224 List<Element> fields = <Element>[];
2287 2225
2288 classElement.forEachInstanceField( 2226 classElement.forEachInstanceField(
2289 (ClassElement enclosingClass, VariableElement member) { 2227 (ClassElement enclosingClass, VariableElement member) {
2290 HInstruction value = fieldValues[member]; 2228 HInstruction value = fieldValues[member];
2291 if (value == null) { 2229 if (value == null) {
2292 // Uninitialized native fields are pre-initialized by the native 2230 // Uninitialized native fields are pre-initialized by the native
2293 // implementation. 2231 // implementation.
2294 assert(invariant( 2232 assert(invariant(
2295 member, isNativeUpgradeFactory || compiler.compilationFailed)); 2233 member, isNativeUpgradeFactory || compiler.compilationFailed));
2296 } else { 2234 } else {
2297 fields.add(member); 2235 fields.add(member);
2298 DartType type = localsHandler.substInContext(member.type); 2236 DartType type = localsHandler.substInContext(member.type);
2299 constructorArguments.add(potentiallyCheckOrTrustType(value, type)); 2237 constructorArguments.add(potentiallyCheckOrTrustType(value, type));
2300 } 2238 }
2301 }, 2239 }, includeSuperAndInjectedMembers: true);
2302 includeSuperAndInjectedMembers: true);
2303 2240
2304 InterfaceType type = classElement.thisType; 2241 InterfaceType type = classElement.thisType;
2305 TypeMask ssaType = 2242 TypeMask ssaType =
2306 new TypeMask.nonNullExact(classElement.declaration, compiler.world); 2243 new TypeMask.nonNullExact(classElement.declaration, compiler.world);
2307 List<DartType> instantiatedTypes; 2244 List<DartType> instantiatedTypes;
2308 addInlinedInstantiation(type); 2245 addInlinedInstantiation(type);
2309 if (!currentInlinedInstantiations.isEmpty) { 2246 if (!currentInlinedInstantiations.isEmpty) {
2310 instantiatedTypes = new List<DartType>.from(currentInlinedInstantiations); 2247 instantiatedTypes = new List<DartType>.from(currentInlinedInstantiations);
2311 } 2248 }
2312 2249
2313 HInstruction newObject; 2250 HInstruction newObject;
2314 if (!isNativeUpgradeFactory) { 2251 if (!isNativeUpgradeFactory) {
2315 newObject = new HForeignNew(classElement, 2252 newObject = new HForeignNew(
2316 ssaType, 2253 classElement, ssaType, constructorArguments, instantiatedTypes);
2317 constructorArguments,
2318 instantiatedTypes);
2319 if (function != null) { 2254 if (function != null) {
2320 // TODO(johnniwinther): Provide source information for creation 2255 // TODO(johnniwinther): Provide source information for creation
2321 // through synthetic constructors. 2256 // through synthetic constructors.
2322 newObject.sourceInformation = 2257 newObject.sourceInformation =
2323 sourceInformationBuilder.buildCreate(function); 2258 sourceInformationBuilder.buildCreate(function);
2324 } 2259 }
2325 add(newObject); 2260 add(newObject);
2326 } else { 2261 } else {
2327 // Bulk assign to the initialized fields. 2262 // Bulk assign to the initialized fields.
2328 newObject = graph.explicitReceiverParameter; 2263 newObject = graph.explicitReceiverParameter;
2329 // Null guard ensures an error if we are being called from an explicit 2264 // Null guard ensures an error if we are being called from an explicit
2330 // 'new' of the constructor instead of via an upgrade. It is optimized out 2265 // 'new' of the constructor instead of via an upgrade. It is optimized out
2331 // if there are field initializers. 2266 // if there are field initializers.
2332 add(new HFieldGet( 2267 add(new HFieldGet(null, newObject, backend.dynamicType,
2333 null, newObject, backend.dynamicType, isAssignable: false)); 2268 isAssignable: false));
2334 for (int i = 0; i < fields.length; i++) { 2269 for (int i = 0; i < fields.length; i++) {
2335 add(new HFieldSet(fields[i], newObject, constructorArguments[i])); 2270 add(new HFieldSet(fields[i], newObject, constructorArguments[i]));
2336 } 2271 }
2337 } 2272 }
2338 removeInlinedInstantiation(type); 2273 removeInlinedInstantiation(type);
2339 // Create the runtime type information, if needed. 2274 // Create the runtime type information, if needed.
2340 if (backend.classNeedsRti(classElement)) { 2275 if (backend.classNeedsRti(classElement)) {
2341 // Read the values of the type arguments and create a list to set on the 2276 // Read the values of the type arguments and create a list to set on the
2342 // newly create object. We can identify the case where the new list 2277 // newly create object. We can identify the case where the new list
2343 // would be of the form: 2278 // would be of the form:
2344 // [getTypeArgumentByIndex(this, 0), .., getTypeArgumentByIndex(this, k)] 2279 // [getTypeArgumentByIndex(this, 0), .., getTypeArgumentByIndex(this, k)]
2345 // and k is the number of type arguments of this. If this is the case, 2280 // and k is the number of type arguments of this. If this is the case,
2346 // we can simply copy the list from this. 2281 // we can simply copy the list from this.
2347 2282
2348 // These locals are modified by [isIndexedTypeArgumentGet]. 2283 // These locals are modified by [isIndexedTypeArgumentGet].
2349 HThis source; // The source of the type arguments. 2284 HThis source; // The source of the type arguments.
2350 bool allIndexed = true; 2285 bool allIndexed = true;
2351 int expectedIndex = 0; 2286 int expectedIndex = 0;
2352 ClassElement contextClass; // The class of `this`. 2287 ClassElement contextClass; // The class of `this`.
2353 int remainingTypeVariables; // The number of 'remaining type variables' 2288 int remainingTypeVariables; // The number of 'remaining type variables'
2354 // of `this`. 2289 // of `this`.
2355 2290
2356 /// Helper to identify instructions that read a type variable without 2291 /// Helper to identify instructions that read a type variable without
2357 /// substitution (that is, directly use the index). These instructions 2292 /// substitution (that is, directly use the index). These instructions
2358 /// are of the form: 2293 /// are of the form:
2359 /// HInvokeStatic(getTypeArgumentByIndex, this, index) 2294 /// HInvokeStatic(getTypeArgumentByIndex, this, index)
2360 /// 2295 ///
2361 /// Return `true` if [instruction] is of that form and the index is the 2296 /// Return `true` if [instruction] is of that form and the index is the
2362 /// next index in the sequence (held in [expectedIndex]). 2297 /// next index in the sequence (held in [expectedIndex]).
2363 bool isIndexedTypeArgumentGet(HInstruction instruction) { 2298 bool isIndexedTypeArgumentGet(HInstruction instruction) {
2364 if (instruction is! HInvokeStatic) return false; 2299 if (instruction is! HInvokeStatic) return false;
(...skipping 21 matching lines...) Expand all
2386 // a copy. Otherwise remove one argument. 2321 // a copy. Otherwise remove one argument.
2387 if (remainingTypeVariables == 0) return false; 2322 if (remainingTypeVariables == 0) return false;
2388 remainingTypeVariables--; 2323 remainingTypeVariables--;
2389 // Check that the index is the one we expect. 2324 // Check that the index is the one we expect.
2390 IntConstantValue constant = index.constant; 2325 IntConstantValue constant = index.constant;
2391 return constant.primitiveValue == expectedIndex++; 2326 return constant.primitiveValue == expectedIndex++;
2392 } 2327 }
2393 2328
2394 List<HInstruction> typeArguments = <HInstruction>[]; 2329 List<HInstruction> typeArguments = <HInstruction>[];
2395 classElement.typeVariables.forEach((TypeVariableType typeVariable) { 2330 classElement.typeVariables.forEach((TypeVariableType typeVariable) {
2396 HInstruction argument = localsHandler.readLocal( 2331 HInstruction argument = localsHandler
2397 localsHandler.getTypeVariableAsLocal(typeVariable)); 2332 .readLocal(localsHandler.getTypeVariableAsLocal(typeVariable));
2398 if (allIndexed && !isIndexedTypeArgumentGet(argument)) { 2333 if (allIndexed && !isIndexedTypeArgumentGet(argument)) {
2399 allIndexed = false; 2334 allIndexed = false;
2400 } 2335 }
2401 typeArguments.add(argument); 2336 typeArguments.add(argument);
2402 }); 2337 });
2403 2338
2404 if (source != null && allIndexed && remainingTypeVariables == 0) { 2339 if (source != null && allIndexed && remainingTypeVariables == 0) {
2405 copyRuntimeTypeInfo(source, newObject); 2340 copyRuntimeTypeInfo(source, newObject);
2406 } else { 2341 } else {
2407 newObject = 2342 newObject =
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
2451 } 2386 }
2452 2387
2453 // Type variables arguments must come after the box (if there is one). 2388 // Type variables arguments must come after the box (if there is one).
2454 ClassElement currentClass = constructor.enclosingClass; 2389 ClassElement currentClass = constructor.enclosingClass;
2455 if (backend.classNeedsRti(currentClass)) { 2390 if (backend.classNeedsRti(currentClass)) {
2456 // If [currentClass] needs RTI, we add the type variables as 2391 // If [currentClass] needs RTI, we add the type variables as
2457 // parameters of the generative constructor body. 2392 // parameters of the generative constructor body.
2458 currentClass.typeVariables.forEach((TypeVariableType argument) { 2393 currentClass.typeVariables.forEach((TypeVariableType argument) {
2459 // TODO(johnniwinther): Substitute [argument] with 2394 // TODO(johnniwinther): Substitute [argument] with
2460 // `localsHandler.substInContext(argument)`. 2395 // `localsHandler.substInContext(argument)`.
2461 bodyCallInputs.add(localsHandler.readLocal( 2396 bodyCallInputs.add(localsHandler
2462 localsHandler.getTypeVariableAsLocal(argument))); 2397 .readLocal(localsHandler.getTypeVariableAsLocal(argument)));
2463 }); 2398 });
2464 } 2399 }
2465 2400
2466 if (!isNativeUpgradeFactory && // TODO(13836): Fix inlining. 2401 if (!isNativeUpgradeFactory && // TODO(13836): Fix inlining.
2467 tryInlineMethod(body, null, null, bodyCallInputs, function)) { 2402 tryInlineMethod(body, null, null, bodyCallInputs, function)) {
2468 pop(); 2403 pop();
2469 } else { 2404 } else {
2470 HInvokeConstructorBody invoke = new HInvokeConstructorBody( 2405 HInvokeConstructorBody invoke = new HInvokeConstructorBody(
2471 body.declaration, bodyCallInputs, backend.nonNullType); 2406 body.declaration, bodyCallInputs, backend.nonNullType);
2472 invoke.sideEffects = 2407 invoke.sideEffects =
(...skipping 23 matching lines...) Expand all
2496 2431
2497 localsHandler.startFunction(element, node); 2432 localsHandler.startFunction(element, node);
2498 close(new HGoto()).addSuccessor(block); 2433 close(new HGoto()).addSuccessor(block);
2499 2434
2500 open(block); 2435 open(block);
2501 2436
2502 // Add the type parameters of the class as parameters of this method. This 2437 // Add the type parameters of the class as parameters of this method. This
2503 // must be done before adding the normal parameters, because their types 2438 // must be done before adding the normal parameters, because their types
2504 // may contain references to type variables. 2439 // may contain references to type variables.
2505 var enclosing = element.enclosingElement; 2440 var enclosing = element.enclosingElement;
2506 if ((element.isConstructor || element.isGenerativeConstructorBody) 2441 if ((element.isConstructor || element.isGenerativeConstructorBody) &&
2507 && backend.classNeedsRti(enclosing)) { 2442 backend.classNeedsRti(enclosing)) {
2508 enclosing.typeVariables.forEach((TypeVariableType typeVariable) { 2443 enclosing.typeVariables.forEach((TypeVariableType typeVariable) {
2509 HParameterValue param = addParameter( 2444 HParameterValue param =
2510 typeVariable.element, backend.nonNullType); 2445 addParameter(typeVariable.element, backend.nonNullType);
2511 localsHandler.directLocals[ 2446 localsHandler.directLocals[
2512 localsHandler.getTypeVariableAsLocal(typeVariable)] = param; 2447 localsHandler.getTypeVariableAsLocal(typeVariable)] = param;
2513 }); 2448 });
2514 } 2449 }
2515 2450
2516 if (element is FunctionElement) { 2451 if (element is FunctionElement) {
2517 FunctionElement functionElement = element; 2452 FunctionElement functionElement = element;
2518 FunctionSignature signature = functionElement.functionSignature; 2453 FunctionSignature signature = functionElement.functionSignature;
2519 2454
2520 // Put the type checks in the first successor of the entry, 2455 // Put the type checks in the first successor of the entry,
2521 // because that is where the type guards will also be inserted. 2456 // because that is where the type guards will also be inserted.
2522 // This way we ensure that a type guard will dominate the type 2457 // This way we ensure that a type guard will dominate the type
2523 // check. 2458 // check.
2524 ClosureScope scopeData = 2459 ClosureScope scopeData = localsHandler.closureData.capturingScopes[node];
2525 localsHandler.closureData.capturingScopes[node];
2526 signature.orderedForEachParameter((ParameterElement parameterElement) { 2460 signature.orderedForEachParameter((ParameterElement parameterElement) {
2527 if (element.isGenerativeConstructorBody) { 2461 if (element.isGenerativeConstructorBody) {
2528 if (scopeData != null && 2462 if (scopeData != null &&
2529 scopeData.isCapturedVariable(parameterElement)) { 2463 scopeData.isCapturedVariable(parameterElement)) {
2530 // The parameter will be a field in the box passed as the 2464 // The parameter will be a field in the box passed as the
2531 // last parameter. So no need to have it. 2465 // last parameter. So no need to have it.
2532 return; 2466 return;
2533 } 2467 }
2534 } 2468 }
2535 HInstruction newParameter = 2469 HInstruction newParameter =
(...skipping 26 matching lines...) Expand all
2562 2496
2563 insertTraceCall(element); 2497 insertTraceCall(element);
2564 insertCoverageCall(element); 2498 insertCoverageCall(element);
2565 } 2499 }
2566 2500
2567 insertTraceCall(Element element) { 2501 insertTraceCall(Element element) {
2568 if (JavaScriptBackend.TRACE_METHOD == 'console') { 2502 if (JavaScriptBackend.TRACE_METHOD == 'console') {
2569 if (element == backend.traceHelper) return; 2503 if (element == backend.traceHelper) return;
2570 n(e) => e == null ? '' : e.name; 2504 n(e) => e == null ? '' : e.name;
2571 String name = "${n(element.library)}:${n(element.enclosingClass)}." 2505 String name = "${n(element.library)}:${n(element.enclosingClass)}."
2572 "${n(element)}"; 2506 "${n(element)}";
2573 HConstant nameConstant = addConstantString(name); 2507 HConstant nameConstant = addConstantString(name);
2574 add(new HInvokeStatic(backend.traceHelper, 2508 add(new HInvokeStatic(backend.traceHelper, <HInstruction>[nameConstant],
2575 <HInstruction>[nameConstant], 2509 backend.dynamicType));
2576 backend.dynamicType));
2577 } 2510 }
2578 } 2511 }
2579 2512
2580 insertCoverageCall(Element element) { 2513 insertCoverageCall(Element element) {
2581 if (JavaScriptBackend.TRACE_METHOD == 'post') { 2514 if (JavaScriptBackend.TRACE_METHOD == 'post') {
2582 if (element == backend.traceHelper) return; 2515 if (element == backend.traceHelper) return;
2583 // TODO(sigmund): create a better uuid for elements. 2516 // TODO(sigmund): create a better uuid for elements.
2584 HConstant idConstant = graph.addConstantInt(element.hashCode, compiler); 2517 HConstant idConstant = graph.addConstantInt(element.hashCode, compiler);
2585 HConstant nameConstant = addConstantString(element.name); 2518 HConstant nameConstant = addConstantString(element.name);
2586 add(new HInvokeStatic(backend.traceHelper, 2519 add(new HInvokeStatic(backend.traceHelper,
2587 <HInstruction>[idConstant, nameConstant], 2520 <HInstruction>[idConstant, nameConstant], backend.dynamicType));
2588 backend.dynamicType));
2589 } 2521 }
2590 } 2522 }
2591 2523
2592 /// Check that [type] is valid in the context of `localsHandler.contextClass`. 2524 /// Check that [type] is valid in the context of `localsHandler.contextClass`.
2593 /// This should only be called in assertions. 2525 /// This should only be called in assertions.
2594 bool assertTypeInContext(DartType type, [Spannable spannable]) { 2526 bool assertTypeInContext(DartType type, [Spannable spannable]) {
2595 return invariant(spannable == null ? CURRENT_ELEMENT_SPANNABLE : spannable, 2527 return invariant(spannable == null ? CURRENT_ELEMENT_SPANNABLE : spannable,
2596 () { 2528 () {
2597 ClassElement contextClass = Types.getClassContext(type); 2529 ClassElement contextClass = Types.getClassContext(type);
2598 return contextClass == null || 2530 return contextClass == null || contextClass == localsHandler.contextClass;
2599 contextClass == localsHandler.contextClass; 2531 },
2600 },
2601 message: "Type '$type' is not valid context of " 2532 message: "Type '$type' is not valid context of "
2602 "${localsHandler.contextClass}."); 2533 "${localsHandler.contextClass}.");
2603 } 2534 }
2604 2535
2605 /// Build a [HTypeConversion] for convertion [original] to type [type]. 2536 /// Build a [HTypeConversion] for convertion [original] to type [type].
2606 /// 2537 ///
2607 /// Invariant: [type] must be valid in the context. 2538 /// Invariant: [type] must be valid in the context.
2608 /// See [LocalsHandler.substInContext]. 2539 /// See [LocalsHandler.substInContext].
2609 HInstruction buildTypeConversion(HInstruction original, 2540 HInstruction buildTypeConversion(
2610 DartType type, 2541 HInstruction original, DartType type, int kind) {
2611 int kind) {
2612 if (type == null) return original; 2542 if (type == null) return original;
2613 type = type.unaliased; 2543 type = type.unaliased;
2614 assert(assertTypeInContext(type, original)); 2544 assert(assertTypeInContext(type, original));
2615 if (type.isInterfaceType && !type.treatAsRaw) { 2545 if (type.isInterfaceType && !type.treatAsRaw) {
2616 TypeMask subtype = new TypeMask.subtype(type.element, compiler.world); 2546 TypeMask subtype = new TypeMask.subtype(type.element, compiler.world);
2617 HInstruction representations = buildTypeArgumentRepresentations(type); 2547 HInstruction representations = buildTypeArgumentRepresentations(type);
2618 add(representations); 2548 add(representations);
2619 return new HTypeConversion.withTypeRepresentation(type, kind, subtype, 2549 return new HTypeConversion.withTypeRepresentation(
2620 original, representations); 2550 type, kind, subtype, original, representations);
2621 } else if (type.isTypeVariable) { 2551 } else if (type.isTypeVariable) {
2622 TypeMask subtype = original.instructionType; 2552 TypeMask subtype = original.instructionType;
2623 HInstruction typeVariable = addTypeVariableReference(type); 2553 HInstruction typeVariable = addTypeVariableReference(type);
2624 return new HTypeConversion.withTypeRepresentation(type, kind, subtype, 2554 return new HTypeConversion.withTypeRepresentation(
2625 original, typeVariable); 2555 type, kind, subtype, original, typeVariable);
2626 } else if (type.isFunctionType) { 2556 } else if (type.isFunctionType) {
2627 String name = kind == HTypeConversion.CAST_TYPE_CHECK 2557 String name =
2628 ? '_asCheck' : '_assertCheck'; 2558 kind == HTypeConversion.CAST_TYPE_CHECK ? '_asCheck' : '_assertCheck';
2629 2559
2630 List<HInstruction> arguments = 2560 List<HInstruction> arguments = <HInstruction>[
2631 <HInstruction>[buildFunctionType(type), original]; 2561 buildFunctionType(type),
2562 original
2563 ];
2632 pushInvokeDynamic( 2564 pushInvokeDynamic(
2633 null, 2565 null,
2634 new Selector.call( 2566 new Selector.call(
2635 new Name(name, helpers.jsHelperLibrary), CallStructure.ONE_ARG), 2567 new Name(name, helpers.jsHelperLibrary), CallStructure.ONE_ARG),
2636 null, 2568 null,
2637 arguments); 2569 arguments);
2638 2570
2639 return new HTypeConversion(type, kind, original.instructionType, pop()); 2571 return new HTypeConversion(type, kind, original.instructionType, pop());
2640 } else { 2572 } else {
2641 return original.convertType(compiler, type, kind); 2573 return original.convertType(compiler, type, kind);
(...skipping 17 matching lines...) Expand all
2659 HInstruction _checkType(HInstruction original, DartType type, int kind) { 2591 HInstruction _checkType(HInstruction original, DartType type, int kind) {
2660 assert(compiler.options.enableTypeAssertions); 2592 assert(compiler.options.enableTypeAssertions);
2661 assert(type != null); 2593 assert(type != null);
2662 type = localsHandler.substInContext(type); 2594 type = localsHandler.substInContext(type);
2663 HInstruction other = buildTypeConversion(original, type, kind); 2595 HInstruction other = buildTypeConversion(original, type, kind);
2664 registry?.registerTypeUse(new TypeUse.isCheck(type)); 2596 registry?.registerTypeUse(new TypeUse.isCheck(type));
2665 return other; 2597 return other;
2666 } 2598 }
2667 2599
2668 HInstruction potentiallyCheckOrTrustType(HInstruction original, DartType type, 2600 HInstruction potentiallyCheckOrTrustType(HInstruction original, DartType type,
2669 { int kind: HTypeConversion.CHECKED_MODE_CHECK }) { 2601 {int kind: HTypeConversion.CHECKED_MODE_CHECK}) {
2670 if (type == null) return original; 2602 if (type == null) return original;
2671 HInstruction checkedOrTrusted = original; 2603 HInstruction checkedOrTrusted = original;
2672 if (compiler.options.trustTypeAnnotations) { 2604 if (compiler.options.trustTypeAnnotations) {
2673 checkedOrTrusted = _trustType(original, type); 2605 checkedOrTrusted = _trustType(original, type);
2674 } else if (compiler.options.enableTypeAssertions) { 2606 } else if (compiler.options.enableTypeAssertions) {
2675 checkedOrTrusted = _checkType(original, type, kind); 2607 checkedOrTrusted = _checkType(original, type, kind);
2676 } 2608 }
2677 if (checkedOrTrusted == original) return original; 2609 if (checkedOrTrusted == original) return original;
2678 add(checkedOrTrusted); 2610 add(checkedOrTrusted);
2679 return checkedOrTrusted; 2611 return checkedOrTrusted;
2680 } 2612 }
2681 2613
2682 void assertIsSubtype(ast.Node node, DartType subtype, DartType supertype, 2614 void assertIsSubtype(
2683 String message) { 2615 ast.Node node, DartType subtype, DartType supertype, String message) {
2684 HInstruction subtypeInstruction = 2616 HInstruction subtypeInstruction =
2685 analyzeTypeArgument(localsHandler.substInContext(subtype)); 2617 analyzeTypeArgument(localsHandler.substInContext(subtype));
2686 HInstruction supertypeInstruction = 2618 HInstruction supertypeInstruction =
2687 analyzeTypeArgument(localsHandler.substInContext(supertype)); 2619 analyzeTypeArgument(localsHandler.substInContext(supertype));
2688 HInstruction messageInstruction = 2620 HInstruction messageInstruction =
2689 graph.addConstantString(new ast.DartString.literal(message), compiler); 2621 graph.addConstantString(new ast.DartString.literal(message), compiler);
2690 Element element = helpers.assertIsSubtype; 2622 Element element = helpers.assertIsSubtype;
2691 var inputs = <HInstruction>[subtypeInstruction, supertypeInstruction, 2623 var inputs = <HInstruction>[
2692 messageInstruction]; 2624 subtypeInstruction,
2693 HInstruction assertIsSubtype = new HInvokeStatic( 2625 supertypeInstruction,
2694 element, inputs, subtypeInstruction.instructionType); 2626 messageInstruction
2627 ];
2628 HInstruction assertIsSubtype =
2629 new HInvokeStatic(element, inputs, subtypeInstruction.instructionType);
2695 registry?.registerTypeVariableBoundsSubtypeCheck(subtype, supertype); 2630 registry?.registerTypeVariableBoundsSubtypeCheck(subtype, supertype);
2696 add(assertIsSubtype); 2631 add(assertIsSubtype);
2697 } 2632 }
2698 2633
2699 HGraph closeFunction() { 2634 HGraph closeFunction() {
2700 // TODO(kasperl): Make this goto an implicit return. 2635 // TODO(kasperl): Make this goto an implicit return.
2701 if (!isAborted()) closeAndGotoExit(new HGoto()); 2636 if (!isAborted()) closeAndGotoExit(new HGoto());
2702 graph.finalize(); 2637 graph.finalize();
2703 return graph; 2638 return graph;
2704 } 2639 }
(...skipping 11 matching lines...) Expand all
2716 return stack.removeLast(); 2651 return stack.removeLast();
2717 } 2652 }
2718 2653
2719 void dup() { 2654 void dup() {
2720 stack.add(stack.last); 2655 stack.add(stack.last);
2721 } 2656 }
2722 2657
2723 HInstruction popBoolified() { 2658 HInstruction popBoolified() {
2724 HInstruction value = pop(); 2659 HInstruction value = pop();
2725 if (_checkOrTrustTypes) { 2660 if (_checkOrTrustTypes) {
2726 return potentiallyCheckOrTrustType( 2661 return potentiallyCheckOrTrustType(value, compiler.coreTypes.boolType,
2727 value,
2728 compiler.coreTypes.boolType,
2729 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK); 2662 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK);
2730 } 2663 }
2731 HInstruction result = new HBoolify(value, backend.boolType); 2664 HInstruction result = new HBoolify(value, backend.boolType);
2732 add(result); 2665 add(result);
2733 return result; 2666 return result;
2734 } 2667 }
2735 2668
2736 HInstruction attachPosition(HInstruction target, ast.Node node) { 2669 HInstruction attachPosition(HInstruction target, ast.Node node) {
2737 if (node != null) { 2670 if (node != null) {
2738 target.sourceInformation = sourceInformationBuilder.buildGeneric(node); 2671 target.sourceInformation = sourceInformationBuilder.buildGeneric(node);
(...skipping 30 matching lines...) Expand all
2769 // 2702 //
2770 void buildCondition() { 2703 void buildCondition() {
2771 visit(node.condition); 2704 visit(node.condition);
2772 pushInvokeStatic(node, helpers.assertTest, [pop()]); 2705 pushInvokeStatic(node, helpers.assertTest, [pop()]);
2773 } 2706 }
2774 void fail() { 2707 void fail() {
2775 visit(node.message); 2708 visit(node.message);
2776 pushInvokeStatic(node, helpers.assertThrow, [pop()]); 2709 pushInvokeStatic(node, helpers.assertThrow, [pop()]);
2777 pop(); 2710 pop();
2778 } 2711 }
2779 handleIf(node, 2712 handleIf(node, visitCondition: buildCondition, visitThen: fail);
2780 visitCondition: buildCondition,
2781 visitThen: fail);
2782 } 2713 }
2783 2714
2784 visitBlock(ast.Block node) { 2715 visitBlock(ast.Block node) {
2785 assert(!isAborted()); 2716 assert(!isAborted());
2786 if (!isReachable) return; // This can only happen when inlining. 2717 if (!isReachable) return; // This can only happen when inlining.
2787 for (Link<ast.Node> link = node.statements.nodes; 2718 for (Link<ast.Node> link = node.statements.nodes;
2788 !link.isEmpty; 2719 !link.isEmpty;
2789 link = link.tail) { 2720 link = link.tail) {
2790 visit(link.head); 2721 visit(link.head);
2791 if (!isReachable) { 2722 if (!isReachable) {
2792 // The block has been aborted by a return or a throw. 2723 // The block has been aborted by a return or a throw.
2793 if (!stack.isEmpty) { 2724 if (!stack.isEmpty) {
2794 reporter.internalError(node, 'Non-empty instruction stack.'); 2725 reporter.internalError(node, 'Non-empty instruction stack.');
2795 } 2726 }
2796 return; 2727 return;
2797 } 2728 }
2798 } 2729 }
2799 assert(!current.isClosed()); 2730 assert(!current.isClosed());
2800 if (!stack.isEmpty) { 2731 if (!stack.isEmpty) {
2801 reporter.internalError(node, 'Non-empty instruction stack.'); 2732 reporter.internalError(node, 'Non-empty instruction stack.');
2802 } 2733 }
2803 } 2734 }
2804 2735
2805 visitClassNode(ast.ClassNode node) { 2736 visitClassNode(ast.ClassNode node) {
2806 reporter.internalError(node, 2737 reporter.internalError(
2807 'SsaBuilder.visitClassNode should not be called.'); 2738 node, 'SsaBuilder.visitClassNode should not be called.');
2808 } 2739 }
2809 2740
2810 visitThrowExpression(ast.Expression expression) { 2741 visitThrowExpression(ast.Expression expression) {
2811 bool old = inExpressionOfThrow; 2742 bool old = inExpressionOfThrow;
2812 try { 2743 try {
2813 inExpressionOfThrow = true; 2744 inExpressionOfThrow = true;
2814 visit(expression); 2745 visit(expression);
2815 } finally { 2746 } finally {
2816 inExpressionOfThrow = old; 2747 inExpressionOfThrow = old;
2817 } 2748 }
(...skipping 16 matching lines...) Expand all
2834 /** 2765 /**
2835 * Creates a new loop-header block. The previous [current] block 2766 * Creates a new loop-header block. The previous [current] block
2836 * is closed with an [HGoto] and replaced by the newly created block. 2767 * is closed with an [HGoto] and replaced by the newly created block.
2837 * Also notifies the locals handler that we're entering a loop. 2768 * Also notifies the locals handler that we're entering a loop.
2838 */ 2769 */
2839 JumpHandler beginLoopHeader(ast.Node node) { 2770 JumpHandler beginLoopHeader(ast.Node node) {
2840 assert(!isAborted()); 2771 assert(!isAborted());
2841 HBasicBlock previousBlock = close(new HGoto()); 2772 HBasicBlock previousBlock = close(new HGoto());
2842 2773
2843 JumpHandler jumpHandler = createJumpHandler(node, isLoopJump: true); 2774 JumpHandler jumpHandler = createJumpHandler(node, isLoopJump: true);
2844 HBasicBlock loopEntry = graph.addNewLoopHeaderBlock( 2775 HBasicBlock loopEntry =
2845 jumpHandler.target, 2776 graph.addNewLoopHeaderBlock(jumpHandler.target, jumpHandler.labels());
2846 jumpHandler.labels());
2847 previousBlock.addSuccessor(loopEntry); 2777 previousBlock.addSuccessor(loopEntry);
2848 open(loopEntry); 2778 open(loopEntry);
2849 2779
2850 localsHandler.beginLoopHeader(loopEntry); 2780 localsHandler.beginLoopHeader(loopEntry);
2851 return jumpHandler; 2781 return jumpHandler;
2852 } 2782 }
2853 2783
2854 /** 2784 /**
2855 * Ends the loop: 2785 * Ends the loop:
2856 * - creates a new block and adds it as successor to the [branchExitBlock] and 2786 * - creates a new block and adds it as successor to the [branchExitBlock] and
2857 * any blocks that end in break. 2787 * any blocks that end in break.
2858 * - opens the new block (setting as [current]). 2788 * - opens the new block (setting as [current]).
2859 * - notifies the locals handler that we're exiting a loop. 2789 * - notifies the locals handler that we're exiting a loop.
2860 * [savedLocals] are the locals from the end of the loop condition. 2790 * [savedLocals] are the locals from the end of the loop condition.
2861 * [branchExitBlock] is the exit (branching) block of the condition. Generally 2791 * [branchExitBlock] is the exit (branching) block of the condition. Generally
2862 * this is not the top of the loop, since this would lead to critical edges. 2792 * this is not the top of the loop, since this would lead to critical edges.
2863 * It is null for degenerate do-while loops that have 2793 * It is null for degenerate do-while loops that have
2864 * no back edge because they abort (throw/return/break in the body and have 2794 * no back edge because they abort (throw/return/break in the body and have
2865 * no continues). 2795 * no continues).
2866 */ 2796 */
2867 void endLoop(HBasicBlock loopEntry, 2797 void endLoop(HBasicBlock loopEntry, HBasicBlock branchExitBlock,
2868 HBasicBlock branchExitBlock, 2798 JumpHandler jumpHandler, LocalsHandler savedLocals) {
2869 JumpHandler jumpHandler,
2870 LocalsHandler savedLocals) {
2871 HBasicBlock loopExitBlock = addNewBlock(); 2799 HBasicBlock loopExitBlock = addNewBlock();
2872 2800
2873 List<LocalsHandler> breakHandlers = <LocalsHandler>[]; 2801 List<LocalsHandler> breakHandlers = <LocalsHandler>[];
2874 // Collect data for the successors and the phis at each break. 2802 // Collect data for the successors and the phis at each break.
2875 jumpHandler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { 2803 jumpHandler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) {
2876 breakInstruction.block.addSuccessor(loopExitBlock); 2804 breakInstruction.block.addSuccessor(loopExitBlock);
2877 breakHandlers.add(locals); 2805 breakHandlers.add(locals);
2878 }); 2806 });
2879 2807
2880 // The exit block is a successor of the loop condition if it is reached. 2808 // The exit block is a successor of the loop condition if it is reached.
(...skipping 29 matching lines...) Expand all
2910 } 2838 }
2911 2839
2912 HSubExpressionBlockInformation wrapExpressionGraph(SubExpression expression) { 2840 HSubExpressionBlockInformation wrapExpressionGraph(SubExpression expression) {
2913 if (expression == null) return null; 2841 if (expression == null) return null;
2914 return new HSubExpressionBlockInformation(expression); 2842 return new HSubExpressionBlockInformation(expression);
2915 } 2843 }
2916 2844
2917 // For while loops, initializer and update are null. 2845 // For while loops, initializer and update are null.
2918 // The condition function must return a boolean result. 2846 // The condition function must return a boolean result.
2919 // None of the functions must leave anything on the stack. 2847 // None of the functions must leave anything on the stack.
2920 void handleLoop(ast.Node loop, 2848 void handleLoop(ast.Node loop, void initialize(), HInstruction condition(),
2921 void initialize(), 2849 void update(), void body()) {
2922 HInstruction condition(),
2923 void update(),
2924 void body()) {
2925 // Generate: 2850 // Generate:
2926 // <initializer> 2851 // <initializer>
2927 // loop-entry: 2852 // loop-entry:
2928 // if (!<condition>) goto loop-exit; 2853 // if (!<condition>) goto loop-exit;
2929 // <body> 2854 // <body>
2930 // <updates> 2855 // <updates>
2931 // goto loop-entry; 2856 // goto loop-entry;
2932 // loop-exit: 2857 // loop-exit:
2933 2858
2934 localsHandler.startLoop(loop); 2859 localsHandler.startLoop(loop);
2935 2860
2936 // The initializer. 2861 // The initializer.
2937 SubExpression initializerGraph = null; 2862 SubExpression initializerGraph = null;
2938 HBasicBlock startBlock; 2863 HBasicBlock startBlock;
2939 if (initialize != null) { 2864 if (initialize != null) {
2940 HBasicBlock initializerBlock = openNewBlock(); 2865 HBasicBlock initializerBlock = openNewBlock();
2941 startBlock = initializerBlock; 2866 startBlock = initializerBlock;
2942 initialize(); 2867 initialize();
2943 assert(!isAborted()); 2868 assert(!isAborted());
2944 initializerGraph = 2869 initializerGraph = new SubExpression(initializerBlock, current);
2945 new SubExpression(initializerBlock, current);
2946 } 2870 }
2947 2871
2948 loopNesting++; 2872 loopNesting++;
2949 JumpHandler jumpHandler = beginLoopHeader(loop); 2873 JumpHandler jumpHandler = beginLoopHeader(loop);
2950 HLoopInformation loopInfo = current.loopInformation; 2874 HLoopInformation loopInfo = current.loopInformation;
2951 HBasicBlock conditionBlock = current; 2875 HBasicBlock conditionBlock = current;
2952 if (startBlock == null) startBlock = conditionBlock; 2876 if (startBlock == null) startBlock = conditionBlock;
2953 2877
2954 HInstruction conditionInstruction = condition(); 2878 HInstruction conditionInstruction = condition();
2955 HBasicBlock conditionEndBlock = 2879 HBasicBlock conditionEndBlock =
(...skipping 22 matching lines...) Expand all
2978 2902
2979 bool loopIsDegenerate = !jumpHandler.hasAnyContinue() && bodyBlock == null; 2903 bool loopIsDegenerate = !jumpHandler.hasAnyContinue() && bodyBlock == null;
2980 if (!loopIsDegenerate) { 2904 if (!loopIsDegenerate) {
2981 // Update. 2905 // Update.
2982 // We create an update block, even when we are in a while loop. There the 2906 // We create an update block, even when we are in a while loop. There the
2983 // update block is the jump-target for continue statements. We could avoid 2907 // update block is the jump-target for continue statements. We could avoid
2984 // the creation if there is no continue, but for now we always create it. 2908 // the creation if there is no continue, but for now we always create it.
2985 HBasicBlock updateBlock = addNewBlock(); 2909 HBasicBlock updateBlock = addNewBlock();
2986 2910
2987 List<LocalsHandler> continueHandlers = <LocalsHandler>[]; 2911 List<LocalsHandler> continueHandlers = <LocalsHandler>[];
2988 jumpHandler.forEachContinue((HContinue instruction, 2912 jumpHandler
2989 LocalsHandler locals) { 2913 .forEachContinue((HContinue instruction, LocalsHandler locals) {
2990 instruction.block.addSuccessor(updateBlock); 2914 instruction.block.addSuccessor(updateBlock);
2991 continueHandlers.add(locals); 2915 continueHandlers.add(locals);
2992 }); 2916 });
2993 2917
2994
2995 if (bodyBlock != null) { 2918 if (bodyBlock != null) {
2996 continueHandlers.add(localsHandler); 2919 continueHandlers.add(localsHandler);
2997 bodyBlock.addSuccessor(updateBlock); 2920 bodyBlock.addSuccessor(updateBlock);
2998 } 2921 }
2999 2922
3000 open(updateBlock); 2923 open(updateBlock);
3001 localsHandler = 2924 localsHandler =
3002 continueHandlers[0].mergeMultiple(continueHandlers, updateBlock); 2925 continueHandlers[0].mergeMultiple(continueHandlers, updateBlock);
3003 2926
3004 List<LabelDefinition> labels = jumpHandler.labels(); 2927 List<LabelDefinition> labels = jumpHandler.labels();
3005 JumpTarget target = elements.getTargetDefinition(loop); 2928 JumpTarget target = elements.getTargetDefinition(loop);
3006 if (!labels.isEmpty) { 2929 if (!labels.isEmpty) {
3007 beginBodyBlock.setBlockFlow( 2930 beginBodyBlock.setBlockFlow(
3008 new HLabeledBlockInformation( 2931 new HLabeledBlockInformation(
3009 new HSubGraphBlockInformation(bodyGraph), 2932 new HSubGraphBlockInformation(bodyGraph), jumpHandler.labels(),
3010 jumpHandler.labels(),
3011 isContinue: true), 2933 isContinue: true),
3012 updateBlock); 2934 updateBlock);
3013 } else if (target != null && target.isContinueTarget) { 2935 } else if (target != null && target.isContinueTarget) {
3014 beginBodyBlock.setBlockFlow( 2936 beginBodyBlock.setBlockFlow(
3015 new HLabeledBlockInformation.implicit( 2937 new HLabeledBlockInformation.implicit(
3016 new HSubGraphBlockInformation(bodyGraph), 2938 new HSubGraphBlockInformation(bodyGraph), target,
3017 target,
3018 isContinue: true), 2939 isContinue: true),
3019 updateBlock); 2940 updateBlock);
3020 } 2941 }
3021 2942
3022 localsHandler.enterLoopUpdates(loop); 2943 localsHandler.enterLoopUpdates(loop);
3023 2944
3024 update(); 2945 update();
3025 2946
3026 HBasicBlock updateEndBlock = close(new HGoto()); 2947 HBasicBlock updateEndBlock = close(new HGoto());
3027 // The back-edge completing the cycle. 2948 // The back-edge completing the cycle.
3028 updateEndBlock.addSuccessor(conditionBlock); 2949 updateEndBlock.addSuccessor(conditionBlock);
3029 updateGraph = new SubExpression(updateBlock, updateEndBlock); 2950 updateGraph = new SubExpression(updateBlock, updateEndBlock);
3030 2951
3031 // Avoid a critical edge from the condition to the loop-exit body. 2952 // Avoid a critical edge from the condition to the loop-exit body.
3032 HBasicBlock conditionExitBlock = addNewBlock(); 2953 HBasicBlock conditionExitBlock = addNewBlock();
3033 open(conditionExitBlock); 2954 open(conditionExitBlock);
3034 close(new HGoto()); 2955 close(new HGoto());
3035 conditionEndBlock.addSuccessor(conditionExitBlock); 2956 conditionEndBlock.addSuccessor(conditionExitBlock);
3036 2957
3037 endLoop(conditionBlock, conditionExitBlock, jumpHandler, savedLocals); 2958 endLoop(conditionBlock, conditionExitBlock, jumpHandler, savedLocals);
3038 2959
3039 conditionBlock.postProcessLoopHeader(); 2960 conditionBlock.postProcessLoopHeader();
3040 HLoopBlockInformation info = 2961 HLoopBlockInformation info = new HLoopBlockInformation(
3041 new HLoopBlockInformation( 2962 _loopKind(loop),
3042 _loopKind(loop), 2963 wrapExpressionGraph(initializerGraph),
3043 wrapExpressionGraph(initializerGraph), 2964 wrapExpressionGraph(conditionExpression),
3044 wrapExpressionGraph(conditionExpression), 2965 wrapStatementGraph(bodyGraph),
3045 wrapStatementGraph(bodyGraph), 2966 wrapExpressionGraph(updateGraph),
3046 wrapExpressionGraph(updateGraph), 2967 conditionBlock.loopInformation.target,
3047 conditionBlock.loopInformation.target, 2968 conditionBlock.loopInformation.labels,
3048 conditionBlock.loopInformation.labels, 2969 sourceInformationBuilder.buildLoop(loop));
3049 sourceInformationBuilder.buildLoop(loop));
3050 2970
3051 startBlock.setBlockFlow(info, current); 2971 startBlock.setBlockFlow(info, current);
3052 loopInfo.loopBlockInformation = info; 2972 loopInfo.loopBlockInformation = info;
3053 } else { 2973 } else {
3054 // The body of the for/while loop always aborts, so there is no back edge. 2974 // The body of the for/while loop always aborts, so there is no back edge.
3055 // We turn the code into: 2975 // We turn the code into:
3056 // if (condition) { 2976 // if (condition) {
3057 // body; 2977 // body;
3058 // } else { 2978 // } else {
3059 // // We always create an empty else block to avoid critical edges. 2979 // // We always create an empty else block to avoid critical edges.
(...skipping 11 matching lines...) Expand all
3071 SubGraph elseGraph = new SubGraph(elseBlock, elseBlock); 2991 SubGraph elseGraph = new SubGraph(elseBlock, elseBlock);
3072 // Remove the loop information attached to the header. 2992 // Remove the loop information attached to the header.
3073 conditionBlock.loopInformation = null; 2993 conditionBlock.loopInformation = null;
3074 2994
3075 // Remove the [HLoopBranch] instruction and replace it with 2995 // Remove the [HLoopBranch] instruction and replace it with
3076 // [HIf]. 2996 // [HIf].
3077 HInstruction condition = conditionEndBlock.last.inputs[0]; 2997 HInstruction condition = conditionEndBlock.last.inputs[0];
3078 conditionEndBlock.addAtExit(new HIf(condition)); 2998 conditionEndBlock.addAtExit(new HIf(condition));
3079 conditionEndBlock.addSuccessor(elseBlock); 2999 conditionEndBlock.addSuccessor(elseBlock);
3080 conditionEndBlock.remove(conditionEndBlock.last); 3000 conditionEndBlock.remove(conditionEndBlock.last);
3081 HIfBlockInformation info = 3001 HIfBlockInformation info = new HIfBlockInformation(
3082 new HIfBlockInformation( 3002 wrapExpressionGraph(conditionExpression),
3083 wrapExpressionGraph(conditionExpression), 3003 wrapStatementGraph(bodyGraph),
3084 wrapStatementGraph(bodyGraph), 3004 wrapStatementGraph(elseGraph));
3085 wrapStatementGraph(elseGraph));
3086 3005
3087 conditionEndBlock.setBlockFlow(info, current); 3006 conditionEndBlock.setBlockFlow(info, current);
3088 HIf ifBlock = conditionEndBlock.last; 3007 HIf ifBlock = conditionEndBlock.last;
3089 ifBlock.blockInformation = conditionEndBlock.blockFlow; 3008 ifBlock.blockInformation = conditionEndBlock.blockFlow;
3090 3009
3091 // If the body has any break, attach a synthesized label to the 3010 // If the body has any break, attach a synthesized label to the
3092 // if block. 3011 // if block.
3093 if (jumpHandler.hasAnyBreak()) { 3012 if (jumpHandler.hasAnyBreak()) {
3094 JumpTarget target = elements.getTargetDefinition(loop); 3013 JumpTarget target = elements.getTargetDefinition(loop);
3095 LabelDefinition label = target.addLabel(null, 'loop'); 3014 LabelDefinition label = target.addLabel(null, 'loop');
3096 label.setBreakTarget(); 3015 label.setBreakTarget();
3097 SubGraph labelGraph = new SubGraph(conditionBlock, current); 3016 SubGraph labelGraph = new SubGraph(conditionBlock, current);
3098 HLabeledBlockInformation labelInfo = new HLabeledBlockInformation( 3017 HLabeledBlockInformation labelInfo = new HLabeledBlockInformation(
3099 new HSubGraphBlockInformation(labelGraph), 3018 new HSubGraphBlockInformation(labelGraph),
3100 <LabelDefinition>[label]); 3019 <LabelDefinition>[label]);
3101 3020
3102 conditionBlock.setBlockFlow(labelInfo, current); 3021 conditionBlock.setBlockFlow(labelInfo, current);
3103 3022
3104 jumpHandler.forEachBreak((HBreak breakInstruction, _) { 3023 jumpHandler.forEachBreak((HBreak breakInstruction, _) {
3105 HBasicBlock block = breakInstruction.block; 3024 HBasicBlock block = breakInstruction.block;
3106 block.addAtExit(new HBreak.toLabel(label)); 3025 block.addAtExit(new HBreak.toLabel(label));
3107 block.remove(breakInstruction); 3026 block.remove(breakInstruction);
3108 }); 3027 });
3109 } 3028 }
3110 } 3029 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
3144 } 3063 }
3145 handleLoop(node, buildInitializer, buildCondition, buildUpdate, buildBody); 3064 handleLoop(node, buildInitializer, buildCondition, buildUpdate, buildBody);
3146 } 3065 }
3147 3066
3148 visitWhile(ast.While node) { 3067 visitWhile(ast.While node) {
3149 assert(isReachable); 3068 assert(isReachable);
3150 HInstruction buildCondition() { 3069 HInstruction buildCondition() {
3151 visit(node.condition); 3070 visit(node.condition);
3152 return popBoolified(); 3071 return popBoolified();
3153 } 3072 }
3154 handleLoop(node, 3073 handleLoop(node, () {}, buildCondition, () {}, () {
3155 () {}, 3074 visit(node.body);
3156 buildCondition, 3075 });
3157 () {},
3158 () { visit(node.body); });
3159 } 3076 }
3160 3077
3161 visitDoWhile(ast.DoWhile node) { 3078 visitDoWhile(ast.DoWhile node) {
3162 assert(isReachable); 3079 assert(isReachable);
3163 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); 3080 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
3164 localsHandler.startLoop(node); 3081 localsHandler.startLoop(node);
3165 loopNesting++; 3082 loopNesting++;
3166 JumpHandler jumpHandler = beginLoopHeader(node); 3083 JumpHandler jumpHandler = beginLoopHeader(node);
3167 HLoopInformation loopInfo = current.loopInformation; 3084 HLoopInformation loopInfo = current.loopInformation;
3168 HBasicBlock loopEntryBlock = current; 3085 HBasicBlock loopEntryBlock = current;
(...skipping 23 matching lines...) Expand all
3192 isAbortingBody = true; 3109 isAbortingBody = true;
3193 bodyExitBlock = lastOpenedBlock; 3110 bodyExitBlock = lastOpenedBlock;
3194 } 3111 }
3195 3112
3196 SubExpression conditionExpression; 3113 SubExpression conditionExpression;
3197 bool loopIsDegenerate = isAbortingBody && !hasContinues; 3114 bool loopIsDegenerate = isAbortingBody && !hasContinues;
3198 if (!loopIsDegenerate) { 3115 if (!loopIsDegenerate) {
3199 HBasicBlock conditionBlock = addNewBlock(); 3116 HBasicBlock conditionBlock = addNewBlock();
3200 3117
3201 List<LocalsHandler> continueHandlers = <LocalsHandler>[]; 3118 List<LocalsHandler> continueHandlers = <LocalsHandler>[];
3202 jumpHandler.forEachContinue((HContinue instruction, 3119 jumpHandler
3203 LocalsHandler locals) { 3120 .forEachContinue((HContinue instruction, LocalsHandler locals) {
3204 instruction.block.addSuccessor(conditionBlock); 3121 instruction.block.addSuccessor(conditionBlock);
3205 continueHandlers.add(locals); 3122 continueHandlers.add(locals);
3206 }); 3123 });
3207 3124
3208 if (!isAbortingBody) { 3125 if (!isAbortingBody) {
3209 bodyExitBlock.addSuccessor(conditionBlock); 3126 bodyExitBlock.addSuccessor(conditionBlock);
3210 } 3127 }
3211 3128
3212 if (!continueHandlers.isEmpty) { 3129 if (!continueHandlers.isEmpty) {
3213 if (!isAbortingBody) continueHandlers.add(localsHandler); 3130 if (!isAbortingBody) continueHandlers.add(localsHandler);
3214 localsHandler = 3131 localsHandler =
3215 savedLocals.mergeMultiple(continueHandlers, conditionBlock); 3132 savedLocals.mergeMultiple(continueHandlers, conditionBlock);
3216 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); 3133 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock);
3217 List<LabelDefinition> labels = jumpHandler.labels(); 3134 List<LabelDefinition> labels = jumpHandler.labels();
3218 HSubGraphBlockInformation bodyInfo = 3135 HSubGraphBlockInformation bodyInfo =
3219 new HSubGraphBlockInformation(bodyGraph); 3136 new HSubGraphBlockInformation(bodyGraph);
3220 HLabeledBlockInformation info; 3137 HLabeledBlockInformation info;
3221 if (!labels.isEmpty) { 3138 if (!labels.isEmpty) {
3222 info = new HLabeledBlockInformation(bodyInfo, labels, 3139 info =
3223 isContinue: true); 3140 new HLabeledBlockInformation(bodyInfo, labels, isContinue: true);
3224 } else { 3141 } else {
3225 info = new HLabeledBlockInformation.implicit(bodyInfo, target, 3142 info = new HLabeledBlockInformation.implicit(bodyInfo, target,
3226 isContinue: true); 3143 isContinue: true);
3227 } 3144 }
3228 bodyEntryBlock.setBlockFlow(info, conditionBlock); 3145 bodyEntryBlock.setBlockFlow(info, conditionBlock);
3229 } 3146 }
3230 open(conditionBlock); 3147 open(conditionBlock);
3231 3148
3232 visit(node.condition); 3149 visit(node.condition);
3233 assert(!isAborted()); 3150 assert(!isAborted());
3234 HInstruction conditionInstruction = popBoolified(); 3151 HInstruction conditionInstruction = popBoolified();
3235 HBasicBlock conditionEndBlock = close( 3152 HBasicBlock conditionEndBlock = close(
3236 new HLoopBranch(conditionInstruction, HLoopBranch.DO_WHILE_LOOP)); 3153 new HLoopBranch(conditionInstruction, HLoopBranch.DO_WHILE_LOOP));
(...skipping 10 matching lines...) Expand all
3247 // Avoid a critical edge from the condition to the loop-exit body. 3164 // Avoid a critical edge from the condition to the loop-exit body.
3248 HBasicBlock conditionExitBlock = addNewBlock(); 3165 HBasicBlock conditionExitBlock = addNewBlock();
3249 open(conditionExitBlock); 3166 open(conditionExitBlock);
3250 close(new HGoto()); 3167 close(new HGoto());
3251 conditionEndBlock.addSuccessor(conditionExitBlock); 3168 conditionEndBlock.addSuccessor(conditionExitBlock);
3252 3169
3253 endLoop(loopEntryBlock, conditionExitBlock, jumpHandler, localsHandler); 3170 endLoop(loopEntryBlock, conditionExitBlock, jumpHandler, localsHandler);
3254 3171
3255 loopEntryBlock.postProcessLoopHeader(); 3172 loopEntryBlock.postProcessLoopHeader();
3256 SubGraph bodyGraph = new SubGraph(loopEntryBlock, bodyExitBlock); 3173 SubGraph bodyGraph = new SubGraph(loopEntryBlock, bodyExitBlock);
3257 HLoopBlockInformation loopBlockInfo = 3174 HLoopBlockInformation loopBlockInfo = new HLoopBlockInformation(
3258 new HLoopBlockInformation( 3175 HLoopBlockInformation.DO_WHILE_LOOP,
3259 HLoopBlockInformation.DO_WHILE_LOOP, 3176 null,
3260 null, 3177 wrapExpressionGraph(conditionExpression),
3261 wrapExpressionGraph(conditionExpression), 3178 wrapStatementGraph(bodyGraph),
3262 wrapStatementGraph(bodyGraph), 3179 null,
3263 null, 3180 loopEntryBlock.loopInformation.target,
3264 loopEntryBlock.loopInformation.target, 3181 loopEntryBlock.loopInformation.labels,
3265 loopEntryBlock.loopInformation.labels, 3182 sourceInformationBuilder.buildLoop(node));
3266 sourceInformationBuilder.buildLoop(node));
3267 loopEntryBlock.setBlockFlow(loopBlockInfo, current); 3183 loopEntryBlock.setBlockFlow(loopBlockInfo, current);
3268 loopInfo.loopBlockInformation = loopBlockInfo; 3184 loopInfo.loopBlockInformation = loopBlockInfo;
3269 } else { 3185 } else {
3270 // Since the loop has no back edge, we remove the loop information on the 3186 // Since the loop has no back edge, we remove the loop information on the
3271 // header. 3187 // header.
3272 loopEntryBlock.loopInformation = null; 3188 loopEntryBlock.loopInformation = null;
3273 3189
3274 if (jumpHandler.hasAnyBreak()) { 3190 if (jumpHandler.hasAnyBreak()) {
3275 // Null branchBlock because the body of the do-while loop always aborts, 3191 // Null branchBlock because the body of the do-while loop always aborts,
3276 // so we never get to the condition. 3192 // so we never get to the condition.
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
3313 closureClassElement.closureFields.forEach((ClosureFieldElement field) { 3229 closureClassElement.closureFields.forEach((ClosureFieldElement field) {
3314 Local capturedLocal = 3230 Local capturedLocal =
3315 nestedClosureData.getLocalVariableForClosureField(field); 3231 nestedClosureData.getLocalVariableForClosureField(field);
3316 assert(capturedLocal != null); 3232 assert(capturedLocal != null);
3317 capturedVariables.add(localsHandler.readLocal(capturedLocal)); 3233 capturedVariables.add(localsHandler.readLocal(capturedLocal));
3318 }); 3234 });
3319 3235
3320 TypeMask type = 3236 TypeMask type =
3321 new TypeMask.nonNullExact(closureClassElement, compiler.world); 3237 new TypeMask.nonNullExact(closureClassElement, compiler.world);
3322 push(new HForeignNew(closureClassElement, type, capturedVariables) 3238 push(new HForeignNew(closureClassElement, type, capturedVariables)
3323 ..sourceInformation = sourceInformationBuilder.buildCreate(node)); 3239 ..sourceInformation = sourceInformationBuilder.buildCreate(node));
3324 3240
3325 Element methodElement = nestedClosureData.closureElement; 3241 Element methodElement = nestedClosureData.closureElement;
3326 registry?.registerInstantiatedClosure(methodElement); 3242 registry?.registerInstantiatedClosure(methodElement);
3327 } 3243 }
3328 3244
3329 visitFunctionDeclaration(ast.FunctionDeclaration node) { 3245 visitFunctionDeclaration(ast.FunctionDeclaration node) {
3330 assert(isReachable); 3246 assert(isReachable);
3331 visit(node.function); 3247 visit(node.function);
3332 LocalFunctionElement localFunction = 3248 LocalFunctionElement localFunction =
3333 elements.getFunctionDefinition(node.function); 3249 elements.getFunctionDefinition(node.function);
3334 localsHandler.updateLocal(localFunction, pop()); 3250 localsHandler.updateLocal(localFunction, pop());
3335 } 3251 }
3336 3252
3337 @override 3253 @override
3338 void visitThisGet(ast.Identifier node, [_]) { 3254 void visitThisGet(ast.Identifier node, [_]) {
3339 stack.add(localsHandler.readThis()); 3255 stack.add(localsHandler.readThis());
3340 } 3256 }
3341 3257
3342 visitIdentifier(ast.Identifier node) { 3258 visitIdentifier(ast.Identifier node) {
3343 if (node.isThis()) { 3259 if (node.isThis()) {
3344 visitThisGet(node); 3260 visitThisGet(node);
3345 } else { 3261 } else {
3346 reporter.internalError(node, 3262 reporter.internalError(
3347 "SsaFromAstMixin.visitIdentifier on non-this."); 3263 node, "SsaFromAstMixin.visitIdentifier on non-this.");
3348 } 3264 }
3349 } 3265 }
3350 3266
3351 visitIf(ast.If node) { 3267 visitIf(ast.If node) {
3352 assert(isReachable); 3268 assert(isReachable);
3353 handleIf( 3269 handleIf(node,
3354 node,
3355 visitCondition: () => visit(node.condition), 3270 visitCondition: () => visit(node.condition),
3356 visitThen: () => visit(node.thenPart), 3271 visitThen: () => visit(node.thenPart),
3357 visitElse: node.elsePart != null ? () => visit(node.elsePart) : null, 3272 visitElse: node.elsePart != null ? () => visit(node.elsePart) : null,
3358 sourceInformation: sourceInformationBuilder.buildIf(node)); 3273 sourceInformation: sourceInformationBuilder.buildIf(node));
3359 } 3274 }
3360 3275
3361 void handleIf(ast.Node diagnosticNode, 3276 void handleIf(ast.Node diagnosticNode,
3362 {void visitCondition(), 3277 {void visitCondition(),
3363 void visitThen(), 3278 void visitThen(),
3364 void visitElse(), 3279 void visitElse(),
3365 SourceInformation sourceInformation}) { 3280 SourceInformation sourceInformation}) {
3366 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, diagnosticNode); 3281 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, diagnosticNode);
3367 branchBuilder.handleIf( 3282 branchBuilder.handleIf(visitCondition, visitThen, visitElse,
3368 visitCondition, visitThen, visitElse,
3369 sourceInformation: sourceInformation); 3283 sourceInformation: sourceInformation);
3370 } 3284 }
3371 3285
3372 @override 3286 @override
3373 void visitIfNull(ast.Send node, ast.Node left, ast.Node right, _) { 3287 void visitIfNull(ast.Send node, ast.Node left, ast.Node right, _) {
3374 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 3288 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node);
3375 brancher.handleIfNull(() => visit(left), () => visit(right)); 3289 brancher.handleIfNull(() => visit(left), () => visit(right));
3376 } 3290 }
3377 3291
3378 @override 3292 @override
3379 void visitLogicalAnd(ast.Send node, ast.Node left, ast.Node right, _) { 3293 void visitLogicalAnd(ast.Send node, ast.Node left, ast.Node right, _) {
3380 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, node); 3294 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, node);
3381 branchBuilder.handleLogicalAndOrWithLeftNode( 3295 branchBuilder.handleLogicalAndOrWithLeftNode(left, () {
3382 left, 3296 visit(right);
3383 () { visit(right); }, 3297 }, isAnd: true);
3384 isAnd: true);
3385 } 3298 }
3386 3299
3387 @override 3300 @override
3388 void visitLogicalOr(ast.Send node, ast.Node left, ast.Node right, _) { 3301 void visitLogicalOr(ast.Send node, ast.Node left, ast.Node right, _) {
3389 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, node); 3302 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, node);
3390 branchBuilder.handleLogicalAndOrWithLeftNode( 3303 branchBuilder.handleLogicalAndOrWithLeftNode(left, () {
3391 left, 3304 visit(right);
3392 () { visit(right); }, 3305 }, isAnd: false);
3393 isAnd: false);
3394 } 3306 }
3395 3307
3396 @override 3308 @override
3397 void visitNot(ast.Send node, ast.Node expression, _) { 3309 void visitNot(ast.Send node, ast.Node expression, _) {
3398 assert(node.argumentsNode is ast.Prefix); 3310 assert(node.argumentsNode is ast.Prefix);
3399 visit(expression); 3311 visit(expression);
3400 SourceInformation sourceInformation = 3312 SourceInformation sourceInformation =
3401 sourceInformationBuilder.buildGeneric(node); 3313 sourceInformationBuilder.buildGeneric(node);
3402 push(new HNot(popBoolified(), backend.boolType) 3314 push(new HNot(popBoolified(), backend.boolType)
3403 ..sourceInformation = sourceInformation); 3315 ..sourceInformation = sourceInformation);
3404 } 3316 }
3405 3317
3406 @override 3318 @override
3407 void visitUnary(ast.Send node, 3319 void visitUnary(
3408 UnaryOperator operator, 3320 ast.Send node, UnaryOperator operator, ast.Node expression, _) {
3409 ast.Node expression,_) {
3410 assert(node.argumentsNode is ast.Prefix); 3321 assert(node.argumentsNode is ast.Prefix);
3411 HInstruction operand = visitAndPop(expression); 3322 HInstruction operand = visitAndPop(expression);
3412 3323
3413 // See if we can constant-fold right away. This avoids rewrites later on. 3324 // See if we can constant-fold right away. This avoids rewrites later on.
3414 if (operand is HConstant) { 3325 if (operand is HConstant) {
3415 UnaryOperation operation = constantSystem.lookupUnary(operator); 3326 UnaryOperation operation = constantSystem.lookupUnary(operator);
3416 HConstant constant = operand; 3327 HConstant constant = operand;
3417 ConstantValue folded = operation.fold(constant.constant); 3328 ConstantValue folded = operation.fold(constant.constant);
3418 if (folded != null) { 3329 if (folded != null) {
3419 stack.add(graph.addConstant(folded, compiler)); 3330 stack.add(graph.addConstant(folded, compiler));
3420 return; 3331 return;
3421 } 3332 }
3422 } 3333 }
3423 3334
3424 pushInvokeDynamic( 3335 pushInvokeDynamic(
3425 node, 3336 node, elements.getSelector(node), elements.getTypeMask(node), [operand],
3426 elements.getSelector(node),
3427 elements.getTypeMask(node),
3428 [operand],
3429 sourceInformation: sourceInformationBuilder.buildGeneric(node)); 3337 sourceInformation: sourceInformationBuilder.buildGeneric(node));
3430 } 3338 }
3431 3339
3432 @override 3340 @override
3433 void visitBinary(ast.Send node, 3341 void visitBinary(ast.Send node, ast.Node left, BinaryOperator operator,
3434 ast.Node left, 3342 ast.Node right, _) {
3435 BinaryOperator operator,
3436 ast.Node right, _) {
3437 handleBinary(node, left, right); 3343 handleBinary(node, left, right);
3438 } 3344 }
3439 3345
3440 @override 3346 @override
3441 void visitIndex(ast.Send node, ast.Node receiver, ast.Node index, _) { 3347 void visitIndex(ast.Send node, ast.Node receiver, ast.Node index, _) {
3442 generateDynamicSend(node); 3348 generateDynamicSend(node);
3443 } 3349 }
3444 3350
3445 @override 3351 @override
3446 void visitEquals(ast.Send node, ast.Node left, ast.Node right, _) { 3352 void visitEquals(ast.Send node, ast.Node left, ast.Node right, _) {
3447 handleBinary(node, left, right); 3353 handleBinary(node, left, right);
3448 } 3354 }
3449 3355
3450 @override 3356 @override
3451 void visitNotEquals(ast.Send node, ast.Node left, ast.Node right, _) { 3357 void visitNotEquals(ast.Send node, ast.Node left, ast.Node right, _) {
3452 handleBinary(node, left, right); 3358 handleBinary(node, left, right);
3453 pushWithPosition(new HNot(popBoolified(), backend.boolType), node.selector); 3359 pushWithPosition(new HNot(popBoolified(), backend.boolType), node.selector);
3454 } 3360 }
3455 3361
3456 void handleBinary(ast.Send node, ast.Node left, ast.Node right) { 3362 void handleBinary(ast.Send node, ast.Node left, ast.Node right) {
3457 visitBinarySend( 3363 visitBinarySend(visitAndPop(left), visitAndPop(right),
3458 visitAndPop(left), 3364 elements.getSelector(node), elements.getTypeMask(node), node,
3459 visitAndPop(right),
3460 elements.getSelector(node),
3461 elements.getTypeMask(node),
3462 node,
3463 sourceInformation: 3365 sourceInformation:
3464 sourceInformationBuilder.buildGeneric(node.selector)); 3366 sourceInformationBuilder.buildGeneric(node.selector));
3465 } 3367 }
3466 3368
3467 /// TODO(johnniwinther): Merge [visitBinarySend] with [handleBinary] and 3369 /// TODO(johnniwinther): Merge [visitBinarySend] with [handleBinary] and
3468 /// remove use of [location] for source information. 3370 /// remove use of [location] for source information.
3469 void visitBinarySend(HInstruction left, 3371 void visitBinarySend(HInstruction left, HInstruction right, Selector selector,
3470 HInstruction right, 3372 TypeMask mask, ast.Send send,
3471 Selector selector, 3373 {SourceInformation sourceInformation}) {
3472 TypeMask mask,
3473 ast.Send send,
3474 {SourceInformation sourceInformation}) {
3475 pushInvokeDynamic(send, selector, mask, [left, right], 3374 pushInvokeDynamic(send, selector, mask, [left, right],
3476 sourceInformation: sourceInformation); 3375 sourceInformation: sourceInformation);
3477 } 3376 }
3478 3377
3479 HInstruction generateInstanceSendReceiver(ast.Send send) { 3378 HInstruction generateInstanceSendReceiver(ast.Send send) {
3480 assert(Elements.isInstanceSend(send, elements)); 3379 assert(Elements.isInstanceSend(send, elements));
3481 if (send.receiver == null) { 3380 if (send.receiver == null) {
3482 return localsHandler.readThis(); 3381 return localsHandler.readThis();
3483 } 3382 }
3484 visit(send.receiver); 3383 visit(send.receiver);
3485 return pop(); 3384 return pop();
3486 } 3385 }
3487 3386
3488 String noSuchMethodTargetSymbolString(Element error, [String prefix]) { 3387 String noSuchMethodTargetSymbolString(Element error, [String prefix]) {
3489 String result = error.name; 3388 String result = error.name;
3490 if (prefix == "set") return "$result="; 3389 if (prefix == "set") return "$result=";
3491 return result; 3390 return result;
3492 } 3391 }
3493 3392
3494 /** 3393 /**
3495 * Returns a set of interceptor classes that contain the given 3394 * Returns a set of interceptor classes that contain the given
3496 * [selector]. 3395 * [selector].
3497 */ 3396 */
3498 void generateInstanceGetterWithCompiledReceiver( 3397 void generateInstanceGetterWithCompiledReceiver(
3499 ast.Send send, 3398 ast.Send send, Selector selector, TypeMask mask, HInstruction receiver) {
3500 Selector selector,
3501 TypeMask mask,
3502 HInstruction receiver) {
3503 assert(Elements.isInstanceSend(send, elements)); 3399 assert(Elements.isInstanceSend(send, elements));
3504 assert(selector.isGetter); 3400 assert(selector.isGetter);
3505 pushInvokeDynamic(send, selector, mask, [receiver], 3401 pushInvokeDynamic(send, selector, mask, [receiver],
3506 sourceInformation: sourceInformationBuilder.buildGet(send)); 3402 sourceInformation: sourceInformationBuilder.buildGet(send));
3507 } 3403 }
3508 3404
3509 /// Inserts a call to checkDeferredIsLoaded for [prefixElement]. 3405 /// Inserts a call to checkDeferredIsLoaded for [prefixElement].
3510 /// If [prefixElement] is [null] ndo nothing. 3406 /// If [prefixElement] is [null] ndo nothing.
3511 void generateIsDeferredLoadedCheckIfNeeded(PrefixElement prefixElement, 3407 void generateIsDeferredLoadedCheckIfNeeded(
3512 ast.Node location) { 3408 PrefixElement prefixElement, ast.Node location) {
3513 if (prefixElement == null) return; 3409 if (prefixElement == null) return;
3514 String loadId = 3410 String loadId =
3515 compiler.deferredLoadTask.getImportDeferName(location, prefixElement); 3411 compiler.deferredLoadTask.getImportDeferName(location, prefixElement);
3516 HInstruction loadIdConstant = addConstantString(loadId); 3412 HInstruction loadIdConstant = addConstantString(loadId);
3517 String uri = prefixElement.deferredImport.uri.toString(); 3413 String uri = prefixElement.deferredImport.uri.toString();
3518 HInstruction uriConstant = addConstantString(uri); 3414 HInstruction uriConstant = addConstantString(uri);
3519 Element helper = helpers.checkDeferredIsLoaded; 3415 Element helper = helpers.checkDeferredIsLoaded;
3520 pushInvokeStatic(location, helper, [loadIdConstant, uriConstant]); 3416 pushInvokeStatic(location, helper, [loadIdConstant, uriConstant]);
3521 pop(); 3417 pop();
3522 } 3418 }
3523 3419
3524 /// Inserts a call to checkDeferredIsLoaded if the send has a prefix that 3420 /// Inserts a call to checkDeferredIsLoaded if the send has a prefix that
3525 /// resolves to a deferred library. 3421 /// resolves to a deferred library.
3526 void generateIsDeferredLoadedCheckOfSend(ast.Send node) { 3422 void generateIsDeferredLoadedCheckOfSend(ast.Send node) {
3527 generateIsDeferredLoadedCheckIfNeeded( 3423 generateIsDeferredLoadedCheckIfNeeded(
3528 compiler.deferredLoadTask.deferredPrefixElement(node, elements), 3424 compiler.deferredLoadTask.deferredPrefixElement(node, elements), node);
3529 node);
3530 } 3425 }
3531 3426
3532 void handleInvalidStaticGet(ast.Send node, Element element) { 3427 void handleInvalidStaticGet(ast.Send node, Element element) {
3533 SourceInformation sourceInformation = 3428 SourceInformation sourceInformation =
3534 sourceInformationBuilder.buildGet(node); 3429 sourceInformationBuilder.buildGet(node);
3535 generateThrowNoSuchMethod( 3430 generateThrowNoSuchMethod(
3536 node, 3431 node, noSuchMethodTargetSymbolString(element, 'get'),
3537 noSuchMethodTargetSymbolString(element, 'get'),
3538 argumentNodes: const Link<ast.Node>(), 3432 argumentNodes: const Link<ast.Node>(),
3539 sourceInformation: sourceInformation); 3433 sourceInformation: sourceInformation);
3540 } 3434 }
3541 3435
3542 /// Generate read access of an unresolved static or top level entity. 3436 /// Generate read access of an unresolved static or top level entity.
3543 void generateStaticUnresolvedGet(ast.Send node, Element element) { 3437 void generateStaticUnresolvedGet(ast.Send node, Element element) {
3544 if (element is ErroneousElement) { 3438 if (element is ErroneousElement) {
3545 SourceInformation sourceInformation = 3439 SourceInformation sourceInformation =
3546 sourceInformationBuilder.buildGet(node); 3440 sourceInformationBuilder.buildGet(node);
3547 // An erroneous element indicates an unresolved static getter. 3441 // An erroneous element indicates an unresolved static getter.
3548 handleInvalidStaticGet(node, element); 3442 handleInvalidStaticGet(node, element);
3549 } else { 3443 } else {
3550 // This happens when [element] has parse errors. 3444 // This happens when [element] has parse errors.
3551 assert(invariant(node, element == null || element.isMalformed)); 3445 assert(invariant(node, element == null || element.isMalformed));
3552 // TODO(ahe): Do something like the above, that is, emit a runtime 3446 // TODO(ahe): Do something like the above, that is, emit a runtime
3553 // error. 3447 // error.
3554 stack.add(graph.addConstantNull(compiler)); 3448 stack.add(graph.addConstantNull(compiler));
3555 } 3449 }
3556 } 3450 }
3557 3451
3558 /// Read a static or top level [field] of constant value. 3452 /// Read a static or top level [field] of constant value.
3559 void generateStaticConstGet( 3453 void generateStaticConstGet(ast.Send node, FieldElement field,
3560 ast.Send node, 3454 ConstantExpression constant, SourceInformation sourceInformation) {
3561 FieldElement field,
3562 ConstantExpression constant,
3563 SourceInformation sourceInformation) {
3564 ConstantValue value = backend.constants.getConstantValue(constant); 3455 ConstantValue value = backend.constants.getConstantValue(constant);
3565 HConstant instruction; 3456 HConstant instruction;
3566 // Constants that are referred via a deferred prefix should be referred 3457 // Constants that are referred via a deferred prefix should be referred
3567 // by reference. 3458 // by reference.
3568 PrefixElement prefix = compiler.deferredLoadTask 3459 PrefixElement prefix =
3569 .deferredPrefixElement(node, elements); 3460 compiler.deferredLoadTask.deferredPrefixElement(node, elements);
3570 if (prefix != null) { 3461 if (prefix != null) {
3571 instruction = 3462 instruction =
3572 graph.addDeferredConstant(value, prefix, sourceInformation, compiler); 3463 graph.addDeferredConstant(value, prefix, sourceInformation, compiler);
3573 } else { 3464 } else {
3574 instruction = graph.addConstant( 3465 instruction = graph.addConstant(value, compiler,
3575 value, compiler, sourceInformation: sourceInformation); 3466 sourceInformation: sourceInformation);
3576 } 3467 }
3577 stack.add(instruction); 3468 stack.add(instruction);
3578 // The inferrer may have found a better type than the constant 3469 // The inferrer may have found a better type than the constant
3579 // handler in the case of lists, because the constant handler 3470 // handler in the case of lists, because the constant handler
3580 // does not look at elements in the list. 3471 // does not look at elements in the list.
3581 TypeMask type = 3472 TypeMask type = TypeMaskFactory.inferredTypeForElement(field, compiler);
3582 TypeMaskFactory.inferredTypeForElement(field, compiler); 3473 if (!type.containsAll(compiler.world) && !instruction.isConstantNull()) {
3583 if (!type.containsAll(compiler.world) &&
3584 !instruction.isConstantNull()) {
3585 // TODO(13429): The inferrer should know that an element 3474 // TODO(13429): The inferrer should know that an element
3586 // cannot be null. 3475 // cannot be null.
3587 instruction.instructionType = type.nonNullable(); 3476 instruction.instructionType = type.nonNullable();
3588 } 3477 }
3589 } 3478 }
3590 3479
3591 @override 3480 @override
3592 void previsitDeferredAccess(ast.Send node, PrefixElement prefix, _) { 3481 void previsitDeferredAccess(ast.Send node, PrefixElement prefix, _) {
3593 generateIsDeferredLoadedCheckIfNeeded(prefix, node); 3482 generateIsDeferredLoadedCheckIfNeeded(prefix, node);
3594 } 3483 }
3595 3484
3596 /// Read a static or top level [field]. 3485 /// Read a static or top level [field].
3597 void generateStaticFieldGet(ast.Send node, FieldElement field) { 3486 void generateStaticFieldGet(ast.Send node, FieldElement field) {
3598 ConstantExpression constant = 3487 ConstantExpression constant =
3599 backend.constants.getConstantForVariable(field); 3488 backend.constants.getConstantForVariable(field);
3600 SourceInformation sourceInformation = 3489 SourceInformation sourceInformation =
3601 sourceInformationBuilder.buildGet(node); 3490 sourceInformationBuilder.buildGet(node);
3602 if (constant != null) { 3491 if (constant != null) {
3603 if (!field.isAssignable) { 3492 if (!field.isAssignable) {
3604 // A static final or const. Get its constant value and inline it if 3493 // A static final or const. Get its constant value and inline it if
3605 // the value can be compiled eagerly. 3494 // the value can be compiled eagerly.
3606 generateStaticConstGet(node, field, constant, sourceInformation); 3495 generateStaticConstGet(node, field, constant, sourceInformation);
3607 } else { 3496 } else {
3608 // TODO(5346): Try to avoid the need for calling [declaration] before 3497 // TODO(5346): Try to avoid the need for calling [declaration] before
3609 // creating an [HStatic]. 3498 // creating an [HStatic].
3610 HInstruction instruction = new HStatic( 3499 HInstruction instruction = new HStatic(field.declaration,
3611 field.declaration,
3612 TypeMaskFactory.inferredTypeForElement(field, compiler)) 3500 TypeMaskFactory.inferredTypeForElement(field, compiler))
3613 ..sourceInformation = sourceInformation; 3501 ..sourceInformation = sourceInformation;
3614 push(instruction); 3502 push(instruction);
3615 } 3503 }
3616 } else { 3504 } else {
3617 HInstruction instruction = new HLazyStatic( 3505 HInstruction instruction = new HLazyStatic(
3618 field, 3506 field, TypeMaskFactory.inferredTypeForElement(field, compiler))
3619 TypeMaskFactory.inferredTypeForElement(field, compiler)) 3507 ..sourceInformation = sourceInformation;
3620 ..sourceInformation = sourceInformation;
3621 push(instruction); 3508 push(instruction);
3622 } 3509 }
3623 } 3510 }
3624 3511
3625 /// Generate a getter invocation of the static or top level [getter]. 3512 /// Generate a getter invocation of the static or top level [getter].
3626 void generateStaticGetterGet(ast.Send node, MethodElement getter) { 3513 void generateStaticGetterGet(ast.Send node, MethodElement getter) {
3627 SourceInformation sourceInformation = 3514 SourceInformation sourceInformation =
3628 sourceInformationBuilder.buildGet(node); 3515 sourceInformationBuilder.buildGet(node);
3629 if (getter.isDeferredLoaderGetter) { 3516 if (getter.isDeferredLoaderGetter) {
3630 generateDeferredLoaderGet(node, getter, sourceInformation); 3517 generateDeferredLoaderGet(node, getter, sourceInformation);
3631 } else { 3518 } else {
3632 pushInvokeStatic(node, getter, <HInstruction>[], 3519 pushInvokeStatic(node, getter, <HInstruction>[],
3633 sourceInformation: sourceInformation); 3520 sourceInformation: sourceInformation);
3634 } 3521 }
3635 } 3522 }
3636 3523
3637 /// Generate a dynamic getter invocation. 3524 /// Generate a dynamic getter invocation.
3638 void generateDynamicGet(ast.Send node) { 3525 void generateDynamicGet(ast.Send node) {
3639 HInstruction receiver = generateInstanceSendReceiver(node); 3526 HInstruction receiver = generateInstanceSendReceiver(node);
3640 generateInstanceGetterWithCompiledReceiver( 3527 generateInstanceGetterWithCompiledReceiver(
3641 node, elements.getSelector(node), elements.getTypeMask(node), receiver); 3528 node, elements.getSelector(node), elements.getTypeMask(node), receiver);
3642 } 3529 }
3643 3530
3644 /// Generate a closurization of the static or top level [function]. 3531 /// Generate a closurization of the static or top level [function].
3645 void generateStaticFunctionGet(ast.Send node, MethodElement function) { 3532 void generateStaticFunctionGet(ast.Send node, MethodElement function) {
3646 // TODO(5346): Try to avoid the need for calling [declaration] before 3533 // TODO(5346): Try to avoid the need for calling [declaration] before
3647 // creating an [HStatic]. 3534 // creating an [HStatic].
3648 SourceInformation sourceInformation = 3535 SourceInformation sourceInformation =
3649 sourceInformationBuilder.buildGet(node); 3536 sourceInformationBuilder.buildGet(node);
3650 push(new HStatic(function.declaration, backend.nonNullType) 3537 push(new HStatic(function.declaration, backend.nonNullType)
3651 ..sourceInformation = sourceInformation); 3538 ..sourceInformation = sourceInformation);
3652 } 3539 }
3653 3540
3654 /// Read a local variable, function or parameter. 3541 /// Read a local variable, function or parameter.
3655 void buildLocalGet(LocalElement local, SourceInformation sourceInformation) { 3542 void buildLocalGet(LocalElement local, SourceInformation sourceInformation) {
3656 stack.add(localsHandler.readLocal( 3543 stack.add(
3657 local, sourceInformation: sourceInformation)); 3544 localsHandler.readLocal(local, sourceInformation: sourceInformation));
3658 } 3545 }
3659 3546
3660 void handleLocalGet(ast.Send node, LocalElement local) { 3547 void handleLocalGet(ast.Send node, LocalElement local) {
3661 buildLocalGet(local, sourceInformationBuilder.buildGet(node)); 3548 buildLocalGet(local, sourceInformationBuilder.buildGet(node));
3662 } 3549 }
3663 3550
3664 @override 3551 @override
3665 void visitDynamicPropertyGet( 3552 void visitDynamicPropertyGet(ast.Send node, ast.Node receiver, Name name, _) {
3666 ast.Send node,
3667 ast.Node receiver,
3668 Name name,
3669 _) {
3670 generateDynamicGet(node); 3553 generateDynamicGet(node);
3671 } 3554 }
3672 3555
3673 @override 3556 @override
3674 void visitIfNotNullDynamicPropertyGet( 3557 void visitIfNotNullDynamicPropertyGet(
3675 ast.Send node, 3558 ast.Send node, ast.Node receiver, Name name, _) {
3676 ast.Node receiver,
3677 Name name,
3678 _) {
3679 // exp?.x compiled as: 3559 // exp?.x compiled as:
3680 // t1 = exp; 3560 // t1 = exp;
3681 // result = t1 == null ? t1 : t1.x; 3561 // result = t1 == null ? t1 : t1.x;
3682 // This is equivalent to t1 == null ? null : t1.x, but in the current form 3562 // This is equivalent to t1 == null ? null : t1.x, but in the current form
3683 // we will be able to later compress it as: 3563 // we will be able to later compress it as:
3684 // t1 || t1.x 3564 // t1 || t1.x
3685 HInstruction expression; 3565 HInstruction expression;
3686 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 3566 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node);
3687 brancher.handleConditional( 3567 brancher.handleConditional(
3688 () { 3568 () {
3689 expression = visitAndPop(receiver); 3569 expression = visitAndPop(receiver);
3690 pushCheckNull(expression); 3570 pushCheckNull(expression);
3691 }, 3571 },
3692 () => stack.add(expression), 3572 () => stack.add(expression),
3693 () { 3573 () {
3694 generateInstanceGetterWithCompiledReceiver( 3574 generateInstanceGetterWithCompiledReceiver(
3695 node, 3575 node,
3696 elements.getSelector(node), 3576 elements.getSelector(node),
3697 elements.getTypeMask(node), 3577 elements.getTypeMask(node),
3698 expression); 3578 expression);
3699 }); 3579 });
3700 } 3580 }
3701 3581
3702 /// Pushes a boolean checking [expression] against null. 3582 /// Pushes a boolean checking [expression] against null.
3703 pushCheckNull(HInstruction expression) { 3583 pushCheckNull(HInstruction expression) {
3704 push(new HIdentity(expression, graph.addConstantNull(compiler), 3584 push(new HIdentity(
3705 null, backend.boolType)); 3585 expression, graph.addConstantNull(compiler), null, backend.boolType));
3706 } 3586 }
3707 3587
3708 @override 3588 @override
3709 void visitLocalVariableGet(ast.Send node, LocalVariableElement variable, _) { 3589 void visitLocalVariableGet(ast.Send node, LocalVariableElement variable, _) {
3710 handleLocalGet(node, variable); 3590 handleLocalGet(node, variable);
3711 } 3591 }
3712 3592
3713 @override 3593 @override
3714 void visitParameterGet(ast.Send node, ParameterElement parameter, _) { 3594 void visitParameterGet(ast.Send node, ParameterElement parameter, _) {
3715 handleLocalGet(node, parameter); 3595 handleLocalGet(node, parameter);
3716 } 3596 }
3717 3597
3718 @override 3598 @override
3719 void visitLocalFunctionGet(ast.Send node, LocalFunctionElement function, _) { 3599 void visitLocalFunctionGet(ast.Send node, LocalFunctionElement function, _) {
3720 handleLocalGet(node, function); 3600 handleLocalGet(node, function);
3721 } 3601 }
3722 3602
3723 @override 3603 @override
3724 void visitStaticFieldGet( 3604 void visitStaticFieldGet(ast.Send node, FieldElement field, _) {
3725 ast.Send node,
3726 FieldElement field,
3727 _) {
3728 generateStaticFieldGet(node, field); 3605 generateStaticFieldGet(node, field);
3729 } 3606 }
3730 3607
3731 @override 3608 @override
3732 void visitStaticFunctionGet( 3609 void visitStaticFunctionGet(ast.Send node, MethodElement function, _) {
3733 ast.Send node,
3734 MethodElement function,
3735 _) {
3736 generateStaticFunctionGet(node, function); 3610 generateStaticFunctionGet(node, function);
3737 } 3611 }
3738 3612
3739 @override 3613 @override
3740 void visitStaticGetterGet( 3614 void visitStaticGetterGet(ast.Send node, FunctionElement getter, _) {
3741 ast.Send node,
3742 FunctionElement getter,
3743 _) {
3744 generateStaticGetterGet(node, getter); 3615 generateStaticGetterGet(node, getter);
3745 } 3616 }
3746 3617
3747 @override 3618 @override
3748 void visitThisPropertyGet( 3619 void visitThisPropertyGet(ast.Send node, Name name, _) {
3749 ast.Send node,
3750 Name name,
3751 _) {
3752 generateDynamicGet(node); 3620 generateDynamicGet(node);
3753 } 3621 }
3754 3622
3755 @override 3623 @override
3756 void visitTopLevelFieldGet( 3624 void visitTopLevelFieldGet(ast.Send node, FieldElement field, _) {
3757 ast.Send node,
3758 FieldElement field,
3759 _) {
3760 generateStaticFieldGet(node, field); 3625 generateStaticFieldGet(node, field);
3761 } 3626 }
3762 3627
3763 @override 3628 @override
3764 void visitTopLevelFunctionGet( 3629 void visitTopLevelFunctionGet(ast.Send node, MethodElement function, _) {
3765 ast.Send node,
3766 MethodElement function,
3767 _) {
3768 generateStaticFunctionGet(node, function); 3630 generateStaticFunctionGet(node, function);
3769 } 3631 }
3770 3632
3771 @override 3633 @override
3772 void visitTopLevelGetterGet( 3634 void visitTopLevelGetterGet(ast.Send node, FunctionElement getter, _) {
3773 ast.Send node,
3774 FunctionElement getter,
3775 _) {
3776 generateStaticGetterGet(node, getter); 3635 generateStaticGetterGet(node, getter);
3777 } 3636 }
3778 3637
3779 void generateInstanceSetterWithCompiledReceiver(ast.Send send, 3638 void generateInstanceSetterWithCompiledReceiver(
3780 HInstruction receiver, 3639 ast.Send send, HInstruction receiver, HInstruction value,
3781 HInstruction value, 3640 {Selector selector, TypeMask mask, ast.Node location}) {
3782 {Selector selector, 3641 assert(invariant(send == null ? location : send,
3783 TypeMask mask,
3784 ast.Node location}) {
3785 assert(invariant(
3786 send == null ? location : send,
3787 send == null || Elements.isInstanceSend(send, elements), 3642 send == null || Elements.isInstanceSend(send, elements),
3788 message: "Unexpected instance setter" 3643 message: "Unexpected instance setter"
3789 "${send != null ? " element: ${elements[send]}" : ""}")); 3644 "${send != null ? " element: ${elements[send]}" : ""}"));
3790 if (selector == null) { 3645 if (selector == null) {
3791 assert(send != null); 3646 assert(send != null);
3792 selector = elements.getSelector(send); 3647 selector = elements.getSelector(send);
3793 if (mask == null) { 3648 if (mask == null) {
3794 mask = elements.getTypeMask(send); 3649 mask = elements.getTypeMask(send);
3795 } 3650 }
3796 } 3651 }
3797 if (location == null) { 3652 if (location == null) {
3798 assert(send != null); 3653 assert(send != null);
3799 location = send; 3654 location = send;
3800 } 3655 }
3801 assert(selector.isSetter); 3656 assert(selector.isSetter);
3802 pushInvokeDynamic(location, selector, mask, [receiver, value], 3657 pushInvokeDynamic(location, selector, mask, [receiver, value],
3803 sourceInformation: sourceInformationBuilder.buildAssignment(location)); 3658 sourceInformation: sourceInformationBuilder.buildAssignment(location));
3804 pop(); 3659 pop();
3805 stack.add(value); 3660 stack.add(value);
3806 } 3661 }
3807 3662
3808 void generateNoSuchSetter(ast.Node location, 3663 void generateNoSuchSetter(
3809 Element element, 3664 ast.Node location, Element element, HInstruction value) {
3810 HInstruction value) {
3811 List<HInstruction> arguments = 3665 List<HInstruction> arguments =
3812 value == null ? const <HInstruction>[] : <HInstruction>[value]; 3666 value == null ? const <HInstruction>[] : <HInstruction>[value];
3813 // An erroneous element indicates an unresolved static setter. 3667 // An erroneous element indicates an unresolved static setter.
3814 generateThrowNoSuchMethod( 3668 generateThrowNoSuchMethod(
3815 location, noSuchMethodTargetSymbolString(element, 'set'), 3669 location, noSuchMethodTargetSymbolString(element, 'set'),
3816 argumentValues: arguments); 3670 argumentValues: arguments);
3817 } 3671 }
3818 3672
3819 void generateNonInstanceSetter(ast.SendSet send, 3673 void generateNonInstanceSetter(
3820 Element element, 3674 ast.SendSet send, Element element, HInstruction value,
3821 HInstruction value, 3675 {ast.Node location}) {
3822 {ast.Node location}) {
3823 if (location == null) { 3676 if (location == null) {
3824 assert(send != null); 3677 assert(send != null);
3825 location = send; 3678 location = send;
3826 } 3679 }
3827 assert(invariant(location, 3680 assert(invariant(
3828 send == null || !Elements.isInstanceSend(send, elements), 3681 location, send == null || !Elements.isInstanceSend(send, elements),
3829 message: "Unexpected non instance setter: $element.")); 3682 message: "Unexpected non instance setter: $element."));
3830 if (Elements.isStaticOrTopLevelField(element)) { 3683 if (Elements.isStaticOrTopLevelField(element)) {
3831 if (element.isSetter) { 3684 if (element.isSetter) {
3832 pushInvokeStatic(location, element, <HInstruction>[value]); 3685 pushInvokeStatic(location, element, <HInstruction>[value]);
3833 pop(); 3686 pop();
3834 } else { 3687 } else {
3835 VariableElement field = element; 3688 VariableElement field = element;
3836 value = potentiallyCheckOrTrustType(value, field.type); 3689 value = potentiallyCheckOrTrustType(value, field.type);
3837 addWithPosition(new HStaticStore(element, value), location); 3690 addWithPosition(new HStaticStore(element, value), location);
3838 } 3691 }
3839 stack.add(value); 3692 stack.add(value);
3840 } else if (Elements.isError(element)) { 3693 } else if (Elements.isError(element)) {
3841 generateNoSuchSetter(location, element, send == null ? null : value); 3694 generateNoSuchSetter(location, element, send == null ? null : value);
3842 } else if (Elements.isMalformed(element)) { 3695 } else if (Elements.isMalformed(element)) {
3843 // TODO(ahe): Do something like [generateWrongArgumentCountError]. 3696 // TODO(ahe): Do something like [generateWrongArgumentCountError].
3844 stack.add(graph.addConstantNull(compiler)); 3697 stack.add(graph.addConstantNull(compiler));
3845 } else { 3698 } else {
3846 stack.add(value); 3699 stack.add(value);
3847 LocalElement local = element; 3700 LocalElement local = element;
3848 // If the value does not already have a name, give it here. 3701 // If the value does not already have a name, give it here.
3849 if (value.sourceElement == null) { 3702 if (value.sourceElement == null) {
3850 value.sourceElement = local; 3703 value.sourceElement = local;
3851 } 3704 }
(...skipping 30 matching lines...) Expand all
3882 } else { 3735 } else {
3883 assert(type.element.isClass); 3736 assert(type.element.isClass);
3884 InterfaceType interface = type; 3737 InterfaceType interface = type;
3885 List<HInstruction> inputs = <HInstruction>[]; 3738 List<HInstruction> inputs = <HInstruction>[];
3886 List<js.Expression> templates = <js.Expression>[]; 3739 List<js.Expression> templates = <js.Expression>[];
3887 for (DartType argument in interface.typeArguments) { 3740 for (DartType argument in interface.typeArguments) {
3888 // As we construct the template in stages, we have to make sure that for 3741 // As we construct the template in stages, we have to make sure that for
3889 // each part the generated sub-template's holes match the index of the 3742 // each part the generated sub-template's holes match the index of the
3890 // inputs that are later used to instantiate it. We do this by starting 3743 // inputs that are later used to instantiate it. We do this by starting
3891 // the indexing with the number of inputs from previous sub-templates. 3744 // the indexing with the number of inputs from previous sub-templates.
3892 templates.add( 3745 templates.add(rtiEncoder.getTypeRepresentationWithPlaceholders(argument,
3893 rtiEncoder.getTypeRepresentationWithPlaceholders( 3746 (variable) {
3894 argument, (variable) { 3747 HInstruction runtimeType = addTypeVariableReference(variable);
3895 HInstruction runtimeType = addTypeVariableReference(variable); 3748 inputs.add(runtimeType);
3896 inputs.add(runtimeType); 3749 }, firstPlaceholderIndex: inputs.length));
3897 }, firstPlaceholderIndex: inputs.length));
3898 } 3750 }
3899 // TODO(sra): This is a fresh template each time. We can't let the 3751 // TODO(sra): This is a fresh template each time. We can't let the
3900 // template manager build them. 3752 // template manager build them.
3901 js.Template code = new js.Template(null, 3753 js.Template code =
3902 new js.ArrayInitializer(templates)); 3754 new js.Template(null, new js.ArrayInitializer(templates));
3903 HInstruction representation = 3755 HInstruction representation = new HForeignCode(
3904 new HForeignCode(code, backend.readableArrayType, inputs, 3756 code, backend.readableArrayType, inputs,
3905 nativeBehavior: native.NativeBehavior.PURE_ALLOCATION); 3757 nativeBehavior: native.NativeBehavior.PURE_ALLOCATION);
3906 return representation; 3758 return representation;
3907 } 3759 }
3908 } 3760 }
3909 3761
3910 @override 3762 @override
3911 void visitAs(ast.Send node, ast.Node expression, DartType type, _) { 3763 void visitAs(ast.Send node, ast.Node expression, DartType type, _) {
3912 HInstruction expressionInstruction = visitAndPop(expression); 3764 HInstruction expressionInstruction = visitAndPop(expression);
3913 if (type.isMalformed) { 3765 if (type.isMalformed) {
3914 ErroneousElement element = type.element; 3766 ErroneousElement element = type.element;
3915 generateTypeError(node, element.message); 3767 generateTypeError(node, element.message);
3916 } else { 3768 } else {
3917 HInstruction converted = buildTypeConversion( 3769 HInstruction converted = buildTypeConversion(expressionInstruction,
3918 expressionInstruction, 3770 localsHandler.substInContext(type), HTypeConversion.CAST_TYPE_CHECK);
3919 localsHandler.substInContext(type),
3920 HTypeConversion.CAST_TYPE_CHECK);
3921 if (converted != expressionInstruction) add(converted); 3771 if (converted != expressionInstruction) add(converted);
3922 stack.add(converted); 3772 stack.add(converted);
3923 } 3773 }
3924 } 3774 }
3925 3775
3926 @override 3776 @override
3927 void visitIs(ast.Send node, ast.Node expression, DartType type, _) { 3777 void visitIs(ast.Send node, ast.Node expression, DartType type, _) {
3928 HInstruction expressionInstruction = visitAndPop(expression); 3778 HInstruction expressionInstruction = visitAndPop(expression);
3929 push(buildIsNode(node, type, expressionInstruction)); 3779 push(buildIsNode(node, type, expressionInstruction));
3930 } 3780 }
3931 3781
3932 @override 3782 @override
3933 void visitIsNot(ast.Send node, ast.Node expression, DartType type, _) { 3783 void visitIsNot(ast.Send node, ast.Node expression, DartType type, _) {
3934 HInstruction expressionInstruction = visitAndPop(expression); 3784 HInstruction expressionInstruction = visitAndPop(expression);
3935 HInstruction instruction = buildIsNode(node, type, expressionInstruction); 3785 HInstruction instruction = buildIsNode(node, type, expressionInstruction);
3936 add(instruction); 3786 add(instruction);
3937 push(new HNot(instruction, backend.boolType)); 3787 push(new HNot(instruction, backend.boolType));
3938 } 3788 }
3939 3789
3940 HInstruction buildIsNode(ast.Node node, 3790 HInstruction buildIsNode(
3941 DartType type, 3791 ast.Node node, DartType type, HInstruction expression) {
3942 HInstruction expression) {
3943 type = localsHandler.substInContext(type).unaliased; 3792 type = localsHandler.substInContext(type).unaliased;
3944 if (type.isFunctionType) { 3793 if (type.isFunctionType) {
3945 List arguments = [buildFunctionType(type), expression]; 3794 List arguments = [buildFunctionType(type), expression];
3946 pushInvokeDynamic( 3795 pushInvokeDynamic(
3947 node, 3796 node,
3948 new Selector.call( 3797 new Selector.call(new PrivateName('_isTest', helpers.jsHelperLibrary),
3949 new PrivateName('_isTest', helpers.jsHelperLibrary),
3950 CallStructure.ONE_ARG), 3798 CallStructure.ONE_ARG),
3951 null, 3799 null,
3952 arguments); 3800 arguments);
3953 return new HIs.compound(type, expression, pop(), backend.boolType); 3801 return new HIs.compound(type, expression, pop(), backend.boolType);
3954 } else if (type.isTypeVariable) { 3802 } else if (type.isTypeVariable) {
3955 HInstruction runtimeType = addTypeVariableReference(type); 3803 HInstruction runtimeType = addTypeVariableReference(type);
3956 Element helper = helpers.checkSubtypeOfRuntimeType; 3804 Element helper = helpers.checkSubtypeOfRuntimeType;
3957 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; 3805 List<HInstruction> inputs = <HInstruction>[expression, runtimeType];
3958 pushInvokeStatic(null, helper, inputs, typeMask: backend.boolType); 3806 pushInvokeStatic(null, helper, inputs, typeMask: backend.boolType);
3959 HInstruction call = pop(); 3807 HInstruction call = pop();
3960 return new HIs.variable(type, expression, call, backend.boolType); 3808 return new HIs.variable(type, expression, call, backend.boolType);
3961 } else if (RuntimeTypes.hasTypeArguments(type)) { 3809 } else if (RuntimeTypes.hasTypeArguments(type)) {
3962 ClassElement element = type.element; 3810 ClassElement element = type.element;
3963 Element helper = helpers.checkSubtype; 3811 Element helper = helpers.checkSubtype;
3964 HInstruction representations = 3812 HInstruction representations = buildTypeArgumentRepresentations(type);
3965 buildTypeArgumentRepresentations(type);
3966 add(representations); 3813 add(representations);
3967 js.Name operator = backend.namer.operatorIs(element); 3814 js.Name operator = backend.namer.operatorIs(element);
3968 HInstruction isFieldName = addConstantStringFromName(operator); 3815 HInstruction isFieldName = addConstantStringFromName(operator);
3969 HInstruction asFieldName = compiler.world.hasAnyStrictSubtype(element) 3816 HInstruction asFieldName = compiler.world.hasAnyStrictSubtype(element)
3970 ? addConstantStringFromName(backend.namer.substitutionName(element)) 3817 ? addConstantStringFromName(backend.namer.substitutionName(element))
3971 : graph.addConstantNull(compiler); 3818 : graph.addConstantNull(compiler);
3972 List<HInstruction> inputs = <HInstruction>[expression, 3819 List<HInstruction> inputs = <HInstruction>[
3973 isFieldName, 3820 expression,
3974 representations, 3821 isFieldName,
3975 asFieldName]; 3822 representations,
3823 asFieldName
3824 ];
3976 pushInvokeStatic(node, helper, inputs, typeMask: backend.boolType); 3825 pushInvokeStatic(node, helper, inputs, typeMask: backend.boolType);
3977 HInstruction call = pop(); 3826 HInstruction call = pop();
3978 return new HIs.compound(type, expression, call, backend.boolType); 3827 return new HIs.compound(type, expression, call, backend.boolType);
3979 } else if (type.isMalformed) { 3828 } else if (type.isMalformed) {
3980 ErroneousElement element = type.element; 3829 ErroneousElement element = type.element;
3981 generateTypeError(node, element.message); 3830 generateTypeError(node, element.message);
3982 HInstruction call = pop(); 3831 HInstruction call = pop();
3983 return new HIs.compound(type, expression, call, backend.boolType); 3832 return new HIs.compound(type, expression, call, backend.boolType);
3984 } else { 3833 } else {
3985 if (backend.hasDirectCheckFor(type)) { 3834 if (backend.hasDirectCheckFor(type)) {
(...skipping 13 matching lines...) Expand all
3999 3848
4000 void addDynamicSendArgumentsToList(ast.Send node, List<HInstruction> list) { 3849 void addDynamicSendArgumentsToList(ast.Send node, List<HInstruction> list) {
4001 CallStructure callStructure = elements.getSelector(node).callStructure; 3850 CallStructure callStructure = elements.getSelector(node).callStructure;
4002 if (callStructure.namedArgumentCount == 0) { 3851 if (callStructure.namedArgumentCount == 0) {
4003 addGenericSendArgumentsToList(node.arguments, list); 3852 addGenericSendArgumentsToList(node.arguments, list);
4004 } else { 3853 } else {
4005 // Visit positional arguments and add them to the list. 3854 // Visit positional arguments and add them to the list.
4006 Link<ast.Node> arguments = node.arguments; 3855 Link<ast.Node> arguments = node.arguments;
4007 int positionalArgumentCount = callStructure.positionalArgumentCount; 3856 int positionalArgumentCount = callStructure.positionalArgumentCount;
4008 for (int i = 0; 3857 for (int i = 0;
4009 i < positionalArgumentCount; 3858 i < positionalArgumentCount;
4010 arguments = arguments.tail, i++) { 3859 arguments = arguments.tail, i++) {
4011 visit(arguments.head); 3860 visit(arguments.head);
4012 list.add(pop()); 3861 list.add(pop());
4013 } 3862 }
4014 3863
4015 // Visit named arguments and add them into a temporary map. 3864 // Visit named arguments and add them into a temporary map.
4016 Map<String, HInstruction> instructions = 3865 Map<String, HInstruction> instructions = new Map<String, HInstruction>();
4017 new Map<String, HInstruction>();
4018 List<String> namedArguments = callStructure.namedArguments; 3866 List<String> namedArguments = callStructure.namedArguments;
4019 int nameIndex = 0; 3867 int nameIndex = 0;
4020 for (; !arguments.isEmpty; arguments = arguments.tail) { 3868 for (; !arguments.isEmpty; arguments = arguments.tail) {
4021 visit(arguments.head); 3869 visit(arguments.head);
4022 instructions[namedArguments[nameIndex++]] = pop(); 3870 instructions[namedArguments[nameIndex++]] = pop();
4023 } 3871 }
4024 3872
4025 // Iterate through the named arguments to add them to the list 3873 // Iterate through the named arguments to add them to the list
4026 // of instructions, in an order that can be shared with 3874 // of instructions, in an order that can be shared with
4027 // selectors with the same named arguments. 3875 // selectors with the same named arguments.
4028 List<String> orderedNames = callStructure.getOrderedNamedArguments(); 3876 List<String> orderedNames = callStructure.getOrderedNamedArguments();
4029 for (String name in orderedNames) { 3877 for (String name in orderedNames) {
4030 list.add(instructions[name]); 3878 list.add(instructions[name]);
4031 } 3879 }
4032 } 3880 }
4033 } 3881 }
4034 3882
4035 /** 3883 /**
4036 * Returns a list with the evaluated [arguments] in the normalized order. 3884 * Returns a list with the evaluated [arguments] in the normalized order.
4037 * 3885 *
4038 * Precondition: `this.applies(element, world)`. 3886 * Precondition: `this.applies(element, world)`.
4039 * Invariant: [element] must be an implementation element. 3887 * Invariant: [element] must be an implementation element.
4040 */ 3888 */
4041 List<HInstruction> makeStaticArgumentList(CallStructure callStructure, 3889 List<HInstruction> makeStaticArgumentList(CallStructure callStructure,
4042 Link<ast.Node> arguments, 3890 Link<ast.Node> arguments, FunctionElement element) {
4043 FunctionElement element) {
4044 assert(invariant(element, element.isImplementation)); 3891 assert(invariant(element, element.isImplementation));
4045 3892
4046 HInstruction compileArgument(ast.Node argument) { 3893 HInstruction compileArgument(ast.Node argument) {
4047 visit(argument); 3894 visit(argument);
4048 return pop(); 3895 return pop();
4049 } 3896 }
4050 3897
4051 return callStructure.makeArgumentsList( 3898 return callStructure.makeArgumentsList(
4052 arguments, 3899 arguments,
4053 element, 3900 element,
4054 compileArgument, 3901 compileArgument,
4055 backend.isJsInterop(element) ? 3902 backend.isJsInterop(element)
4056 handleConstantForOptionalParameterJsInterop : 3903 ? handleConstantForOptionalParameterJsInterop
4057 handleConstantForOptionalParameter); 3904 : handleConstantForOptionalParameter);
4058 } 3905 }
4059 3906
4060 void addGenericSendArgumentsToList(Link<ast.Node> link, List<HInstruction> lis t) { 3907 void addGenericSendArgumentsToList(
3908 Link<ast.Node> link, List<HInstruction> list) {
4061 for (; !link.isEmpty; link = link.tail) { 3909 for (; !link.isEmpty; link = link.tail) {
4062 visit(link.head); 3910 visit(link.head);
4063 list.add(pop()); 3911 list.add(pop());
4064 } 3912 }
4065 } 3913 }
4066 3914
4067 /// Generate a dynamic method, getter or setter invocation. 3915 /// Generate a dynamic method, getter or setter invocation.
4068 void generateDynamicSend(ast.Send node) { 3916 void generateDynamicSend(ast.Send node) {
4069 HInstruction receiver = generateInstanceSendReceiver(node); 3917 HInstruction receiver = generateInstanceSendReceiver(node);
4070 _generateDynamicSend(node, receiver); 3918 _generateDynamicSend(node, receiver);
4071 } 3919 }
4072 3920
4073 void _generateDynamicSend(ast.Send node, HInstruction receiver) { 3921 void _generateDynamicSend(ast.Send node, HInstruction receiver) {
4074 Selector selector = elements.getSelector(node); 3922 Selector selector = elements.getSelector(node);
4075 TypeMask mask = elements.getTypeMask(node); 3923 TypeMask mask = elements.getTypeMask(node);
4076 SourceInformation sourceInformation = 3924 SourceInformation sourceInformation =
4077 sourceInformationBuilder.buildCall(node, node.selector); 3925 sourceInformationBuilder.buildCall(node, node.selector);
4078 3926
4079 List<HInstruction> inputs = <HInstruction>[]; 3927 List<HInstruction> inputs = <HInstruction>[];
4080 inputs.add(receiver); 3928 inputs.add(receiver);
4081 addDynamicSendArgumentsToList(node, inputs); 3929 addDynamicSendArgumentsToList(node, inputs);
4082 3930
4083 pushInvokeDynamic(node, selector, mask, inputs, 3931 pushInvokeDynamic(node, selector, mask, inputs,
4084 sourceInformation: sourceInformation); 3932 sourceInformation: sourceInformation);
4085 if (selector.isSetter || selector.isIndexSet) { 3933 if (selector.isSetter || selector.isIndexSet) {
4086 pop(); 3934 pop();
4087 stack.add(inputs.last); 3935 stack.add(inputs.last);
4088 } 3936 }
4089 } 3937 }
4090 3938
4091 @override 3939 @override
4092 visitDynamicPropertyInvoke( 3940 visitDynamicPropertyInvoke(ast.Send node, ast.Node receiver,
4093 ast.Send node, 3941 ast.NodeList arguments, Selector selector, _) {
4094 ast.Node receiver,
4095 ast.NodeList arguments,
4096 Selector selector,
4097 _) {
4098 generateDynamicSend(node); 3942 generateDynamicSend(node);
4099 } 3943 }
4100 3944
4101 @override 3945 @override
4102 visitIfNotNullDynamicPropertyInvoke( 3946 visitIfNotNullDynamicPropertyInvoke(ast.Send node, ast.Node receiver,
4103 ast.Send node, 3947 ast.NodeList arguments, Selector selector, _) {
4104 ast.Node receiver,
4105 ast.NodeList arguments,
4106 Selector selector,
4107 _) {
4108 /// Desugar `exp?.m()` to `(t1 = exp) == null ? t1 : t1.m()` 3948 /// Desugar `exp?.m()` to `(t1 = exp) == null ? t1 : t1.m()`
4109 HInstruction receiver; 3949 HInstruction receiver;
4110 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 3950 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node);
4111 brancher.handleConditional( 3951 brancher.handleConditional(() {
4112 () { 3952 receiver = generateInstanceSendReceiver(node);
4113 receiver = generateInstanceSendReceiver(node); 3953 pushCheckNull(receiver);
4114 pushCheckNull(receiver); 3954 }, () => stack.add(receiver), () => _generateDynamicSend(node, receiver));
4115 },
4116 () => stack.add(receiver),
4117 () => _generateDynamicSend(node, receiver));
4118 } 3955 }
4119 3956
4120 @override 3957 @override
4121 visitThisPropertyInvoke( 3958 visitThisPropertyInvoke(
4122 ast.Send node, 3959 ast.Send node, ast.NodeList arguments, Selector selector, _) {
4123 ast.NodeList arguments,
4124 Selector selector,
4125 _) {
4126 generateDynamicSend(node); 3960 generateDynamicSend(node);
4127 } 3961 }
4128 3962
4129 @override 3963 @override
4130 visitExpressionInvoke( 3964 visitExpressionInvoke(ast.Send node, ast.Node expression,
4131 ast.Send node, 3965 ast.NodeList arguments, CallStructure callStructure, _) {
4132 ast.Node expression, 3966 generateCallInvoke(node, visitAndPop(expression),
4133 ast.NodeList arguments,
4134 CallStructure callStructure,
4135 _) {
4136 generateCallInvoke(
4137 node,
4138 visitAndPop(expression),
4139 sourceInformationBuilder.buildCall(node, node.argumentsNode)); 3967 sourceInformationBuilder.buildCall(node, node.argumentsNode));
4140 } 3968 }
4141 3969
4142 @override 3970 @override
4143 visitThisInvoke( 3971 visitThisInvoke(
4144 ast.Send node, 3972 ast.Send node, ast.NodeList arguments, CallStructure callStructure, _) {
4145 ast.NodeList arguments, 3973 generateCallInvoke(node, localsHandler.readThis(),
4146 CallStructure callStructure,
4147 _) {
4148 generateCallInvoke(
4149 node,
4150 localsHandler.readThis(),
4151 sourceInformationBuilder.buildCall(node, node.argumentsNode)); 3974 sourceInformationBuilder.buildCall(node, node.argumentsNode));
4152 } 3975 }
4153 3976
4154 @override 3977 @override
4155 visitParameterInvoke( 3978 visitParameterInvoke(ast.Send node, ParameterElement parameter,
4156 ast.Send node, 3979 ast.NodeList arguments, CallStructure callStructure, _) {
4157 ParameterElement parameter, 3980 generateCallInvoke(node, localsHandler.readLocal(parameter),
4158 ast.NodeList arguments,
4159 CallStructure callStructure,
4160 _) {
4161 generateCallInvoke(
4162 node,
4163 localsHandler.readLocal(parameter),
4164 sourceInformationBuilder.buildCall(node, node.argumentsNode)); 3981 sourceInformationBuilder.buildCall(node, node.argumentsNode));
4165 } 3982 }
4166 3983
4167 @override 3984 @override
4168 visitLocalVariableInvoke( 3985 visitLocalVariableInvoke(ast.Send node, LocalVariableElement variable,
4169 ast.Send node, 3986 ast.NodeList arguments, CallStructure callStructure, _) {
4170 LocalVariableElement variable, 3987 generateCallInvoke(node, localsHandler.readLocal(variable),
4171 ast.NodeList arguments,
4172 CallStructure callStructure,
4173 _) {
4174 generateCallInvoke(
4175 node,
4176 localsHandler.readLocal(variable),
4177 sourceInformationBuilder.buildCall(node, node.argumentsNode)); 3988 sourceInformationBuilder.buildCall(node, node.argumentsNode));
4178 } 3989 }
4179 3990
4180 @override 3991 @override
4181 visitLocalFunctionInvoke( 3992 visitLocalFunctionInvoke(ast.Send node, LocalFunctionElement function,
4182 ast.Send node, 3993 ast.NodeList arguments, CallStructure callStructure, _) {
4183 LocalFunctionElement function, 3994 generateCallInvoke(node, localsHandler.readLocal(function),
4184 ast.NodeList arguments,
4185 CallStructure callStructure,
4186 _) {
4187 generateCallInvoke(
4188 node,
4189 localsHandler.readLocal(function),
4190 sourceInformationBuilder.buildCall(node, node.argumentsNode)); 3995 sourceInformationBuilder.buildCall(node, node.argumentsNode));
4191 } 3996 }
4192 3997
4193 @override 3998 @override
4194 visitLocalFunctionIncompatibleInvoke( 3999 visitLocalFunctionIncompatibleInvoke(
4195 ast.Send node, 4000 ast.Send node,
4196 LocalFunctionElement function, 4001 LocalFunctionElement function,
4197 ast.NodeList arguments, 4002 ast.NodeList arguments,
4198 CallStructure callStructure, 4003 CallStructure callStructure,
4199 _) { 4004 _) {
4200 generateCallInvoke(node, localsHandler.readLocal(function), 4005 generateCallInvoke(node, localsHandler.readLocal(function),
4201 sourceInformationBuilder.buildCall(node, node.argumentsNode)); 4006 sourceInformationBuilder.buildCall(node, node.argumentsNode));
4202 } 4007 }
4203 4008
4204 void handleForeignJs(ast.Send node) { 4009 void handleForeignJs(ast.Send node) {
4205 Link<ast.Node> link = node.arguments; 4010 Link<ast.Node> link = node.arguments;
4206 // Don't visit the first argument, which is the type, and the second 4011 // Don't visit the first argument, which is the type, and the second
4207 // argument, which is the foreign code. 4012 // argument, which is the foreign code.
4208 if (link.isEmpty || link.tail.isEmpty) { 4013 if (link.isEmpty || link.tail.isEmpty) {
4209 // We should not get here because the call should be compiled to NSM. 4014 // We should not get here because the call should be compiled to NSM.
4210 reporter.internalError(node.argumentsNode, 4015 reporter.internalError(
4211 'At least two arguments expected.'); 4016 node.argumentsNode, 'At least two arguments expected.');
4212 } 4017 }
4213 native.NativeBehavior nativeBehavior = 4018 native.NativeBehavior nativeBehavior =
4214 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node); 4019 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node);
4215 4020
4216 List<HInstruction> inputs = <HInstruction>[]; 4021 List<HInstruction> inputs = <HInstruction>[];
4217 addGenericSendArgumentsToList(link.tail.tail, inputs); 4022 addGenericSendArgumentsToList(link.tail.tail, inputs);
4218 4023
4219 if (nativeBehavior.codeTemplate.positionalArgumentCount != inputs.length) { 4024 if (nativeBehavior.codeTemplate.positionalArgumentCount != inputs.length) {
4220 reporter.reportErrorMessage( 4025 reporter.reportErrorMessage(node, MessageKind.GENERIC, {
4221 node, MessageKind.GENERIC, 4026 'text': 'Mismatch between number of placeholders'
4222 {'text': 4027 ' and number of arguments.'
4223 'Mismatch between number of placeholders' 4028 });
4224 ' and number of arguments.'}); 4029 stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
4225 stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
4226 return; 4030 return;
4227 } 4031 }
4228 4032
4229 if (native.HasCapturedPlaceholders.check(nativeBehavior.codeTemplate.ast)) { 4033 if (native.HasCapturedPlaceholders.check(nativeBehavior.codeTemplate.ast)) {
4230 reporter.reportErrorMessage(node, MessageKind.JS_PLACEHOLDER_CAPTURE); 4034 reporter.reportErrorMessage(node, MessageKind.JS_PLACEHOLDER_CAPTURE);
4231 } 4035 }
4232 4036
4233 TypeMask ssaType = 4037 TypeMask ssaType =
4234 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler); 4038 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler);
4235 4039
4236 SourceInformation sourceInformation = 4040 SourceInformation sourceInformation =
4237 sourceInformationBuilder.buildCall(node, node.argumentsNode); 4041 sourceInformationBuilder.buildCall(node, node.argumentsNode);
4238 if (nativeBehavior.codeTemplate.isExpression) { 4042 if (nativeBehavior.codeTemplate.isExpression) {
4239 push(new HForeignCode( 4043 push(new HForeignCode(nativeBehavior.codeTemplate, ssaType, inputs,
4240 nativeBehavior.codeTemplate, ssaType, inputs, 4044 effects: nativeBehavior.sideEffects, nativeBehavior: nativeBehavior)
4241 effects: nativeBehavior.sideEffects, 4045 ..sourceInformation = sourceInformation);
4242 nativeBehavior: nativeBehavior)
4243 ..sourceInformation = sourceInformation);
4244 } else { 4046 } else {
4245 push(new HForeignCode( 4047 push(new HForeignCode(nativeBehavior.codeTemplate, ssaType, inputs,
4246 nativeBehavior.codeTemplate, ssaType, inputs,
4247 isStatement: true, 4048 isStatement: true,
4248 effects: nativeBehavior.sideEffects, 4049 effects: nativeBehavior.sideEffects,
4249 nativeBehavior: nativeBehavior) 4050 nativeBehavior: nativeBehavior)
4250 ..sourceInformation = sourceInformation); 4051 ..sourceInformation = sourceInformation);
4251 } 4052 }
4252 } 4053 }
4253 4054
4254 void handleJsStringConcat(ast.Send node) { 4055 void handleJsStringConcat(ast.Send node) {
4255 List<HInstruction> inputs = <HInstruction>[]; 4056 List<HInstruction> inputs = <HInstruction>[];
4256 addGenericSendArgumentsToList(node.arguments, inputs); 4057 addGenericSendArgumentsToList(node.arguments, inputs);
4257 if (inputs.length != 2) { 4058 if (inputs.length != 2) {
4258 reporter.internalError(node.argumentsNode, 'Two arguments expected.'); 4059 reporter.internalError(node.argumentsNode, 'Two arguments expected.');
4259 } 4060 }
4260 push(new HStringConcat(inputs[0], inputs[1], backend.stringType)); 4061 push(new HStringConcat(inputs[0], inputs[1], backend.stringType));
4261 } 4062 }
4262 4063
4263 void handleForeignJsCurrentIsolateContext(ast.Send node) { 4064 void handleForeignJsCurrentIsolateContext(ast.Send node) {
4264 if (!node.arguments.isEmpty) { 4065 if (!node.arguments.isEmpty) {
4265 reporter.internalError(node, 4066 reporter.internalError(
4266 'Too many arguments to JS_CURRENT_ISOLATE_CONTEXT.'); 4067 node, 'Too many arguments to JS_CURRENT_ISOLATE_CONTEXT.');
4267 } 4068 }
4268 4069
4269 if (!compiler.hasIsolateSupport) { 4070 if (!compiler.hasIsolateSupport) {
4270 // If the isolate library is not used, we just generate code 4071 // If the isolate library is not used, we just generate code
4271 // to fetch the static state. 4072 // to fetch the static state.
4272 String name = backend.namer.staticStateHolder; 4073 String name = backend.namer.staticStateHolder;
4273 push(new HForeignCode( 4074 push(new HForeignCode(
4274 js.js.parseForeignJS(name), 4075 js.js.parseForeignJS(name), backend.dynamicType, <HInstruction>[],
4275 backend.dynamicType,
4276 <HInstruction>[],
4277 nativeBehavior: native.NativeBehavior.DEPENDS_OTHER)); 4076 nativeBehavior: native.NativeBehavior.DEPENDS_OTHER));
4278 } else { 4077 } else {
4279 // Call a helper method from the isolate library. The isolate 4078 // Call a helper method from the isolate library. The isolate
4280 // library uses its own isolate structure, that encapsulates 4079 // library uses its own isolate structure, that encapsulates
4281 // Leg's isolate. 4080 // Leg's isolate.
4282 Element element = helpers.currentIsolate; 4081 Element element = helpers.currentIsolate;
4283 if (element == null) { 4082 if (element == null) {
4284 reporter.internalError(node, 4083 reporter.internalError(node, 'Isolate library and compiler mismatch.');
4285 'Isolate library and compiler mismatch.');
4286 } 4084 }
4287 pushInvokeStatic(null, element, [], typeMask: backend.dynamicType); 4085 pushInvokeStatic(null, element, [], typeMask: backend.dynamicType);
4288 } 4086 }
4289 } 4087 }
4290 4088
4291 void handleForeignJsGetFlag(ast.Send node) { 4089 void handleForeignJsGetFlag(ast.Send node) {
4292 List<ast.Node> arguments = node.arguments.toList(); 4090 List<ast.Node> arguments = node.arguments.toList();
4293 ast.Node argument; 4091 ast.Node argument;
4294 switch (arguments.length) { 4092 switch (arguments.length) {
4295 case 0: 4093 case 0:
4296 reporter.reportErrorMessage( 4094 reporter.reportErrorMessage(node, MessageKind.GENERIC,
4297 node, MessageKind.GENERIC, 4095 {'text': 'Error: Expected one argument to JS_GET_FLAG.'});
4298 {'text': 'Error: Expected one argument to JS_GET_FLAG.'}); 4096 return;
4299 return; 4097 case 1:
4300 case 1: 4098 argument = arguments[0];
4301 argument = arguments[0]; 4099 break;
4302 break; 4100 default:
4303 default: 4101 for (int i = 1; i < arguments.length; i++) {
4304 for (int i = 1; i < arguments.length; i++) { 4102 reporter.reportErrorMessage(arguments[i], MessageKind.GENERIC,
4305 reporter.reportErrorMessage( 4103 {'text': 'Error: Extra argument to JS_GET_FLAG.'});
4306 arguments[i], MessageKind.GENERIC, 4104 }
4307 {'text': 'Error: Extra argument to JS_GET_FLAG.'}); 4105 return;
4308 } 4106 }
4309 return; 4107 ast.LiteralString string = argument.asLiteralString();
4310 } 4108 if (string == null) {
4311 ast.LiteralString string = argument.asLiteralString(); 4109 reporter.reportErrorMessage(argument, MessageKind.GENERIC,
4312 if (string == null) { 4110 {'text': 'Error: Expected a literal string.'});
4313 reporter.reportErrorMessage( 4111 }
4314 argument, MessageKind.GENERIC, 4112 String name = string.dartString.slowToString();
4315 {'text': 'Error: Expected a literal string.'}); 4113 bool value = false;
4316 } 4114 switch (name) {
4317 String name = string.dartString.slowToString(); 4115 case 'MUST_RETAIN_METADATA':
4318 bool value = false; 4116 value = backend.mustRetainMetadata;
4319 switch (name) { 4117 break;
4320 case 'MUST_RETAIN_METADATA': 4118 case 'USE_CONTENT_SECURITY_POLICY':
4321 value = backend.mustRetainMetadata; 4119 value = compiler.options.useContentSecurityPolicy;
4322 break; 4120 break;
4323 case 'USE_CONTENT_SECURITY_POLICY': 4121 default:
4324 value = compiler.options.useContentSecurityPolicy; 4122 reporter.reportErrorMessage(node, MessageKind.GENERIC,
4325 break; 4123 {'text': 'Error: Unknown internal flag "$name".'});
4326 default: 4124 }
4327 reporter.reportErrorMessage( 4125 stack.add(graph.addConstantBool(value, compiler));
4328 node, MessageKind.GENERIC,
4329 {'text': 'Error: Unknown internal flag "$name".'});
4330 }
4331 stack.add(graph.addConstantBool(value, compiler));
4332 } 4126 }
4333 4127
4334 void handleForeignJsGetName(ast.Send node) { 4128 void handleForeignJsGetName(ast.Send node) {
4335 List<ast.Node> arguments = node.arguments.toList(); 4129 List<ast.Node> arguments = node.arguments.toList();
4336 ast.Node argument; 4130 ast.Node argument;
4337 switch (arguments.length) { 4131 switch (arguments.length) {
4338 case 0: 4132 case 0:
4339 reporter.reportErrorMessage( 4133 reporter.reportErrorMessage(node, MessageKind.GENERIC,
4340 node, MessageKind.GENERIC, 4134 {'text': 'Error: Expected one argument to JS_GET_NAME.'});
4341 {'text': 'Error: Expected one argument to JS_GET_NAME.'}); 4135 return;
4342 return; 4136 case 1:
4343 case 1: 4137 argument = arguments[0];
4344 argument = arguments[0]; 4138 break;
4345 break; 4139 default:
4346 default: 4140 for (int i = 1; i < arguments.length; i++) {
4347 for (int i = 1; i < arguments.length; i++) { 4141 reporter.reportErrorMessage(arguments[i], MessageKind.GENERIC,
4348 reporter.reportErrorMessage( 4142 {'text': 'Error: Extra argument to JS_GET_NAME.'});
4349 arguments[i], MessageKind.GENERIC, 4143 }
4350 {'text': 'Error: Extra argument to JS_GET_NAME.'}); 4144 return;
4351 }
4352 return;
4353 } 4145 }
4354 Element element = elements[argument]; 4146 Element element = elements[argument];
4355 if (element == null || 4147 if (element == null ||
4356 element is! FieldElement || 4148 element is! FieldElement ||
4357 element.enclosingClass != helpers.jsGetNameEnum) { 4149 element.enclosingClass != helpers.jsGetNameEnum) {
4358 reporter.reportErrorMessage( 4150 reporter.reportErrorMessage(argument, MessageKind.GENERIC,
4359 argument, MessageKind.GENERIC,
4360 {'text': 'Error: Expected a JsGetName enum value.'}); 4151 {'text': 'Error: Expected a JsGetName enum value.'});
4361 } 4152 }
4362 EnumClassElement enumClass = element.enclosingClass; 4153 EnumClassElement enumClass = element.enclosingClass;
4363 int index = enumClass.enumValues.indexOf(element); 4154 int index = enumClass.enumValues.indexOf(element);
4364 stack.add( 4155 stack.add(addConstantStringFromName(
4365 addConstantStringFromName( 4156 backend.namer.getNameForJsGetName(argument, JsGetName.values[index])));
4366 backend.namer.getNameForJsGetName(
4367 argument, JsGetName.values[index])));
4368 } 4157 }
4369 4158
4370 void handleForeignJsBuiltin(ast.Send node) { 4159 void handleForeignJsBuiltin(ast.Send node) {
4371 List<ast.Node> arguments = node.arguments.toList(); 4160 List<ast.Node> arguments = node.arguments.toList();
4372 ast.Node argument; 4161 ast.Node argument;
4373 if (arguments.length < 2) { 4162 if (arguments.length < 2) {
4374 reporter.reportErrorMessage( 4163 reporter.reportErrorMessage(node, MessageKind.GENERIC,
4375 node, MessageKind.GENERIC,
4376 {'text': 'Error: Expected at least two arguments to JS_BUILTIN.'}); 4164 {'text': 'Error: Expected at least two arguments to JS_BUILTIN.'});
4377 } 4165 }
4378 4166
4379 Element builtinElement = elements[arguments[1]]; 4167 Element builtinElement = elements[arguments[1]];
4380 if (builtinElement == null || 4168 if (builtinElement == null ||
4381 (builtinElement is! FieldElement) || 4169 (builtinElement is! FieldElement) ||
4382 builtinElement.enclosingClass != helpers.jsBuiltinEnum) { 4170 builtinElement.enclosingClass != helpers.jsBuiltinEnum) {
4383 reporter.reportErrorMessage( 4171 reporter.reportErrorMessage(argument, MessageKind.GENERIC,
4384 argument, MessageKind.GENERIC,
4385 {'text': 'Error: Expected a JsBuiltin enum value.'}); 4172 {'text': 'Error: Expected a JsBuiltin enum value.'});
4386 } 4173 }
4387 EnumClassElement enumClass = builtinElement.enclosingClass; 4174 EnumClassElement enumClass = builtinElement.enclosingClass;
4388 int index = enumClass.enumValues.indexOf(builtinElement); 4175 int index = enumClass.enumValues.indexOf(builtinElement);
4389 4176
4390 js.Template template = 4177 js.Template template =
4391 backend.emitter.builtinTemplateFor(JsBuiltin.values[index]); 4178 backend.emitter.builtinTemplateFor(JsBuiltin.values[index]);
4392 4179
4393 List<HInstruction> compiledArguments = <HInstruction>[]; 4180 List<HInstruction> compiledArguments = <HInstruction>[];
4394 for (int i = 2; i < arguments.length; i++) { 4181 for (int i = 2; i < arguments.length; i++) {
4395 visit(arguments[i]); 4182 visit(arguments[i]);
4396 compiledArguments.add(pop()); 4183 compiledArguments.add(pop());
4397 } 4184 }
4398 4185
4399 native.NativeBehavior nativeBehavior = 4186 native.NativeBehavior nativeBehavior =
4400 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node); 4187 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node);
4401 4188
4402 TypeMask ssaType = 4189 TypeMask ssaType =
4403 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler); 4190 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler);
4404 4191
4405 push(new HForeignCode(template, 4192 push(new HForeignCode(template, ssaType, compiledArguments,
4406 ssaType, 4193 nativeBehavior: nativeBehavior));
4407 compiledArguments,
4408 nativeBehavior: nativeBehavior));
4409 } 4194 }
4410 4195
4411 void handleForeignJsEmbeddedGlobal(ast.Send node) { 4196 void handleForeignJsEmbeddedGlobal(ast.Send node) {
4412 List<ast.Node> arguments = node.arguments.toList(); 4197 List<ast.Node> arguments = node.arguments.toList();
4413 ast.Node globalNameNode; 4198 ast.Node globalNameNode;
4414 switch (arguments.length) { 4199 switch (arguments.length) {
4415 case 0: 4200 case 0:
4416 case 1: 4201 case 1:
4417 reporter.reportErrorMessage( 4202 reporter.reportErrorMessage(node, MessageKind.GENERIC,
4418 node, MessageKind.GENERIC, 4203 {'text': 'Error: Expected two arguments to JS_EMBEDDED_GLOBAL.'});
4419 {'text': 'Error: Expected two arguments to JS_EMBEDDED_GLOBAL.'}); 4204 return;
4420 return; 4205 case 2:
4421 case 2: 4206 // The type has been extracted earlier. We are only interested in the
4422 // The type has been extracted earlier. We are only interested in the 4207 // name in this function.
4423 // name in this function. 4208 globalNameNode = arguments[1];
4424 globalNameNode = arguments[1]; 4209 break;
4425 break; 4210 default:
4426 default: 4211 for (int i = 2; i < arguments.length; i++) {
4427 for (int i = 2; i < arguments.length; i++) { 4212 reporter.reportErrorMessage(arguments[i], MessageKind.GENERIC,
4428 reporter.reportErrorMessage( 4213 {'text': 'Error: Extra argument to JS_EMBEDDED_GLOBAL.'});
4429 arguments[i], MessageKind.GENERIC, 4214 }
4430 {'text': 'Error: Extra argument to JS_EMBEDDED_GLOBAL.'}); 4215 return;
4431 }
4432 return;
4433 } 4216 }
4434 visit(globalNameNode); 4217 visit(globalNameNode);
4435 HInstruction globalNameHNode = pop(); 4218 HInstruction globalNameHNode = pop();
4436 if (!globalNameHNode.isConstantString()) { 4219 if (!globalNameHNode.isConstantString()) {
4437 reporter.reportErrorMessage( 4220 reporter.reportErrorMessage(arguments[1], MessageKind.GENERIC, {
4438 arguments[1], MessageKind.GENERIC, 4221 'text': 'Error: Expected String as second argument '
4439 {'text': 'Error: Expected String as second argument ' 4222 'to JS_EMBEDDED_GLOBAL.'
4440 'to JS_EMBEDDED_GLOBAL.'}); 4223 });
4441 return; 4224 return;
4442 } 4225 }
4443 HConstant hConstant = globalNameHNode; 4226 HConstant hConstant = globalNameHNode;
4444 StringConstantValue constant = hConstant.constant; 4227 StringConstantValue constant = hConstant.constant;
4445 String globalName = constant.primitiveValue.slowToString(); 4228 String globalName = constant.primitiveValue.slowToString();
4446 js.Template expr = js.js.expressionTemplateYielding( 4229 js.Template expr = js.js.expressionTemplateYielding(
4447 backend.emitter.generateEmbeddedGlobalAccess(globalName)); 4230 backend.emitter.generateEmbeddedGlobalAccess(globalName));
4448 native.NativeBehavior nativeBehavior = 4231 native.NativeBehavior nativeBehavior =
4449 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node); 4232 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node);
4450 TypeMask ssaType = 4233 TypeMask ssaType =
4451 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler); 4234 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler);
4452 push(new HForeignCode(expr, ssaType, const [], 4235 push(new HForeignCode(expr, ssaType, const [],
4453 nativeBehavior: nativeBehavior)); 4236 nativeBehavior: nativeBehavior));
4454 } 4237 }
4455 4238
4456 void handleJsInterceptorConstant(ast.Send node) { 4239 void handleJsInterceptorConstant(ast.Send node) {
4457 // Single argument must be a TypeConstant which is converted into a 4240 // Single argument must be a TypeConstant which is converted into a
4458 // InterceptorConstant. 4241 // InterceptorConstant.
4459 if (!node.arguments.isEmpty && node.arguments.tail.isEmpty) { 4242 if (!node.arguments.isEmpty && node.arguments.tail.isEmpty) {
4460 ast.Node argument = node.arguments.head; 4243 ast.Node argument = node.arguments.head;
4461 visit(argument); 4244 visit(argument);
4462 HInstruction argumentInstruction = pop(); 4245 HInstruction argumentInstruction = pop();
4463 if (argumentInstruction is HConstant) { 4246 if (argumentInstruction is HConstant) {
4464 ConstantValue argumentConstant = argumentInstruction.constant; 4247 ConstantValue argumentConstant = argumentInstruction.constant;
4465 if (argumentConstant is TypeConstantValue) { 4248 if (argumentConstant is TypeConstantValue) {
4466 ConstantValue constant = 4249 ConstantValue constant =
4467 new InterceptorConstantValue(argumentConstant.representedType); 4250 new InterceptorConstantValue(argumentConstant.representedType);
4468 HInstruction instruction = graph.addConstant(constant, compiler); 4251 HInstruction instruction = graph.addConstant(constant, compiler);
4469 stack.add(instruction); 4252 stack.add(instruction);
4470 return; 4253 return;
4471 } 4254 }
4472 } 4255 }
4473 } 4256 }
4474 reporter.reportErrorMessage( 4257 reporter.reportErrorMessage(
4475 node, 4258 node, MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT);
4476 MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT);
4477 stack.add(graph.addConstantNull(compiler)); 4259 stack.add(graph.addConstantNull(compiler));
4478 } 4260 }
4479 4261
4480 void handleForeignJsCallInIsolate(ast.Send node) { 4262 void handleForeignJsCallInIsolate(ast.Send node) {
4481 Link<ast.Node> link = node.arguments; 4263 Link<ast.Node> link = node.arguments;
4482 if (!compiler.hasIsolateSupport) { 4264 if (!compiler.hasIsolateSupport) {
4483 // If the isolate library is not used, we just invoke the 4265 // If the isolate library is not used, we just invoke the
4484 // closure. 4266 // closure.
4485 visit(link.tail.head); 4267 visit(link.tail.head);
4486 push(new HInvokeClosure(new Selector.callClosure(0), 4268 push(new HInvokeClosure(new Selector.callClosure(0),
4487 <HInstruction>[pop()], 4269 <HInstruction>[pop()], backend.dynamicType));
4488 backend.dynamicType));
4489 } else { 4270 } else {
4490 // Call a helper method from the isolate library. 4271 // Call a helper method from the isolate library.
4491 Element element = helpers.callInIsolate; 4272 Element element = helpers.callInIsolate;
4492 if (element == null) { 4273 if (element == null) {
4493 reporter.internalError(node, 4274 reporter.internalError(node, 'Isolate library and compiler mismatch.');
4494 'Isolate library and compiler mismatch.');
4495 } 4275 }
4496 List<HInstruction> inputs = <HInstruction>[]; 4276 List<HInstruction> inputs = <HInstruction>[];
4497 addGenericSendArgumentsToList(link, inputs); 4277 addGenericSendArgumentsToList(link, inputs);
4498 pushInvokeStatic(node, element, inputs, typeMask: backend.dynamicType); 4278 pushInvokeStatic(node, element, inputs, typeMask: backend.dynamicType);
4499 } 4279 }
4500 } 4280 }
4501 4281
4502 FunctionSignature handleForeignRawFunctionRef(ast.Send node, String name) { 4282 FunctionSignature handleForeignRawFunctionRef(ast.Send node, String name) {
4503 if (node.arguments.isEmpty || !node.arguments.tail.isEmpty) { 4283 if (node.arguments.isEmpty || !node.arguments.tail.isEmpty) {
4504 reporter.internalError(node.argumentsNode, 4284 reporter.internalError(
4505 '"$name" requires exactly one argument.'); 4285 node.argumentsNode, '"$name" requires exactly one argument.');
4506 } 4286 }
4507 ast.Node closure = node.arguments.head; 4287 ast.Node closure = node.arguments.head;
4508 Element element = elements[closure]; 4288 Element element = elements[closure];
4509 if (!Elements.isStaticOrTopLevelFunction(element)) { 4289 if (!Elements.isStaticOrTopLevelFunction(element)) {
4510 reporter.internalError(closure, 4290 reporter.internalError(
4511 '"$name" requires a static or top-level method.'); 4291 closure, '"$name" requires a static or top-level method.');
4512 } 4292 }
4513 FunctionElement function = element; 4293 FunctionElement function = element;
4514 // TODO(johnniwinther): Try to eliminate the need to distinguish declaration 4294 // TODO(johnniwinther): Try to eliminate the need to distinguish declaration
4515 // and implementation signatures. Currently it is need because the 4295 // and implementation signatures. Currently it is need because the
4516 // signatures have different elements for parameters. 4296 // signatures have different elements for parameters.
4517 FunctionElement implementation = function.implementation; 4297 FunctionElement implementation = function.implementation;
4518 FunctionSignature params = implementation.functionSignature; 4298 FunctionSignature params = implementation.functionSignature;
4519 if (params.optionalParameterCount != 0) { 4299 if (params.optionalParameterCount != 0) {
4520 reporter.internalError(closure, 4300 reporter.internalError(
4521 '"$name" does not handle closure with optional parameters.'); 4301 closure, '"$name" does not handle closure with optional parameters.');
4522 } 4302 }
4523 4303
4524 registry?.registerStaticUse( 4304 registry?.registerStaticUse(new StaticUse.foreignUse(function));
4525 new StaticUse.foreignUse(function));
4526 push(new HForeignCode( 4305 push(new HForeignCode(
4527 js.js.expressionTemplateYielding( 4306 js.js.expressionTemplateYielding(
4528 backend.emitter.staticFunctionAccess(function)), 4307 backend.emitter.staticFunctionAccess(function)),
4529 backend.dynamicType, 4308 backend.dynamicType,
4530 <HInstruction>[], 4309 <HInstruction>[],
4531 nativeBehavior: native.NativeBehavior.PURE)); 4310 nativeBehavior: native.NativeBehavior.PURE));
4532 return params; 4311 return params;
4533 } 4312 }
4534 4313
4535 void handleForeignDartClosureToJs(ast.Send node, String name) { 4314 void handleForeignDartClosureToJs(ast.Send node, String name) {
4536 // TODO(ahe): This implements DART_CLOSURE_TO_JS and should probably take 4315 // TODO(ahe): This implements DART_CLOSURE_TO_JS and should probably take
4537 // care to wrap the closure in another closure that saves the current 4316 // care to wrap the closure in another closure that saves the current
4538 // isolate. 4317 // isolate.
4539 handleForeignRawFunctionRef(node, name); 4318 handleForeignRawFunctionRef(node, name);
4540 } 4319 }
4541 4320
4542 void handleForeignJsSetStaticState(ast.Send node) { 4321 void handleForeignJsSetStaticState(ast.Send node) {
4543 if (node.arguments.isEmpty || !node.arguments.tail.isEmpty) { 4322 if (node.arguments.isEmpty || !node.arguments.tail.isEmpty) {
4544 reporter.internalError(node.argumentsNode, 4323 reporter.internalError(
4545 'Exactly one argument required.'); 4324 node.argumentsNode, 'Exactly one argument required.');
4546 } 4325 }
4547 visit(node.arguments.head); 4326 visit(node.arguments.head);
4548 String isolateName = backend.namer.staticStateHolder; 4327 String isolateName = backend.namer.staticStateHolder;
4549 SideEffects sideEffects = new SideEffects.empty(); 4328 SideEffects sideEffects = new SideEffects.empty();
4550 sideEffects.setAllSideEffects(); 4329 sideEffects.setAllSideEffects();
4551 push(new HForeignCode( 4330 push(new HForeignCode(js.js.parseForeignJS("$isolateName = #"),
4552 js.js.parseForeignJS("$isolateName = #"), 4331 backend.dynamicType, <HInstruction>[pop()],
4553 backend.dynamicType,
4554 <HInstruction>[pop()],
4555 nativeBehavior: native.NativeBehavior.CHANGES_OTHER, 4332 nativeBehavior: native.NativeBehavior.CHANGES_OTHER,
4556 effects: sideEffects)); 4333 effects: sideEffects));
4557 } 4334 }
4558 4335
4559 void handleForeignJsGetStaticState(ast.Send node) { 4336 void handleForeignJsGetStaticState(ast.Send node) {
4560 if (!node.arguments.isEmpty) { 4337 if (!node.arguments.isEmpty) {
4561 reporter.internalError(node.argumentsNode, 'Too many arguments.'); 4338 reporter.internalError(node.argumentsNode, 'Too many arguments.');
4562 } 4339 }
4563 push(new HForeignCode(js.js.parseForeignJS(backend.namer.staticStateHolder), 4340 push(new HForeignCode(js.js.parseForeignJS(backend.namer.staticStateHolder),
4564 backend.dynamicType, 4341 backend.dynamicType, <HInstruction>[],
4565 <HInstruction>[], 4342 nativeBehavior: native.NativeBehavior.DEPENDS_OTHER));
4566 nativeBehavior: native.NativeBehavior.DEPENDS_OTHER));
4567 } 4343 }
4568 4344
4569 void handleForeignSend(ast.Send node, FunctionElement element) { 4345 void handleForeignSend(ast.Send node, FunctionElement element) {
4570 String name = element.name; 4346 String name = element.name;
4571 if (name == 'JS') { 4347 if (name == 'JS') {
4572 handleForeignJs(node); 4348 handleForeignJs(node);
4573 } else if (name == 'JS_CURRENT_ISOLATE_CONTEXT') { 4349 } else if (name == 'JS_CURRENT_ISOLATE_CONTEXT') {
4574 handleForeignJsCurrentIsolateContext(node); 4350 handleForeignJsCurrentIsolateContext(node);
4575 } else if (name == 'JS_CALL_IN_ISOLATE') { 4351 } else if (name == 'JS_CALL_IN_ISOLATE') {
4576 handleForeignJsCallInIsolate(node); 4352 handleForeignJsCallInIsolate(node);
(...skipping 17 matching lines...) Expand all
4594 stack.add(graph.addConstantNull(compiler)); 4370 stack.add(graph.addConstantNull(compiler));
4595 } else if (name == 'JS_INTERCEPTOR_CONSTANT') { 4371 } else if (name == 'JS_INTERCEPTOR_CONSTANT') {
4596 handleJsInterceptorConstant(node); 4372 handleJsInterceptorConstant(node);
4597 } else if (name == 'JS_STRING_CONCAT') { 4373 } else if (name == 'JS_STRING_CONCAT') {
4598 handleJsStringConcat(node); 4374 handleJsStringConcat(node);
4599 } else { 4375 } else {
4600 reporter.internalError(node, "Unknown foreign: ${element}"); 4376 reporter.internalError(node, "Unknown foreign: ${element}");
4601 } 4377 }
4602 } 4378 }
4603 4379
4604 generateDeferredLoaderGet(ast.Send node, 4380 generateDeferredLoaderGet(ast.Send node, FunctionElement deferredLoader,
4605 FunctionElement deferredLoader, 4381 SourceInformation sourceInformation) {
4606 SourceInformation sourceInformation) {
4607 // Until now we only handle these as getters. 4382 // Until now we only handle these as getters.
4608 invariant(node, deferredLoader.isDeferredLoaderGetter); 4383 invariant(node, deferredLoader.isDeferredLoaderGetter);
4609 Element loadFunction = compiler.loadLibraryFunction; 4384 Element loadFunction = compiler.loadLibraryFunction;
4610 PrefixElement prefixElement = deferredLoader.enclosingElement; 4385 PrefixElement prefixElement = deferredLoader.enclosingElement;
4611 String loadId = 4386 String loadId =
4612 compiler.deferredLoadTask.getImportDeferName(node, prefixElement); 4387 compiler.deferredLoadTask.getImportDeferName(node, prefixElement);
4613 var inputs = [graph.addConstantString( 4388 var inputs = [
4614 new ast.DartString.literal(loadId), compiler)]; 4389 graph.addConstantString(new ast.DartString.literal(loadId), compiler)
4390 ];
4615 push(new HInvokeStatic(loadFunction, inputs, backend.nonNullType, 4391 push(new HInvokeStatic(loadFunction, inputs, backend.nonNullType,
4616 targetCanThrow: false) 4392 targetCanThrow: false)..sourceInformation = sourceInformation);
4617 ..sourceInformation = sourceInformation);
4618 } 4393 }
4619 4394
4620 generateSuperNoSuchMethodSend(ast.Send node, 4395 generateSuperNoSuchMethodSend(
4621 Selector selector, 4396 ast.Send node, Selector selector, List<HInstruction> arguments) {
4622 List<HInstruction> arguments) {
4623 String name = selector.name; 4397 String name = selector.name;
4624 4398
4625 ClassElement cls = currentNonClosureClass; 4399 ClassElement cls = currentNonClosureClass;
4626 MethodElement element = cls.lookupSuperMember(Identifiers.noSuchMethod_); 4400 MethodElement element = cls.lookupSuperMember(Identifiers.noSuchMethod_);
4627 if (!Selectors.noSuchMethod_.signatureApplies(element)) { 4401 if (!Selectors.noSuchMethod_.signatureApplies(element)) {
4628 element = coreClasses.objectClass.lookupMember(Identifiers.noSuchMethod_); 4402 element = coreClasses.objectClass.lookupMember(Identifiers.noSuchMethod_);
4629 } 4403 }
4630 if (compiler.enabledInvokeOn && !element.enclosingClass.isObject) { 4404 if (compiler.enabledInvokeOn && !element.enclosingClass.isObject) {
4631 // Register the call as dynamic if [noSuchMethod] on the super 4405 // Register the call as dynamic if [noSuchMethod] on the super
4632 // class is _not_ the default implementation from [Object], in 4406 // class is _not_ the default implementation from [Object], in
4633 // case the [noSuchMethod] implementation calls 4407 // case the [noSuchMethod] implementation calls
4634 // [JSInvocationMirror._invokeOn]. 4408 // [JSInvocationMirror._invokeOn].
4635 // TODO(johnniwinther): Register this more precisely. 4409 // TODO(johnniwinther): Register this more precisely.
4636 registry?.registerDynamicUse(new DynamicUse(selector, null)); 4410 registry?.registerDynamicUse(new DynamicUse(selector, null));
4637 } 4411 }
4638 String publicName = name; 4412 String publicName = name;
4639 if (selector.isSetter) publicName += '='; 4413 if (selector.isSetter) publicName += '=';
4640 4414
4641 ConstantValue nameConstant = constantSystem.createString( 4415 ConstantValue nameConstant =
4642 new ast.DartString.literal(publicName)); 4416 constantSystem.createString(new ast.DartString.literal(publicName));
4643 4417
4644 js.Name internalName = backend.namer.invocationName(selector); 4418 js.Name internalName = backend.namer.invocationName(selector);
4645 4419
4646 Element createInvocationMirror = helpers.createInvocationMirror; 4420 Element createInvocationMirror = helpers.createInvocationMirror;
4647 var argumentsInstruction = buildLiteralList(arguments); 4421 var argumentsInstruction = buildLiteralList(arguments);
4648 add(argumentsInstruction); 4422 add(argumentsInstruction);
4649 4423
4650 var argumentNames = new List<HInstruction>(); 4424 var argumentNames = new List<HInstruction>();
4651 for (String argumentName in selector.namedArguments) { 4425 for (String argumentName in selector.namedArguments) {
4652 ConstantValue argumentNameConstant = 4426 ConstantValue argumentNameConstant =
4653 constantSystem.createString(new ast.DartString.literal(argumentName)); 4427 constantSystem.createString(new ast.DartString.literal(argumentName));
4654 argumentNames.add(graph.addConstant(argumentNameConstant, compiler)); 4428 argumentNames.add(graph.addConstant(argumentNameConstant, compiler));
4655 } 4429 }
4656 var argumentNamesInstruction = buildLiteralList(argumentNames); 4430 var argumentNamesInstruction = buildLiteralList(argumentNames);
4657 add(argumentNamesInstruction); 4431 add(argumentNamesInstruction);
4658 4432
4659 ConstantValue kindConstant = 4433 ConstantValue kindConstant =
4660 constantSystem.createInt(selector.invocationMirrorKind); 4434 constantSystem.createInt(selector.invocationMirrorKind);
4661 4435
4662 pushInvokeStatic(null, 4436 pushInvokeStatic(
4663 createInvocationMirror, 4437 null,
4664 [graph.addConstant(nameConstant, compiler), 4438 createInvocationMirror,
4665 graph.addConstantStringFromName(internalName, compiler), 4439 [
4666 graph.addConstant(kindConstant, compiler), 4440 graph.addConstant(nameConstant, compiler),
4667 argumentsInstruction, 4441 graph.addConstantStringFromName(internalName, compiler),
4668 argumentNamesInstruction], 4442 graph.addConstant(kindConstant, compiler),
4669 typeMask: backend.dynamicType); 4443 argumentsInstruction,
4444 argumentNamesInstruction
4445 ],
4446 typeMask: backend.dynamicType);
4670 4447
4671 var inputs = <HInstruction>[pop()]; 4448 var inputs = <HInstruction>[pop()];
4672 push(buildInvokeSuper(Selectors.noSuchMethod_, element, inputs)); 4449 push(buildInvokeSuper(Selectors.noSuchMethod_, element, inputs));
4673 } 4450 }
4674 4451
4675 /// Generate a call to a super method or constructor. 4452 /// Generate a call to a super method or constructor.
4676 void generateSuperInvoke(ast.Send node, 4453 void generateSuperInvoke(ast.Send node, FunctionElement function,
4677 FunctionElement function, 4454 SourceInformation sourceInformation) {
4678 SourceInformation sourceInformation) {
4679 // TODO(5347): Try to avoid the need for calling [implementation] before 4455 // TODO(5347): Try to avoid the need for calling [implementation] before
4680 // calling [makeStaticArgumentList]. 4456 // calling [makeStaticArgumentList].
4681 Selector selector = elements.getSelector(node); 4457 Selector selector = elements.getSelector(node);
4682 assert(invariant(node, 4458 assert(invariant(
4683 selector.applies(function.implementation, compiler.world), 4459 node, selector.applies(function.implementation, compiler.world),
4684 message: "$selector does not apply to ${function.implementation}")); 4460 message: "$selector does not apply to ${function.implementation}"));
4685 List<HInstruction> inputs = 4461 List<HInstruction> inputs = makeStaticArgumentList(
4686 makeStaticArgumentList(selector.callStructure, 4462 selector.callStructure, node.arguments, function.implementation);
4687 node.arguments,
4688 function.implementation);
4689 push(buildInvokeSuper(selector, function, inputs, sourceInformation)); 4463 push(buildInvokeSuper(selector, function, inputs, sourceInformation));
4690 } 4464 }
4691 4465
4692 /// Access the value from the super [element]. 4466 /// Access the value from the super [element].
4693 void handleSuperGet(ast.Send node, Element element) { 4467 void handleSuperGet(ast.Send node, Element element) {
4694 Selector selector = elements.getSelector(node); 4468 Selector selector = elements.getSelector(node);
4695 SourceInformation sourceInformation = 4469 SourceInformation sourceInformation =
4696 sourceInformationBuilder.buildGet(node); 4470 sourceInformationBuilder.buildGet(node);
4697 push(buildInvokeSuper( 4471 push(buildInvokeSuper(
4698 selector, element, const <HInstruction>[], sourceInformation)); 4472 selector, element, const <HInstruction>[], sourceInformation));
4699 } 4473 }
4700 4474
4701 /// Invoke .call on the value retrieved from the super [element]. 4475 /// Invoke .call on the value retrieved from the super [element].
4702 void handleSuperCallInvoke(ast.Send node, Element element) { 4476 void handleSuperCallInvoke(ast.Send node, Element element) {
4703 Selector selector = elements.getSelector(node); 4477 Selector selector = elements.getSelector(node);
4704 HInstruction target = buildInvokeSuper( 4478 HInstruction target = buildInvokeSuper(selector, element,
4705 selector, element, const <HInstruction>[], 4479 const <HInstruction>[], sourceInformationBuilder.buildGet(node));
4706 sourceInformationBuilder.buildGet(node));
4707 add(target); 4480 add(target);
4708 generateCallInvoke( 4481 generateCallInvoke(node, target,
4709 node,
4710 target,
4711 sourceInformationBuilder.buildCall(node, node.argumentsNode)); 4482 sourceInformationBuilder.buildCall(node, node.argumentsNode));
4712 } 4483 }
4713 4484
4714 /// Invoke super [method]. 4485 /// Invoke super [method].
4715 void handleSuperMethodInvoke( 4486 void handleSuperMethodInvoke(ast.Send node, MethodElement method) {
4716 ast.Send node, 4487 generateSuperInvoke(
4717 MethodElement method) { 4488 node, method, sourceInformationBuilder.buildCall(node, node.selector));
4718 generateSuperInvoke(node, method,
4719 sourceInformationBuilder.buildCall(node, node.selector));
4720 } 4489 }
4721 4490
4722 /// Access an unresolved super property. 4491 /// Access an unresolved super property.
4723 void handleUnresolvedSuperInvoke(ast.Send node) { 4492 void handleUnresolvedSuperInvoke(ast.Send node) {
4724 Selector selector = elements.getSelector(node); 4493 Selector selector = elements.getSelector(node);
4725 List<HInstruction> arguments = <HInstruction>[]; 4494 List<HInstruction> arguments = <HInstruction>[];
4726 if (!node.isPropertyAccess) { 4495 if (!node.isPropertyAccess) {
4727 addGenericSendArgumentsToList(node.arguments, arguments); 4496 addGenericSendArgumentsToList(node.arguments, arguments);
4728 } 4497 }
4729 generateSuperNoSuchMethodSend(node, selector, arguments); 4498 generateSuperNoSuchMethodSend(node, selector, arguments);
4730 } 4499 }
4731 4500
4732 @override 4501 @override
4733 void visitUnresolvedSuperIndex( 4502 void visitUnresolvedSuperIndex(
4734 ast.Send node, 4503 ast.Send node, Element element, ast.Node index, _) {
4735 Element element,
4736 ast.Node index,
4737 _) {
4738 handleUnresolvedSuperInvoke(node); 4504 handleUnresolvedSuperInvoke(node);
4739 } 4505 }
4740 4506
4741 @override 4507 @override
4742 void visitUnresolvedSuperUnary( 4508 void visitUnresolvedSuperUnary(
4743 ast.Send node, 4509 ast.Send node, UnaryOperator operator, Element element, _) {
4744 UnaryOperator operator,
4745 Element element,
4746 _) {
4747 handleUnresolvedSuperInvoke(node); 4510 handleUnresolvedSuperInvoke(node);
4748 } 4511 }
4749 4512
4750 @override 4513 @override
4751 void visitUnresolvedSuperBinary( 4514 void visitUnresolvedSuperBinary(ast.Send node, Element element,
4752 ast.Send node, 4515 BinaryOperator operator, ast.Node argument, _) {
4753 Element element,
4754 BinaryOperator operator,
4755 ast.Node argument,
4756 _) {
4757 handleUnresolvedSuperInvoke(node); 4516 handleUnresolvedSuperInvoke(node);
4758 } 4517 }
4759 4518
4760 @override 4519 @override
4761 void visitUnresolvedSuperGet( 4520 void visitUnresolvedSuperGet(ast.Send node, Element element, _) {
4762 ast.Send node,
4763 Element element,
4764 _) {
4765 handleUnresolvedSuperInvoke(node); 4521 handleUnresolvedSuperInvoke(node);
4766 } 4522 }
4767 4523
4768 @override 4524 @override
4769 void visitUnresolvedSuperSet( 4525 void visitUnresolvedSuperSet(
4770 ast.Send node, 4526 ast.Send node, Element element, ast.Node rhs, _) {
4771 Element element,
4772 ast.Node rhs,
4773 _) {
4774 handleSuperSendSet(node); 4527 handleSuperSendSet(node);
4775 } 4528 }
4776 4529
4777 @override 4530 @override
4778 void visitSuperSetterGet( 4531 void visitSuperSetterGet(ast.Send node, MethodElement setter, _) {
4779 ast.Send node,
4780 MethodElement setter,
4781 _) {
4782 handleUnresolvedSuperInvoke(node); 4532 handleUnresolvedSuperInvoke(node);
4783 } 4533 }
4784 4534
4785 @override 4535 @override
4786 void visitUnresolvedSuperInvoke( 4536 void visitUnresolvedSuperInvoke(
4787 ast.Send node, 4537 ast.Send node, Element element, ast.Node argument, Selector selector, _) {
4788 Element element,
4789 ast.Node argument,
4790 Selector selector,
4791 _) {
4792 handleUnresolvedSuperInvoke(node); 4538 handleUnresolvedSuperInvoke(node);
4793 } 4539 }
4794 4540
4795 @override 4541 @override
4796 void visitSuperFieldGet( 4542 void visitSuperFieldGet(ast.Send node, FieldElement field, _) {
4797 ast.Send node,
4798 FieldElement field,
4799 _) {
4800 handleSuperGet(node, field); 4543 handleSuperGet(node, field);
4801 } 4544 }
4802 4545
4803 @override 4546 @override
4804 void visitSuperGetterGet( 4547 void visitSuperGetterGet(ast.Send node, MethodElement method, _) {
4805 ast.Send node,
4806 MethodElement method,
4807 _) {
4808 handleSuperGet(node, method); 4548 handleSuperGet(node, method);
4809 } 4549 }
4810 4550
4811 @override 4551 @override
4812 void visitSuperMethodGet( 4552 void visitSuperMethodGet(ast.Send node, MethodElement method, _) {
4813 ast.Send node,
4814 MethodElement method,
4815 _) {
4816 handleSuperGet(node, method); 4553 handleSuperGet(node, method);
4817 } 4554 }
4818 4555
4819 @override 4556 @override
4820 void visitSuperFieldInvoke( 4557 void visitSuperFieldInvoke(ast.Send node, FieldElement field,
4821 ast.Send node, 4558 ast.NodeList arguments, CallStructure callStructure, _) {
4822 FieldElement field,
4823 ast.NodeList arguments,
4824 CallStructure callStructure,
4825 _) {
4826 handleSuperCallInvoke(node, field); 4559 handleSuperCallInvoke(node, field);
4827 } 4560 }
4828 4561
4829 @override 4562 @override
4830 void visitSuperGetterInvoke( 4563 void visitSuperGetterInvoke(ast.Send node, MethodElement getter,
4831 ast.Send node, 4564 ast.NodeList arguments, CallStructure callStructure, _) {
4832 MethodElement getter,
4833 ast.NodeList arguments,
4834 CallStructure callStructure,
4835 _) {
4836 handleSuperCallInvoke(node, getter); 4565 handleSuperCallInvoke(node, getter);
4837 } 4566 }
4838 4567
4839 @override 4568 @override
4840 void visitSuperMethodInvoke( 4569 void visitSuperMethodInvoke(ast.Send node, MethodElement method,
4841 ast.Send node, 4570 ast.NodeList arguments, CallStructure callStructure, _) {
4842 MethodElement method,
4843 ast.NodeList arguments,
4844 CallStructure callStructure,
4845 _) {
4846 handleSuperMethodInvoke(node, method); 4571 handleSuperMethodInvoke(node, method);
4847 } 4572 }
4848 4573
4849 @override 4574 @override
4850 void visitSuperIndex( 4575 void visitSuperIndex(ast.Send node, MethodElement method, ast.Node index, _) {
4851 ast.Send node,
4852 MethodElement method,
4853 ast.Node index,
4854 _) {
4855 handleSuperMethodInvoke(node, method); 4576 handleSuperMethodInvoke(node, method);
4856 } 4577 }
4857 4578
4858 @override 4579 @override
4859 void visitSuperEquals( 4580 void visitSuperEquals(
4860 ast.Send node, 4581 ast.Send node, MethodElement method, ast.Node argument, _) {
4861 MethodElement method,
4862 ast.Node argument,
4863 _) {
4864 handleSuperMethodInvoke(node, method); 4582 handleSuperMethodInvoke(node, method);
4865 } 4583 }
4866 4584
4867 @override 4585 @override
4868 void visitSuperBinary( 4586 void visitSuperBinary(ast.Send node, MethodElement method,
4869 ast.Send node, 4587 BinaryOperator operator, ast.Node argument, _) {
4870 MethodElement method,
4871 BinaryOperator operator,
4872 ast.Node argument,
4873 _) {
4874 handleSuperMethodInvoke(node, method); 4588 handleSuperMethodInvoke(node, method);
4875 } 4589 }
4876 4590
4877 @override 4591 @override
4878 void visitSuperNotEquals( 4592 void visitSuperNotEquals(
4879 ast.Send node, 4593 ast.Send node, MethodElement method, ast.Node argument, _) {
4880 MethodElement method,
4881 ast.Node argument,
4882 _) {
4883 handleSuperMethodInvoke(node, method); 4594 handleSuperMethodInvoke(node, method);
4884 pushWithPosition(new HNot(popBoolified(), backend.boolType), node.selector); 4595 pushWithPosition(new HNot(popBoolified(), backend.boolType), node.selector);
4885 } 4596 }
4886 4597
4887 @override 4598 @override
4888 void visitSuperUnary( 4599 void visitSuperUnary(
4889 ast.Send node, 4600 ast.Send node, UnaryOperator operator, MethodElement method, _) {
4890 UnaryOperator operator,
4891 MethodElement method,
4892 _) {
4893 handleSuperMethodInvoke(node, method); 4601 handleSuperMethodInvoke(node, method);
4894 } 4602 }
4895 4603
4896 @override 4604 @override
4897 void visitSuperMethodIncompatibleInvoke( 4605 void visitSuperMethodIncompatibleInvoke(ast.Send node, MethodElement method,
4898 ast.Send node, 4606 ast.NodeList arguments, CallStructure callStructure, _) {
4899 MethodElement method,
4900 ast.NodeList arguments,
4901 CallStructure callStructure,
4902 _) {
4903 handleInvalidSuperInvoke(node, arguments); 4607 handleInvalidSuperInvoke(node, arguments);
4904 } 4608 }
4905 4609
4906 @override 4610 @override
4907 void visitSuperSetterInvoke( 4611 void visitSuperSetterInvoke(ast.Send node, SetterElement setter,
4908 ast.Send node, 4612 ast.NodeList arguments, CallStructure callStructure, _) {
4909 SetterElement setter,
4910 ast.NodeList arguments,
4911 CallStructure callStructure,
4912 _) {
4913 handleInvalidSuperInvoke(node, arguments); 4613 handleInvalidSuperInvoke(node, arguments);
4914 } 4614 }
4915 4615
4916 void handleInvalidSuperInvoke(ast.Send node, ast.NodeList arguments) { 4616 void handleInvalidSuperInvoke(ast.Send node, ast.NodeList arguments) {
4917 Selector selector = elements.getSelector(node); 4617 Selector selector = elements.getSelector(node);
4918 List<HInstruction> inputs = <HInstruction>[]; 4618 List<HInstruction> inputs = <HInstruction>[];
4919 addGenericSendArgumentsToList(arguments.nodes, inputs); 4619 addGenericSendArgumentsToList(arguments.nodes, inputs);
4920 generateSuperNoSuchMethodSend(node, selector, inputs); 4620 generateSuperNoSuchMethodSend(node, selector, inputs);
4921 } 4621 }
4922 4622
4923 bool needsSubstitutionForTypeVariableAccess(ClassElement cls) { 4623 bool needsSubstitutionForTypeVariableAccess(ClassElement cls) {
4924 ClassWorld classWorld = compiler.world; 4624 ClassWorld classWorld = compiler.world;
4925 if (classWorld.isUsedAsMixin(cls)) return true; 4625 if (classWorld.isUsedAsMixin(cls)) return true;
4926 4626
4927 return compiler.world.anyStrictSubclassOf(cls, (ClassElement subclass) { 4627 return compiler.world.anyStrictSubclassOf(cls, (ClassElement subclass) {
4928 return !rti.isTrivialSubstitution(subclass, cls); 4628 return !rti.isTrivialSubstitution(subclass, cls);
4929 }); 4629 });
4930 } 4630 }
4931 4631
4932 /** 4632 /**
4933 * Generate code to extract the type arguments from the object, substitute 4633 * Generate code to extract the type arguments from the object, substitute
4934 * them as an instance of the type we are testing against (if necessary), and 4634 * them as an instance of the type we are testing against (if necessary), and
4935 * extract the type argument by the index of the variable in the list of type 4635 * extract the type argument by the index of the variable in the list of type
4936 * variables for that class. 4636 * variables for that class.
4937 */ 4637 */
4938 HInstruction readTypeVariable( 4638 HInstruction readTypeVariable(ClassElement cls, TypeVariableElement variable,
4939 ClassElement cls,
4940 TypeVariableElement variable,
4941 {SourceInformation sourceInformation}) { 4639 {SourceInformation sourceInformation}) {
4942 assert(sourceElement.isInstanceMember); 4640 assert(sourceElement.isInstanceMember);
4943 4641
4944 HInstruction target = localsHandler.readThis(); 4642 HInstruction target = localsHandler.readThis();
4945 HConstant index = graph.addConstantInt(variable.index, compiler); 4643 HConstant index = graph.addConstantInt(variable.index, compiler);
4946 4644
4947 if (needsSubstitutionForTypeVariableAccess(cls)) { 4645 if (needsSubstitutionForTypeVariableAccess(cls)) {
4948 // TODO(ahe): Creating a string here is unfortunate. It is slow (due to 4646 // TODO(ahe): Creating a string here is unfortunate. It is slow (due to
4949 // string concatenation in the implementation), and may prevent 4647 // string concatenation in the implementation), and may prevent
4950 // segmentation of '$'. 4648 // segmentation of '$'.
4951 js.Name substitutionName = backend.namer.runtimeTypeName(cls); 4649 js.Name substitutionName = backend.namer.runtimeTypeName(cls);
4952 HInstruction substitutionNameInstr = graph.addConstantStringFromName( 4650 HInstruction substitutionNameInstr =
4953 substitutionName, compiler); 4651 graph.addConstantStringFromName(substitutionName, compiler);
4954 pushInvokeStatic(null, 4652 pushInvokeStatic(null, helpers.getRuntimeTypeArgument,
4955 helpers.getRuntimeTypeArgument, 4653 [target, substitutionNameInstr, index],
4956 [target, substitutionNameInstr, index], 4654 typeMask: backend.dynamicType, sourceInformation: sourceInformation);
4957 typeMask: backend.dynamicType,
4958 sourceInformation: sourceInformation);
4959 } else { 4655 } else {
4960 pushInvokeStatic( 4656 pushInvokeStatic(null, helpers.getTypeArgumentByIndex, [target, index],
4961 null, 4657 typeMask: backend.dynamicType, sourceInformation: sourceInformation);
4962 helpers.getTypeArgumentByIndex,
4963 [target, index],
4964 typeMask: backend.dynamicType,
4965 sourceInformation: sourceInformation);
4966 } 4658 }
4967 return pop(); 4659 return pop();
4968 } 4660 }
4969 4661
4970 // TODO(karlklose): this is needed to avoid a bug where the resolved type is 4662 // TODO(karlklose): this is needed to avoid a bug where the resolved type is
4971 // not stored on a type annotation in the closure translator. Remove when 4663 // not stored on a type annotation in the closure translator. Remove when
4972 // fixed. 4664 // fixed.
4973 bool hasDirectLocal(Local local) { 4665 bool hasDirectLocal(Local local) {
4974 return !localsHandler.isAccessedDirectly(local) || 4666 return !localsHandler.isAccessedDirectly(local) ||
4975 localsHandler.directLocals[local] != null; 4667 localsHandler.directLocals[local] != null;
4976 } 4668 }
4977 4669
4978 /** 4670 /**
4979 * Helper to create an instruction that gets the value of a type variable. 4671 * Helper to create an instruction that gets the value of a type variable.
4980 */ 4672 */
4981 HInstruction addTypeVariableReference( 4673 HInstruction addTypeVariableReference(TypeVariableType type,
4982 TypeVariableType type,
4983 {SourceInformation sourceInformation}) { 4674 {SourceInformation sourceInformation}) {
4984
4985 assert(assertTypeInContext(type)); 4675 assert(assertTypeInContext(type));
4986 Element member = sourceElement; 4676 Element member = sourceElement;
4987 bool isClosure = member.enclosingElement.isClosure; 4677 bool isClosure = member.enclosingElement.isClosure;
4988 if (isClosure) { 4678 if (isClosure) {
4989 ClosureClassElement closureClass = member.enclosingElement; 4679 ClosureClassElement closureClass = member.enclosingElement;
4990 member = closureClass.methodElement; 4680 member = closureClass.methodElement;
4991 member = member.outermostEnclosingMemberOrTopLevel; 4681 member = member.outermostEnclosingMemberOrTopLevel;
4992 } 4682 }
4993 bool isInConstructorContext = member.isConstructor || 4683 bool isInConstructorContext =
4994 member.isGenerativeConstructorBody; 4684 member.isConstructor || member.isGenerativeConstructorBody;
4995 Local typeVariableLocal = localsHandler.getTypeVariableAsLocal(type); 4685 Local typeVariableLocal = localsHandler.getTypeVariableAsLocal(type);
4996 if (isClosure) { 4686 if (isClosure) {
4997 if (member.isFactoryConstructor || 4687 if (member.isFactoryConstructor ||
4998 (isInConstructorContext && hasDirectLocal(typeVariableLocal))) { 4688 (isInConstructorContext && hasDirectLocal(typeVariableLocal))) {
4999 // The type variable is used from a closure in a factory constructor. 4689 // The type variable is used from a closure in a factory constructor.
5000 // The value of the type argument is stored as a local on the closure 4690 // The value of the type argument is stored as a local on the closure
5001 // itself. 4691 // itself.
5002 return localsHandler.readLocal( 4692 return localsHandler.readLocal(typeVariableLocal,
5003 typeVariableLocal, sourceInformation: sourceInformation); 4693 sourceInformation: sourceInformation);
5004 } else if (member.isFunction || 4694 } else if (member.isFunction ||
5005 member.isGetter || 4695 member.isGetter ||
5006 member.isSetter || 4696 member.isSetter ||
5007 isInConstructorContext) { 4697 isInConstructorContext) {
5008 // The type variable is stored on the "enclosing object" and needs to be 4698 // The type variable is stored on the "enclosing object" and needs to be
5009 // accessed using the this-reference in the closure. 4699 // accessed using the this-reference in the closure.
5010 return readTypeVariable( 4700 return readTypeVariable(member.enclosingClass, type.element,
5011 member.enclosingClass,
5012 type.element,
5013 sourceInformation: sourceInformation); 4701 sourceInformation: sourceInformation);
5014 } else { 4702 } else {
5015 assert(member.isField); 4703 assert(member.isField);
5016 // The type variable is stored in a parameter of the method. 4704 // The type variable is stored in a parameter of the method.
5017 return localsHandler.readLocal(typeVariableLocal); 4705 return localsHandler.readLocal(typeVariableLocal);
5018 } 4706 }
5019 } else if (isInConstructorContext || 4707 } else if (isInConstructorContext ||
5020 // When [member] is a field, we can be either 4708 // When [member] is a field, we can be either
5021 // generating a checked setter or inlining its 4709 // generating a checked setter or inlining its
5022 // initializer in a constructor. An initializer is 4710 // initializer in a constructor. An initializer is
5023 // never built standalone, so in that case [target] is not 4711 // never built standalone, so in that case [target] is not
5024 // the [member] itself. 4712 // the [member] itself.
5025 (member.isField && member != target)) { 4713 (member.isField && member != target)) {
5026 // The type variable is stored in a parameter of the method. 4714 // The type variable is stored in a parameter of the method.
5027 return localsHandler.readLocal( 4715 return localsHandler.readLocal(typeVariableLocal,
5028 typeVariableLocal, sourceInformation: sourceInformation); 4716 sourceInformation: sourceInformation);
5029 } else if (member.isInstanceMember) { 4717 } else if (member.isInstanceMember) {
5030 // The type variable is stored on the object. 4718 // The type variable is stored on the object.
5031 return readTypeVariable( 4719 return readTypeVariable(member.enclosingClass, type.element,
5032 member.enclosingClass,
5033 type.element,
5034 sourceInformation: sourceInformation); 4720 sourceInformation: sourceInformation);
5035 } else { 4721 } else {
5036 reporter.internalError(type.element, 4722 reporter.internalError(
5037 'Unexpected type variable in static context.'); 4723 type.element, 'Unexpected type variable in static context.');
5038 return null; 4724 return null;
5039 } 4725 }
5040 } 4726 }
5041 4727
5042 HInstruction analyzeTypeArgument( 4728 HInstruction analyzeTypeArgument(DartType argument,
5043 DartType argument,
5044 {SourceInformation sourceInformation}) { 4729 {SourceInformation sourceInformation}) {
5045
5046 assert(assertTypeInContext(argument)); 4730 assert(assertTypeInContext(argument));
5047 if (argument.treatAsDynamic) { 4731 if (argument.treatAsDynamic) {
5048 // Represent [dynamic] as [null]. 4732 // Represent [dynamic] as [null].
5049 return graph.addConstantNull(compiler); 4733 return graph.addConstantNull(compiler);
5050 } 4734 }
5051 4735
5052 if (argument.isTypeVariable) { 4736 if (argument.isTypeVariable) {
5053 return addTypeVariableReference( 4737 return addTypeVariableReference(argument,
5054 argument, sourceInformation: sourceInformation); 4738 sourceInformation: sourceInformation);
5055 } 4739 }
5056 4740
5057 List<HInstruction> inputs = <HInstruction>[]; 4741 List<HInstruction> inputs = <HInstruction>[];
5058 4742
5059 js.Expression template = 4743 js.Expression template =
5060 rtiEncoder.getTypeRepresentationWithPlaceholders(argument, (variable) { 4744 rtiEncoder.getTypeRepresentationWithPlaceholders(argument, (variable) {
5061 inputs.add(addTypeVariableReference(variable)); 4745 inputs.add(addTypeVariableReference(variable));
5062 }); 4746 });
5063 4747
5064 js.Template code = new js.Template(null, template); 4748 js.Template code = new js.Template(null, template);
5065 HInstruction result = new HForeignCode(code, backend.stringType, inputs, 4749 HInstruction result = new HForeignCode(code, backend.stringType, inputs,
5066 nativeBehavior: native.NativeBehavior.PURE); 4750 nativeBehavior: native.NativeBehavior.PURE);
5067 add(result); 4751 add(result);
5068 return result; 4752 return result;
5069 } 4753 }
5070 4754
5071 HInstruction handleListConstructor(InterfaceType type, 4755 HInstruction handleListConstructor(
5072 ast.Node currentNode, 4756 InterfaceType type, ast.Node currentNode, HInstruction newObject) {
5073 HInstruction newObject) {
5074 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) { 4757 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) {
5075 return newObject; 4758 return newObject;
5076 } 4759 }
5077 List<HInstruction> inputs = <HInstruction>[]; 4760 List<HInstruction> inputs = <HInstruction>[];
5078 type = localsHandler.substInContext(type); 4761 type = localsHandler.substInContext(type);
5079 type.typeArguments.forEach((DartType argument) { 4762 type.typeArguments.forEach((DartType argument) {
5080 inputs.add(analyzeTypeArgument(argument)); 4763 inputs.add(analyzeTypeArgument(argument));
5081 }); 4764 });
5082 // TODO(15489): Register at codegen. 4765 // TODO(15489): Register at codegen.
5083 registry?.registerInstantiation(type); 4766 registry?.registerInstantiation(type);
5084 return callSetRuntimeTypeInfo(type.element, inputs, newObject); 4767 return callSetRuntimeTypeInfo(type.element, inputs, newObject);
5085 } 4768 }
5086 4769
5087 void copyRuntimeTypeInfo(HInstruction source, HInstruction target) { 4770 void copyRuntimeTypeInfo(HInstruction source, HInstruction target) {
5088 Element copyHelper = helpers.copyTypeArguments; 4771 Element copyHelper = helpers.copyTypeArguments;
5089 pushInvokeStatic(null, copyHelper, [source, target], 4772 pushInvokeStatic(null, copyHelper, [source, target],
5090 sourceInformation: target.sourceInformation); 4773 sourceInformation: target.sourceInformation);
5091 pop(); 4774 pop();
5092 } 4775 }
5093 4776
5094 HInstruction callSetRuntimeTypeInfo(ClassElement element, 4777 HInstruction callSetRuntimeTypeInfo(ClassElement element,
5095 List<HInstruction> rtiInputs, 4778 List<HInstruction> rtiInputs, HInstruction newObject) {
5096 HInstruction newObject) {
5097 if (!backend.classNeedsRti(element) || element.typeVariables.isEmpty) { 4779 if (!backend.classNeedsRti(element) || element.typeVariables.isEmpty) {
5098 return newObject; 4780 return newObject;
5099 } 4781 }
5100 4782
5101 HInstruction typeInfo = buildLiteralList(rtiInputs); 4783 HInstruction typeInfo = buildLiteralList(rtiInputs);
5102 add(typeInfo); 4784 add(typeInfo);
5103 4785
5104 // Set the runtime type information on the object. 4786 // Set the runtime type information on the object.
5105 Element typeInfoSetterElement = helpers.setRuntimeTypeInfo; 4787 Element typeInfoSetterElement = helpers.setRuntimeTypeInfo;
5106 pushInvokeStatic( 4788 pushInvokeStatic(
5107 null, 4789 null, typeInfoSetterElement, <HInstruction>[newObject, typeInfo],
5108 typeInfoSetterElement,
5109 <HInstruction>[newObject, typeInfo],
5110 typeMask: backend.dynamicType, 4790 typeMask: backend.dynamicType,
5111 sourceInformation: newObject.sourceInformation); 4791 sourceInformation: newObject.sourceInformation);
5112 4792
5113 // The new object will now be referenced through the 4793 // The new object will now be referenced through the
5114 // `setRuntimeTypeInfo` call. We therefore set the type of that 4794 // `setRuntimeTypeInfo` call. We therefore set the type of that
5115 // instruction to be of the object's type. 4795 // instruction to be of the object's type.
5116 assert(invariant( 4796 assert(invariant(CURRENT_ELEMENT_SPANNABLE,
5117 CURRENT_ELEMENT_SPANNABLE,
5118 stack.last is HInvokeStatic || stack.last == newObject, 4797 stack.last is HInvokeStatic || stack.last == newObject,
5119 message: 4798 message: "Unexpected `stack.last`: Found ${stack.last}, "
5120 "Unexpected `stack.last`: Found ${stack.last}, " 4799 "expected ${newObject} or an HInvokeStatic. "
5121 "expected ${newObject} or an HInvokeStatic. " 4800 "State: element=$element, rtiInputs=$rtiInputs, stack=$stack."));
5122 "State: element=$element, rtiInputs=$rtiInputs, stack=$stack."));
5123 stack.last.instructionType = newObject.instructionType; 4801 stack.last.instructionType = newObject.instructionType;
5124 return pop(); 4802 return pop();
5125 } 4803 }
5126 4804
5127 void handleNewSend(ast.NewExpression node) { 4805 void handleNewSend(ast.NewExpression node) {
5128 ast.Send send = node.send; 4806 ast.Send send = node.send;
5129 generateIsDeferredLoadedCheckOfSend(send); 4807 generateIsDeferredLoadedCheckOfSend(send);
5130 4808
5131 bool isFixedList = false; 4809 bool isFixedList = false;
5132 bool isFixedListConstructorCall = 4810 bool isFixedListConstructorCall =
5133 Elements.isFixedListConstructorCall(elements[send], send, compiler); 4811 Elements.isFixedListConstructorCall(elements[send], send, compiler);
5134 bool isGrowableListConstructorCall = 4812 bool isGrowableListConstructorCall =
5135 Elements.isGrowableListConstructorCall(elements[send], send, compiler); 4813 Elements.isGrowableListConstructorCall(elements[send], send, compiler);
5136 4814
5137 TypeMask computeType(element) { 4815 TypeMask computeType(element) {
5138 Element originalElement = elements[send]; 4816 Element originalElement = elements[send];
5139 if (isFixedListConstructorCall 4817 if (isFixedListConstructorCall ||
5140 || Elements.isFilledListConstructorCall( 4818 Elements.isFilledListConstructorCall(
5141 originalElement, send, compiler)) { 4819 originalElement, send, compiler)) {
5142 isFixedList = true; 4820 isFixedList = true;
5143 TypeMask inferred = 4821 TypeMask inferred =
5144 TypeMaskFactory.inferredForNode(sourceElement, send, compiler); 4822 TypeMaskFactory.inferredForNode(sourceElement, send, compiler);
5145 return inferred.containsAll(compiler.world) 4823 return inferred.containsAll(compiler.world)
5146 ? backend.fixedArrayType 4824 ? backend.fixedArrayType
5147 : inferred; 4825 : inferred;
5148 } else if (isGrowableListConstructorCall) { 4826 } else if (isGrowableListConstructorCall) {
5149 TypeMask inferred = 4827 TypeMask inferred =
5150 TypeMaskFactory.inferredForNode(sourceElement, send, compiler); 4828 TypeMaskFactory.inferredForNode(sourceElement, send, compiler);
5151 return inferred.containsAll(compiler.world) 4829 return inferred.containsAll(compiler.world)
5152 ? backend.extendableArrayType 4830 ? backend.extendableArrayType
5153 : inferred; 4831 : inferred;
5154 } else if (Elements.isConstructorOfTypedArraySubclass( 4832 } else if (Elements.isConstructorOfTypedArraySubclass(
5155 originalElement, compiler)) { 4833 originalElement, compiler)) {
5156 isFixedList = true; 4834 isFixedList = true;
5157 TypeMask inferred = 4835 TypeMask inferred =
5158 TypeMaskFactory.inferredForNode(sourceElement, send, compiler); 4836 TypeMaskFactory.inferredForNode(sourceElement, send, compiler);
5159 ClassElement cls = element.enclosingClass; 4837 ClassElement cls = element.enclosingClass;
5160 assert(backend.isNative(cls.thisType.element)); 4838 assert(backend.isNative(cls.thisType.element));
5161 return inferred.containsAll(compiler.world) 4839 return inferred.containsAll(compiler.world)
5162 ? new TypeMask.nonNullExact(cls.thisType.element, compiler.world) 4840 ? new TypeMask.nonNullExact(cls.thisType.element, compiler.world)
5163 : inferred; 4841 : inferred;
5164 } else if (element.isGenerativeConstructor) { 4842 } else if (element.isGenerativeConstructor) {
5165 ClassElement cls = element.enclosingClass; 4843 ClassElement cls = element.enclosingClass;
(...skipping 17 matching lines...) Expand all
5183 constructor = constructorImplementation.effectiveTarget; 4861 constructor = constructorImplementation.effectiveTarget;
5184 4862
5185 final bool isSymbolConstructor = 4863 final bool isSymbolConstructor =
5186 constructorDeclaration == compiler.symbolConstructor; 4864 constructorDeclaration == compiler.symbolConstructor;
5187 final bool isJSArrayTypedConstructor = 4865 final bool isJSArrayTypedConstructor =
5188 constructorDeclaration == helpers.jsArrayTypedConstructor; 4866 constructorDeclaration == helpers.jsArrayTypedConstructor;
5189 4867
5190 if (isSymbolConstructor) { 4868 if (isSymbolConstructor) {
5191 constructor = compiler.symbolValidatedConstructor; 4869 constructor = compiler.symbolValidatedConstructor;
5192 assert(invariant(send, constructor != null, 4870 assert(invariant(send, constructor != null,
5193 message: 'Constructor Symbol.validated is missing')); 4871 message: 'Constructor Symbol.validated is missing'));
5194 callStructure = compiler.symbolValidatedConstructorSelector.callStructure; 4872 callStructure = compiler.symbolValidatedConstructorSelector.callStructure;
5195 assert(invariant(send, callStructure != null, 4873 assert(invariant(send, callStructure != null,
5196 message: 'Constructor Symbol.validated is missing')); 4874 message: 'Constructor Symbol.validated is missing'));
5197 } 4875 }
5198 4876
5199 bool isRedirected = constructorDeclaration.isRedirectingFactory; 4877 bool isRedirected = constructorDeclaration.isRedirectingFactory;
5200 if (!constructorDeclaration.isCyclicRedirection) { 4878 if (!constructorDeclaration.isCyclicRedirection) {
5201 // Insert a check for every deferred redirection on the path to the 4879 // Insert a check for every deferred redirection on the path to the
5202 // final target. 4880 // final target.
5203 ConstructorElement target = constructorDeclaration; 4881 ConstructorElement target = constructorDeclaration;
5204 while (target.isRedirectingFactory) { 4882 while (target.isRedirectingFactory) {
5205 if (constructorDeclaration.redirectionDeferredPrefix != null) { 4883 if (constructorDeclaration.redirectionDeferredPrefix != null) {
5206 generateIsDeferredLoadedCheckIfNeeded( 4884 generateIsDeferredLoadedCheckIfNeeded(
5207 target.redirectionDeferredPrefix, 4885 target.redirectionDeferredPrefix, node);
5208 node);
5209 } 4886 }
5210 target = target.immediateRedirectionTarget; 4887 target = target.immediateRedirectionTarget;
5211 } 4888 }
5212 } 4889 }
5213 InterfaceType type = elements.getType(node); 4890 InterfaceType type = elements.getType(node);
5214 InterfaceType expectedType = 4891 InterfaceType expectedType =
5215 constructorDeclaration.computeEffectiveTargetType(type); 4892 constructorDeclaration.computeEffectiveTargetType(type);
5216 expectedType = localsHandler.substInContext(expectedType); 4893 expectedType = localsHandler.substInContext(expectedType);
5217 4894
5218 if (compiler.elementHasCompileTimeError(constructor)) { 4895 if (compiler.elementHasCompileTimeError(constructor)) {
(...skipping 15 matching lines...) Expand all
5234 pop(); 4911 pop();
5235 }); 4912 });
5236 generateAbstractClassInstantiationError(send, cls.name); 4913 generateAbstractClassInstantiationError(send, cls.name);
5237 return; 4914 return;
5238 } 4915 }
5239 4916
5240 // TODO(5347): Try to avoid the need for calling [implementation] before 4917 // TODO(5347): Try to avoid the need for calling [implementation] before
5241 // calling [makeStaticArgumentList]. 4918 // calling [makeStaticArgumentList].
5242 constructorImplementation = constructor.implementation; 4919 constructorImplementation = constructor.implementation;
5243 if (constructorImplementation.isMalformed || 4920 if (constructorImplementation.isMalformed ||
5244 !callStructure.signatureApplies( 4921 !callStructure
5245 constructorImplementation.functionSignature)) { 4922 .signatureApplies(constructorImplementation.functionSignature)) {
5246 generateWrongArgumentCountError(send, constructor, send.arguments); 4923 generateWrongArgumentCountError(send, constructor, send.arguments);
5247 return; 4924 return;
5248 } 4925 }
5249 4926
5250 var inputs = <HInstruction>[]; 4927 var inputs = <HInstruction>[];
5251 if (constructor.isGenerativeConstructor && 4928 if (constructor.isGenerativeConstructor &&
5252 backend.isNativeOrExtendsNative(constructor.enclosingClass) && 4929 backend.isNativeOrExtendsNative(constructor.enclosingClass) &&
5253 !backend.isJsInterop(constructor)) { 4930 !backend.isJsInterop(constructor)) {
5254 // Native class generative constructors take a pre-constructed object. 4931 // Native class generative constructors take a pre-constructed object.
5255 inputs.add(graph.addConstantNull(compiler)); 4932 inputs.add(graph.addConstantNull(compiler));
5256 } 4933 }
5257 inputs.addAll(makeStaticArgumentList(callStructure, 4934 inputs.addAll(makeStaticArgumentList(
5258 send.arguments, 4935 callStructure, send.arguments, constructorImplementation));
5259 constructorImplementation));
5260 4936
5261 TypeMask elementType = computeType(constructor); 4937 TypeMask elementType = computeType(constructor);
5262 if (isFixedListConstructorCall) { 4938 if (isFixedListConstructorCall) {
5263 if (!inputs[0].isNumber(compiler)) { 4939 if (!inputs[0].isNumber(compiler)) {
5264 HTypeConversion conversion = new HTypeConversion( 4940 HTypeConversion conversion = new HTypeConversion(
5265 null, HTypeConversion.ARGUMENT_TYPE_CHECK, backend.numType, 4941 null,
5266 inputs[0], null); 4942 HTypeConversion.ARGUMENT_TYPE_CHECK,
4943 backend.numType,
4944 inputs[0],
4945 null);
5267 add(conversion); 4946 add(conversion);
5268 inputs[0] = conversion; 4947 inputs[0] = conversion;
5269 } 4948 }
5270 js.Template code = js.js.parseForeignJS('new Array(#)'); 4949 js.Template code = js.js.parseForeignJS('new Array(#)');
5271 var behavior = new native.NativeBehavior(); 4950 var behavior = new native.NativeBehavior();
5272 behavior.typesReturned.add(expectedType); 4951 behavior.typesReturned.add(expectedType);
5273 // The allocation can throw only if the given length is a double or 4952 // The allocation can throw only if the given length is a double or
5274 // outside the unsigned 32 bit range. 4953 // outside the unsigned 32 bit range.
5275 // TODO(sra): Array allocation should be an instruction so that canThrow 4954 // TODO(sra): Array allocation should be an instruction so that canThrow
5276 // can depend on a length type discovered in optimization. 4955 // can depend on a length type discovered in optimization.
5277 bool canThrow = true; 4956 bool canThrow = true;
5278 if (inputs[0].isInteger(compiler) && inputs[0] is HConstant) { 4957 if (inputs[0].isInteger(compiler) && inputs[0] is HConstant) {
5279 var constant = inputs[0]; 4958 var constant = inputs[0];
5280 int value = constant.constant.primitiveValue; 4959 int value = constant.constant.primitiveValue;
5281 if (0 <= value && value < 0x100000000) canThrow = false; 4960 if (0 <= value && value < 0x100000000) canThrow = false;
5282 } 4961 }
5283 HForeignCode foreign = new HForeignCode(code, elementType, inputs, 4962 HForeignCode foreign = new HForeignCode(code, elementType, inputs,
5284 nativeBehavior: behavior, 4963 nativeBehavior: behavior,
5285 throwBehavior: canThrow 4964 throwBehavior: canThrow
5286 ? native.NativeThrowBehavior.MAY 4965 ? native.NativeThrowBehavior.MAY
5287 : native.NativeThrowBehavior.NEVER); 4966 : native.NativeThrowBehavior.NEVER);
5288 push(foreign); 4967 push(foreign);
5289 TypesInferrer inferrer = compiler.typesTask.typesInferrer; 4968 TypesInferrer inferrer = compiler.typesTask.typesInferrer;
5290 if (inferrer.isFixedArrayCheckedForGrowable(send)) { 4969 if (inferrer.isFixedArrayCheckedForGrowable(send)) {
5291 js.Template code = js.js.parseForeignJS(r'#.fixed$length = Array'); 4970 js.Template code = js.js.parseForeignJS(r'#.fixed$length = Array');
5292 // We set the instruction as [canThrow] to avoid it being dead code. 4971 // We set the instruction as [canThrow] to avoid it being dead code.
5293 // We need a finer grained side effect. 4972 // We need a finer grained side effect.
5294 add(new HForeignCode(code, backend.nullType, [stack.last], 4973 add(new HForeignCode(code, backend.nullType, [stack.last],
5295 throwBehavior: native.NativeThrowBehavior.MAY)); 4974 throwBehavior: native.NativeThrowBehavior.MAY));
5296 } 4975 }
5297 } else if (isGrowableListConstructorCall) { 4976 } else if (isGrowableListConstructorCall) {
5298 push(buildLiteralList(<HInstruction>[])); 4977 push(buildLiteralList(<HInstruction>[]));
5299 stack.last.instructionType = elementType; 4978 stack.last.instructionType = elementType;
5300 } else { 4979 } else {
5301 SourceInformation sourceInformation = 4980 SourceInformation sourceInformation =
5302 sourceInformationBuilder.buildNew(send); 4981 sourceInformationBuilder.buildNew(send);
5303 potentiallyAddTypeArguments(inputs, cls, expectedType); 4982 potentiallyAddTypeArguments(inputs, cls, expectedType);
5304 addInlinedInstantiation(expectedType); 4983 addInlinedInstantiation(expectedType);
5305 pushInvokeStatic(node, constructor, inputs, 4984 pushInvokeStatic(node, constructor, inputs,
(...skipping 10 matching lines...) Expand all
5316 if (context != null) { 4995 if (context != null) {
5317 context.allocatedFixedLists.add(newInstance); 4996 context.allocatedFixedLists.add(newInstance);
5318 } 4997 }
5319 } 4998 }
5320 4999
5321 // The List constructor forwards to a Dart static method that does 5000 // The List constructor forwards to a Dart static method that does
5322 // not know about the type argument. Therefore we special case 5001 // not know about the type argument. Therefore we special case
5323 // this constructor to have the setRuntimeTypeInfo called where 5002 // this constructor to have the setRuntimeTypeInfo called where
5324 // the 'new' is done. 5003 // the 'new' is done.
5325 if (backend.classNeedsRti(coreClasses.listClass) && 5004 if (backend.classNeedsRti(coreClasses.listClass) &&
5326 (isFixedListConstructorCall || isGrowableListConstructorCall || 5005 (isFixedListConstructorCall ||
5327 isJSArrayTypedConstructor)) { 5006 isGrowableListConstructorCall ||
5007 isJSArrayTypedConstructor)) {
5328 newInstance = handleListConstructor(type, send, pop()); 5008 newInstance = handleListConstructor(type, send, pop());
5329 stack.add(newInstance); 5009 stack.add(newInstance);
5330 } 5010 }
5331 5011
5332 // Finally, if we called a redirecting factory constructor, check the type. 5012 // Finally, if we called a redirecting factory constructor, check the type.
5333 if (isRedirected) { 5013 if (isRedirected) {
5334 HInstruction checked = potentiallyCheckOrTrustType(newInstance, type); 5014 HInstruction checked = potentiallyCheckOrTrustType(newInstance, type);
5335 if (checked != newInstance) { 5015 if (checked != newInstance) {
5336 pop(); 5016 pop();
5337 stack.add(checked); 5017 stack.add(checked);
5338 } 5018 }
5339 } 5019 }
5340 } 5020 }
5341 5021
5342 void potentiallyAddTypeArguments(List<HInstruction> inputs, ClassElement cls, 5022 void potentiallyAddTypeArguments(
5343 InterfaceType expectedType, 5023 List<HInstruction> inputs, ClassElement cls, InterfaceType expectedType,
5344 {SourceInformation sourceInformation}) { 5024 {SourceInformation sourceInformation}) {
5345 if (!backend.classNeedsRti(cls)) return; 5025 if (!backend.classNeedsRti(cls)) return;
5346 assert(expectedType.typeArguments.isEmpty || 5026 assert(expectedType.typeArguments.isEmpty ||
5347 cls.typeVariables.length == expectedType.typeArguments.length); 5027 cls.typeVariables.length == expectedType.typeArguments.length);
5348 expectedType.typeArguments.forEach((DartType argument) { 5028 expectedType.typeArguments.forEach((DartType argument) {
5349 inputs.add(analyzeTypeArgument( 5029 inputs.add(
5350 argument, sourceInformation: sourceInformation)); 5030 analyzeTypeArgument(argument, sourceInformation: sourceInformation));
5351 }); 5031 });
5352 } 5032 }
5353 5033
5354 /// In checked mode checks the [type] of [node] to be well-bounded. The method 5034 /// In checked mode checks the [type] of [node] to be well-bounded. The method
5355 /// returns [:true:] if an error can be statically determined. 5035 /// returns [:true:] if an error can be statically determined.
5356 bool checkTypeVariableBounds(ast.NewExpression node, InterfaceType type) { 5036 bool checkTypeVariableBounds(ast.NewExpression node, InterfaceType type) {
5357 if (!compiler.options.enableTypeAssertions) return false; 5037 if (!compiler.options.enableTypeAssertions) return false;
5358 5038
5359 Map<DartType, Set<DartType>> seenChecksMap = 5039 Map<DartType, Set<DartType>> seenChecksMap =
5360 new Map<DartType, Set<DartType>>(); 5040 new Map<DartType, Set<DartType>>();
5361 bool definitelyFails = false; 5041 bool definitelyFails = false;
5362 5042
5363 addTypeVariableBoundCheck(GenericType instance, 5043 addTypeVariableBoundCheck(GenericType instance, DartType typeArgument,
5364 DartType typeArgument, 5044 TypeVariableType typeVariable, DartType bound) {
5365 TypeVariableType typeVariable,
5366 DartType bound) {
5367 if (definitelyFails) return; 5045 if (definitelyFails) return;
5368 5046
5369 int subtypeRelation = compiler.types.computeSubtypeRelation(typeArgument, bound); 5047 int subtypeRelation =
5048 compiler.types.computeSubtypeRelation(typeArgument, bound);
5370 if (subtypeRelation == Types.IS_SUBTYPE) return; 5049 if (subtypeRelation == Types.IS_SUBTYPE) return;
5371 5050
5372 String message = 5051 String message = "Can't create an instance of malbounded type '$type': "
5373 "Can't create an instance of malbounded type '$type': "
5374 "'${typeArgument}' is not a subtype of bound '${bound}' for " 5052 "'${typeArgument}' is not a subtype of bound '${bound}' for "
5375 "type variable '${typeVariable}' of type " 5053 "type variable '${typeVariable}' of type "
5376 "${type == instance 5054 "${type == instance
5377 ? "'${type.element.thisType}'" 5055 ? "'${type.element.thisType}'"
5378 : "'${instance.element.thisType}' on the supertype " 5056 : "'${instance.element.thisType}' on the supertype "
5379 "'${instance}' of '${type}'" 5057 "'${instance}' of '${type}'"
5380 }."; 5058 }.";
5381 if (subtypeRelation == Types.NOT_SUBTYPE) { 5059 if (subtypeRelation == Types.NOT_SUBTYPE) {
5382 generateTypeError(node, message); 5060 generateTypeError(node, message);
5383 definitelyFails = true; 5061 definitelyFails = true;
5384 return; 5062 return;
5385 } else if (subtypeRelation == Types.MAYBE_SUBTYPE) { 5063 } else if (subtypeRelation == Types.MAYBE_SUBTYPE) {
5386 Set<DartType> seenChecks = 5064 Set<DartType> seenChecks =
5387 seenChecksMap.putIfAbsent(typeArgument, () => new Set<DartType>()); 5065 seenChecksMap.putIfAbsent(typeArgument, () => new Set<DartType>());
5388 if (!seenChecks.contains(bound)) { 5066 if (!seenChecks.contains(bound)) {
5389 seenChecks.add(bound); 5067 seenChecks.add(bound);
5390 assertIsSubtype(node, typeArgument, bound, message); 5068 assertIsSubtype(node, typeArgument, bound, message);
5391 } 5069 }
5392 } 5070 }
5393 } 5071 }
5394 5072
5395 compiler.types.checkTypeVariableBounds(type, addTypeVariableBoundCheck); 5073 compiler.types.checkTypeVariableBounds(type, addTypeVariableBoundCheck);
5396 if (definitelyFails) { 5074 if (definitelyFails) {
5397 return true; 5075 return true;
5398 } 5076 }
5399 for (InterfaceType supertype in type.element.allSupertypes) { 5077 for (InterfaceType supertype in type.element.allSupertypes) {
5400 DartType instance = type.asInstanceOf(supertype.element); 5078 DartType instance = type.asInstanceOf(supertype.element);
5401 compiler.types.checkTypeVariableBounds(instance, 5079 compiler.types
5402 addTypeVariableBoundCheck); 5080 .checkTypeVariableBounds(instance, addTypeVariableBoundCheck);
5403 if (definitelyFails) { 5081 if (definitelyFails) {
5404 return true; 5082 return true;
5405 } 5083 }
5406 } 5084 }
5407 return false; 5085 return false;
5408 } 5086 }
5409 5087
5410 visitStaticSend(ast.Send node) { 5088 visitStaticSend(ast.Send node) {
5411 internalError(node, "Unexpected visitStaticSend"); 5089 internalError(node, "Unexpected visitStaticSend");
5412 } 5090 }
5413 5091
5414 /// Generate an invocation to the static or top level [function]. 5092 /// Generate an invocation to the static or top level [function].
5415 void generateStaticFunctionInvoke( 5093 void generateStaticFunctionInvoke(
5416 ast.Send node, 5094 ast.Send node, FunctionElement function, CallStructure callStructure) {
5417 FunctionElement function,
5418 CallStructure callStructure) {
5419 List<HInstruction> inputs = makeStaticArgumentList( 5095 List<HInstruction> inputs = makeStaticArgumentList(
5420 callStructure, 5096 callStructure, node.arguments, function.implementation);
5421 node.arguments,
5422 function.implementation);
5423 5097
5424 if (function == compiler.identicalFunction) { 5098 if (function == compiler.identicalFunction) {
5425 pushWithPosition( 5099 pushWithPosition(
5426 new HIdentity(inputs[0], inputs[1], null, backend.boolType), node); 5100 new HIdentity(inputs[0], inputs[1], null, backend.boolType), node);
5427 return; 5101 return;
5428 } else { 5102 } else {
5429 pushInvokeStatic(node, function, inputs, 5103 pushInvokeStatic(node, function, inputs,
5430 sourceInformation: sourceInformationBuilder.buildCall( 5104 sourceInformation:
5431 node, node.selector)); 5105 sourceInformationBuilder.buildCall(node, node.selector));
5432 } 5106 }
5433 } 5107 }
5434 5108
5435 /// Generate an invocation to a static or top level function with the wrong 5109 /// Generate an invocation to a static or top level function with the wrong
5436 /// number of arguments. 5110 /// number of arguments.
5437 void generateStaticFunctionIncompatibleInvoke(ast.Send node, 5111 void generateStaticFunctionIncompatibleInvoke(
5438 Element element) { 5112 ast.Send node, Element element) {
5439 generateWrongArgumentCountError(node, element, node.arguments); 5113 generateWrongArgumentCountError(node, element, node.arguments);
5440 } 5114 }
5441 5115
5442 @override 5116 @override
5443 void visitStaticFieldInvoke( 5117 void visitStaticFieldInvoke(ast.Send node, FieldElement field,
5444 ast.Send node, 5118 ast.NodeList arguments, CallStructure callStructure, _) {
5445 FieldElement field,
5446 ast.NodeList arguments,
5447 CallStructure callStructure,
5448 _) {
5449 generateStaticFieldGet(node, field); 5119 generateStaticFieldGet(node, field);
5450 generateCallInvoke( 5120 generateCallInvoke(node, pop(),
5451 node,
5452 pop(),
5453 sourceInformationBuilder.buildCall(node, node.argumentsNode)); 5121 sourceInformationBuilder.buildCall(node, node.argumentsNode));
5454 } 5122 }
5455 5123
5456 @override 5124 @override
5457 void visitStaticFunctionInvoke( 5125 void visitStaticFunctionInvoke(ast.Send node, MethodElement function,
5458 ast.Send node, 5126 ast.NodeList arguments, CallStructure callStructure, _) {
5459 MethodElement function,
5460 ast.NodeList arguments,
5461 CallStructure callStructure,
5462 _) {
5463 generateStaticFunctionInvoke(node, function, callStructure); 5127 generateStaticFunctionInvoke(node, function, callStructure);
5464 } 5128 }
5465 5129
5466 @override 5130 @override
5467 void visitStaticFunctionIncompatibleInvoke( 5131 void visitStaticFunctionIncompatibleInvoke(
5468 ast.Send node, 5132 ast.Send node,
5469 MethodElement function, 5133 MethodElement function,
5470 ast.NodeList arguments, 5134 ast.NodeList arguments,
5471 CallStructure callStructure, 5135 CallStructure callStructure,
5472 _) { 5136 _) {
5473 generateStaticFunctionIncompatibleInvoke(node, function); 5137 generateStaticFunctionIncompatibleInvoke(node, function);
5474 } 5138 }
5475 5139
5476 @override 5140 @override
5477 void visitStaticGetterInvoke( 5141 void visitStaticGetterInvoke(ast.Send node, FunctionElement getter,
5478 ast.Send node, 5142 ast.NodeList arguments, CallStructure callStructure, _) {
5479 FunctionElement getter,
5480 ast.NodeList arguments,
5481 CallStructure callStructure,
5482 _) {
5483 generateStaticGetterGet(node, getter); 5143 generateStaticGetterGet(node, getter);
5484 generateCallInvoke( 5144 generateCallInvoke(node, pop(),
5485 node,
5486 pop(),
5487 sourceInformationBuilder.buildCall(node, node.argumentsNode)); 5145 sourceInformationBuilder.buildCall(node, node.argumentsNode));
5488 } 5146 }
5489 5147
5490 @override 5148 @override
5491 void visitTopLevelFieldInvoke( 5149 void visitTopLevelFieldInvoke(ast.Send node, FieldElement field,
5492 ast.Send node, 5150 ast.NodeList arguments, CallStructure callStructure, _) {
5493 FieldElement field,
5494 ast.NodeList arguments,
5495 CallStructure callStructure,
5496 _) {
5497 generateStaticFieldGet(node, field); 5151 generateStaticFieldGet(node, field);
5498 generateCallInvoke( 5152 generateCallInvoke(node, pop(),
5499 node,
5500 pop(),
5501 sourceInformationBuilder.buildCall(node, node.argumentsNode)); 5153 sourceInformationBuilder.buildCall(node, node.argumentsNode));
5502 } 5154 }
5503 5155
5504 @override 5156 @override
5505 void visitTopLevelFunctionInvoke( 5157 void visitTopLevelFunctionInvoke(ast.Send node, MethodElement function,
5506 ast.Send node, 5158 ast.NodeList arguments, CallStructure callStructure, _) {
5507 MethodElement function,
5508 ast.NodeList arguments,
5509 CallStructure callStructure,
5510 _) {
5511 if (backend.isForeign(function)) { 5159 if (backend.isForeign(function)) {
5512 handleForeignSend(node, function); 5160 handleForeignSend(node, function);
5513 } else { 5161 } else {
5514 generateStaticFunctionInvoke(node, function, callStructure); 5162 generateStaticFunctionInvoke(node, function, callStructure);
5515 } 5163 }
5516 } 5164 }
5517 5165
5518 @override 5166 @override
5519 void visitTopLevelFunctionIncompatibleInvoke( 5167 void visitTopLevelFunctionIncompatibleInvoke(
5520 ast.Send node, 5168 ast.Send node,
5521 MethodElement function, 5169 MethodElement function,
5522 ast.NodeList arguments, 5170 ast.NodeList arguments,
5523 CallStructure callStructure, 5171 CallStructure callStructure,
5524 _) { 5172 _) {
5525 generateStaticFunctionIncompatibleInvoke(node, function); 5173 generateStaticFunctionIncompatibleInvoke(node, function);
5526 } 5174 }
5527 5175
5528 @override 5176 @override
5529 void visitTopLevelGetterInvoke( 5177 void visitTopLevelGetterInvoke(ast.Send node, FunctionElement getter,
5530 ast.Send node, 5178 ast.NodeList arguments, CallStructure callStructure, _) {
5531 FunctionElement getter,
5532 ast.NodeList arguments,
5533 CallStructure callStructure,
5534 _) {
5535 generateStaticGetterGet(node, getter); 5179 generateStaticGetterGet(node, getter);
5536 generateCallInvoke( 5180 generateCallInvoke(node, pop(),
5537 node,
5538 pop(),
5539 sourceInformationBuilder.buildCall(node, node.argumentsNode)); 5181 sourceInformationBuilder.buildCall(node, node.argumentsNode));
5540 } 5182 }
5541 5183
5542 @override 5184 @override
5543 void visitTopLevelSetterGet( 5185 void visitTopLevelSetterGet(ast.Send node, MethodElement setter, _) {
5544 ast.Send node,
5545 MethodElement setter,
5546 _) {
5547 handleInvalidStaticGet(node, setter); 5186 handleInvalidStaticGet(node, setter);
5548 } 5187 }
5549 5188
5550 @override 5189 @override
5551 void visitStaticSetterGet( 5190 void visitStaticSetterGet(ast.Send node, MethodElement setter, _) {
5552 ast.Send node,
5553 MethodElement setter,
5554 _) {
5555 handleInvalidStaticGet(node, setter); 5191 handleInvalidStaticGet(node, setter);
5556 } 5192 }
5557 5193
5558 @override 5194 @override
5559 void visitUnresolvedGet( 5195 void visitUnresolvedGet(ast.Send node, Element element, _) {
5560 ast.Send node,
5561 Element element,
5562 _) {
5563 generateStaticUnresolvedGet(node, element); 5196 generateStaticUnresolvedGet(node, element);
5564 } 5197 }
5565 5198
5566 void handleInvalidStaticInvoke(ast.Send node, Element element) { 5199 void handleInvalidStaticInvoke(ast.Send node, Element element) {
5567 generateThrowNoSuchMethod(node, 5200 generateThrowNoSuchMethod(node, noSuchMethodTargetSymbolString(element),
5568 noSuchMethodTargetSymbolString(element), 5201 argumentNodes: node.arguments);
5569 argumentNodes: node.arguments);
5570 } 5202 }
5571 5203
5572 @override 5204 @override
5573 void visitStaticSetterInvoke( 5205 void visitStaticSetterInvoke(ast.Send node, MethodElement setter,
5574 ast.Send node, 5206 ast.NodeList arguments, CallStructure callStructure, _) {
5575 MethodElement setter,
5576 ast.NodeList arguments,
5577 CallStructure callStructure,
5578 _) {
5579 handleInvalidStaticInvoke(node, setter); 5207 handleInvalidStaticInvoke(node, setter);
5580 } 5208 }
5581 5209
5582 @override 5210 @override
5583 void visitTopLevelSetterInvoke( 5211 void visitTopLevelSetterInvoke(ast.Send node, MethodElement setter,
5584 ast.Send node, 5212 ast.NodeList arguments, CallStructure callStructure, _) {
5585 MethodElement setter,
5586 ast.NodeList arguments,
5587 CallStructure callStructure,
5588 _) {
5589 handleInvalidStaticInvoke(node, setter); 5213 handleInvalidStaticInvoke(node, setter);
5590 } 5214 }
5591 5215
5592 @override 5216 @override
5593 void visitUnresolvedInvoke( 5217 void visitUnresolvedInvoke(ast.Send node, Element element,
5594 ast.Send node, 5218 ast.NodeList arguments, Selector selector, _) {
5595 Element element,
5596 ast.NodeList arguments,
5597 Selector selector,
5598 _) {
5599 if (element is ErroneousElement) { 5219 if (element is ErroneousElement) {
5600 // An erroneous element indicates that the function could not be 5220 // An erroneous element indicates that the function could not be
5601 // resolved (a warning has been issued). 5221 // resolved (a warning has been issued).
5602 handleInvalidStaticInvoke(node, element); 5222 handleInvalidStaticInvoke(node, element);
5603 } else { 5223 } else {
5604 // TODO(ahe): Do something like [generateWrongArgumentCountError]. 5224 // TODO(ahe): Do something like [generateWrongArgumentCountError].
5605 stack.add(graph.addConstantNull(compiler)); 5225 stack.add(graph.addConstantNull(compiler));
5606 } 5226 }
5607 return; 5227 return;
5608 } 5228 }
5609 5229
5610 HConstant addConstantString(String string) { 5230 HConstant addConstantString(String string) {
5611 ast.DartString dartString = new ast.DartString.literal(string); 5231 ast.DartString dartString = new ast.DartString.literal(string);
5612 return graph.addConstantString(dartString, compiler); 5232 return graph.addConstantString(dartString, compiler);
5613 } 5233 }
5614 5234
5615 HConstant addConstantStringFromName(js.Name name) { 5235 HConstant addConstantStringFromName(js.Name name) {
5616 return graph.addConstantStringFromName(name, compiler); 5236 return graph.addConstantStringFromName(name, compiler);
5617 } 5237 }
5618 5238
5619 visitClassTypeLiteralGet( 5239 visitClassTypeLiteralGet(ast.Send node, ConstantExpression constant, _) {
5620 ast.Send node,
5621 ConstantExpression constant,
5622 _) {
5623 generateConstantTypeLiteral(node); 5240 generateConstantTypeLiteral(node);
5624 } 5241 }
5625 5242
5626 visitClassTypeLiteralInvoke( 5243 visitClassTypeLiteralInvoke(ast.Send node, ConstantExpression constant,
5627 ast.Send node, 5244 ast.NodeList arguments, CallStructure callStructure, _) {
5628 ConstantExpression constant,
5629 ast.NodeList arguments,
5630 CallStructure callStructure,
5631 _) {
5632 generateConstantTypeLiteral(node); 5245 generateConstantTypeLiteral(node);
5633 generateTypeLiteralCall(node); 5246 generateTypeLiteralCall(node);
5634 } 5247 }
5635 5248
5636 visitTypedefTypeLiteralGet( 5249 visitTypedefTypeLiteralGet(ast.Send node, ConstantExpression constant, _) {
5637 ast.Send node,
5638 ConstantExpression constant,
5639 _) {
5640 generateConstantTypeLiteral(node); 5250 generateConstantTypeLiteral(node);
5641 } 5251 }
5642 5252
5643 visitTypedefTypeLiteralInvoke( 5253 visitTypedefTypeLiteralInvoke(ast.Send node, ConstantExpression constant,
5644 ast.Send node, 5254 ast.NodeList arguments, CallStructure callStructure, _) {
5645 ConstantExpression constant,
5646 ast.NodeList arguments,
5647 CallStructure callStructure,
5648 _) {
5649 generateConstantTypeLiteral(node); 5255 generateConstantTypeLiteral(node);
5650 generateTypeLiteralCall(node); 5256 generateTypeLiteralCall(node);
5651 } 5257 }
5652 5258
5653 visitTypeVariableTypeLiteralGet( 5259 visitTypeVariableTypeLiteralGet(
5654 ast.Send node, 5260 ast.Send node, TypeVariableElement element, _) {
5655 TypeVariableElement element,
5656 _) {
5657 generateTypeVariableLiteral(node, element.type); 5261 generateTypeVariableLiteral(node, element.type);
5658 } 5262 }
5659 5263
5660 visitTypeVariableTypeLiteralInvoke( 5264 visitTypeVariableTypeLiteralInvoke(ast.Send node, TypeVariableElement element,
5661 ast.Send node, 5265 ast.NodeList arguments, CallStructure callStructure, _) {
5662 TypeVariableElement element,
5663 ast.NodeList arguments,
5664 CallStructure callStructure,
5665 _) {
5666 generateTypeVariableLiteral(node, element.type); 5266 generateTypeVariableLiteral(node, element.type);
5667 generateTypeLiteralCall(node); 5267 generateTypeLiteralCall(node);
5668 } 5268 }
5669 5269
5670 visitDynamicTypeLiteralGet( 5270 visitDynamicTypeLiteralGet(ast.Send node, ConstantExpression constant, _) {
5671 ast.Send node,
5672 ConstantExpression constant,
5673 _) {
5674 generateConstantTypeLiteral(node); 5271 generateConstantTypeLiteral(node);
5675 } 5272 }
5676 5273
5677 visitDynamicTypeLiteralInvoke( 5274 visitDynamicTypeLiteralInvoke(ast.Send node, ConstantExpression constant,
5678 ast.Send node, 5275 ast.NodeList arguments, CallStructure callStructure, _) {
5679 ConstantExpression constant,
5680 ast.NodeList arguments,
5681 CallStructure callStructure,
5682 _) {
5683 generateConstantTypeLiteral(node); 5276 generateConstantTypeLiteral(node);
5684 generateTypeLiteralCall(node); 5277 generateTypeLiteralCall(node);
5685 } 5278 }
5686 5279
5687 /// Generate the constant value for a constant type literal. 5280 /// Generate the constant value for a constant type literal.
5688 void generateConstantTypeLiteral(ast.Send node) { 5281 void generateConstantTypeLiteral(ast.Send node) {
5689 // TODO(karlklose): add type representation 5282 // TODO(karlklose): add type representation
5690 if (node.isCall) { 5283 if (node.isCall) {
5691 // The node itself is not a constant but we register the selector (the 5284 // The node itself is not a constant but we register the selector (the
5692 // identifier that refers to the class/typedef) as a constant. 5285 // identifier that refers to the class/typedef) as a constant.
5693 stack.add(addConstant(node.selector)); 5286 stack.add(addConstant(node.selector));
5694 } else { 5287 } else {
5695 stack.add(addConstant(node)); 5288 stack.add(addConstant(node));
5696 } 5289 }
5697 } 5290 }
5698 5291
5699 /// Generate the literal for [typeVariable] in the current context. 5292 /// Generate the literal for [typeVariable] in the current context.
5700 void generateTypeVariableLiteral(ast.Send node, 5293 void generateTypeVariableLiteral(
5701 TypeVariableType typeVariable) { 5294 ast.Send node, TypeVariableType typeVariable) {
5702 DartType type = localsHandler.substInContext(typeVariable); 5295 DartType type = localsHandler.substInContext(typeVariable);
5703 HInstruction value = analyzeTypeArgument(type, 5296 HInstruction value = analyzeTypeArgument(type,
5704 sourceInformation: sourceInformationBuilder.buildGet(node)); 5297 sourceInformation: sourceInformationBuilder.buildGet(node));
5705 pushInvokeStatic(node, 5298 pushInvokeStatic(node, helpers.runtimeTypeToString, [value],
5706 helpers.runtimeTypeToString, 5299 typeMask: backend.stringType);
5707 [value], 5300 pushInvokeStatic(node, helpers.createRuntimeType, [pop()]);
5708 typeMask: backend.stringType);
5709 pushInvokeStatic(node,
5710 helpers.createRuntimeType,
5711 [pop()]);
5712 } 5301 }
5713 5302
5714 /// Generate a call to a type literal. 5303 /// Generate a call to a type literal.
5715 void generateTypeLiteralCall(ast.Send node) { 5304 void generateTypeLiteralCall(ast.Send node) {
5716 // This send is of the form 'e(...)', where e is resolved to a type 5305 // This send is of the form 'e(...)', where e is resolved to a type
5717 // reference. We create a regular closure call on the result of the type 5306 // reference. We create a regular closure call on the result of the type
5718 // reference instead of creating a NoSuchMethodError to avoid pulling it 5307 // reference instead of creating a NoSuchMethodError to avoid pulling it
5719 // in if it is not used (e.g., in a try/catch). 5308 // in if it is not used (e.g., in a try/catch).
5720 HInstruction target = pop(); 5309 HInstruction target = pop();
5721 generateCallInvoke(node, target, 5310 generateCallInvoke(node, target,
5722 sourceInformationBuilder.buildCall(node, node.argumentsNode)); 5311 sourceInformationBuilder.buildCall(node, node.argumentsNode));
5723 } 5312 }
5724 5313
5725 /// Generate a '.call' invocation on [target]. 5314 /// Generate a '.call' invocation on [target].
5726 void generateCallInvoke(ast.Send node, 5315 void generateCallInvoke(
5727 HInstruction target, 5316 ast.Send node, HInstruction target, SourceInformation sourceInformation) {
5728 SourceInformation sourceInformation) {
5729 Selector selector = elements.getSelector(node); 5317 Selector selector = elements.getSelector(node);
5730 List<HInstruction> inputs = <HInstruction>[target]; 5318 List<HInstruction> inputs = <HInstruction>[target];
5731 addDynamicSendArgumentsToList(node, inputs); 5319 addDynamicSendArgumentsToList(node, inputs);
5732 push(new HInvokeClosure( 5320 push(new HInvokeClosure(
5733 new Selector.callClosureFrom(selector), 5321 new Selector.callClosureFrom(selector), inputs, backend.dynamicType)
5734 inputs, backend.dynamicType) 5322 ..sourceInformation = sourceInformation);
5735 ..sourceInformation = sourceInformation);
5736 } 5323 }
5737 5324
5738 visitGetterSend(ast.Send node) { 5325 visitGetterSend(ast.Send node) {
5739 internalError(node, "Unexpected visitGetterSend"); 5326 internalError(node, "Unexpected visitGetterSend");
5740 } 5327 }
5741 5328
5742 // TODO(antonm): migrate rest of SsaFromAstMixin to internalError. 5329 // TODO(antonm): migrate rest of SsaFromAstMixin to internalError.
5743 internalError(Spannable node, String reason) { 5330 internalError(Spannable node, String reason) {
5744 reporter.internalError(node, reason); 5331 reporter.internalError(node, reason);
5745 } 5332 }
5746 5333
5747 void generateError(ast.Node node, String message, Element helper) { 5334 void generateError(ast.Node node, String message, Element helper) {
5748 HInstruction errorMessage = addConstantString(message); 5335 HInstruction errorMessage = addConstantString(message);
5749 pushInvokeStatic(node, helper, [errorMessage]); 5336 pushInvokeStatic(node, helper, [errorMessage]);
5750 } 5337 }
5751 5338
5752 void generateRuntimeError(ast.Node node, String message) { 5339 void generateRuntimeError(ast.Node node, String message) {
5753 generateError(node, message, helpers.throwRuntimeError); 5340 generateError(node, message, helpers.throwRuntimeError);
5754 } 5341 }
5755 5342
5756 void generateTypeError(ast.Node node, String message) { 5343 void generateTypeError(ast.Node node, String message) {
5757 generateError(node, message, helpers.throwTypeError); 5344 generateError(node, message, helpers.throwTypeError);
5758 } 5345 }
5759 5346
5760 void generateAbstractClassInstantiationError(ast.Node node, String message) { 5347 void generateAbstractClassInstantiationError(ast.Node node, String message) {
5761 generateError(node, 5348 generateError(node, message, helpers.throwAbstractClassInstantiationError);
5762 message,
5763 helpers.throwAbstractClassInstantiationError);
5764 } 5349 }
5765 5350
5766 void generateThrowNoSuchMethod(ast.Node diagnosticNode, 5351 void generateThrowNoSuchMethod(ast.Node diagnosticNode, String methodName,
5767 String methodName, 5352 {Link<ast.Node> argumentNodes,
5768 {Link<ast.Node> argumentNodes, 5353 List<HInstruction> argumentValues,
5769 List<HInstruction> argumentValues, 5354 List<String> existingArguments,
5770 List<String> existingArguments, 5355 SourceInformation sourceInformation}) {
5771 SourceInformation sourceInformation}) {
5772 Element helper = helpers.throwNoSuchMethod; 5356 Element helper = helpers.throwNoSuchMethod;
5773 ConstantValue receiverConstant = 5357 ConstantValue receiverConstant =
5774 constantSystem.createString(new ast.DartString.empty()); 5358 constantSystem.createString(new ast.DartString.empty());
5775 HInstruction receiver = graph.addConstant(receiverConstant, compiler); 5359 HInstruction receiver = graph.addConstant(receiverConstant, compiler);
5776 ast.DartString dartString = new ast.DartString.literal(methodName); 5360 ast.DartString dartString = new ast.DartString.literal(methodName);
5777 ConstantValue nameConstant = constantSystem.createString(dartString); 5361 ConstantValue nameConstant = constantSystem.createString(dartString);
5778 HInstruction name = graph.addConstant(nameConstant, compiler); 5362 HInstruction name = graph.addConstant(nameConstant, compiler);
5779 if (argumentValues == null) { 5363 if (argumentValues == null) {
5780 argumentValues = <HInstruction>[]; 5364 argumentValues = <HInstruction>[];
5781 argumentNodes.forEach((argumentNode) { 5365 argumentNodes.forEach((argumentNode) {
(...skipping 10 matching lines...) Expand all
5792 for (String name in existingArguments) { 5376 for (String name in existingArguments) {
5793 HInstruction nameConstant = 5377 HInstruction nameConstant =
5794 graph.addConstantString(new ast.DartString.literal(name), compiler); 5378 graph.addConstantString(new ast.DartString.literal(name), compiler);
5795 existingNames.add(nameConstant); 5379 existingNames.add(nameConstant);
5796 } 5380 }
5797 existingNamesList = buildLiteralList(existingNames); 5381 existingNamesList = buildLiteralList(existingNames);
5798 add(existingNamesList); 5382 add(existingNamesList);
5799 } else { 5383 } else {
5800 existingNamesList = graph.addConstantNull(compiler); 5384 existingNamesList = graph.addConstantNull(compiler);
5801 } 5385 }
5802 pushInvokeStatic(diagnosticNode, 5386 pushInvokeStatic(
5803 helper, 5387 diagnosticNode, helper, [receiver, name, arguments, existingNamesList],
5804 [receiver, name, arguments, existingNamesList], 5388 sourceInformation: sourceInformation);
5805 sourceInformation: sourceInformation);
5806 } 5389 }
5807 5390
5808 /** 5391 /**
5809 * Generate code to throw a [NoSuchMethodError] exception for calling a 5392 * Generate code to throw a [NoSuchMethodError] exception for calling a
5810 * method with a wrong number of arguments or mismatching named optional 5393 * method with a wrong number of arguments or mismatching named optional
5811 * arguments. 5394 * arguments.
5812 */ 5395 */
5813 void generateWrongArgumentCountError(ast.Node diagnosticNode, 5396 void generateWrongArgumentCountError(ast.Node diagnosticNode,
5814 FunctionElement function, 5397 FunctionElement function, Link<ast.Node> argumentNodes) {
5815 Link<ast.Node> argumentNodes) {
5816 List<String> existingArguments = <String>[]; 5398 List<String> existingArguments = <String>[];
5817 FunctionSignature signature = function.functionSignature; 5399 FunctionSignature signature = function.functionSignature;
5818 signature.forEachParameter((Element parameter) { 5400 signature.forEachParameter((Element parameter) {
5819 existingArguments.add(parameter.name); 5401 existingArguments.add(parameter.name);
5820 }); 5402 });
5821 generateThrowNoSuchMethod(diagnosticNode, 5403 generateThrowNoSuchMethod(diagnosticNode, function.name,
5822 function.name, 5404 argumentNodes: argumentNodes, existingArguments: existingArguments);
5823 argumentNodes: argumentNodes,
5824 existingArguments: existingArguments);
5825 } 5405 }
5826 5406
5827 @override 5407 @override
5828 void bulkHandleNode(ast.Node node, String message, _) { 5408 void bulkHandleNode(ast.Node node, String message, _) {
5829 internalError(node, "Unexpected bulk handled node: $node"); 5409 internalError(node, "Unexpected bulk handled node: $node");
5830 } 5410 }
5831 5411
5832 @override 5412 @override
5833 void bulkHandleNew(ast.NewExpression node, [_]) { 5413 void bulkHandleNew(ast.NewExpression node, [_]) {
5834 Element element = elements[node.send]; 5414 Element element = elements[node.send];
5835 final bool isSymbolConstructor = element == compiler.symbolConstructor; 5415 final bool isSymbolConstructor = element == compiler.symbolConstructor;
5836 if (!Elements.isMalformed(element)) { 5416 if (!Elements.isMalformed(element)) {
5837 ConstructorElement function = element; 5417 ConstructorElement function = element;
5838 element = function.effectiveTarget; 5418 element = function.effectiveTarget;
5839 } 5419 }
5840 if (Elements.isError(element)) { 5420 if (Elements.isError(element)) {
5841 ErroneousElement error = element; 5421 ErroneousElement error = element;
5842 if (error.messageKind == MessageKind.CANNOT_FIND_CONSTRUCTOR || 5422 if (error.messageKind == MessageKind.CANNOT_FIND_CONSTRUCTOR ||
5843 error.messageKind == MessageKind.CANNOT_FIND_UNNAMED_CONSTRUCTOR) { 5423 error.messageKind == MessageKind.CANNOT_FIND_UNNAMED_CONSTRUCTOR) {
5844 generateThrowNoSuchMethod( 5424 generateThrowNoSuchMethod(
5845 node.send, 5425 node.send, noSuchMethodTargetSymbolString(error, 'constructor'),
5846 noSuchMethodTargetSymbolString(error, 'constructor'),
5847 argumentNodes: node.send.arguments); 5426 argumentNodes: node.send.arguments);
5848 } else { 5427 } else {
5849 MessageTemplate template = MessageTemplate.TEMPLATES[error.messageKind]; 5428 MessageTemplate template = MessageTemplate.TEMPLATES[error.messageKind];
5850 Message message = template.message(error.messageArguments); 5429 Message message = template.message(error.messageArguments);
5851 generateRuntimeError(node.send, message.toString()); 5430 generateRuntimeError(node.send, message.toString());
5852 } 5431 }
5853 } else if (Elements.isMalformed(element)) { 5432 } else if (Elements.isMalformed(element)) {
5854 // TODO(ahe): Do something like [generateWrongArgumentCountError]. 5433 // TODO(ahe): Do something like [generateWrongArgumentCountError].
5855 stack.add(graph.addConstantNull(compiler)); 5434 stack.add(graph.addConstantNull(compiler));
5856 } else if (node.isConst) { 5435 } else if (node.isConst) {
(...skipping 13 matching lines...) Expand all
5870 void errorNonConstantConstructorInvoke( 5449 void errorNonConstantConstructorInvoke(
5871 ast.NewExpression node, 5450 ast.NewExpression node,
5872 Element element, 5451 Element element,
5873 DartType type, 5452 DartType type,
5874 ast.NodeList arguments, 5453 ast.NodeList arguments,
5875 CallStructure callStructure, 5454 CallStructure callStructure,
5876 _) { 5455 _) {
5877 bulkHandleNew(node); 5456 bulkHandleNew(node);
5878 } 5457 }
5879 5458
5880 void pushInvokeDynamic(ast.Node node, 5459 void pushInvokeDynamic(ast.Node node, Selector selector, TypeMask mask,
5881 Selector selector, 5460 List<HInstruction> arguments,
5882 TypeMask mask, 5461 {SourceInformation sourceInformation}) {
5883 List<HInstruction> arguments,
5884 {SourceInformation sourceInformation}) {
5885
5886 // We prefer to not inline certain operations on indexables, 5462 // We prefer to not inline certain operations on indexables,
5887 // because the constant folder will handle them better and turn 5463 // because the constant folder will handle them better and turn
5888 // them into simpler instructions that allow further 5464 // them into simpler instructions that allow further
5889 // optimizations. 5465 // optimizations.
5890 bool isOptimizableOperationOnIndexable(Selector selector, Element element) { 5466 bool isOptimizableOperationOnIndexable(Selector selector, Element element) {
5891 bool isLength = selector.isGetter 5467 bool isLength = selector.isGetter && selector.name == "length";
5892 && selector.name == "length";
5893 if (isLength || selector.isIndex) { 5468 if (isLength || selector.isIndex) {
5894 return compiler.world.isSubtypeOf( 5469 return compiler.world.isSubtypeOf(
5895 element.enclosingClass.declaration, 5470 element.enclosingClass.declaration, helpers.jsIndexableClass);
5896 helpers.jsIndexableClass);
5897 } else if (selector.isIndexSet) { 5471 } else if (selector.isIndexSet) {
5898 return compiler.world.isSubtypeOf( 5472 return compiler.world.isSubtypeOf(element.enclosingClass.declaration,
5899 element.enclosingClass.declaration,
5900 helpers.jsMutableIndexableClass); 5473 helpers.jsMutableIndexableClass);
5901 } else { 5474 } else {
5902 return false; 5475 return false;
5903 } 5476 }
5904 } 5477 }
5905 5478
5906 bool isOptimizableOperation(Selector selector, Element element) { 5479 bool isOptimizableOperation(Selector selector, Element element) {
5907 ClassElement cls = element.enclosingClass; 5480 ClassElement cls = element.enclosingClass;
5908 if (isOptimizableOperationOnIndexable(selector, element)) return true; 5481 if (isOptimizableOperationOnIndexable(selector, element)) return true;
5909 if (!backend.interceptedClasses.contains(cls)) return false; 5482 if (!backend.interceptedClasses.contains(cls)) return false;
(...skipping 23 matching lines...) Expand all
5933 HInstruction receiver = arguments[0]; 5506 HInstruction receiver = arguments[0];
5934 List<HInstruction> inputs = <HInstruction>[]; 5507 List<HInstruction> inputs = <HInstruction>[];
5935 bool isIntercepted = backend.isInterceptedSelector(selector); 5508 bool isIntercepted = backend.isInterceptedSelector(selector);
5936 if (isIntercepted) { 5509 if (isIntercepted) {
5937 inputs.add(invokeInterceptor(receiver)); 5510 inputs.add(invokeInterceptor(receiver));
5938 } 5511 }
5939 inputs.addAll(arguments); 5512 inputs.addAll(arguments);
5940 TypeMask type = 5513 TypeMask type =
5941 TypeMaskFactory.inferredTypeForSelector(selector, mask, compiler); 5514 TypeMaskFactory.inferredTypeForSelector(selector, mask, compiler);
5942 if (selector.isGetter) { 5515 if (selector.isGetter) {
5943 push( 5516 push(new HInvokeDynamicGetter(selector, mask, null, inputs, type)
5944 new HInvokeDynamicGetter(selector, mask, null, inputs, type) 5517 ..sourceInformation = sourceInformation);
5945 ..sourceInformation = sourceInformation);
5946 } else if (selector.isSetter) { 5518 } else if (selector.isSetter) {
5947 push( 5519 push(new HInvokeDynamicSetter(selector, mask, null, inputs, type)
5948 new HInvokeDynamicSetter(selector, mask, null, inputs, type) 5520 ..sourceInformation = sourceInformation);
5949 ..sourceInformation = sourceInformation);
5950 } else { 5521 } else {
5951 push( 5522 push(new HInvokeDynamicMethod(selector, mask, inputs, type, isIntercepted)
5952 new HInvokeDynamicMethod(selector, mask, inputs, type, isIntercepted) 5523 ..sourceInformation = sourceInformation);
5953 ..sourceInformation = sourceInformation);
5954 } 5524 }
5955 } 5525 }
5956 5526
5957 bool _hasNamedParameters(FunctionElement function) { 5527 bool _hasNamedParameters(FunctionElement function) {
5958 FunctionSignature params = function.functionSignature; 5528 FunctionSignature params = function.functionSignature;
5959 return params.optionalParameterCount > 0 5529 return params.optionalParameterCount > 0 &&
5960 && params.optionalParametersAreNamed; 5530 params.optionalParametersAreNamed;
5961 } 5531 }
5962 5532
5963 HForeignCode invokeJsInteropFunction(FunctionElement element, 5533 HForeignCode invokeJsInteropFunction(FunctionElement element,
5964 List<HInstruction> arguments, 5534 List<HInstruction> arguments, SourceInformation sourceInformation) {
5965 SourceInformation sourceInformation) {
5966 assert(backend.isJsInterop(element)); 5535 assert(backend.isJsInterop(element));
5967 nativeEmitter.nativeMethods.add(element); 5536 nativeEmitter.nativeMethods.add(element);
5968 String templateString; 5537 String templateString;
5969 5538
5970 if (element.isFactoryConstructor && 5539 if (element.isFactoryConstructor &&
5971 backend.jsInteropAnalysis.hasAnonymousAnnotation(element.contextClass)) { 5540 backend.jsInteropAnalysis
5541 .hasAnonymousAnnotation(element.contextClass)) {
5972 // Factory constructor that is syntactic sugar for creating a JavaScript 5542 // Factory constructor that is syntactic sugar for creating a JavaScript
5973 // object literal. 5543 // object literal.
5974 ConstructorElement constructor = element; 5544 ConstructorElement constructor = element;
5975 FunctionSignature params = constructor.functionSignature; 5545 FunctionSignature params = constructor.functionSignature;
5976 int i = 0; 5546 int i = 0;
5977 int positions = 0; 5547 int positions = 0;
5978 var filteredArguments = <HInstruction>[]; 5548 var filteredArguments = <HInstruction>[];
5979 var parameterNameMap = new Map<String, js.Expression>(); 5549 var parameterNameMap = new Map<String, js.Expression>();
5980 params.orderedForEachParameter((ParameterElement parameter) { 5550 params.orderedForEachParameter((ParameterElement parameter) {
5981 // TODO(jacobr): throw if parameter names do not match names of property 5551 // TODO(jacobr): throw if parameter names do not match names of property
5982 // names in the class. 5552 // names in the class.
5983 assert (parameter.isNamed); 5553 assert(parameter.isNamed);
5984 HInstruction argument = arguments[i]; 5554 HInstruction argument = arguments[i];
5985 if (argument != null) { 5555 if (argument != null) {
5986 filteredArguments.add(argument); 5556 filteredArguments.add(argument);
5987 parameterNameMap[parameter.name] = 5557 parameterNameMap[parameter.name] =
5988 new js.InterpolatedExpression(positions++); 5558 new js.InterpolatedExpression(positions++);
5989 } 5559 }
5990 i++; 5560 i++;
5991 }); 5561 });
5992 var codeTemplate = new js.Template(null, 5562 var codeTemplate =
5993 js.objectLiteral(parameterNameMap)); 5563 new js.Template(null, js.objectLiteral(parameterNameMap));
5994 5564
5995 var nativeBehavior = new native.NativeBehavior() 5565 var nativeBehavior = new native.NativeBehavior()
5996 ..codeTemplate = codeTemplate; 5566 ..codeTemplate = codeTemplate;
5997 if (compiler.options.trustJSInteropTypeAnnotations) { 5567 if (compiler.options.trustJSInteropTypeAnnotations) {
5998 nativeBehavior.typesReturned.add(constructor.enclosingClass.thisType); 5568 nativeBehavior.typesReturned.add(constructor.enclosingClass.thisType);
5999 } 5569 }
6000 return new HForeignCode( 5570 return new HForeignCode(
6001 codeTemplate, 5571 codeTemplate, backend.dynamicType, filteredArguments,
6002 backend.dynamicType, filteredArguments,
6003 nativeBehavior: nativeBehavior) 5572 nativeBehavior: nativeBehavior)
6004 ..sourceInformation = sourceInformation; 5573 ..sourceInformation = sourceInformation;
6005 } 5574 }
6006 var target = new HForeignCode(js.js.parseForeignJS( 5575 var target = new HForeignCode(
6007 "${backend.namer.fixedBackendPath(element)}." 5576 js.js.parseForeignJS("${backend.namer.fixedBackendPath(element)}."
6008 "${backend.nativeData.getFixedBackendName(element)}"), 5577 "${backend.nativeData.getFixedBackendName(element)}"),
6009 backend.dynamicType, 5578 backend.dynamicType,
6010 <HInstruction>[]); 5579 <HInstruction>[]);
6011 add(target); 5580 add(target);
6012 // Strip off trailing arguments that were not specified. 5581 // Strip off trailing arguments that were not specified.
6013 // we could assert that the trailing arguments are all null. 5582 // we could assert that the trailing arguments are all null.
6014 // TODO(jacobr): rewrite named arguments to an object literal matching 5583 // TODO(jacobr): rewrite named arguments to an object literal matching
6015 // the factory constructor case. 5584 // the factory constructor case.
6016 arguments = arguments.where((arg) => arg != null).toList(); 5585 arguments = arguments.where((arg) => arg != null).toList();
6017 var inputs = <HInstruction>[target]..addAll(arguments); 5586 var inputs = <HInstruction>[target]..addAll(arguments);
6018 5587
6019 var nativeBehavior = new native.NativeBehavior() 5588 var nativeBehavior = new native.NativeBehavior()
6020 ..sideEffects.setAllSideEffects(); 5589 ..sideEffects.setAllSideEffects();
6021 5590
6022 DartType type = element.isConstructor ? 5591 DartType type = element.isConstructor
6023 element.enclosingClass.thisType : element.type.returnType; 5592 ? element.enclosingClass.thisType
5593 : element.type.returnType;
6024 // Native behavior effects here are similar to native/behavior.dart. 5594 // Native behavior effects here are similar to native/behavior.dart.
6025 // The return type is dynamic if we don't trust js-interop type 5595 // The return type is dynamic if we don't trust js-interop type
6026 // declarations. 5596 // declarations.
6027 nativeBehavior.typesReturned.add( 5597 nativeBehavior.typesReturned.add(compiler
6028 compiler.options.trustJSInteropTypeAnnotations 5598 .options.trustJSInteropTypeAnnotations ? type : const DynamicType());
6029 ? type : const DynamicType());
6030 5599
6031 // The allocation effects include the declared type if it is native (which 5600 // The allocation effects include the declared type if it is native (which
6032 // includes js interop types). 5601 // includes js interop types).
6033 if (type.element != null && backend.isNative(type.element)) { 5602 if (type.element != null && backend.isNative(type.element)) {
6034 nativeBehavior.typesInstantiated.add(type); 5603 nativeBehavior.typesInstantiated.add(type);
6035 } 5604 }
6036 5605
6037 // It also includes any other JS interop type if we don't trust the 5606 // It also includes any other JS interop type if we don't trust the
6038 // annotation or if is declared too broad. 5607 // annotation or if is declared too broad.
6039 if (!compiler.options.trustJSInteropTypeAnnotations || type.isObject || 5608 if (!compiler.options.trustJSInteropTypeAnnotations ||
5609 type.isObject ||
6040 type.isDynamic) { 5610 type.isDynamic) {
6041 nativeBehavior.typesInstantiated.add( 5611 nativeBehavior.typesInstantiated
6042 backend.helpers.jsJavaScriptObjectClass.thisType); 5612 .add(backend.helpers.jsJavaScriptObjectClass.thisType);
6043 } 5613 }
6044 5614
6045 String code; 5615 String code;
6046 if (element.isGetter) { 5616 if (element.isGetter) {
6047 code = "#"; 5617 code = "#";
6048 } else if (element.isSetter) { 5618 } else if (element.isSetter) {
6049 code = "# = #"; 5619 code = "# = #";
6050 } else { 5620 } else {
6051 var args = new List.filled(arguments.length, '#').join(','); 5621 var args = new List.filled(arguments.length, '#').join(',');
6052 code = element.isConstructor ? "new #($args)" : "#($args)"; 5622 code = element.isConstructor ? "new #($args)" : "#($args)";
6053 } 5623 }
6054 js.Template codeTemplate = js.js.parseForeignJS(code); 5624 js.Template codeTemplate = js.js.parseForeignJS(code);
6055 nativeBehavior.codeTemplate = codeTemplate; 5625 nativeBehavior.codeTemplate = codeTemplate;
6056 5626
6057 return new HForeignCode( 5627 return new HForeignCode(codeTemplate, backend.dynamicType, inputs,
6058 codeTemplate, 5628 nativeBehavior: nativeBehavior)..sourceInformation = sourceInformation;
6059 backend.dynamicType, inputs,
6060 nativeBehavior: nativeBehavior)
6061 ..sourceInformation = sourceInformation;
6062 } 5629 }
6063 5630
6064 void pushInvokeStatic(ast.Node location, 5631 void pushInvokeStatic(
6065 Element element, 5632 ast.Node location, Element element, List<HInstruction> arguments,
6066 List<HInstruction> arguments, 5633 {TypeMask typeMask,
6067 {TypeMask typeMask, 5634 InterfaceType instanceType,
6068 InterfaceType instanceType, 5635 SourceInformation sourceInformation}) {
6069 SourceInformation sourceInformation}) {
6070 // TODO(johnniwinther): Use [sourceInformation] instead of [location]. 5636 // TODO(johnniwinther): Use [sourceInformation] instead of [location].
6071 if (tryInlineMethod(element, null, null, arguments, location, 5637 if (tryInlineMethod(element, null, null, arguments, location,
6072 instanceType: instanceType)) { 5638 instanceType: instanceType)) {
6073 return; 5639 return;
6074 } 5640 }
6075 5641
6076 if (typeMask == null) { 5642 if (typeMask == null) {
6077 typeMask = 5643 typeMask =
6078 TypeMaskFactory.inferredReturnTypeForElement(element, compiler); 5644 TypeMaskFactory.inferredReturnTypeForElement(element, compiler);
6079 } 5645 }
6080 bool targetCanThrow = !compiler.world.getCannotThrow(element); 5646 bool targetCanThrow = !compiler.world.getCannotThrow(element);
6081 // TODO(5346): Try to avoid the need for calling [declaration] before 5647 // TODO(5346): Try to avoid the need for calling [declaration] before
6082 var instruction; 5648 var instruction;
6083 if (backend.isJsInterop(element)) { 5649 if (backend.isJsInterop(element)) {
6084 instruction = invokeJsInteropFunction(element, arguments, 5650 instruction =
6085 sourceInformation); 5651 invokeJsInteropFunction(element, arguments, sourceInformation);
6086 } else { 5652 } else {
6087 // creating an [HInvokeStatic]. 5653 // creating an [HInvokeStatic].
6088 instruction = new HInvokeStatic( 5654 instruction = new HInvokeStatic(element.declaration, arguments, typeMask,
6089 element.declaration, arguments, typeMask,
6090 targetCanThrow: targetCanThrow) 5655 targetCanThrow: targetCanThrow)
6091 ..sourceInformation = sourceInformation; 5656 ..sourceInformation = sourceInformation;
6092 if (!currentInlinedInstantiations.isEmpty) { 5657 if (!currentInlinedInstantiations.isEmpty) {
6093 instruction.instantiatedTypes = new List<DartType>.from( 5658 instruction.instantiatedTypes =
6094 currentInlinedInstantiations); 5659 new List<DartType>.from(currentInlinedInstantiations);
6095 } 5660 }
6096 instruction.sideEffects = compiler.world.getSideEffectsOfElement(element); 5661 instruction.sideEffects = compiler.world.getSideEffectsOfElement(element);
6097 } 5662 }
6098 if (location == null) { 5663 if (location == null) {
6099 push(instruction); 5664 push(instruction);
6100 } else { 5665 } else {
6101 pushWithPosition(instruction, location); 5666 pushWithPosition(instruction, location);
6102 } 5667 }
6103 } 5668 }
6104 5669
6105 HInstruction buildInvokeSuper(Selector selector, 5670 HInstruction buildInvokeSuper(
6106 Element element, 5671 Selector selector, Element element, List<HInstruction> arguments,
6107 List<HInstruction> arguments, 5672 [SourceInformation sourceInformation]) {
6108 [SourceInformation sourceInformation]) {
6109 HInstruction receiver = localsHandler.readThis(); 5673 HInstruction receiver = localsHandler.readThis();
6110 // TODO(5346): Try to avoid the need for calling [declaration] before 5674 // TODO(5346): Try to avoid the need for calling [declaration] before
6111 // creating an [HStatic]. 5675 // creating an [HStatic].
6112 List<HInstruction> inputs = <HInstruction>[]; 5676 List<HInstruction> inputs = <HInstruction>[];
6113 if (backend.isInterceptedSelector(selector) && 5677 if (backend.isInterceptedSelector(selector) &&
6114 // Fields don't need an interceptor; consider generating HFieldGet/Set 5678 // Fields don't need an interceptor; consider generating HFieldGet/Set
6115 // instead. 5679 // instead.
6116 element.kind != ElementKind.FIELD) { 5680 element.kind != ElementKind.FIELD) {
6117 inputs.add(invokeInterceptor(receiver)); 5681 inputs.add(invokeInterceptor(receiver));
6118 } 5682 }
6119 inputs.add(receiver); 5683 inputs.add(receiver);
6120 inputs.addAll(arguments); 5684 inputs.addAll(arguments);
6121 TypeMask type; 5685 TypeMask type;
6122 if (!element.isGetter && selector.isGetter) { 5686 if (!element.isGetter && selector.isGetter) {
6123 type = TypeMaskFactory.inferredTypeForElement(element, compiler); 5687 type = TypeMaskFactory.inferredTypeForElement(element, compiler);
6124 } else { 5688 } else {
6125 type = TypeMaskFactory.inferredReturnTypeForElement(element, compiler); 5689 type = TypeMaskFactory.inferredReturnTypeForElement(element, compiler);
6126 } 5690 }
6127 HInstruction instruction = new HInvokeSuper( 5691 HInstruction instruction = new HInvokeSuper(element, currentNonClosureClass,
6128 element, 5692 selector, inputs, type, sourceInformation,
6129 currentNonClosureClass,
6130 selector,
6131 inputs,
6132 type,
6133 sourceInformation,
6134 isSetter: selector.isSetter || selector.isIndexSet); 5693 isSetter: selector.isSetter || selector.isIndexSet);
6135 instruction.sideEffects = 5694 instruction.sideEffects =
6136 compiler.world.getSideEffectsOfSelector(selector, null); 5695 compiler.world.getSideEffectsOfSelector(selector, null);
6137 return instruction; 5696 return instruction;
6138 } 5697 }
6139 5698
6140 void handleComplexOperatorSend(ast.SendSet node, 5699 void handleComplexOperatorSend(
6141 HInstruction receiver, 5700 ast.SendSet node, HInstruction receiver, Link<ast.Node> arguments) {
6142 Link<ast.Node> arguments) {
6143 HInstruction rhs; 5701 HInstruction rhs;
6144 if (node.isPrefix || node.isPostfix) { 5702 if (node.isPrefix || node.isPostfix) {
6145 rhs = graph.addConstantInt(1, compiler); 5703 rhs = graph.addConstantInt(1, compiler);
6146 } else { 5704 } else {
6147 visit(arguments.head); 5705 visit(arguments.head);
6148 assert(arguments.tail.isEmpty); 5706 assert(arguments.tail.isEmpty);
6149 rhs = pop(); 5707 rhs = pop();
6150 } 5708 }
6151 visitBinarySend( 5709 visitBinarySend(
6152 receiver, 5710 receiver,
6153 rhs, 5711 rhs,
6154 elements.getOperatorSelectorInComplexSendSet(node), 5712 elements.getOperatorSelectorInComplexSendSet(node),
6155 elements.getOperatorTypeMaskInComplexSendSet(node), 5713 elements.getOperatorTypeMaskInComplexSendSet(node),
6156 node, 5714 node,
6157 sourceInformation: 5715 sourceInformation:
6158 sourceInformationBuilder.buildGeneric(node.assignmentOperator)); 5716 sourceInformationBuilder.buildGeneric(node.assignmentOperator));
6159 } 5717 }
6160 5718
6161 void handleSuperSendSet(ast.SendSet node) { 5719 void handleSuperSendSet(ast.SendSet node) {
6162 Element element = elements[node]; 5720 Element element = elements[node];
6163 List<HInstruction> setterInputs = <HInstruction>[]; 5721 List<HInstruction> setterInputs = <HInstruction>[];
6164 void generateSuperSendSet() { 5722 void generateSuperSendSet() {
6165 Selector setterSelector = elements.getSelector(node); 5723 Selector setterSelector = elements.getSelector(node);
6166 if (Elements.isUnresolved(element) 5724 if (Elements.isUnresolved(element) ||
6167 || !setterSelector.applies(element, compiler.world)) { 5725 !setterSelector.applies(element, compiler.world)) {
6168 generateSuperNoSuchMethodSend( 5726 generateSuperNoSuchMethodSend(node, setterSelector, setterInputs);
6169 node, setterSelector, setterInputs);
6170 pop(); 5727 pop();
6171 } else { 5728 } else {
6172 add(buildInvokeSuper(setterSelector, element, setterInputs)); 5729 add(buildInvokeSuper(setterSelector, element, setterInputs));
6173 } 5730 }
6174 } 5731 }
6175 if (identical(node.assignmentOperator.source, '=')) { 5732 if (identical(node.assignmentOperator.source, '=')) {
6176 addDynamicSendArgumentsToList(node, setterInputs); 5733 addDynamicSendArgumentsToList(node, setterInputs);
6177 generateSuperSendSet(); 5734 generateSuperSendSet();
6178 stack.add(setterInputs.last); 5735 stack.add(setterInputs.last);
6179 } else { 5736 } else {
6180 Element getter = elements[node.selector]; 5737 Element getter = elements[node.selector];
6181 List<HInstruction> getterInputs = <HInstruction>[]; 5738 List<HInstruction> getterInputs = <HInstruction>[];
6182 Link<ast.Node> arguments = node.arguments; 5739 Link<ast.Node> arguments = node.arguments;
6183 if (node.isIndex) { 5740 if (node.isIndex) {
6184 // If node is of the form [:super.foo[0] += 2:], the send has 5741 // If node is of the form [:super.foo[0] += 2:], the send has
6185 // two arguments: the index and the left hand side. We get 5742 // two arguments: the index and the left hand side. We get
6186 // the index and add it as input of the getter and the 5743 // the index and add it as input of the getter and the
6187 // setter. 5744 // setter.
6188 visit(arguments.head); 5745 visit(arguments.head);
6189 arguments = arguments.tail; 5746 arguments = arguments.tail;
6190 HInstruction index = pop(); 5747 HInstruction index = pop();
6191 getterInputs.add(index); 5748 getterInputs.add(index);
6192 setterInputs.add(index); 5749 setterInputs.add(index);
6193 } 5750 }
6194 HInstruction getterInstruction; 5751 HInstruction getterInstruction;
6195 Selector getterSelector = 5752 Selector getterSelector =
6196 elements.getGetterSelectorInComplexSendSet(node); 5753 elements.getGetterSelectorInComplexSendSet(node);
6197 if (Elements.isUnresolved(getter)) { 5754 if (Elements.isUnresolved(getter)) {
6198 generateSuperNoSuchMethodSend( 5755 generateSuperNoSuchMethodSend(node, getterSelector, getterInputs);
6199 node,
6200 getterSelector,
6201 getterInputs);
6202 getterInstruction = pop(); 5756 getterInstruction = pop();
6203 } else { 5757 } else {
6204 getterInstruction = buildInvokeSuper( 5758 getterInstruction =
6205 getterSelector, getter, getterInputs); 5759 buildInvokeSuper(getterSelector, getter, getterInputs);
6206 add(getterInstruction); 5760 add(getterInstruction);
6207 } 5761 }
6208 5762
6209 if (node.isIfNullAssignment) { 5763 if (node.isIfNullAssignment) {
6210 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 5764 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node);
6211 brancher.handleIfNull(() => stack.add(getterInstruction), 5765 brancher.handleIfNull(() => stack.add(getterInstruction), () {
6212 () { 5766 addDynamicSendArgumentsToList(node, setterInputs);
6213 addDynamicSendArgumentsToList(node, setterInputs); 5767 generateSuperSendSet();
6214 generateSuperSendSet(); 5768 stack.add(setterInputs.last);
6215 stack.add(setterInputs.last); 5769 });
6216 });
6217 } else { 5770 } else {
6218 handleComplexOperatorSend(node, getterInstruction, arguments); 5771 handleComplexOperatorSend(node, getterInstruction, arguments);
6219 setterInputs.add(pop()); 5772 setterInputs.add(pop());
6220 generateSuperSendSet(); 5773 generateSuperSendSet();
6221 stack.add(node.isPostfix ? getterInstruction : setterInputs.last); 5774 stack.add(node.isPostfix ? getterInstruction : setterInputs.last);
6222 } 5775 }
6223 } 5776 }
6224 } 5777 }
6225 5778
6226 @override 5779 @override
6227 void handleSuperCompounds( 5780 void handleSuperCompounds(
6228 ast.SendSet node, 5781 ast.SendSet node,
6229 Element getter, 5782 Element getter,
6230 CompoundGetter getterKind, 5783 CompoundGetter getterKind,
6231 Element setter, 5784 Element setter,
6232 CompoundSetter setterKind, 5785 CompoundSetter setterKind,
6233 CompoundRhs rhs, 5786 CompoundRhs rhs,
6234 _) { 5787 _) {
6235 handleSuperSendSet(node); 5788 handleSuperSendSet(node);
6236 } 5789 }
6237 5790
6238 @override 5791 @override
6239 void visitFinalSuperFieldSet( 5792 void visitFinalSuperFieldSet(
6240 ast.SendSet node, 5793 ast.SendSet node, FieldElement field, ast.Node rhs, _) {
6241 FieldElement field,
6242 ast.Node rhs,
6243 _) {
6244 handleSuperSendSet(node); 5794 handleSuperSendSet(node);
6245 } 5795 }
6246 5796
6247 @override 5797 @override
6248 void visitSuperFieldSet( 5798 void visitSuperFieldSet(
6249 ast.SendSet node, 5799 ast.SendSet node, FieldElement field, ast.Node rhs, _) {
6250 FieldElement field,
6251 ast.Node rhs,
6252 _) {
6253 handleSuperSendSet(node); 5800 handleSuperSendSet(node);
6254 } 5801 }
6255 5802
6256 @override 5803 @override
6257 void visitSuperGetterSet( 5804 void visitSuperGetterSet(
6258 ast.SendSet node, 5805 ast.SendSet node, FunctionElement getter, ast.Node rhs, _) {
6259 FunctionElement getter,
6260 ast.Node rhs,
6261 _) {
6262 handleSuperSendSet(node); 5806 handleSuperSendSet(node);
6263 } 5807 }
6264 5808
6265 @override 5809 @override
6266 void visitSuperIndexSet( 5810 void visitSuperIndexSet(ast.SendSet node, FunctionElement function,
6267 ast.SendSet node, 5811 ast.Node index, ast.Node rhs, _) {
6268 FunctionElement function,
6269 ast.Node index,
6270 ast.Node rhs,
6271 _) {
6272 handleSuperSendSet(node); 5812 handleSuperSendSet(node);
6273 } 5813 }
6274 5814
6275 @override 5815 @override
6276 void visitSuperMethodSet( 5816 void visitSuperMethodSet(
6277 ast.Send node, 5817 ast.Send node, MethodElement method, ast.Node rhs, _) {
6278 MethodElement method,
6279 ast.Node rhs,
6280 _) {
6281 handleSuperSendSet(node); 5818 handleSuperSendSet(node);
6282 } 5819 }
6283 5820
6284 @override 5821 @override
6285 void visitSuperSetterSet( 5822 void visitSuperSetterSet(
6286 ast.SendSet node, 5823 ast.SendSet node, FunctionElement setter, ast.Node rhs, _) {
6287 FunctionElement setter,
6288 ast.Node rhs,
6289 _) {
6290 handleSuperSendSet(node); 5824 handleSuperSendSet(node);
6291 } 5825 }
6292 5826
6293 @override 5827 @override
6294 void visitUnresolvedSuperIndexSet( 5828 void visitUnresolvedSuperIndexSet(
6295 ast.Send node, 5829 ast.Send node, Element element, ast.Node index, ast.Node rhs, _) {
6296 Element element,
6297 ast.Node index,
6298 ast.Node rhs,
6299 _) {
6300 handleSuperSendSet(node); 5830 handleSuperSendSet(node);
6301 } 5831 }
6302 5832
6303 @override 5833 @override
6304 void visitSuperIndexPrefix( 5834 void visitSuperIndexPrefix(
6305 ast.Send node, 5835 ast.Send node,
6306 MethodElement indexFunction, 5836 MethodElement indexFunction,
6307 MethodElement indexSetFunction, 5837 MethodElement indexSetFunction,
6308 ast.Node index, 5838 ast.Node index,
6309 IncDecOperator operator, 5839 IncDecOperator operator,
6310 _) { 5840 _) {
6311 handleSuperSendSet(node); 5841 handleSuperSendSet(node);
6312 } 5842 }
6313 5843
6314 @override 5844 @override
6315 void visitSuperIndexPostfix( 5845 void visitSuperIndexPostfix(
6316 ast.Send node, 5846 ast.Send node,
6317 MethodElement indexFunction, 5847 MethodElement indexFunction,
6318 MethodElement indexSetFunction, 5848 MethodElement indexSetFunction,
6319 ast.Node index, 5849 ast.Node index,
6320 IncDecOperator operator, 5850 IncDecOperator operator,
6321 _) { 5851 _) {
6322 handleSuperSendSet(node); 5852 handleSuperSendSet(node);
6323 } 5853 }
6324 5854
6325 @override 5855 @override
6326 void visitUnresolvedSuperGetterIndexPrefix( 5856 void visitUnresolvedSuperGetterIndexPrefix(ast.Send node, Element element,
6327 ast.Send node, 5857 MethodElement setter, ast.Node index, IncDecOperator operator, _) {
6328 Element element,
6329 MethodElement setter,
6330 ast.Node index,
6331 IncDecOperator operator,
6332 _) {
6333 handleSuperSendSet(node); 5858 handleSuperSendSet(node);
6334 } 5859 }
6335 5860
6336 @override 5861 @override
6337 void visitUnresolvedSuperGetterIndexPostfix( 5862 void visitUnresolvedSuperGetterIndexPostfix(ast.Send node, Element element,
6338 ast.Send node, 5863 MethodElement setter, ast.Node index, IncDecOperator operator, _) {
6339 Element element,
6340 MethodElement setter,
6341 ast.Node index,
6342 IncDecOperator operator,
6343 _) {
6344 handleSuperSendSet(node); 5864 handleSuperSendSet(node);
6345 } 5865 }
6346 5866
6347 @override 5867 @override
6348 void visitUnresolvedSuperSetterIndexPrefix( 5868 void visitUnresolvedSuperSetterIndexPrefix(
6349 ast.Send node, 5869 ast.Send node,
6350 MethodElement indexFunction, 5870 MethodElement indexFunction,
6351 Element element, 5871 Element element,
6352 ast.Node index, 5872 ast.Node index,
6353 IncDecOperator operator, 5873 IncDecOperator operator,
6354 _) { 5874 _) {
6355 handleSuperSendSet(node); 5875 handleSuperSendSet(node);
6356 } 5876 }
6357 5877
6358 @override 5878 @override
6359 void visitUnresolvedSuperSetterIndexPostfix( 5879 void visitUnresolvedSuperSetterIndexPostfix(
6360 ast.Send node, 5880 ast.Send node,
6361 MethodElement indexFunction, 5881 MethodElement indexFunction,
6362 Element element, 5882 Element element,
6363 ast.Node index, 5883 ast.Node index,
6364 IncDecOperator operator, 5884 IncDecOperator operator,
6365 _) { 5885 _) {
6366 handleSuperSendSet(node); 5886 handleSuperSendSet(node);
6367 } 5887 }
6368 5888
6369 @override 5889 @override
6370 void visitUnresolvedSuperIndexPrefix( 5890 void visitUnresolvedSuperIndexPrefix(ast.Send node, Element element,
6371 ast.Send node, 5891 ast.Node index, IncDecOperator operator, _) {
6372 Element element,
6373 ast.Node index,
6374 IncDecOperator operator,
6375 _) {
6376 handleSuperSendSet(node); 5892 handleSuperSendSet(node);
6377 } 5893 }
6378 5894
6379 @override 5895 @override
6380 void visitUnresolvedSuperIndexPostfix( 5896 void visitUnresolvedSuperIndexPostfix(ast.Send node, Element element,
6381 ast.Send node, 5897 ast.Node index, IncDecOperator operator, _) {
6382 Element element,
6383 ast.Node index,
6384 IncDecOperator operator,
6385 _) {
6386 handleSuperSendSet(node); 5898 handleSuperSendSet(node);
6387 } 5899 }
6388 5900
6389 @override 5901 @override
6390 void visitSuperCompoundIndexSet( 5902 void visitSuperCompoundIndexSet(
6391 ast.SendSet node, 5903 ast.SendSet node,
6392 MethodElement getter, 5904 MethodElement getter,
6393 MethodElement setter, 5905 MethodElement setter,
6394 ast.Node index, 5906 ast.Node index,
6395 AssignmentOperator operator, 5907 AssignmentOperator operator,
(...skipping 20 matching lines...) Expand all
6416 MethodElement getter, 5928 MethodElement getter,
6417 Element element, 5929 Element element,
6418 ast.Node index, 5930 ast.Node index,
6419 AssignmentOperator operator, 5931 AssignmentOperator operator,
6420 ast.Node rhs, 5932 ast.Node rhs,
6421 _) { 5933 _) {
6422 handleSuperSendSet(node); 5934 handleSuperSendSet(node);
6423 } 5935 }
6424 5936
6425 @override 5937 @override
6426 void visitUnresolvedSuperCompoundIndexSet( 5938 void visitUnresolvedSuperCompoundIndexSet(ast.Send node, Element element,
6427 ast.Send node, 5939 ast.Node index, AssignmentOperator operator, ast.Node rhs, _) {
6428 Element element,
6429 ast.Node index,
6430 AssignmentOperator operator,
6431 ast.Node rhs,
6432 _) {
6433 handleSuperSendSet(node); 5940 handleSuperSendSet(node);
6434 } 5941 }
6435 5942
6436 @override 5943 @override
6437 void visitSuperFieldCompound( 5944 void visitSuperFieldCompound(ast.Send node, FieldElement field,
6438 ast.Send node, 5945 AssignmentOperator operator, ast.Node rhs, _) {
6439 FieldElement field,
6440 AssignmentOperator operator,
6441 ast.Node rhs,
6442 _) {
6443 handleSuperSendSet(node); 5946 handleSuperSendSet(node);
6444 } 5947 }
6445 5948
6446 @override 5949 @override
6447 void visitFinalSuperFieldCompound( 5950 void visitFinalSuperFieldCompound(ast.Send node, FieldElement field,
6448 ast.Send node, 5951 AssignmentOperator operator, ast.Node rhs, _) {
6449 FieldElement field,
6450 AssignmentOperator operator,
6451 ast.Node rhs,
6452 _) {
6453 handleSuperSendSet(node); 5952 handleSuperSendSet(node);
6454 } 5953 }
6455 5954
6456 @override 5955 @override
6457 void visitFinalSuperFieldPrefix( 5956 void visitFinalSuperFieldPrefix(
6458 ast.Send node, 5957 ast.Send node, FieldElement field, IncDecOperator operator, _) {
6459 FieldElement field,
6460 IncDecOperator operator,
6461 _) {
6462 handleSuperSendSet(node); 5958 handleSuperSendSet(node);
6463 } 5959 }
6464 5960
6465 @override 5961 @override
6466 void visitUnresolvedSuperPrefix( 5962 void visitUnresolvedSuperPrefix(
6467 ast.Send node, 5963 ast.Send node, Element element, IncDecOperator operator, _) {
6468 Element element,
6469 IncDecOperator operator,
6470 _) {
6471 handleSuperSendSet(node); 5964 handleSuperSendSet(node);
6472 } 5965 }
6473 5966
6474 @override 5967 @override
6475 void visitUnresolvedSuperPostfix( 5968 void visitUnresolvedSuperPostfix(
6476 ast.Send node, 5969 ast.Send node, Element element, IncDecOperator operator, _) {
6477 Element element,
6478 IncDecOperator operator,
6479 _) {
6480 handleSuperSendSet(node); 5970 handleSuperSendSet(node);
6481 } 5971 }
6482 5972
6483 @override 5973 @override
6484 void visitUnresolvedSuperCompound( 5974 void visitUnresolvedSuperCompound(ast.Send node, Element element,
6485 ast.Send node, 5975 AssignmentOperator operator, ast.Node rhs, _) {
6486 Element element,
6487 AssignmentOperator operator,
6488 ast.Node rhs,
6489 _) {
6490 handleSuperSendSet(node); 5976 handleSuperSendSet(node);
6491 } 5977 }
6492 5978
6493 @override 5979 @override
6494 void visitFinalSuperFieldPostfix( 5980 void visitFinalSuperFieldPostfix(
6495 ast.Send node, 5981 ast.Send node, FieldElement field, IncDecOperator operator, _) {
6496 FieldElement field,
6497 IncDecOperator operator,
6498 _) {
6499 handleSuperSendSet(node); 5982 handleSuperSendSet(node);
6500 } 5983 }
6501 5984
6502 @override 5985 @override
6503 void visitSuperFieldFieldCompound( 5986 void visitSuperFieldFieldCompound(ast.Send node, FieldElement readField,
6504 ast.Send node, 5987 FieldElement writtenField, AssignmentOperator operator, ast.Node rhs, _) {
6505 FieldElement readField,
6506 FieldElement writtenField,
6507 AssignmentOperator operator,
6508 ast.Node rhs,
6509 _) {
6510 handleSuperSendSet(node); 5988 handleSuperSendSet(node);
6511 } 5989 }
6512 5990
6513 @override 5991 @override
6514 void visitSuperGetterSetterCompound( 5992 void visitSuperGetterSetterCompound(ast.Send node, FunctionElement getter,
6515 ast.Send node, 5993 FunctionElement setter, AssignmentOperator operator, ast.Node rhs, _) {
6516 FunctionElement getter,
6517 FunctionElement setter,
6518 AssignmentOperator operator,
6519 ast.Node rhs,
6520 _) {
6521 handleSuperSendSet(node); 5994 handleSuperSendSet(node);
6522 } 5995 }
6523 5996
6524 @override 5997 @override
6525 void visitSuperMethodSetterCompound( 5998 void visitSuperMethodSetterCompound(ast.Send node, FunctionElement method,
6526 ast.Send node, 5999 FunctionElement setter, AssignmentOperator operator, ast.Node rhs, _) {
6527 FunctionElement method,
6528 FunctionElement setter,
6529 AssignmentOperator operator,
6530 ast.Node rhs,
6531 _) {
6532 handleSuperSendSet(node); 6000 handleSuperSendSet(node);
6533 } 6001 }
6534 6002
6535 @override 6003 @override
6536 void visitSuperMethodCompound( 6004 void visitSuperMethodCompound(ast.Send node, FunctionElement method,
6537 ast.Send node, 6005 AssignmentOperator operator, ast.Node rhs, _) {
6538 FunctionElement method,
6539 AssignmentOperator operator,
6540 ast.Node rhs,
6541 _) {
6542 handleSuperSendSet(node); 6006 handleSuperSendSet(node);
6543 } 6007 }
6544 6008
6545 @override 6009 @override
6546 void visitUnresolvedSuperGetterCompound( 6010 void visitUnresolvedSuperGetterCompound(ast.Send node, Element element,
6547 ast.Send node, 6011 MethodElement setter, AssignmentOperator operator, ast.Node rhs, _) {
6548 Element element,
6549 MethodElement setter,
6550 AssignmentOperator operator,
6551 ast.Node rhs,
6552 _) {
6553 handleSuperSendSet(node); 6012 handleSuperSendSet(node);
6554 } 6013 }
6555 6014
6556 @override 6015 @override
6557 void visitUnresolvedSuperSetterCompound( 6016 void visitUnresolvedSuperSetterCompound(ast.Send node, MethodElement getter,
6558 ast.Send node, 6017 Element element, AssignmentOperator operator, ast.Node rhs, _) {
6559 MethodElement getter,
6560 Element element,
6561 AssignmentOperator operator,
6562 ast.Node rhs,
6563 _) {
6564 handleSuperSendSet(node); 6018 handleSuperSendSet(node);
6565 } 6019 }
6566 6020
6567 @override 6021 @override
6568 void visitSuperFieldSetterCompound( 6022 void visitSuperFieldSetterCompound(ast.Send node, FieldElement field,
6569 ast.Send node, 6023 FunctionElement setter, AssignmentOperator operator, ast.Node rhs, _) {
6570 FieldElement field,
6571 FunctionElement setter,
6572 AssignmentOperator operator,
6573 ast.Node rhs,
6574 _) {
6575 handleSuperSendSet(node); 6024 handleSuperSendSet(node);
6576 } 6025 }
6577 6026
6578 @override 6027 @override
6579 void visitSuperGetterFieldCompound( 6028 void visitSuperGetterFieldCompound(ast.Send node, FunctionElement getter,
6580 ast.Send node, 6029 FieldElement field, AssignmentOperator operator, ast.Node rhs, _) {
6581 FunctionElement getter,
6582 FieldElement field,
6583 AssignmentOperator operator,
6584 ast.Node rhs,
6585 _) {
6586 handleSuperSendSet(node); 6030 handleSuperSendSet(node);
6587 } 6031 }
6588 6032
6589 @override 6033 @override
6590 void visitIndexSet( 6034 void visitIndexSet(
6591 ast.SendSet node, 6035 ast.SendSet node, ast.Node receiver, ast.Node index, ast.Node rhs, _) {
6592 ast.Node receiver,
6593 ast.Node index,
6594 ast.Node rhs,
6595 _) {
6596 generateDynamicSend(node); 6036 generateDynamicSend(node);
6597 } 6037 }
6598 6038
6599 @override 6039 @override
6600 void visitCompoundIndexSet( 6040 void visitCompoundIndexSet(ast.SendSet node, ast.Node receiver,
6601 ast.SendSet node, 6041 ast.Node index, AssignmentOperator operator, ast.Node rhs, _) {
6602 ast.Node receiver,
6603 ast.Node index,
6604 AssignmentOperator operator,
6605 ast.Node rhs,
6606 _) {
6607 generateIsDeferredLoadedCheckOfSend(node); 6042 generateIsDeferredLoadedCheckOfSend(node);
6608 handleIndexSendSet(node); 6043 handleIndexSendSet(node);
6609 } 6044 }
6610 6045
6611 @override 6046 @override
6612 void visitIndexPrefix( 6047 void visitIndexPrefix(ast.Send node, ast.Node receiver, ast.Node index,
6613 ast.Send node, 6048 IncDecOperator operator, _) {
6614 ast.Node receiver,
6615 ast.Node index,
6616 IncDecOperator operator,
6617 _) {
6618 generateIsDeferredLoadedCheckOfSend(node); 6049 generateIsDeferredLoadedCheckOfSend(node);
6619 handleIndexSendSet(node); 6050 handleIndexSendSet(node);
6620 } 6051 }
6621 6052
6622 @override 6053 @override
6623 void visitIndexPostfix( 6054 void visitIndexPostfix(ast.Send node, ast.Node receiver, ast.Node index,
6624 ast.Send node, 6055 IncDecOperator operator, _) {
6625 ast.Node receiver,
6626 ast.Node index,
6627 IncDecOperator operator,
6628 _) {
6629 generateIsDeferredLoadedCheckOfSend(node); 6056 generateIsDeferredLoadedCheckOfSend(node);
6630 handleIndexSendSet(node); 6057 handleIndexSendSet(node);
6631 } 6058 }
6632 6059
6633 void handleIndexSendSet(ast.SendSet node) { 6060 void handleIndexSendSet(ast.SendSet node) {
6634 ast.Operator op = node.assignmentOperator; 6061 ast.Operator op = node.assignmentOperator;
6635 if ("=" == op.source) { 6062 if ("=" == op.source) {
6636 internalError(node, "Unexpected index set."); 6063 internalError(node, "Unexpected index set.");
6637 } else { 6064 } else {
6638 visit(node.receiver); 6065 visit(node.receiver);
6639 HInstruction receiver = pop(); 6066 HInstruction receiver = pop();
6640 Link<ast.Node> arguments = node.arguments; 6067 Link<ast.Node> arguments = node.arguments;
6641 HInstruction index; 6068 HInstruction index;
6642 if (node.isIndex) { 6069 if (node.isIndex) {
6643 visit(arguments.head); 6070 visit(arguments.head);
6644 arguments = arguments.tail; 6071 arguments = arguments.tail;
6645 index = pop(); 6072 index = pop();
6646 } 6073 }
6647 6074
6648 pushInvokeDynamic( 6075 pushInvokeDynamic(node, elements.getGetterSelectorInComplexSendSet(node),
6649 node, 6076 elements.getGetterTypeMaskInComplexSendSet(node), [receiver, index]);
6650 elements.getGetterSelectorInComplexSendSet(node),
6651 elements.getGetterTypeMaskInComplexSendSet(node),
6652 [receiver, index]);
6653 HInstruction getterInstruction = pop(); 6077 HInstruction getterInstruction = pop();
6654 if (node.isIfNullAssignment) { 6078 if (node.isIfNullAssignment) {
6655 // Compile x[i] ??= e as: 6079 // Compile x[i] ??= e as:
6656 // t1 = x[i] 6080 // t1 = x[i]
6657 // if (t1 == null) 6081 // if (t1 == null)
6658 // t1 = x[i] = e; 6082 // t1 = x[i] = e;
6659 // result = t1 6083 // result = t1
6660 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 6084 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node);
6661 brancher.handleIfNull(() => stack.add(getterInstruction), 6085 brancher.handleIfNull(() => stack.add(getterInstruction), () {
6662 () { 6086 visit(arguments.head);
6663 visit(arguments.head); 6087 HInstruction value = pop();
6664 HInstruction value = pop(); 6088 pushInvokeDynamic(node, elements.getSelector(node),
6665 pushInvokeDynamic( 6089 elements.getTypeMask(node), [receiver, index, value]);
6666 node, 6090 pop();
6667 elements.getSelector(node), 6091 stack.add(value);
6668 elements.getTypeMask(node), 6092 });
6669 [receiver, index, value]);
6670 pop();
6671 stack.add(value);
6672 });
6673 } else { 6093 } else {
6674 handleComplexOperatorSend(node, getterInstruction, arguments); 6094 handleComplexOperatorSend(node, getterInstruction, arguments);
6675 HInstruction value = pop(); 6095 HInstruction value = pop();
6676 pushInvokeDynamic( 6096 pushInvokeDynamic(node, elements.getSelector(node),
6677 node, 6097 elements.getTypeMask(node), [receiver, index, value]);
6678 elements.getSelector(node),
6679 elements.getTypeMask(node),
6680 [receiver, index, value]);
6681 pop(); 6098 pop();
6682 if (node.isPostfix) { 6099 if (node.isPostfix) {
6683 stack.add(getterInstruction); 6100 stack.add(getterInstruction);
6684 } else { 6101 } else {
6685 stack.add(value); 6102 stack.add(value);
6686 } 6103 }
6687 } 6104 }
6688 } 6105 }
6689 } 6106 }
6690 6107
6691 @override 6108 @override
6692 void visitThisPropertySet( 6109 void visitThisPropertySet(ast.SendSet node, Name name, ast.Node rhs, _) {
6693 ast.SendSet node,
6694 Name name,
6695 ast.Node rhs,
6696 _) {
6697 generateInstanceSetterWithCompiledReceiver( 6110 generateInstanceSetterWithCompiledReceiver(
6698 node, 6111 node, localsHandler.readThis(), visitAndPop(rhs));
6699 localsHandler.readThis(),
6700 visitAndPop(rhs));
6701 } 6112 }
6702 6113
6703 @override 6114 @override
6704 void visitDynamicPropertySet( 6115 void visitDynamicPropertySet(
6705 ast.SendSet node, 6116 ast.SendSet node, ast.Node receiver, Name name, ast.Node rhs, _) {
6706 ast.Node receiver,
6707 Name name,
6708 ast.Node rhs,
6709 _) {
6710 generateInstanceSetterWithCompiledReceiver( 6117 generateInstanceSetterWithCompiledReceiver(
6711 node, 6118 node, generateInstanceSendReceiver(node), visitAndPop(rhs));
6712 generateInstanceSendReceiver(node),
6713 visitAndPop(rhs));
6714 } 6119 }
6715 6120
6716 @override 6121 @override
6717 void visitIfNotNullDynamicPropertySet( 6122 void visitIfNotNullDynamicPropertySet(
6718 ast.SendSet node, 6123 ast.SendSet node, ast.Node receiver, Name name, ast.Node rhs, _) {
6719 ast.Node receiver,
6720 Name name,
6721 ast.Node rhs,
6722 _) {
6723 // compile e?.x = e2 to: 6124 // compile e?.x = e2 to:
6724 // 6125 //
6725 // t1 = e 6126 // t1 = e
6726 // if (t1 == null) 6127 // if (t1 == null)
6727 // result = t1 // same as result = null 6128 // result = t1 // same as result = null
6728 // else 6129 // else
6729 // result = e.x = e2 6130 // result = e.x = e2
6730 HInstruction receiverInstruction; 6131 HInstruction receiverInstruction;
6731 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 6132 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node);
6732 brancher.handleConditional( 6133 brancher.handleConditional(
6733 () { 6134 () {
6734 receiverInstruction = generateInstanceSendReceiver(node); 6135 receiverInstruction = generateInstanceSendReceiver(node);
6735 pushCheckNull(receiverInstruction); 6136 pushCheckNull(receiverInstruction);
6736 }, 6137 },
6737 () => stack.add(receiverInstruction), 6138 () => stack.add(receiverInstruction),
6738 () { 6139 () {
6739 generateInstanceSetterWithCompiledReceiver( 6140 generateInstanceSetterWithCompiledReceiver(
6740 node, 6141 node, receiverInstruction, visitAndPop(rhs));
6741 receiverInstruction,
6742 visitAndPop(rhs));
6743 }); 6142 });
6744 } 6143 }
6745 6144
6746 @override 6145 @override
6747 void visitParameterSet( 6146 void visitParameterSet(
6748 ast.SendSet node, 6147 ast.SendSet node, ParameterElement parameter, ast.Node rhs, _) {
6749 ParameterElement parameter,
6750 ast.Node rhs,
6751 _) {
6752 generateNonInstanceSetter(node, parameter, visitAndPop(rhs)); 6148 generateNonInstanceSetter(node, parameter, visitAndPop(rhs));
6753 } 6149 }
6754 6150
6755 @override 6151 @override
6756 void visitFinalParameterSet( 6152 void visitFinalParameterSet(
6757 ast.SendSet node, 6153 ast.SendSet node, ParameterElement parameter, ast.Node rhs, _) {
6758 ParameterElement parameter,
6759 ast.Node rhs,
6760 _) {
6761 generateNoSuchSetter(node, parameter, visitAndPop(rhs)); 6154 generateNoSuchSetter(node, parameter, visitAndPop(rhs));
6762 } 6155 }
6763 6156
6764 @override 6157 @override
6765 void visitLocalVariableSet( 6158 void visitLocalVariableSet(
6766 ast.SendSet node, 6159 ast.SendSet node, LocalVariableElement variable, ast.Node rhs, _) {
6767 LocalVariableElement variable,
6768 ast.Node rhs,
6769 _) {
6770 generateNonInstanceSetter(node, variable, visitAndPop(rhs)); 6160 generateNonInstanceSetter(node, variable, visitAndPop(rhs));
6771 } 6161 }
6772 6162
6773 @override 6163 @override
6774 void visitFinalLocalVariableSet( 6164 void visitFinalLocalVariableSet(
6775 ast.SendSet node, 6165 ast.SendSet node, LocalVariableElement variable, ast.Node rhs, _) {
6776 LocalVariableElement variable,
6777 ast.Node rhs,
6778 _) {
6779 generateNoSuchSetter(node, variable, visitAndPop(rhs)); 6166 generateNoSuchSetter(node, variable, visitAndPop(rhs));
6780 } 6167 }
6781 6168
6782 @override 6169 @override
6783 void visitLocalFunctionSet( 6170 void visitLocalFunctionSet(
6784 ast.SendSet node, 6171 ast.SendSet node, LocalFunctionElement function, ast.Node rhs, _) {
6785 LocalFunctionElement function,
6786 ast.Node rhs,
6787 _) {
6788 generateNoSuchSetter(node, function, visitAndPop(rhs)); 6172 generateNoSuchSetter(node, function, visitAndPop(rhs));
6789 } 6173 }
6790 6174
6791 @override 6175 @override
6792 void visitTopLevelFieldSet( 6176 void visitTopLevelFieldSet(
6793 ast.SendSet node, 6177 ast.SendSet node, FieldElement field, ast.Node rhs, _) {
6794 FieldElement field,
6795 ast.Node rhs,
6796 _) {
6797 generateIsDeferredLoadedCheckOfSend(node); 6178 generateIsDeferredLoadedCheckOfSend(node);
6798 generateNonInstanceSetter(node, field, visitAndPop(rhs)); 6179 generateNonInstanceSetter(node, field, visitAndPop(rhs));
6799 } 6180 }
6800 6181
6801 @override 6182 @override
6802 void visitFinalTopLevelFieldSet( 6183 void visitFinalTopLevelFieldSet(
6803 ast.SendSet node, 6184 ast.SendSet node, FieldElement field, ast.Node rhs, _) {
6804 FieldElement field,
6805 ast.Node rhs,
6806 _) {
6807 generateIsDeferredLoadedCheckOfSend(node); 6185 generateIsDeferredLoadedCheckOfSend(node);
6808 generateNoSuchSetter(node, field, visitAndPop(rhs)); 6186 generateNoSuchSetter(node, field, visitAndPop(rhs));
6809 } 6187 }
6810 6188
6811 @override 6189 @override
6812 void visitTopLevelGetterSet( 6190 void visitTopLevelGetterSet(
6813 ast.SendSet node, 6191 ast.SendSet node, GetterElement getter, ast.Node rhs, _) {
6814 GetterElement getter,
6815 ast.Node rhs,
6816 _) {
6817 generateIsDeferredLoadedCheckOfSend(node); 6192 generateIsDeferredLoadedCheckOfSend(node);
6818 generateNoSuchSetter(node, getter, visitAndPop(rhs)); 6193 generateNoSuchSetter(node, getter, visitAndPop(rhs));
6819 } 6194 }
6820 6195
6821 @override 6196 @override
6822 void visitTopLevelSetterSet( 6197 void visitTopLevelSetterSet(
6823 ast.SendSet node, 6198 ast.SendSet node, SetterElement setter, ast.Node rhs, _) {
6824 SetterElement setter,
6825 ast.Node rhs,
6826 _) {
6827 generateIsDeferredLoadedCheckOfSend(node); 6199 generateIsDeferredLoadedCheckOfSend(node);
6828 generateNonInstanceSetter(node, setter, visitAndPop(rhs)); 6200 generateNonInstanceSetter(node, setter, visitAndPop(rhs));
6829 } 6201 }
6830 6202
6831 @override 6203 @override
6832 void visitTopLevelFunctionSet( 6204 void visitTopLevelFunctionSet(
6833 ast.SendSet node, 6205 ast.SendSet node, MethodElement function, ast.Node rhs, _) {
6834 MethodElement function,
6835 ast.Node rhs,
6836 _) {
6837 generateIsDeferredLoadedCheckOfSend(node); 6206 generateIsDeferredLoadedCheckOfSend(node);
6838 generateNoSuchSetter(node, function, visitAndPop(rhs)); 6207 generateNoSuchSetter(node, function, visitAndPop(rhs));
6839 } 6208 }
6840 6209
6841 @override 6210 @override
6842 void visitStaticFieldSet( 6211 void visitStaticFieldSet(
6843 ast.SendSet node, 6212 ast.SendSet node, FieldElement field, ast.Node rhs, _) {
6844 FieldElement field,
6845 ast.Node rhs,
6846 _) {
6847 generateIsDeferredLoadedCheckOfSend(node); 6213 generateIsDeferredLoadedCheckOfSend(node);
6848 generateNonInstanceSetter(node, field, visitAndPop(rhs)); 6214 generateNonInstanceSetter(node, field, visitAndPop(rhs));
6849 } 6215 }
6850 6216
6851 @override 6217 @override
6852 void visitFinalStaticFieldSet( 6218 void visitFinalStaticFieldSet(
6853 ast.SendSet node, 6219 ast.SendSet node, FieldElement field, ast.Node rhs, _) {
6854 FieldElement field,
6855 ast.Node rhs,
6856 _) {
6857 generateIsDeferredLoadedCheckOfSend(node); 6220 generateIsDeferredLoadedCheckOfSend(node);
6858 generateNoSuchSetter(node, field, visitAndPop(rhs)); 6221 generateNoSuchSetter(node, field, visitAndPop(rhs));
6859 } 6222 }
6860 6223
6861 @override 6224 @override
6862 void visitStaticGetterSet( 6225 void visitStaticGetterSet(
6863 ast.SendSet node, 6226 ast.SendSet node, GetterElement getter, ast.Node rhs, _) {
6864 GetterElement getter,
6865 ast.Node rhs,
6866 _) {
6867 generateIsDeferredLoadedCheckOfSend(node); 6227 generateIsDeferredLoadedCheckOfSend(node);
6868 generateNoSuchSetter(node, getter, visitAndPop(rhs)); 6228 generateNoSuchSetter(node, getter, visitAndPop(rhs));
6869 } 6229 }
6870 6230
6871 @override 6231 @override
6872 void visitStaticSetterSet( 6232 void visitStaticSetterSet(
6873 ast.SendSet node, 6233 ast.SendSet node, SetterElement setter, ast.Node rhs, _) {
6874 SetterElement setter,
6875 ast.Node rhs,
6876 _) {
6877 generateIsDeferredLoadedCheckOfSend(node); 6234 generateIsDeferredLoadedCheckOfSend(node);
6878 generateNonInstanceSetter(node, setter, visitAndPop(rhs)); 6235 generateNonInstanceSetter(node, setter, visitAndPop(rhs));
6879 } 6236 }
6880 6237
6881 @override 6238 @override
6882 void visitStaticFunctionSet( 6239 void visitStaticFunctionSet(
6883 ast.SendSet node, 6240 ast.SendSet node, MethodElement function, ast.Node rhs, _) {
6884 MethodElement function,
6885 ast.Node rhs,
6886 _) {
6887 generateIsDeferredLoadedCheckOfSend(node); 6241 generateIsDeferredLoadedCheckOfSend(node);
6888 generateNoSuchSetter(node, function, visitAndPop(rhs)); 6242 generateNoSuchSetter(node, function, visitAndPop(rhs));
6889 } 6243 }
6890 6244
6891 @override 6245 @override
6892 void visitUnresolvedSet( 6246 void visitUnresolvedSet(ast.SendSet node, Element element, ast.Node rhs, _) {
6893 ast.SendSet node,
6894 Element element,
6895 ast.Node rhs,
6896 _) {
6897 generateIsDeferredLoadedCheckOfSend(node); 6247 generateIsDeferredLoadedCheckOfSend(node);
6898 generateNonInstanceSetter(node, element, visitAndPop(rhs)); 6248 generateNonInstanceSetter(node, element, visitAndPop(rhs));
6899 } 6249 }
6900 6250
6901 @override 6251 @override
6902 void visitClassTypeLiteralSet( 6252 void visitClassTypeLiteralSet(
6903 ast.SendSet node, 6253 ast.SendSet node, TypeConstantExpression constant, ast.Node rhs, _) {
6904 TypeConstantExpression constant,
6905 ast.Node rhs,
6906 _) {
6907 generateThrowNoSuchMethod(node, constant.type.name, 6254 generateThrowNoSuchMethod(node, constant.type.name,
6908 argumentNodes: node.arguments); 6255 argumentNodes: node.arguments);
6909 } 6256 }
6910 6257
6911 @override 6258 @override
6912 void visitTypedefTypeLiteralSet( 6259 void visitTypedefTypeLiteralSet(
6913 ast.SendSet node, 6260 ast.SendSet node, TypeConstantExpression constant, ast.Node rhs, _) {
6914 TypeConstantExpression constant,
6915 ast.Node rhs,
6916 _) {
6917 generateThrowNoSuchMethod(node, constant.type.name, 6261 generateThrowNoSuchMethod(node, constant.type.name,
6918 argumentNodes: node.arguments); 6262 argumentNodes: node.arguments);
6919 } 6263 }
6920 6264
6921 @override 6265 @override
6922 void visitDynamicTypeLiteralSet( 6266 void visitDynamicTypeLiteralSet(
6923 ast.SendSet node, 6267 ast.SendSet node, TypeConstantExpression constant, ast.Node rhs, _) {
6924 TypeConstantExpression constant,
6925 ast.Node rhs,
6926 _) {
6927 generateThrowNoSuchMethod(node, constant.type.name, 6268 generateThrowNoSuchMethod(node, constant.type.name,
6928 argumentNodes: node.arguments); 6269 argumentNodes: node.arguments);
6929 } 6270 }
6930 6271
6931 @override 6272 @override
6932 void visitTypeVariableTypeLiteralSet( 6273 void visitTypeVariableTypeLiteralSet(
6933 ast.SendSet node, 6274 ast.SendSet node, TypeVariableElement element, ast.Node rhs, _) {
6934 TypeVariableElement element,
6935 ast.Node rhs,
6936 _) {
6937 generateThrowNoSuchMethod(node, element.name, 6275 generateThrowNoSuchMethod(node, element.name,
6938 argumentNodes: node.arguments); 6276 argumentNodes: node.arguments);
6939 } 6277 }
6940 6278
6941 void handleCompoundSendSet(ast.SendSet node) { 6279 void handleCompoundSendSet(ast.SendSet node) {
6942 Element element = elements[node]; 6280 Element element = elements[node];
6943 Element getter = elements[node.selector]; 6281 Element getter = elements[node.selector];
6944 6282
6945 if (!Elements.isUnresolved(getter) && getter.impliesType) { 6283 if (!Elements.isUnresolved(getter) && getter.impliesType) {
6946 if (node.isIfNullAssignment) { 6284 if (node.isIfNullAssignment) {
6947 // C ??= x is compiled just as C. 6285 // C ??= x is compiled just as C.
6948 stack.add(addConstant(node.selector)); 6286 stack.add(addConstant(node.selector));
6949 } else { 6287 } else {
6950 ast.Identifier selector = node.selector; 6288 ast.Identifier selector = node.selector;
6951 generateThrowNoSuchMethod(node, selector.source, 6289 generateThrowNoSuchMethod(node, selector.source,
6952 argumentNodes: node.arguments); 6290 argumentNodes: node.arguments);
6953 } 6291 }
6954 return; 6292 return;
6955 } 6293 }
6956 6294
6957 if (Elements.isInstanceSend(node, elements)) { 6295 if (Elements.isInstanceSend(node, elements)) {
6958 void generateAssignment(HInstruction receiver) { 6296 void generateAssignment(HInstruction receiver) {
6959 // desugars `e.x op= e2` to `e.x = e.x op e2` 6297 // desugars `e.x op= e2` to `e.x = e.x op e2`
6960 generateInstanceGetterWithCompiledReceiver( 6298 generateInstanceGetterWithCompiledReceiver(
6961 node, 6299 node,
6962 elements.getGetterSelectorInComplexSendSet(node), 6300 elements.getGetterSelectorInComplexSendSet(node),
6963 elements.getGetterTypeMaskInComplexSendSet(node), 6301 elements.getGetterTypeMaskInComplexSendSet(node),
6964 receiver); 6302 receiver);
6965 HInstruction getterInstruction = pop(); 6303 HInstruction getterInstruction = pop();
6966 if (node.isIfNullAssignment) { 6304 if (node.isIfNullAssignment) {
6967 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 6305 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node);
6968 brancher.handleIfNull(() => stack.add(getterInstruction), 6306 brancher.handleIfNull(() => stack.add(getterInstruction), () {
6969 () { 6307 visit(node.arguments.head);
6970 visit(node.arguments.head); 6308 generateInstanceSetterWithCompiledReceiver(node, receiver, pop());
6971 generateInstanceSetterWithCompiledReceiver( 6309 });
6972 node, receiver, pop());
6973 });
6974 } else { 6310 } else {
6975 handleComplexOperatorSend(node, getterInstruction, node.arguments); 6311 handleComplexOperatorSend(node, getterInstruction, node.arguments);
6976 HInstruction value = pop(); 6312 HInstruction value = pop();
6977 generateInstanceSetterWithCompiledReceiver(node, receiver, value); 6313 generateInstanceSetterWithCompiledReceiver(node, receiver, value);
6978 } 6314 }
6979 if (node.isPostfix) { 6315 if (node.isPostfix) {
6980 pop(); 6316 pop();
6981 stack.add(getterInstruction); 6317 stack.add(getterInstruction);
6982 } 6318 }
6983 } 6319 }
6984 if (node.isConditional) { 6320 if (node.isConditional) {
6985 // generate `e?.x op= e2` as: 6321 // generate `e?.x op= e2` as:
6986 // t1 = e 6322 // t1 = e
6987 // t1 == null ? t1 : (t1.x = t1.x op e2); 6323 // t1 == null ? t1 : (t1.x = t1.x op e2);
6988 HInstruction receiver; 6324 HInstruction receiver;
6989 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 6325 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node);
6990 brancher.handleConditional( 6326 brancher.handleConditional(() {
6991 () { 6327 receiver = generateInstanceSendReceiver(node);
6992 receiver = generateInstanceSendReceiver(node); 6328 pushCheckNull(receiver);
6993 pushCheckNull(receiver); 6329 }, () => stack.add(receiver), () => generateAssignment(receiver));
6994 },
6995 () => stack.add(receiver),
6996 () => generateAssignment(receiver));
6997 } else { 6330 } else {
6998 generateAssignment(generateInstanceSendReceiver(node)); 6331 generateAssignment(generateInstanceSendReceiver(node));
6999 } 6332 }
7000 return; 6333 return;
7001 } 6334 }
7002 6335
7003 if (getter.isMalformed) { 6336 if (getter.isMalformed) {
7004 generateStaticUnresolvedGet(node, getter); 6337 generateStaticUnresolvedGet(node, getter);
7005 } else if (getter.isField) { 6338 } else if (getter.isField) {
7006 generateStaticFieldGet(node, getter); 6339 generateStaticFieldGet(node, getter);
7007 } else if (getter.isGetter) { 6340 } else if (getter.isGetter) {
7008 generateStaticGetterGet(node, getter); 6341 generateStaticGetterGet(node, getter);
7009 } else if (getter.isFunction) { 6342 } else if (getter.isFunction) {
7010 generateStaticFunctionGet(node, getter); 6343 generateStaticFunctionGet(node, getter);
7011 } else if (getter.isLocal) { 6344 } else if (getter.isLocal) {
7012 handleLocalGet(node, getter); 6345 handleLocalGet(node, getter);
7013 } else { 6346 } else {
7014 internalError(node, "Unexpected getter: $getter"); 6347 internalError(node, "Unexpected getter: $getter");
7015 } 6348 }
7016 HInstruction getterInstruction = pop(); 6349 HInstruction getterInstruction = pop();
7017 if (node.isIfNullAssignment) { 6350 if (node.isIfNullAssignment) {
7018 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 6351 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node);
7019 brancher.handleIfNull(() => stack.add(getterInstruction), 6352 brancher.handleIfNull(() => stack.add(getterInstruction), () {
7020 () { 6353 visit(node.arguments.head);
7021 visit(node.arguments.head); 6354 generateNonInstanceSetter(node, element, pop());
7022 generateNonInstanceSetter(node, element, pop()); 6355 });
7023 });
7024 } else { 6356 } else {
7025 handleComplexOperatorSend(node, getterInstruction, node.arguments); 6357 handleComplexOperatorSend(node, getterInstruction, node.arguments);
7026 HInstruction value = pop(); 6358 HInstruction value = pop();
7027 generateNonInstanceSetter(node, element, value); 6359 generateNonInstanceSetter(node, element, value);
7028 } 6360 }
7029 if (node.isPostfix) { 6361 if (node.isPostfix) {
7030 pop(); 6362 pop();
7031 stack.add(getterInstruction); 6363 stack.add(getterInstruction);
7032 } 6364 }
7033 } 6365 }
7034 6366
7035 @override 6367 @override
7036 void handleDynamicCompounds( 6368 void handleDynamicCompounds(
7037 ast.Send node, 6369 ast.Send node, ast.Node receiver, Name name, CompoundRhs rhs, _) {
7038 ast.Node receiver,
7039 Name name,
7040 CompoundRhs rhs,
7041 _) {
7042 handleCompoundSendSet(node); 6370 handleCompoundSendSet(node);
7043 } 6371 }
7044 6372
7045 @override 6373 @override
7046 void handleLocalCompounds( 6374 void handleLocalCompounds(
7047 ast.SendSet node, 6375 ast.SendSet node, LocalElement local, CompoundRhs rhs, _,
7048 LocalElement local,
7049 CompoundRhs rhs,
7050 _,
7051 {bool isSetterValid}) { 6376 {bool isSetterValid}) {
7052 handleCompoundSendSet(node); 6377 handleCompoundSendSet(node);
7053 } 6378 }
7054 6379
7055 @override 6380 @override
7056 void handleStaticCompounds( 6381 void handleStaticCompounds(
7057 ast.SendSet node, 6382 ast.SendSet node,
7058 Element getter, 6383 Element getter,
7059 CompoundGetter getterKind, 6384 CompoundGetter getterKind,
7060 Element setter, 6385 Element setter,
7061 CompoundSetter setterKind, 6386 CompoundSetter setterKind,
7062 CompoundRhs rhs, 6387 CompoundRhs rhs,
7063 _) { 6388 _) {
7064 handleCompoundSendSet(node); 6389 handleCompoundSendSet(node);
7065 } 6390 }
7066 6391
7067 @override 6392 @override
7068 handleDynamicSetIfNulls( 6393 handleDynamicSetIfNulls(
7069 ast.Send node, 6394 ast.Send node, ast.Node receiver, Name name, ast.Node rhs, arg) {
7070 ast.Node receiver,
7071 Name name,
7072 ast.Node rhs,
7073 arg) {
7074 handleCompoundSendSet(node); 6395 handleCompoundSendSet(node);
7075 } 6396 }
7076 6397
7077 @override 6398 @override
7078 handleLocalSetIfNulls( 6399 handleLocalSetIfNulls(ast.SendSet node, LocalElement local, ast.Node rhs, arg,
7079 ast.SendSet node,
7080 LocalElement local,
7081 ast.Node rhs,
7082 arg,
7083 {bool isSetterValid}) { 6400 {bool isSetterValid}) {
7084 handleCompoundSendSet(node); 6401 handleCompoundSendSet(node);
7085 } 6402 }
7086 6403
7087 @override 6404 @override
7088 handleStaticSetIfNulls( 6405 handleStaticSetIfNulls(
7089 ast.SendSet node, 6406 ast.SendSet node,
7090 Element getter, 6407 Element getter,
7091 CompoundGetter getterKind, 6408 CompoundGetter getterKind,
7092 Element setter, 6409 Element setter,
7093 CompoundSetter setterKind, 6410 CompoundSetter setterKind,
7094 ast.Node rhs, 6411 ast.Node rhs,
7095 arg) { 6412 arg) {
7096 handleCompoundSendSet(node); 6413 handleCompoundSendSet(node);
7097 } 6414 }
7098 6415
7099 @override 6416 @override
7100 handleSuperSetIfNulls( 6417 handleSuperSetIfNulls(
7101 ast.SendSet node, 6418 ast.SendSet node,
7102 Element getter, 6419 Element getter,
7103 CompoundGetter getterKind, 6420 CompoundGetter getterKind,
7104 Element setter, 6421 Element setter,
7105 CompoundSetter setterKind, 6422 CompoundSetter setterKind,
7106 ast.Node rhs, 6423 ast.Node rhs,
7107 arg) { 6424 arg) {
7108 handleSuperSendSet(node); 6425 handleSuperSendSet(node);
7109 } 6426 }
7110 6427
7111 @override 6428 @override
7112 handleSuperIndexSetIfNull( 6429 handleSuperIndexSetIfNull(ast.SendSet node, Element indexFunction,
7113 ast.SendSet node, 6430 Element indexSetFunction, ast.Node index, ast.Node rhs, arg,
7114 Element indexFunction, 6431 {bool isGetterValid, bool isSetterValid}) {
7115 Element indexSetFunction,
7116 ast.Node index,
7117 ast.Node rhs,
7118 arg,
7119 {bool isGetterValid,
7120 bool isSetterValid}) {
7121 handleCompoundSendSet(node); 6432 handleCompoundSendSet(node);
7122 } 6433 }
7123 6434
7124 @override 6435 @override
7125 visitIndexSetIfNull( 6436 visitIndexSetIfNull(
7126 ast.SendSet node, 6437 ast.SendSet node, ast.Node receiver, ast.Node index, ast.Node rhs, arg,
7127 ast.Node receiver, 6438 {bool isGetterValid, bool isSetterValid}) {
7128 ast.Node index,
7129 ast.Node rhs,
7130 arg,
7131 {bool isGetterValid,
7132 bool isSetterValid}) {
7133 generateIsDeferredLoadedCheckOfSend(node); 6439 generateIsDeferredLoadedCheckOfSend(node);
7134 handleIndexSendSet(node); 6440 handleIndexSendSet(node);
7135 } 6441 }
7136 6442
7137 @override 6443 @override
7138 handleTypeLiteralConstantSetIfNulls( 6444 handleTypeLiteralConstantSetIfNulls(
7139 ast.SendSet node, 6445 ast.SendSet node, ConstantExpression constant, ast.Node rhs, arg) {
7140 ConstantExpression constant,
7141 ast.Node rhs,
7142 arg) {
7143 // The type variable is never `null`. 6446 // The type variable is never `null`.
7144 generateConstantTypeLiteral(node); 6447 generateConstantTypeLiteral(node);
7145 } 6448 }
7146 6449
7147 @override 6450 @override
7148 visitTypeVariableTypeLiteralSetIfNull( 6451 visitTypeVariableTypeLiteralSetIfNull(
7149 ast.Send node, 6452 ast.Send node, TypeVariableElement element, ast.Node rhs, arg) {
7150 TypeVariableElement element,
7151 ast.Node rhs,
7152 arg) {
7153 // The type variable is never `null`. 6453 // The type variable is never `null`.
7154 generateTypeVariableLiteral(node, element.type); 6454 generateTypeVariableLiteral(node, element.type);
7155 } 6455 }
7156 6456
7157 void visitLiteralInt(ast.LiteralInt node) { 6457 void visitLiteralInt(ast.LiteralInt node) {
7158 stack.add(graph.addConstantInt(node.value, compiler)); 6458 stack.add(graph.addConstantInt(node.value, compiler));
7159 } 6459 }
7160 6460
7161 void visitLiteralDouble(ast.LiteralDouble node) { 6461 void visitLiteralDouble(ast.LiteralDouble node) {
7162 stack.add(graph.addConstantDouble(node.value, compiler)); 6462 stack.add(graph.addConstantDouble(node.value, compiler));
(...skipping 24 matching lines...) Expand all
7187 } 6487 }
7188 6488
7189 void visitLiteralNull(ast.LiteralNull node) { 6489 void visitLiteralNull(ast.LiteralNull node) {
7190 stack.add(graph.addConstantNull(compiler)); 6490 stack.add(graph.addConstantNull(compiler));
7191 } 6491 }
7192 6492
7193 visitNodeList(ast.NodeList node) { 6493 visitNodeList(ast.NodeList node) {
7194 for (Link<ast.Node> link = node.nodes; !link.isEmpty; link = link.tail) { 6494 for (Link<ast.Node> link = node.nodes; !link.isEmpty; link = link.tail) {
7195 if (isAborted()) { 6495 if (isAborted()) {
7196 reporter.reportHintMessage( 6496 reporter.reportHintMessage(
7197 link.head, 6497 link.head, MessageKind.GENERIC, {'text': 'dead code'});
7198 MessageKind.GENERIC,
7199 {'text': 'dead code'});
7200 } else { 6498 } else {
7201 visit(link.head); 6499 visit(link.head);
7202 } 6500 }
7203 } 6501 }
7204 } 6502 }
7205 6503
7206 void visitParenthesizedExpression(ast.ParenthesizedExpression node) { 6504 void visitParenthesizedExpression(ast.ParenthesizedExpression node) {
7207 visit(node.expression); 6505 visit(node.expression);
7208 } 6506 }
7209 6507
7210 visitOperator(ast.Operator node) { 6508 visitOperator(ast.Operator node) {
7211 // Operators are intercepted in their surrounding Send nodes. 6509 // Operators are intercepted in their surrounding Send nodes.
7212 reporter.internalError(node, 6510 reporter.internalError(
7213 'SsaBuilder.visitOperator should not be called.'); 6511 node, 'SsaBuilder.visitOperator should not be called.');
7214 } 6512 }
7215 6513
7216 visitCascade(ast.Cascade node) { 6514 visitCascade(ast.Cascade node) {
7217 visit(node.expression); 6515 visit(node.expression);
7218 // Remove the result and reveal the duplicated receiver on the stack. 6516 // Remove the result and reveal the duplicated receiver on the stack.
7219 pop(); 6517 pop();
7220 } 6518 }
7221 6519
7222 visitCascadeReceiver(ast.CascadeReceiver node) { 6520 visitCascadeReceiver(ast.CascadeReceiver node) {
7223 visit(node.expression); 6521 visit(node.expression);
7224 dup(); 6522 dup();
7225 } 6523 }
7226 6524
7227 void handleInTryStatement() { 6525 void handleInTryStatement() {
7228 if (!inTryStatement) return; 6526 if (!inTryStatement) return;
7229 HBasicBlock block = close(new HExitTry()); 6527 HBasicBlock block = close(new HExitTry());
7230 HBasicBlock newBlock = graph.addNewBlock(); 6528 HBasicBlock newBlock = graph.addNewBlock();
7231 block.addSuccessor(newBlock); 6529 block.addSuccessor(newBlock);
7232 open(newBlock); 6530 open(newBlock);
7233 } 6531 }
7234 6532
7235 visitRethrow(ast.Rethrow node) { 6533 visitRethrow(ast.Rethrow node) {
7236 HInstruction exception = rethrowableException; 6534 HInstruction exception = rethrowableException;
7237 if (exception == null) { 6535 if (exception == null) {
7238 exception = graph.addConstantNull(compiler); 6536 exception = graph.addConstantNull(compiler);
7239 reporter.internalError(node, 6537 reporter.internalError(node, 'rethrowableException should not be null.');
7240 'rethrowableException should not be null.');
7241 } 6538 }
7242 handleInTryStatement(); 6539 handleInTryStatement();
7243 closeAndGotoExit( 6540 closeAndGotoExit(new HThrow(
7244 new HThrow(exception, 6541 exception, sourceInformationBuilder.buildThrow(node),
7245 sourceInformationBuilder.buildThrow(node), 6542 isRethrow: true));
7246 isRethrow: true));
7247 } 6543 }
7248 6544
7249 visitRedirectingFactoryBody(ast.RedirectingFactoryBody node) { 6545 visitRedirectingFactoryBody(ast.RedirectingFactoryBody node) {
7250 ConstructorElement targetConstructor = 6546 ConstructorElement targetConstructor =
7251 elements.getRedirectingTargetConstructor(node).implementation; 6547 elements.getRedirectingTargetConstructor(node).implementation;
7252 ConstructorElement redirectingConstructor = sourceElement.implementation; 6548 ConstructorElement redirectingConstructor = sourceElement.implementation;
7253 List<HInstruction> inputs = <HInstruction>[]; 6549 List<HInstruction> inputs = <HInstruction>[];
7254 FunctionSignature targetSignature = targetConstructor.functionSignature; 6550 FunctionSignature targetSignature = targetConstructor.functionSignature;
7255 FunctionSignature redirectingSignature = 6551 FunctionSignature redirectingSignature =
7256 redirectingConstructor.functionSignature; 6552 redirectingConstructor.functionSignature;
7257 6553
7258 List<Element> targetRequireds = targetSignature.requiredParameters; 6554 List<Element> targetRequireds = targetSignature.requiredParameters;
7259 List<Element> redirectingRequireds 6555 List<Element> redirectingRequireds =
7260 = redirectingSignature.requiredParameters; 6556 redirectingSignature.requiredParameters;
7261 6557
7262 List<Element> targetOptionals = 6558 List<Element> targetOptionals = targetSignature.orderedOptionalParameters;
7263 targetSignature.orderedOptionalParameters;
7264 List<Element> redirectingOptionals = 6559 List<Element> redirectingOptionals =
7265 redirectingSignature.orderedOptionalParameters; 6560 redirectingSignature.orderedOptionalParameters;
7266 6561
7267 // TODO(25579): This code can do the wrong thing redirecting constructor and 6562 // TODO(25579): This code can do the wrong thing redirecting constructor and
7268 // the target do not correspond. It is correct if there is no 6563 // the target do not correspond. It is correct if there is no
7269 // warning. Ideally the redirecting constructor and the target would be the 6564 // warning. Ideally the redirecting constructor and the target would be the
7270 // same function. 6565 // same function.
7271 6566
7272 void loadLocal(ParameterElement parameter) { 6567 void loadLocal(ParameterElement parameter) {
7273 inputs.add(localsHandler.readLocal(parameter)); 6568 inputs.add(localsHandler.readLocal(parameter));
7274 } 6569 }
7275 void loadPosition(int position, ParameterElement optionalParameter) { 6570 void loadPosition(int position, ParameterElement optionalParameter) {
7276 if (position < redirectingRequireds.length) { 6571 if (position < redirectingRequireds.length) {
7277 loadLocal(redirectingRequireds[position]); 6572 loadLocal(redirectingRequireds[position]);
7278 } else if (position < redirectingSignature.parameterCount && 6573 } else if (position < redirectingSignature.parameterCount &&
7279 !redirectingSignature.optionalParametersAreNamed) { 6574 !redirectingSignature.optionalParametersAreNamed) {
7280 loadLocal(redirectingOptionals[position - redirectingRequireds.length]); 6575 loadLocal(redirectingOptionals[position - redirectingRequireds.length]);
7281 } else if (optionalParameter != null) { 6576 } else if (optionalParameter != null) {
7282 inputs.add(handleConstantForOptionalParameter(optionalParameter)); 6577 inputs.add(handleConstantForOptionalParameter(optionalParameter));
7283 } else { 6578 } else {
7284 // Wrong. 6579 // Wrong.
7285 inputs.add(graph.addConstantNull(compiler)); 6580 inputs.add(graph.addConstantNull(compiler));
7286 } 6581 }
7287 } 6582 }
7288 6583
7289 int position = 0; 6584 int position = 0;
7290 6585
7291 for (ParameterElement targetParameter in targetRequireds) { 6586 for (ParameterElement targetParameter in targetRequireds) {
7292 loadPosition(position++, null); 6587 loadPosition(position++, null);
7293 } 6588 }
7294 6589
7295 if (targetOptionals.isNotEmpty) { 6590 if (targetOptionals.isNotEmpty) {
7296 if (targetSignature.optionalParametersAreNamed) { 6591 if (targetSignature.optionalParametersAreNamed) {
7297 for (ParameterElement parameter in targetOptionals) { 6592 for (ParameterElement parameter in targetOptionals) {
7298 ParameterElement redirectingParameter = 6593 ParameterElement redirectingParameter = redirectingOptionals
7299 redirectingOptionals.firstWhere( 6594 .firstWhere((p) => p.name == parameter.name, orElse: () => null);
7300 (p) => p.name == parameter.name,
7301 orElse: () => null);
7302 if (redirectingParameter == null) { 6595 if (redirectingParameter == null) {
7303 inputs.add(handleConstantForOptionalParameter(parameter)); 6596 inputs.add(handleConstantForOptionalParameter(parameter));
7304 } else { 6597 } else {
7305 inputs.add(localsHandler.readLocal(redirectingParameter)); 6598 inputs.add(localsHandler.readLocal(redirectingParameter));
7306 } 6599 }
7307 } 6600 }
7308 } else { 6601 } else {
7309 for (ParameterElement parameter in targetOptionals) { 6602 for (ParameterElement parameter in targetOptionals) {
7310 loadPosition(position++, parameter); 6603 loadPosition(position++, parameter);
7311 } 6604 }
(...skipping 16 matching lines...) Expand all
7328 } 6621 }
7329 6622
7330 /// Returns true if the [type] is a valid return type for an asynchronous 6623 /// Returns true if the [type] is a valid return type for an asynchronous
7331 /// function. 6624 /// function.
7332 /// 6625 ///
7333 /// Asynchronous functions return a `Future`, and a valid return is thus 6626 /// Asynchronous functions return a `Future`, and a valid return is thus
7334 /// either dynamic, Object, or Future. 6627 /// either dynamic, Object, or Future.
7335 /// 6628 ///
7336 /// We do not accept the internal Future implementation class. 6629 /// We do not accept the internal Future implementation class.
7337 bool isValidAsyncReturnType(DartType type) { 6630 bool isValidAsyncReturnType(DartType type) {
7338 assert (isBuildingAsyncFunction); 6631 assert(isBuildingAsyncFunction);
7339 // TODO(sigurdm): In an internal library a function could be declared: 6632 // TODO(sigurdm): In an internal library a function could be declared:
7340 // 6633 //
7341 // _FutureImpl foo async => 1; 6634 // _FutureImpl foo async => 1;
7342 // 6635 //
7343 // This should be valid (because the actual value returned from an async 6636 // This should be valid (because the actual value returned from an async
7344 // function is a `_FutureImpl`), but currently false is returned in this 6637 // function is a `_FutureImpl`), but currently false is returned in this
7345 // case. 6638 // case.
7346 return type.isDynamic || 6639 return type.isDynamic ||
7347 type.isObject || 6640 type.isObject ||
7348 (type is InterfaceType && 6641 (type is InterfaceType && type.element == coreClasses.futureClass);
7349 type.element == coreClasses.futureClass);
7350 } 6642 }
7351 6643
7352 visitReturn(ast.Return node) { 6644 visitReturn(ast.Return node) {
7353 if (identical(node.beginToken.stringValue, 'native')) { 6645 if (identical(node.beginToken.stringValue, 'native')) {
7354 native.handleSsaNative(this, node.expression); 6646 native.handleSsaNative(this, node.expression);
7355 return; 6647 return;
7356 } 6648 }
7357 HInstruction value; 6649 HInstruction value;
7358 if (node.expression == null) { 6650 if (node.expression == null) {
7359 value = graph.addConstantNull(compiler); 6651 value = graph.addConstantNull(compiler);
7360 } else { 6652 } else {
7361 visit(node.expression); 6653 visit(node.expression);
7362 value = pop(); 6654 value = pop();
7363 if (isBuildingAsyncFunction) { 6655 if (isBuildingAsyncFunction) {
7364 if (compiler.options.enableTypeAssertions && 6656 if (compiler.options.enableTypeAssertions &&
7365 !isValidAsyncReturnType(returnType)) { 6657 !isValidAsyncReturnType(returnType)) {
7366 String message = 6658 String message = "Async function returned a Future, "
7367 "Async function returned a Future, " 6659 "was declared to return a $returnType.";
7368 "was declared to return a $returnType.";
7369 generateTypeError(node, message); 6660 generateTypeError(node, message);
7370 pop(); 6661 pop();
7371 return; 6662 return;
7372 } 6663 }
7373 } else { 6664 } else {
7374 value = potentiallyCheckOrTrustType(value, returnType); 6665 value = potentiallyCheckOrTrustType(value, returnType);
7375 } 6666 }
7376 } 6667 }
7377 6668
7378 handleInTryStatement(); 6669 handleInTryStatement();
(...skipping 13 matching lines...) Expand all
7392 visitYield(ast.Yield node) { 6683 visitYield(ast.Yield node) {
7393 visit(node.expression); 6684 visit(node.expression);
7394 HInstruction yielded = pop(); 6685 HInstruction yielded = pop();
7395 add(new HYield(yielded, node.hasStar)); 6686 add(new HYield(yielded, node.hasStar));
7396 } 6687 }
7397 6688
7398 visitAwait(ast.Await node) { 6689 visitAwait(ast.Await node) {
7399 visit(node.expression); 6690 visit(node.expression);
7400 HInstruction awaited = pop(); 6691 HInstruction awaited = pop();
7401 // TODO(herhut): Improve this type. 6692 // TODO(herhut): Improve this type.
7402 push(new HAwait(awaited, new TypeMask.subclass( 6693 push(new HAwait(awaited,
7403 coreClasses.objectClass, compiler.world))); 6694 new TypeMask.subclass(coreClasses.objectClass, compiler.world)));
7404 } 6695 }
7405 6696
7406 visitTypeAnnotation(ast.TypeAnnotation node) { 6697 visitTypeAnnotation(ast.TypeAnnotation node) {
7407 reporter.internalError(node, 6698 reporter.internalError(node, 'Visiting type annotation in SSA builder.');
7408 'Visiting type annotation in SSA builder.');
7409 } 6699 }
7410 6700
7411 visitVariableDefinitions(ast.VariableDefinitions node) { 6701 visitVariableDefinitions(ast.VariableDefinitions node) {
7412 assert(isReachable); 6702 assert(isReachable);
7413 for (Link<ast.Node> link = node.definitions.nodes; 6703 for (Link<ast.Node> link = node.definitions.nodes;
7414 !link.isEmpty; 6704 !link.isEmpty;
7415 link = link.tail) { 6705 link = link.tail) {
7416 ast.Node definition = link.head; 6706 ast.Node definition = link.head;
7417 LocalElement local = elements[definition]; 6707 LocalElement local = elements[definition];
7418 if (definition is ast.Identifier) { 6708 if (definition is ast.Identifier) {
7419 HInstruction initialValue = graph.addConstantNull(compiler); 6709 HInstruction initialValue = graph.addConstantNull(compiler);
7420 localsHandler.updateLocal(local, initialValue); 6710 localsHandler.updateLocal(local, initialValue);
7421 } else { 6711 } else {
7422 ast.SendSet node = definition; 6712 ast.SendSet node = definition;
7423 generateNonInstanceSetter( 6713 generateNonInstanceSetter(
7424 node, local, visitAndPop(node.arguments.first)); 6714 node, local, visitAndPop(node.arguments.first));
7425 pop(); // Discard value. 6715 pop(); // Discard value.
7426 } 6716 }
7427 } 6717 }
7428 } 6718 }
7429 6719
7430 HInstruction setRtiIfNeeded(HInstruction object, ast.Node node) { 6720 HInstruction setRtiIfNeeded(HInstruction object, ast.Node node) {
7431 InterfaceType type = localsHandler.substInContext(elements.getType(node)); 6721 InterfaceType type = localsHandler.substInContext(elements.getType(node));
7432 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) { 6722 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) {
7433 return object; 6723 return object;
7434 } 6724 }
7435 List<HInstruction> arguments = <HInstruction>[]; 6725 List<HInstruction> arguments = <HInstruction>[];
7436 for (DartType argument in type.typeArguments) { 6726 for (DartType argument in type.typeArguments) {
7437 arguments.add(analyzeTypeArgument(argument)); 6727 arguments.add(analyzeTypeArgument(argument));
7438 } 6728 }
7439 // TODO(15489): Register at codegen. 6729 // TODO(15489): Register at codegen.
7440 registry?.registerInstantiation(type); 6730 registry?.registerInstantiation(type);
7441 return callSetRuntimeTypeInfo(type.element, arguments, object); 6731 return callSetRuntimeTypeInfo(type.element, arguments, object);
7442 } 6732 }
7443 6733
7444 visitLiteralList(ast.LiteralList node) { 6734 visitLiteralList(ast.LiteralList node) {
7445 HInstruction instruction; 6735 HInstruction instruction;
7446 6736
7447 if (node.isConst) { 6737 if (node.isConst) {
7448 instruction = addConstant(node); 6738 instruction = addConstant(node);
7449 } else { 6739 } else {
7450 List<HInstruction> inputs = <HInstruction>[]; 6740 List<HInstruction> inputs = <HInstruction>[];
7451 for (Link<ast.Node> link = node.elements.nodes; 6741 for (Link<ast.Node> link = node.elements.nodes;
7452 !link.isEmpty; 6742 !link.isEmpty;
7453 link = link.tail) { 6743 link = link.tail) {
7454 visit(link.head); 6744 visit(link.head);
7455 inputs.add(pop()); 6745 inputs.add(pop());
7456 } 6746 }
7457 instruction = buildLiteralList(inputs); 6747 instruction = buildLiteralList(inputs);
7458 add(instruction); 6748 add(instruction);
7459 instruction = setRtiIfNeeded(instruction, node); 6749 instruction = setRtiIfNeeded(instruction, node);
7460 } 6750 }
7461 6751
7462 TypeMask type = 6752 TypeMask type =
7463 TypeMaskFactory.inferredForNode(sourceElement, node, compiler); 6753 TypeMaskFactory.inferredForNode(sourceElement, node, compiler);
7464 if (!type.containsAll(compiler.world)) instruction.instructionType = type; 6754 if (!type.containsAll(compiler.world)) instruction.instructionType = type;
7465 stack.add(instruction); 6755 stack.add(instruction);
7466 } 6756 }
7467 6757
7468 visitConditional(ast.Conditional node) { 6758 visitConditional(ast.Conditional node) {
7469 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node); 6759 SsaBranchBuilder brancher = new SsaBranchBuilder(this, node);
7470 brancher.handleConditional(() => visit(node.condition), 6760 brancher.handleConditional(() => visit(node.condition),
7471 () => visit(node.thenExpression), 6761 () => visit(node.thenExpression), () => visit(node.elseExpression));
7472 () => visit(node.elseExpression));
7473 } 6762 }
7474 6763
7475 visitStringInterpolation(ast.StringInterpolation node) { 6764 visitStringInterpolation(ast.StringInterpolation node) {
7476 StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this, node); 6765 StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this, node);
7477 stringBuilder.visit(node); 6766 stringBuilder.visit(node);
7478 stack.add(stringBuilder.result); 6767 stack.add(stringBuilder.result);
7479 } 6768 }
7480 6769
7481 visitStringInterpolationPart(ast.StringInterpolationPart node) { 6770 visitStringInterpolationPart(ast.StringInterpolationPart node) {
7482 // The parts are iterated in visitStringInterpolation. 6771 // The parts are iterated in visitStringInterpolation.
7483 reporter.internalError(node, 6772 reporter.internalError(
7484 'SsaBuilder.visitStringInterpolation should not be called.'); 6773 node, 'SsaBuilder.visitStringInterpolation should not be called.');
7485 } 6774 }
7486 6775
7487 visitEmptyStatement(ast.EmptyStatement node) { 6776 visitEmptyStatement(ast.EmptyStatement node) {
7488 // Do nothing, empty statement. 6777 // Do nothing, empty statement.
7489 } 6778 }
7490 6779
7491 visitModifiers(ast.Modifiers node) { 6780 visitModifiers(ast.Modifiers node) {
7492 compiler.unimplemented(node, 'SsaFromAstMixin.visitModifiers.'); 6781 compiler.unimplemented(node, 'SsaFromAstMixin.visitModifiers.');
7493 } 6782 }
7494 6783
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
7544 } 6833 }
7545 return new JumpHandler(this, element); 6834 return new JumpHandler(this, element);
7546 } 6835 }
7547 6836
7548 visitAsyncForIn(ast.AsyncForIn node) { 6837 visitAsyncForIn(ast.AsyncForIn node) {
7549 // The async-for is implemented with a StreamIterator. 6838 // The async-for is implemented with a StreamIterator.
7550 HInstruction streamIterator; 6839 HInstruction streamIterator;
7551 6840
7552 visit(node.expression); 6841 visit(node.expression);
7553 HInstruction expression = pop(); 6842 HInstruction expression = pop();
7554 pushInvokeStatic(node, 6843 pushInvokeStatic(node, helpers.streamIteratorConstructor,
7555 helpers.streamIteratorConstructor, 6844 [expression, graph.addConstantNull(compiler)]);
7556 [expression, graph.addConstantNull(compiler)]);
7557 streamIterator = pop(); 6845 streamIterator = pop();
7558 6846
7559 void buildInitializer() {} 6847 void buildInitializer() {}
7560 6848
7561 HInstruction buildCondition() { 6849 HInstruction buildCondition() {
7562 Selector selector = Selectors.moveNext; 6850 Selector selector = Selectors.moveNext;
7563 TypeMask mask = elements.getMoveNextTypeMask(node); 6851 TypeMask mask = elements.getMoveNextTypeMask(node);
7564 pushInvokeDynamic(node, selector, mask, [streamIterator]); 6852 pushInvokeDynamic(node, selector, mask, [streamIterator]);
7565 HInstruction future = pop(); 6853 HInstruction future = pop();
7566 push(new HAwait(future, 6854 push(new HAwait(future,
7567 new TypeMask.subclass(coreClasses.objectClass, compiler.world))); 6855 new TypeMask.subclass(coreClasses.objectClass, compiler.world)));
7568 return popBoolified(); 6856 return popBoolified();
7569 } 6857 }
7570 void buildBody() { 6858 void buildBody() {
7571 Selector call = Selectors.current; 6859 Selector call = Selectors.current;
7572 TypeMask callMask = elements.getCurrentTypeMask(node); 6860 TypeMask callMask = elements.getCurrentTypeMask(node);
7573 pushInvokeDynamic(node, call, callMask, [streamIterator]); 6861 pushInvokeDynamic(node, call, callMask, [streamIterator]);
7574 6862
7575 ast.Node identifier = node.declaredIdentifier; 6863 ast.Node identifier = node.declaredIdentifier;
7576 Element variable = elements.getForInVariable(node); 6864 Element variable = elements.getForInVariable(node);
7577 Selector selector = elements.getSelector(identifier); 6865 Selector selector = elements.getSelector(identifier);
7578 TypeMask mask = elements.getTypeMask(identifier); 6866 TypeMask mask = elements.getTypeMask(identifier);
7579 6867
7580 HInstruction value = pop(); 6868 HInstruction value = pop();
7581 if (identifier.asSend() != null 6869 if (identifier.asSend() != null &&
7582 && Elements.isInstanceSend(identifier, elements)) { 6870 Elements.isInstanceSend(identifier, elements)) {
7583 HInstruction receiver = generateInstanceSendReceiver(identifier); 6871 HInstruction receiver = generateInstanceSendReceiver(identifier);
7584 assert(receiver != null); 6872 assert(receiver != null);
7585 generateInstanceSetterWithCompiledReceiver( 6873 generateInstanceSetterWithCompiledReceiver(null, receiver, value,
7586 null, 6874 selector: selector, mask: mask, location: identifier);
7587 receiver,
7588 value,
7589 selector: selector,
7590 mask: mask,
7591 location: identifier);
7592 } else { 6875 } else {
7593 generateNonInstanceSetter( 6876 generateNonInstanceSetter(null, variable, value, location: identifier);
7594 null, variable, value, location: identifier);
7595 } 6877 }
7596 pop(); // Pop the value pushed by the setter call. 6878 pop(); // Pop the value pushed by the setter call.
7597 6879
7598 visit(node.body); 6880 visit(node.body);
7599 } 6881 }
7600 6882
7601 void buildUpdate() {}; 6883 void buildUpdate() {}
6884 ;
7602 6885
7603 buildProtectedByFinally(() { 6886 buildProtectedByFinally(() {
7604 handleLoop(node, 6887 handleLoop(
7605 buildInitializer, 6888 node, buildInitializer, buildCondition, buildUpdate, buildBody);
7606 buildCondition,
7607 buildUpdate,
7608 buildBody);
7609 }, () { 6889 }, () {
7610 pushInvokeDynamic(node, 6890 pushInvokeDynamic(node, Selectors.cancel, null, [streamIterator]);
7611 Selectors.cancel, 6891 push(new HAwait(pop(),
7612 null, 6892 new TypeMask.subclass(coreClasses.objectClass, compiler.world)));
7613 [streamIterator]);
7614 push(new HAwait(pop(), new TypeMask.subclass(
7615 coreClasses.objectClass, compiler.world)));
7616 pop(); 6893 pop();
7617 }); 6894 });
7618 } 6895 }
7619 6896
7620 visitSyncForIn(ast.SyncForIn node) { 6897 visitSyncForIn(ast.SyncForIn node) {
7621 // The 'get iterator' selector for this node has the inferred receiver type. 6898 // The 'get iterator' selector for this node has the inferred receiver type.
7622 // If the receiver supports JavaScript indexing we generate an indexing loop 6899 // If the receiver supports JavaScript indexing we generate an indexing loop
7623 // instead of allocating an iterator object. 6900 // instead of allocating an iterator object.
7624 6901
7625 // This scheme recognizes for-in on direct lists. It does not recognize all 6902 // This scheme recognizes for-in on direct lists. It does not recognize all
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
7682 buildAssignLoopVariable(ast.ForIn node, HInstruction value) { 6959 buildAssignLoopVariable(ast.ForIn node, HInstruction value) {
7683 ast.Node identifier = node.declaredIdentifier; 6960 ast.Node identifier = node.declaredIdentifier;
7684 Element variable = elements.getForInVariable(node); 6961 Element variable = elements.getForInVariable(node);
7685 Selector selector = elements.getSelector(identifier); 6962 Selector selector = elements.getSelector(identifier);
7686 TypeMask mask = elements.getTypeMask(identifier); 6963 TypeMask mask = elements.getTypeMask(identifier);
7687 6964
7688 if (identifier.asSend() != null && 6965 if (identifier.asSend() != null &&
7689 Elements.isInstanceSend(identifier, elements)) { 6966 Elements.isInstanceSend(identifier, elements)) {
7690 HInstruction receiver = generateInstanceSendReceiver(identifier); 6967 HInstruction receiver = generateInstanceSendReceiver(identifier);
7691 assert(receiver != null); 6968 assert(receiver != null);
7692 generateInstanceSetterWithCompiledReceiver( 6969 generateInstanceSetterWithCompiledReceiver(null, receiver, value,
7693 null, 6970 selector: selector, mask: mask, location: identifier);
7694 receiver,
7695 value,
7696 selector: selector,
7697 mask: mask,
7698 location: identifier);
7699 } else { 6971 } else {
7700 generateNonInstanceSetter(null, variable, value, location: identifier); 6972 generateNonInstanceSetter(null, variable, value, location: identifier);
7701 } 6973 }
7702 pop(); // Discard the value pushed by the setter call. 6974 pop(); // Discard the value pushed by the setter call.
7703 } 6975 }
7704 6976
7705 buildSyncForInIndexable(ast.ForIn node, TypeMask arrayType) { 6977 buildSyncForInIndexable(ast.ForIn node, TypeMask arrayType) {
7706 // Generate a structure equivalent to: 6978 // Generate a structure equivalent to:
7707 // 6979 //
7708 // int end = a.length; 6980 // int end = a.length;
7709 // for (int i = 0; 6981 // for (int i = 0;
7710 // i < a.length; 6982 // i < a.length;
7711 // checkConcurrentModificationError(a.length == end, a), ++i) { 6983 // checkConcurrentModificationError(a.length == end, a), ++i) {
7712 // <declaredIdentifier> = a[i]; 6984 // <declaredIdentifier> = a[i];
7713 // <body> 6985 // <body>
7714 // } 6986 // }
7715 Element loopVariable = elements.getForInVariable(node); 6987 Element loopVariable = elements.getForInVariable(node);
7716 SyntheticLocal indexVariable = new SyntheticLocal('_i', loopVariable); 6988 SyntheticLocal indexVariable = new SyntheticLocal('_i', loopVariable);
7717 TypeMask boolType = backend.boolType; 6989 TypeMask boolType = backend.boolType;
7718 6990
7719 // These variables are shared by initializer, condition, body and update. 6991 // These variables are shared by initializer, condition, body and update.
7720 HInstruction array; // Set in buildInitializer. 6992 HInstruction array; // Set in buildInitializer.
7721 bool isFixed; // Set in buildInitializer. 6993 bool isFixed; // Set in buildInitializer.
7722 HInstruction originalLength = null; // Set for growable lists. 6994 HInstruction originalLength = null; // Set for growable lists.
7723 6995
7724 HInstruction buildGetLength() { 6996 HInstruction buildGetLength() {
7725 Element lengthElement = helpers.jsIndexableLength; 6997 Element lengthElement = helpers.jsIndexableLength;
7726 HFieldGet result = new HFieldGet( 6998 HFieldGet result = new HFieldGet(
7727 lengthElement, array, backend.positiveIntType, 6999 lengthElement, array, backend.positiveIntType,
7728 isAssignable: !isFixed); 7000 isAssignable: !isFixed);
7729 add(result); 7001 add(result);
7730 return result; 7002 return result;
7731 } 7003 }
7732 7004
7733 void buildConcurrentModificationErrorCheck() { 7005 void buildConcurrentModificationErrorCheck() {
7734 if (originalLength == null) return; 7006 if (originalLength == null) return;
7735 // The static call checkConcurrentModificationError() is expanded in 7007 // The static call checkConcurrentModificationError() is expanded in
7736 // codegen to: 7008 // codegen to:
7737 // 7009 //
7738 // array.length == _end || throwConcurrentModificationError(array) 7010 // array.length == _end || throwConcurrentModificationError(array)
7739 // 7011 //
7740 HInstruction length = buildGetLength(); 7012 HInstruction length = buildGetLength();
7741 push(new HIdentity(length, originalLength, null, boolType)); 7013 push(new HIdentity(length, originalLength, null, boolType));
7742 pushInvokeStatic(node, 7014 pushInvokeStatic(
7743 helpers.checkConcurrentModificationError, 7015 node, helpers.checkConcurrentModificationError, [pop(), array]);
7744 [pop(), array]);
7745 pop(); 7016 pop();
7746 } 7017 }
7747 7018
7748 void buildInitializer() { 7019 void buildInitializer() {
7749 visit(node.expression); 7020 visit(node.expression);
7750 array = pop(); 7021 array = pop();
7751 isFixed = isFixedLength(array.instructionType, compiler); 7022 isFixed = isFixedLength(array.instructionType, compiler);
7752 localsHandler.updateLocal(indexVariable, 7023 localsHandler.updateLocal(
7753 graph.addConstantInt(0, compiler)); 7024 indexVariable, graph.addConstantInt(0, compiler));
7754 originalLength = buildGetLength(); 7025 originalLength = buildGetLength();
7755 } 7026 }
7756 7027
7757 HInstruction buildCondition() { 7028 HInstruction buildCondition() {
7758 HInstruction index = localsHandler.readLocal(indexVariable); 7029 HInstruction index = localsHandler.readLocal(indexVariable);
7759 HInstruction length = buildGetLength(); 7030 HInstruction length = buildGetLength();
7760 HInstruction compare = new HLess(index, length, null, boolType); 7031 HInstruction compare = new HLess(index, length, null, boolType);
7761 add(compare); 7032 add(compare);
7762 return compare; 7033 return compare;
7763 } 7034 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
7803 7074
7804 handleLoop(node, buildInitializer, buildCondition, buildUpdate, buildBody); 7075 handleLoop(node, buildInitializer, buildCondition, buildUpdate, buildBody);
7805 } 7076 }
7806 7077
7807 visitLabel(ast.Label node) { 7078 visitLabel(ast.Label node) {
7808 reporter.internalError(node, 'SsaFromAstMixin.visitLabel.'); 7079 reporter.internalError(node, 'SsaFromAstMixin.visitLabel.');
7809 } 7080 }
7810 7081
7811 visitLabeledStatement(ast.LabeledStatement node) { 7082 visitLabeledStatement(ast.LabeledStatement node) {
7812 ast.Statement body = node.statement; 7083 ast.Statement body = node.statement;
7813 if (body is ast.Loop 7084 if (body is ast.Loop ||
7814 || body is ast.SwitchStatement 7085 body is ast.SwitchStatement ||
7815 || Elements.isUnusedLabel(node, elements)) { 7086 Elements.isUnusedLabel(node, elements)) {
7816 // Loops and switches handle their own labels. 7087 // Loops and switches handle their own labels.
7817 visit(body); 7088 visit(body);
7818 return; 7089 return;
7819 } 7090 }
7820 JumpTarget targetElement = elements.getTargetDefinition(body); 7091 JumpTarget targetElement = elements.getTargetDefinition(body);
7821 LocalsHandler beforeLocals = new LocalsHandler.from(localsHandler); 7092 LocalsHandler beforeLocals = new LocalsHandler.from(localsHandler);
7822 assert(targetElement.isBreakTarget); 7093 assert(targetElement.isBreakTarget);
7823 JumpHandler handler = new JumpHandler(this, targetElement); 7094 JumpHandler handler = new JumpHandler(this, targetElement);
7824 // Introduce a new basic block. 7095 // Introduce a new basic block.
7825 HBasicBlock entryBlock = openNewBlock(); 7096 HBasicBlock entryBlock = openNewBlock();
(...skipping 10 matching lines...) Expand all
7836 if (!isAborted()) { 7107 if (!isAborted()) {
7837 goto(current, joinBlock); 7108 goto(current, joinBlock);
7838 breakHandlers.add(localsHandler); 7109 breakHandlers.add(localsHandler);
7839 } 7110 }
7840 open(joinBlock); 7111 open(joinBlock);
7841 localsHandler = beforeLocals.mergeMultiple(breakHandlers, joinBlock); 7112 localsHandler = beforeLocals.mergeMultiple(breakHandlers, joinBlock);
7842 7113
7843 if (hasBreak) { 7114 if (hasBreak) {
7844 // There was at least one reachable break, so the label is needed. 7115 // There was at least one reachable break, so the label is needed.
7845 entryBlock.setBlockFlow( 7116 entryBlock.setBlockFlow(
7846 new HLabeledBlockInformation(new HSubGraphBlockInformation(bodyGraph), 7117 new HLabeledBlockInformation(
7847 handler.labels()), 7118 new HSubGraphBlockInformation(bodyGraph), handler.labels()),
7848 joinBlock); 7119 joinBlock);
7849 } 7120 }
7850 handler.close(); 7121 handler.close();
7851 } 7122 }
7852 7123
7853 visitLiteralMap(ast.LiteralMap node) { 7124 visitLiteralMap(ast.LiteralMap node) {
7854 if (node.isConst) { 7125 if (node.isConst) {
7855 stack.add(addConstant(node)); 7126 stack.add(addConstant(node));
7856 return; 7127 return;
7857 } 7128 }
7858 List<HInstruction> listInputs = <HInstruction>[]; 7129 List<HInstruction> listInputs = <HInstruction>[];
7859 for (Link<ast.Node> link = node.entries.nodes; 7130 for (Link<ast.Node> link = node.entries.nodes;
7860 !link.isEmpty; 7131 !link.isEmpty;
7861 link = link.tail) { 7132 link = link.tail) {
7862 visit(link.head); 7133 visit(link.head);
7863 listInputs.add(pop()); 7134 listInputs.add(pop());
7864 listInputs.add(pop()); 7135 listInputs.add(pop());
7865 } 7136 }
7866 7137
7867 Element constructor; 7138 Element constructor;
7868 List<HInstruction> inputs = <HInstruction>[]; 7139 List<HInstruction> inputs = <HInstruction>[];
7869 7140
7870 if (listInputs.isEmpty) { 7141 if (listInputs.isEmpty) {
7871 constructor = helpers.mapLiteralConstructorEmpty; 7142 constructor = helpers.mapLiteralConstructorEmpty;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
7910 // If rti is needed and the map literal has no type parameters, 7181 // If rti is needed and the map literal has no type parameters,
7911 // 'constructor' is a static function that forwards the call to the factory 7182 // 'constructor' is a static function that forwards the call to the factory
7912 // constructor without type parameters. 7183 // constructor without type parameters.
7913 assert(constructor is ConstructorElement || constructor is FunctionElement); 7184 assert(constructor is ConstructorElement || constructor is FunctionElement);
7914 7185
7915 // The instruction type will always be a subtype of the mapLiteralClass, but 7186 // The instruction type will always be a subtype of the mapLiteralClass, but
7916 // type inference might discover a more specific type, or find nothing (in 7187 // type inference might discover a more specific type, or find nothing (in
7917 // dart2js unit tests). 7188 // dart2js unit tests).
7918 TypeMask mapType = 7189 TypeMask mapType =
7919 new TypeMask.nonNullSubtype(helpers.mapLiteralClass, compiler.world); 7190 new TypeMask.nonNullSubtype(helpers.mapLiteralClass, compiler.world);
7920 TypeMask returnTypeMask = TypeMaskFactory.inferredReturnTypeForElement( 7191 TypeMask returnTypeMask =
7921 constructor, compiler); 7192 TypeMaskFactory.inferredReturnTypeForElement(constructor, compiler);
7922 TypeMask instructionType = 7193 TypeMask instructionType =
7923 mapType.intersection(returnTypeMask, compiler.world); 7194 mapType.intersection(returnTypeMask, compiler.world);
7924 7195
7925 addInlinedInstantiation(expectedType); 7196 addInlinedInstantiation(expectedType);
7926 pushInvokeStatic(node, constructor, inputs, 7197 pushInvokeStatic(node, constructor, inputs,
7927 typeMask: instructionType, instanceType: expectedType); 7198 typeMask: instructionType, instanceType: expectedType);
7928 removeInlinedInstantiation(expectedType); 7199 removeInlinedInstantiation(expectedType);
7929 } 7200 }
7930 7201
7931 visitLiteralMapEntry(ast.LiteralMapEntry node) { 7202 visitLiteralMapEntry(ast.LiteralMapEntry node) {
7932 visit(node.value); 7203 visit(node.value);
7933 visit(node.key); 7204 visit(node.key);
7934 } 7205 }
7935 7206
7936 visitNamedArgument(ast.NamedArgument node) { 7207 visitNamedArgument(ast.NamedArgument node) {
7937 visit(node.expression); 7208 visit(node.expression);
7938 } 7209 }
7939 7210
7940 Map<ast.CaseMatch, ConstantValue> buildSwitchCaseConstants( 7211 Map<ast.CaseMatch, ConstantValue> buildSwitchCaseConstants(
7941 ast.SwitchStatement node) { 7212 ast.SwitchStatement node) {
7942
7943 Map<ast.CaseMatch, ConstantValue> constants = 7213 Map<ast.CaseMatch, ConstantValue> constants =
7944 new Map<ast.CaseMatch, ConstantValue>(); 7214 new Map<ast.CaseMatch, ConstantValue>();
7945 for (ast.SwitchCase switchCase in node.cases) { 7215 for (ast.SwitchCase switchCase in node.cases) {
7946 for (ast.Node labelOrCase in switchCase.labelsAndCases) { 7216 for (ast.Node labelOrCase in switchCase.labelsAndCases) {
7947 if (labelOrCase is ast.CaseMatch) { 7217 if (labelOrCase is ast.CaseMatch) {
7948 ast.CaseMatch match = labelOrCase; 7218 ast.CaseMatch match = labelOrCase;
7949 ConstantValue constant = getConstantForNode(match.expression); 7219 ConstantValue constant = getConstantForNode(match.expression);
7950 constants[labelOrCase] = constant; 7220 constants[labelOrCase] = constant;
7951 } 7221 }
7952 } 7222 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
7986 buildSimpleSwitchStatement(node, constants); 7256 buildSimpleSwitchStatement(node, constants);
7987 } else { 7257 } else {
7988 buildComplexSwitchStatement(node, constants, caseIndex, hasDefault); 7258 buildComplexSwitchStatement(node, constants, caseIndex, hasDefault);
7989 } 7259 }
7990 } 7260 }
7991 7261
7992 /** 7262 /**
7993 * Builds a simple switch statement which does not handle uses of continue 7263 * Builds a simple switch statement which does not handle uses of continue
7994 * statements to labeled switch cases. 7264 * statements to labeled switch cases.
7995 */ 7265 */
7996 void buildSimpleSwitchStatement(ast.SwitchStatement node, 7266 void buildSimpleSwitchStatement(
7997 Map<ast.CaseMatch, ConstantValue> constants) { 7267 ast.SwitchStatement node, Map<ast.CaseMatch, ConstantValue> constants) {
7998 JumpHandler jumpHandler = createJumpHandler(node, isLoopJump: false); 7268 JumpHandler jumpHandler = createJumpHandler(node, isLoopJump: false);
7999 HInstruction buildExpression() { 7269 HInstruction buildExpression() {
8000 visit(node.expression); 7270 visit(node.expression);
8001 return pop(); 7271 return pop();
8002 } 7272 }
8003 Iterable<ConstantValue> getConstants(ast.SwitchCase switchCase) { 7273 Iterable<ConstantValue> getConstants(ast.SwitchCase switchCase) {
8004 List<ConstantValue> constantList = <ConstantValue>[]; 7274 List<ConstantValue> constantList = <ConstantValue>[];
8005 for (ast.Node labelOrCase in switchCase.labelsAndCases) { 7275 for (ast.Node labelOrCase in switchCase.labelsAndCases) {
8006 if (labelOrCase is ast.CaseMatch) { 7276 if (labelOrCase is ast.CaseMatch) {
8007 constantList.add(constants[labelOrCase]); 7277 constantList.add(constants[labelOrCase]);
8008 } 7278 }
8009 } 7279 }
8010 return constantList; 7280 return constantList;
8011 } 7281 }
8012 bool isDefaultCase(ast.SwitchCase switchCase) { 7282 bool isDefaultCase(ast.SwitchCase switchCase) {
8013 return switchCase.isDefaultCase; 7283 return switchCase.isDefaultCase;
8014 } 7284 }
8015 void buildSwitchCase(ast.SwitchCase node) { 7285 void buildSwitchCase(ast.SwitchCase node) {
8016 visit(node.statements); 7286 visit(node.statements);
8017 } 7287 }
8018 handleSwitch(node, 7288 handleSwitch(node, jumpHandler, buildExpression, node.cases, getConstants,
8019 jumpHandler, 7289 isDefaultCase, buildSwitchCase);
8020 buildExpression,
8021 node.cases,
8022 getConstants,
8023 isDefaultCase,
8024 buildSwitchCase);
8025 jumpHandler.close(); 7290 jumpHandler.close();
8026 } 7291 }
8027 7292
8028 /** 7293 /**
8029 * Builds a switch statement that can handle arbitrary uses of continue 7294 * Builds a switch statement that can handle arbitrary uses of continue
8030 * statements to labeled switch cases. 7295 * statements to labeled switch cases.
8031 */ 7296 */
8032 void buildComplexSwitchStatement(ast.SwitchStatement node, 7297 void buildComplexSwitchStatement(
8033 Map<ast.CaseMatch, ConstantValue> constants, 7298 ast.SwitchStatement node,
8034 Map<ast.SwitchCase, int> caseIndex, 7299 Map<ast.CaseMatch, ConstantValue> constants,
8035 bool hasDefault) { 7300 Map<ast.SwitchCase, int> caseIndex,
7301 bool hasDefault) {
8036 // If the switch statement has switch cases targeted by continue 7302 // If the switch statement has switch cases targeted by continue
8037 // statements we create the following encoding: 7303 // statements we create the following encoding:
8038 // 7304 //
8039 // switch (e) { 7305 // switch (e) {
8040 // l_1: case e0: s_1; break; 7306 // l_1: case e0: s_1; break;
8041 // l_2: case e1: s_2; continue l_i; 7307 // l_2: case e1: s_2; continue l_i;
8042 // ... 7308 // ...
8043 // l_n: default: s_n; continue l_j; 7309 // l_n: default: s_n; continue l_j;
8044 // } 7310 // }
8045 // 7311 //
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
8097 int index = caseIndex[switchCase]; 7363 int index = caseIndex[switchCase];
8098 HInstruction value = graph.addConstantInt(index, compiler); 7364 HInstruction value = graph.addConstantInt(index, compiler);
8099 localsHandler.updateLocal(switchTarget, value); 7365 localsHandler.updateLocal(switchTarget, value);
8100 } else { 7366 } else {
8101 // Generate synthetic default case 'target = null; break;'. 7367 // Generate synthetic default case 'target = null; break;'.
8102 HInstruction value = graph.addConstantNull(compiler); 7368 HInstruction value = graph.addConstantNull(compiler);
8103 localsHandler.updateLocal(switchTarget, value); 7369 localsHandler.updateLocal(switchTarget, value);
8104 } 7370 }
8105 jumpTargets[switchTarget].generateBreak(); 7371 jumpTargets[switchTarget].generateBreak();
8106 } 7372 }
8107 handleSwitch(node, 7373 handleSwitch(node, jumpHandler, buildExpression, switchCases, getConstants,
8108 jumpHandler, 7374 isDefaultCase, buildSwitchCase);
8109 buildExpression,
8110 switchCases,
8111 getConstants,
8112 isDefaultCase,
8113 buildSwitchCase);
8114 jumpHandler.close(); 7375 jumpHandler.close();
8115 7376
8116 HInstruction buildCondition() => 7377 HInstruction buildCondition() => graph.addConstantBool(true, compiler);
8117 graph.addConstantBool(true, compiler);
8118 7378
8119 void buildSwitch() { 7379 void buildSwitch() {
8120 HInstruction buildExpression() { 7380 HInstruction buildExpression() {
8121 return localsHandler.readLocal(switchTarget); 7381 return localsHandler.readLocal(switchTarget);
8122 } 7382 }
8123 Iterable<ConstantValue> getConstants(ast.SwitchCase switchCase) { 7383 Iterable<ConstantValue> getConstants(ast.SwitchCase switchCase) {
8124 return <ConstantValue>[constantSystem.createInt(caseIndex[switchCase])]; 7384 return <ConstantValue>[constantSystem.createInt(caseIndex[switchCase])];
8125 } 7385 }
8126 void buildSwitchCase(ast.SwitchCase switchCase) { 7386 void buildSwitchCase(ast.SwitchCase switchCase) {
8127 visit(switchCase.statements); 7387 visit(switchCase.statements);
8128 if (!isAborted()) { 7388 if (!isAborted()) {
8129 // Ensure that we break the loop if the case falls through. (This 7389 // Ensure that we break the loop if the case falls through. (This
8130 // is only possible for the last case.) 7390 // is only possible for the last case.)
8131 jumpTargets[switchTarget].generateBreak(); 7391 jumpTargets[switchTarget].generateBreak();
8132 } 7392 }
8133 } 7393 }
8134 // Pass a [NullJumpHandler] because the target for the contained break 7394 // Pass a [NullJumpHandler] because the target for the contained break
8135 // is not the generated switch statement but instead the loop generated 7395 // is not the generated switch statement but instead the loop generated
8136 // in the call to [handleLoop] below. 7396 // in the call to [handleLoop] below.
8137 handleSwitch(node, 7397 handleSwitch(
8138 new NullJumpHandler(reporter), 7398 node,
8139 buildExpression, node.cases, getConstants, 7399 new NullJumpHandler(reporter),
8140 (_) => false, // No case is default. 7400 buildExpression,
8141 buildSwitchCase); 7401 node.cases,
7402 getConstants,
7403 (_) => false, // No case is default.
7404 buildSwitchCase);
8142 } 7405 }
8143 7406
8144 void buildLoop() { 7407 void buildLoop() {
8145 handleLoop(node, 7408 handleLoop(node, () {}, buildCondition, () {}, buildSwitch);
8146 () {},
8147 buildCondition,
8148 () {},
8149 buildSwitch);
8150 } 7409 }
8151 7410
8152 if (hasDefault) { 7411 if (hasDefault) {
8153 buildLoop(); 7412 buildLoop();
8154 } else { 7413 } else {
8155 // If the switch statement has no default case, surround the loop with 7414 // If the switch statement has no default case, surround the loop with
8156 // a test of the target. 7415 // a test of the target.
8157 void buildCondition() { 7416 void buildCondition() {
8158 js.Template code = js.js.parseForeignJS('#'); 7417 js.Template code = js.js.parseForeignJS('#');
8159 push(new HForeignCode( 7418 push(new HForeignCode(
8160 code, 7419 code, backend.boolType, [localsHandler.readLocal(switchTarget)],
8161 backend.boolType,
8162 [localsHandler.readLocal(switchTarget)],
8163 nativeBehavior: native.NativeBehavior.PURE)); 7420 nativeBehavior: native.NativeBehavior.PURE));
8164 } 7421 }
8165 handleIf(node, 7422 handleIf(node,
8166 visitCondition: buildCondition, 7423 visitCondition: buildCondition,
8167 visitThen: buildLoop, 7424 visitThen: buildLoop,
8168 visitElse: () => {}); 7425 visitElse: () => {});
8169 } 7426 }
8170 } 7427 }
8171 7428
8172 /** 7429 /**
8173 * Creates a switch statement. 7430 * Creates a switch statement.
8174 * 7431 *
8175 * [jumpHandler] is the [JumpHandler] for the created switch statement. 7432 * [jumpHandler] is the [JumpHandler] for the created switch statement.
8176 * [buildExpression] creates the switch expression. 7433 * [buildExpression] creates the switch expression.
8177 * [switchCases] must be either an [Iterable] of [ast.SwitchCase] nodes or 7434 * [switchCases] must be either an [Iterable] of [ast.SwitchCase] nodes or
8178 * a [Link] or a [ast.NodeList] of [ast.SwitchCase] nodes. 7435 * a [Link] or a [ast.NodeList] of [ast.SwitchCase] nodes.
8179 * [getConstants] returns the set of constants for a switch case. 7436 * [getConstants] returns the set of constants for a switch case.
8180 * [isDefaultCase] returns [:true:] if the provided switch case should be 7437 * [isDefaultCase] returns [:true:] if the provided switch case should be
8181 * considered default for the created switch statement. 7438 * considered default for the created switch statement.
8182 * [buildSwitchCase] creates the statements for the switch case. 7439 * [buildSwitchCase] creates the statements for the switch case.
8183 */ 7440 */
8184 void handleSwitch( 7441 void handleSwitch(
8185 ast.Node errorNode, 7442 ast.Node errorNode,
8186 JumpHandler jumpHandler, 7443 JumpHandler jumpHandler,
8187 HInstruction buildExpression(), 7444 HInstruction buildExpression(),
8188 var switchCases, 7445 var switchCases,
8189 Iterable<ConstantValue> getConstants(ast.SwitchCase switchCase), 7446 Iterable<ConstantValue> getConstants(ast.SwitchCase switchCase),
8190 bool isDefaultCase(ast.SwitchCase switchCase), 7447 bool isDefaultCase(ast.SwitchCase switchCase),
8191 void buildSwitchCase(ast.SwitchCase switchCase)) { 7448 void buildSwitchCase(ast.SwitchCase switchCase)) {
8192
8193 HBasicBlock expressionStart = openNewBlock(); 7449 HBasicBlock expressionStart = openNewBlock();
8194 HInstruction expression = buildExpression(); 7450 HInstruction expression = buildExpression();
8195 if (switchCases.isEmpty) { 7451 if (switchCases.isEmpty) {
8196 return; 7452 return;
8197 } 7453 }
8198 7454
8199 HSwitch switchInstruction = new HSwitch(<HInstruction>[expression]); 7455 HSwitch switchInstruction = new HSwitch(<HInstruction>[expression]);
8200 HBasicBlock expressionEnd = close(switchInstruction); 7456 HBasicBlock expressionEnd = close(switchInstruction);
8201 LocalsHandler savedLocals = localsHandler; 7457 LocalsHandler savedLocals = localsHandler;
8202 7458
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
8248 // If we never jump to the join block, [caseHandlers] will stay empty, and 7504 // If we never jump to the join block, [caseHandlers] will stay empty, and
8249 // the join block is never added to the graph. 7505 // the join block is never added to the graph.
8250 HBasicBlock joinBlock = new HBasicBlock(); 7506 HBasicBlock joinBlock = new HBasicBlock();
8251 List<LocalsHandler> caseHandlers = <LocalsHandler>[]; 7507 List<LocalsHandler> caseHandlers = <LocalsHandler>[];
8252 jumpHandler.forEachBreak((HBreak instruction, LocalsHandler locals) { 7508 jumpHandler.forEachBreak((HBreak instruction, LocalsHandler locals) {
8253 instruction.block.addSuccessor(joinBlock); 7509 instruction.block.addSuccessor(joinBlock);
8254 caseHandlers.add(locals); 7510 caseHandlers.add(locals);
8255 }); 7511 });
8256 jumpHandler.forEachContinue((HContinue instruction, LocalsHandler locals) { 7512 jumpHandler.forEachContinue((HContinue instruction, LocalsHandler locals) {
8257 assert(invariant(errorNode, false, 7513 assert(invariant(errorNode, false,
8258 message: 'Continue cannot target a switch.')); 7514 message: 'Continue cannot target a switch.'));
8259 }); 7515 });
8260 if (!isAborted()) { 7516 if (!isAborted()) {
8261 current.close(new HGoto()); 7517 current.close(new HGoto());
8262 lastOpenedBlock.addSuccessor(joinBlock); 7518 lastOpenedBlock.addSuccessor(joinBlock);
8263 caseHandlers.add(localsHandler); 7519 caseHandlers.add(localsHandler);
8264 } 7520 }
8265 if (!hasDefault) { 7521 if (!hasDefault) {
8266 // Always create a default case, to avoid a critical edge in the 7522 // Always create a default case, to avoid a critical edge in the
8267 // graph. 7523 // graph.
8268 HBasicBlock defaultCase = addNewBlock(); 7524 HBasicBlock defaultCase = addNewBlock();
8269 expressionEnd.addSuccessor(defaultCase); 7525 expressionEnd.addSuccessor(defaultCase);
8270 open(defaultCase); 7526 open(defaultCase);
8271 close(new HGoto()); 7527 close(new HGoto());
8272 defaultCase.addSuccessor(joinBlock); 7528 defaultCase.addSuccessor(joinBlock);
8273 caseHandlers.add(savedLocals); 7529 caseHandlers.add(savedLocals);
8274 statements.add(new HSubGraphBlockInformation(new SubGraph( 7530 statements.add(new HSubGraphBlockInformation(
8275 defaultCase, defaultCase))); 7531 new SubGraph(defaultCase, defaultCase)));
8276 } 7532 }
8277 assert(caseHandlers.length == joinBlock.predecessors.length); 7533 assert(caseHandlers.length == joinBlock.predecessors.length);
8278 if (caseHandlers.length != 0) { 7534 if (caseHandlers.length != 0) {
8279 graph.addBlock(joinBlock); 7535 graph.addBlock(joinBlock);
8280 open(joinBlock); 7536 open(joinBlock);
8281 if (caseHandlers.length == 1) { 7537 if (caseHandlers.length == 1) {
8282 localsHandler = caseHandlers[0]; 7538 localsHandler = caseHandlers[0];
8283 } else { 7539 } else {
8284 localsHandler = savedLocals.mergeMultiple(caseHandlers, joinBlock); 7540 localsHandler = savedLocals.mergeMultiple(caseHandlers, joinBlock);
8285 } 7541 }
8286 } else { 7542 } else {
8287 // The joinblock is not used. 7543 // The joinblock is not used.
8288 joinBlock = null; 7544 joinBlock = null;
8289 } 7545 }
8290 7546
8291 HSubExpressionBlockInformation expressionInfo = 7547 HSubExpressionBlockInformation expressionInfo =
8292 new HSubExpressionBlockInformation(new SubExpression(expressionStart, 7548 new HSubExpressionBlockInformation(
8293 expressionEnd)); 7549 new SubExpression(expressionStart, expressionEnd));
8294 expressionStart.setBlockFlow( 7550 expressionStart.setBlockFlow(
8295 new HSwitchBlockInformation(expressionInfo, 7551 new HSwitchBlockInformation(expressionInfo, statements,
8296 statements, 7552 jumpHandler.target, jumpHandler.labels()),
8297 jumpHandler.target,
8298 jumpHandler.labels()),
8299 joinBlock); 7553 joinBlock);
8300 7554
8301 jumpHandler.close(); 7555 jumpHandler.close();
8302 } 7556 }
8303 7557
8304 visitSwitchCase(ast.SwitchCase node) { 7558 visitSwitchCase(ast.SwitchCase node) {
8305 reporter.internalError(node, 'SsaFromAstMixin.visitSwitchCase.'); 7559 reporter.internalError(node, 'SsaFromAstMixin.visitSwitchCase.');
8306 } 7560 }
8307 7561
8308 visitCaseMatch(ast.CaseMatch node) { 7562 visitCaseMatch(ast.CaseMatch node) {
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
8389 addExitTrySuccessor(startFinallyBlock); 7643 addExitTrySuccessor(startFinallyBlock);
8390 7644
8391 // Use the locals handler not altered by the catch and finally 7645 // Use the locals handler not altered by the catch and finally
8392 // blocks. 7646 // blocks.
8393 // TODO(sigurdm): We can probably do this, because try-variables are boxed. 7647 // TODO(sigurdm): We can probably do this, because try-variables are boxed.
8394 // Need to verify. 7648 // Need to verify.
8395 localsHandler = savedLocals; 7649 localsHandler = savedLocals;
8396 open(exitBlock); 7650 open(exitBlock);
8397 enterBlock.setBlockFlow( 7651 enterBlock.setBlockFlow(
8398 new HTryBlockInformation( 7652 new HTryBlockInformation(
8399 wrapStatementGraph(bodyGraph), 7653 wrapStatementGraph(bodyGraph),
8400 null, // No catch-variable. 7654 null, // No catch-variable.
8401 null, // No catchGraph. 7655 null, // No catchGraph.
8402 wrapStatementGraph(finallyGraph)), 7656 wrapStatementGraph(finallyGraph)),
8403 exitBlock); 7657 exitBlock);
8404 inTryStatement = oldInTryStatement; 7658 inTryStatement = oldInTryStatement;
8405 } 7659 }
8406 7660
8407 visitTryStatement(ast.TryStatement node) { 7661 visitTryStatement(ast.TryStatement node) {
8408 // Save the current locals. The catch block and the finally block 7662 // Save the current locals. The catch block and the finally block
8409 // must not reuse the existing locals handler. None of the variables 7663 // must not reuse the existing locals handler. None of the variables
8410 // that have been defined in the body-block will be used, but for 7664 // that have been defined in the body-block will be used, but for
8411 // loops we will add (unnecessary) phis that will reference the body 7665 // loops we will add (unnecessary) phis that will reference the body
8412 // variables. This makes it look as if the variables were used 7666 // variables. This makes it look as if the variables were used
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
8482 } 7736 }
8483 } 7737 }
8484 } 7738 }
8485 7739
8486 void visitThen() { 7740 void visitThen() {
8487 ast.CatchBlock catchBlock = link.head; 7741 ast.CatchBlock catchBlock = link.head;
8488 link = link.tail; 7742 link = link.tail;
8489 if (catchBlock.exception != null) { 7743 if (catchBlock.exception != null) {
8490 LocalVariableElement exceptionVariable = 7744 LocalVariableElement exceptionVariable =
8491 elements[catchBlock.exception]; 7745 elements[catchBlock.exception];
8492 localsHandler.updateLocal(exceptionVariable, 7746 localsHandler.updateLocal(exceptionVariable, unwrappedException);
8493 unwrappedException);
8494 } 7747 }
8495 ast.Node trace = catchBlock.trace; 7748 ast.Node trace = catchBlock.trace;
8496 if (trace != null) { 7749 if (trace != null) {
8497 pushInvokeStatic(trace, helpers.traceFromException, [exception]); 7750 pushInvokeStatic(trace, helpers.traceFromException, [exception]);
8498 HInstruction traceInstruction = pop(); 7751 HInstruction traceInstruction = pop();
8499 LocalVariableElement traceVariable = elements[trace]; 7752 LocalVariableElement traceVariable = elements[trace];
8500 localsHandler.updateLocal(traceVariable, traceInstruction); 7753 localsHandler.updateLocal(traceVariable, traceInstruction);
8501 } 7754 }
8502 visit(catchBlock); 7755 visit(catchBlock);
8503 } 7756 }
8504 7757
8505 void visitElse() { 7758 void visitElse() {
8506 if (link.isEmpty) { 7759 if (link.isEmpty) {
8507 closeAndGotoExit( 7760 closeAndGotoExit(new HThrow(exception, exception.sourceInformation,
8508 new HThrow(exception, 7761 isRethrow: true));
8509 exception.sourceInformation,
8510 isRethrow: true));
8511 } else { 7762 } else {
8512 ast.CatchBlock newBlock = link.head; 7763 ast.CatchBlock newBlock = link.head;
8513 handleIf(node, 7764 handleIf(node, visitCondition: () {
8514 visitCondition: () { pushCondition(newBlock); }, 7765 pushCondition(newBlock);
8515 visitThen: visitThen, 7766 }, visitThen: visitThen, visitElse: visitElse);
8516 visitElse: visitElse);
8517 } 7767 }
8518 } 7768 }
8519 7769
8520 ast.CatchBlock firstBlock = link.head; 7770 ast.CatchBlock firstBlock = link.head;
8521 handleIf(node, 7771 handleIf(node, visitCondition: () {
8522 visitCondition: () { pushCondition(firstBlock); }, 7772 pushCondition(firstBlock);
8523 visitThen: visitThen, 7773 }, visitThen: visitThen, visitElse: visitElse);
8524 visitElse: visitElse);
8525 if (!isAborted()) endCatchBlock = close(new HGoto()); 7774 if (!isAborted()) endCatchBlock = close(new HGoto());
8526 7775
8527 rethrowableException = oldRethrowableException; 7776 rethrowableException = oldRethrowableException;
8528 tryInstruction.catchBlock = startCatchBlock; 7777 tryInstruction.catchBlock = startCatchBlock;
8529 catchGraph = new SubGraph(startCatchBlock, lastOpenedBlock); 7778 catchGraph = new SubGraph(startCatchBlock, lastOpenedBlock);
8530 } 7779 }
8531 7780
8532 SubGraph finallyGraph = null; 7781 SubGraph finallyGraph = null;
8533 if (node.finallyBlock != null) { 7782 if (node.finallyBlock != null) {
8534 localsHandler = new LocalsHandler.from(savedLocals); 7783 localsHandler = new LocalsHandler.from(savedLocals);
8535 startFinallyBlock = graph.addNewBlock(); 7784 startFinallyBlock = graph.addNewBlock();
8536 open(startFinallyBlock); 7785 open(startFinallyBlock);
8537 visit(node.finallyBlock); 7786 visit(node.finallyBlock);
8538 if (!isAborted()) endFinallyBlock = close(new HGoto()); 7787 if (!isAborted()) endFinallyBlock = close(new HGoto());
8539 tryInstruction.finallyBlock = startFinallyBlock; 7788 tryInstruction.finallyBlock = startFinallyBlock;
8540 finallyGraph = new SubGraph(startFinallyBlock, lastOpenedBlock); 7789 finallyGraph = new SubGraph(startFinallyBlock, lastOpenedBlock);
8541 } 7790 }
8542 7791
8543 HBasicBlock exitBlock = graph.addNewBlock(); 7792 HBasicBlock exitBlock = graph.addNewBlock();
8544 7793
8545 addOptionalSuccessor(b1, b2) { if (b2 != null) b1.addSuccessor(b2); } 7794 addOptionalSuccessor(b1, b2) {
7795 if (b2 != null) b1.addSuccessor(b2);
7796 }
8546 addExitTrySuccessor(successor) { 7797 addExitTrySuccessor(successor) {
8547 if (successor == null) return; 7798 if (successor == null) return;
8548 // Iterate over all blocks created inside this try/catch, and 7799 // Iterate over all blocks created inside this try/catch, and
8549 // attach successor information to blocks that end with 7800 // attach successor information to blocks that end with
8550 // [HExitTry]. 7801 // [HExitTry].
8551 for (int i = startTryBlock.id; i < successor.id; i++) { 7802 for (int i = startTryBlock.id; i < successor.id; i++) {
8552 HBasicBlock block = graph.blocks[i]; 7803 HBasicBlock block = graph.blocks[i];
8553 var last = block.last; 7804 var last = block.last;
8554 if (last is HExitTry) { 7805 if (last is HExitTry) {
8555 block.addSuccessor(successor); 7806 block.addSuccessor(successor);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
8589 // we explicitely mark this block a predecessor of the catch 7840 // we explicitely mark this block a predecessor of the catch
8590 // block and the finally block. 7841 // block and the finally block.
8591 addExitTrySuccessor(startCatchBlock); 7842 addExitTrySuccessor(startCatchBlock);
8592 addExitTrySuccessor(startFinallyBlock); 7843 addExitTrySuccessor(startFinallyBlock);
8593 7844
8594 // Use the locals handler not altered by the catch and finally 7845 // Use the locals handler not altered by the catch and finally
8595 // blocks. 7846 // blocks.
8596 localsHandler = savedLocals; 7847 localsHandler = savedLocals;
8597 open(exitBlock); 7848 open(exitBlock);
8598 enterBlock.setBlockFlow( 7849 enterBlock.setBlockFlow(
8599 new HTryBlockInformation( 7850 new HTryBlockInformation(wrapStatementGraph(bodyGraph), exception,
8600 wrapStatementGraph(bodyGraph), 7851 wrapStatementGraph(catchGraph), wrapStatementGraph(finallyGraph)),
8601 exception,
8602 wrapStatementGraph(catchGraph),
8603 wrapStatementGraph(finallyGraph)),
8604 exitBlock); 7852 exitBlock);
8605 inTryStatement = oldInTryStatement; 7853 inTryStatement = oldInTryStatement;
8606 } 7854 }
8607 7855
8608 visitCatchBlock(ast.CatchBlock node) { 7856 visitCatchBlock(ast.CatchBlock node) {
8609 visit(node.block); 7857 visit(node.block);
8610 } 7858 }
8611 7859
8612 visitTypedef(ast.Typedef node) { 7860 visitTypedef(ast.Typedef node) {
8613 compiler.unimplemented(node, 'SsaFromAstMixin.visitTypedef.'); 7861 compiler.unimplemented(node, 'SsaFromAstMixin.visitTypedef.');
8614 } 7862 }
8615 7863
8616 visitTypeVariable(ast.TypeVariable node) { 7864 visitTypeVariable(ast.TypeVariable node) {
8617 reporter.internalError(node, 'SsaFromAstMixin.visitTypeVariable.'); 7865 reporter.internalError(node, 'SsaFromAstMixin.visitTypeVariable.');
8618 } 7866 }
8619 7867
8620 /** 7868 /**
8621 * This method is invoked before inlining the body of [function] into this 7869 * This method is invoked before inlining the body of [function] into this
8622 * [SsaBuilder]. 7870 * [SsaBuilder].
8623 */ 7871 */
8624 void enterInlinedMethod(FunctionElement function, 7872 void enterInlinedMethod(FunctionElement function, ast.Node _,
8625 ast.Node _, 7873 List<HInstruction> compiledArguments,
8626 List<HInstruction> compiledArguments, 7874 {InterfaceType instanceType}) {
8627 {InterfaceType instanceType}) {
8628 AstInliningState state = new AstInliningState( 7875 AstInliningState state = new AstInliningState(
8629 function, returnLocal, returnType, elements, stack, localsHandler, 7876 function,
7877 returnLocal,
7878 returnType,
7879 elements,
7880 stack,
7881 localsHandler,
8630 inTryStatement, 7882 inTryStatement,
8631 allInlinedFunctionsCalledOnce && isFunctionCalledOnce(function)); 7883 allInlinedFunctionsCalledOnce && isFunctionCalledOnce(function));
8632 inliningStack.add(state); 7884 inliningStack.add(state);
8633 7885
8634 // Setting up the state of the (AST) builder is performed even when the 7886 // Setting up the state of the (AST) builder is performed even when the
8635 // inlined function is in IR, because the irInliner uses the [returnElement] 7887 // inlined function is in IR, because the irInliner uses the [returnElement]
8636 // of the AST builder. 7888 // of the AST builder.
8637 setupStateForInlining( 7889 setupStateForInlining(function, compiledArguments,
8638 function, compiledArguments, instanceType: instanceType); 7890 instanceType: instanceType);
8639 } 7891 }
8640 7892
8641 void leaveInlinedMethod() { 7893 void leaveInlinedMethod() {
8642 HInstruction result = localsHandler.readLocal(returnLocal); 7894 HInstruction result = localsHandler.readLocal(returnLocal);
8643 AstInliningState state = inliningStack.removeLast(); 7895 AstInliningState state = inliningStack.removeLast();
8644 restoreState(state); 7896 restoreState(state);
8645 stack.add(result); 7897 stack.add(result);
8646 } 7898 }
8647 7899
8648 void doInline(FunctionElement function) { 7900 void doInline(FunctionElement function) {
8649 visitInlinedFunction(function); 7901 visitInlinedFunction(function);
8650 } 7902 }
8651 7903
8652 void emitReturn(HInstruction value, ast.Node node) { 7904 void emitReturn(HInstruction value, ast.Node node) {
8653 if (inliningStack.isEmpty) { 7905 if (inliningStack.isEmpty) {
8654 closeAndGotoExit(new HReturn(value, 7906 closeAndGotoExit(
8655 sourceInformationBuilder.buildReturn(node))); 7907 new HReturn(value, sourceInformationBuilder.buildReturn(node)));
8656 } else { 7908 } else {
8657 localsHandler.updateLocal(returnLocal, value); 7909 localsHandler.updateLocal(returnLocal, value);
8658 } 7910 }
8659 } 7911 }
8660 7912
8661 @override 7913 @override
8662 void handleTypeLiteralConstantCompounds( 7914 void handleTypeLiteralConstantCompounds(
8663 ast.SendSet node, 7915 ast.SendSet node, ConstantExpression constant, CompoundRhs rhs, _) {
8664 ConstantExpression constant,
8665 CompoundRhs rhs,
8666 _) {
8667 handleTypeLiteralCompound(node); 7916 handleTypeLiteralCompound(node);
8668 } 7917 }
8669 7918
8670 @override 7919 @override
8671 void handleTypeVariableTypeLiteralCompounds( 7920 void handleTypeVariableTypeLiteralCompounds(
8672 ast.SendSet node, 7921 ast.SendSet node, TypeVariableElement typeVariable, CompoundRhs rhs, _) {
8673 TypeVariableElement typeVariable,
8674 CompoundRhs rhs,
8675 _) {
8676 handleTypeLiteralCompound(node); 7922 handleTypeLiteralCompound(node);
8677 } 7923 }
8678 7924
8679 void handleTypeLiteralCompound(ast.SendSet node) { 7925 void handleTypeLiteralCompound(ast.SendSet node) {
8680 generateIsDeferredLoadedCheckOfSend(node); 7926 generateIsDeferredLoadedCheckOfSend(node);
8681 ast.Identifier selector = node.selector; 7927 ast.Identifier selector = node.selector;
8682 generateThrowNoSuchMethod(node, selector.source, 7928 generateThrowNoSuchMethod(node, selector.source,
8683 argumentNodes: node.arguments); 7929 argumentNodes: node.arguments);
8684 } 7930 }
8685 7931
8686 @override 7932 @override
8687 void visitConstantGet( 7933 void visitConstantGet(ast.Send node, ConstantExpression constant, _) {
8688 ast.Send node,
8689 ConstantExpression constant,
8690 _) {
8691 visitNode(node); 7934 visitNode(node);
8692 } 7935 }
8693 7936
8694 @override 7937 @override
8695 void visitConstantInvoke( 7938 void visitConstantInvoke(ast.Send node, ConstantExpression constant,
8696 ast.Send node, 7939 ast.NodeList arguments, CallStructure callStreucture, _) {
8697 ConstantExpression constant,
8698 ast.NodeList arguments,
8699 CallStructure callStreucture,
8700 _) {
8701 visitNode(node); 7940 visitNode(node);
8702 } 7941 }
8703 7942
8704 @override 7943 @override
8705 void errorUndefinedBinaryExpression( 7944 void errorUndefinedBinaryExpression(
8706 ast.Send node, 7945 ast.Send node, ast.Node left, ast.Operator operator, ast.Node right, _) {
8707 ast.Node left,
8708 ast.Operator operator,
8709 ast.Node right,
8710 _) {
8711 visitNode(node); 7946 visitNode(node);
8712 } 7947 }
8713 7948
8714 @override 7949 @override
8715 void errorUndefinedUnaryExpression( 7950 void errorUndefinedUnaryExpression(
8716 ast.Send node, 7951 ast.Send node, ast.Operator operator, ast.Node expression, _) {
8717 ast.Operator operator,
8718 ast.Node expression,
8719 _) {
8720 visitNode(node); 7952 visitNode(node);
8721 } 7953 }
8722 7954
8723 @override 7955 @override
8724 void bulkHandleError(ast.Node node, ErroneousElement error, _) { 7956 void bulkHandleError(ast.Node node, ErroneousElement error, _) {
8725 // TODO(johnniwinther): Use an uncatchable error when supported. 7957 // TODO(johnniwinther): Use an uncatchable error when supported.
8726 generateRuntimeError(node, error.message); 7958 generateRuntimeError(node, error.message);
8727 } 7959 }
8728 } 7960 }
8729 7961
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
8767 append(stringify(node, expression)); 7999 append(stringify(node, expression));
8768 return; 8000 return;
8769 } 8001 }
8770 8002
8771 // If the `toString` method is guaranteed to return a string we can call it 8003 // If the `toString` method is guaranteed to return a string we can call it
8772 // directly. 8004 // directly.
8773 Selector selector = Selectors.toString_; 8005 Selector selector = Selectors.toString_;
8774 TypeMask type = TypeMaskFactory.inferredTypeForSelector( 8006 TypeMask type = TypeMaskFactory.inferredTypeForSelector(
8775 selector, expression.instructionType, compiler); 8007 selector, expression.instructionType, compiler);
8776 if (type.containsOnlyString(compiler.world)) { 8008 if (type.containsOnlyString(compiler.world)) {
8777 builder.pushInvokeDynamic( 8009 builder.pushInvokeDynamic(node, selector, expression.instructionType,
8778 node, selector, 8010 <HInstruction>[expression]);
8779 expression.instructionType, <HInstruction>[expression]);
8780 append(builder.pop()); 8011 append(builder.pop());
8781 return; 8012 return;
8782 } 8013 }
8783 8014
8784 append(stringify(node, expression)); 8015 append(stringify(node, expression));
8785 } 8016 }
8786 8017
8787 void visitStringInterpolation(ast.StringInterpolation node) { 8018 void visitStringInterpolation(ast.StringInterpolation node) {
8788 node.visitChildren(this); 8019 node.visitChildren(this);
8789 } 8020 }
8790 8021
8791 void visitStringInterpolationPart(ast.StringInterpolationPart node) { 8022 void visitStringInterpolationPart(ast.StringInterpolationPart node) {
8792 visit(node.expression); 8023 visit(node.expression);
8793 visit(node.string); 8024 visit(node.string);
8794 } 8025 }
8795 8026
8796 void visitStringJuxtaposition(ast.StringJuxtaposition node) { 8027 void visitStringJuxtaposition(ast.StringJuxtaposition node) {
8797 node.visitChildren(this); 8028 node.visitChildren(this);
8798 } 8029 }
8799 8030
8800 void visitNodeList(ast.NodeList node) { 8031 void visitNodeList(ast.NodeList node) {
8801 node.visitChildren(this); 8032 node.visitChildren(this);
8802 } 8033 }
8803 8034
8804 void append(HInstruction expression) { 8035 void append(HInstruction expression) {
8805 result = (result == null) ? expression : concat(result, expression); 8036 result = (result == null) ? expression : concat(result, expression);
8806 } 8037 }
8807 8038
8808 HInstruction concat(HInstruction left, HInstruction right) { 8039 HInstruction concat(HInstruction left, HInstruction right) {
8809 HInstruction instruction = new HStringConcat( 8040 HInstruction instruction =
8810 left, right, builder.backend.stringType); 8041 new HStringConcat(left, right, builder.backend.stringType);
8811 builder.add(instruction); 8042 builder.add(instruction);
8812 return instruction; 8043 return instruction;
8813 } 8044 }
8814 8045
8815 HInstruction stringify(ast.Node node, HInstruction expression) { 8046 HInstruction stringify(ast.Node node, HInstruction expression) {
8816 HInstruction instruction = 8047 HInstruction instruction =
8817 new HStringify(expression, builder.backend.stringType); 8048 new HStringify(expression, builder.backend.stringType);
8818 builder.add(instruction); 8049 builder.add(instruction);
8819 return instruction; 8050 return instruction;
8820 } 8051 }
(...skipping 14 matching lines...) Expand all
8835 static const INLINING_NODES_INSIDE_LOOP_ARG_FACTOR = 4; 8066 static const INLINING_NODES_INSIDE_LOOP_ARG_FACTOR = 4;
8836 8067
8837 bool seenReturn = false; 8068 bool seenReturn = false;
8838 bool tooDifficult = false; 8069 bool tooDifficult = false;
8839 int nodeCount = 0; 8070 int nodeCount = 0;
8840 final int maxInliningNodes; 8071 final int maxInliningNodes;
8841 final bool useMaxInliningNodes; 8072 final bool useMaxInliningNodes;
8842 final bool allowLoops; 8073 final bool allowLoops;
8843 final bool enableUserAssertions; 8074 final bool enableUserAssertions;
8844 8075
8845 InlineWeeder(this.maxInliningNodes, 8076 InlineWeeder(this.maxInliningNodes, this.useMaxInliningNodes, this.allowLoops,
8846 this.useMaxInliningNodes, 8077 this.enableUserAssertions);
8847 this.allowLoops,
8848 this.enableUserAssertions);
8849 8078
8850 static bool canBeInlined(FunctionElement function, 8079 static bool canBeInlined(
8851 int maxInliningNodes, 8080 FunctionElement function, int maxInliningNodes, bool useMaxInliningNodes,
8852 bool useMaxInliningNodes, 8081 {bool allowLoops: false, bool enableUserAssertions: null}) {
8853 {bool allowLoops: false,
8854 bool enableUserAssertions: null}) {
8855 assert(enableUserAssertions is bool); // Ensure we passed it. 8082 assert(enableUserAssertions is bool); // Ensure we passed it.
8856 if (function.resolvedAst.elements.containsTryStatement) return false; 8083 if (function.resolvedAst.elements.containsTryStatement) return false;
8857 8084
8858 InlineWeeder weeder = 8085 InlineWeeder weeder = new InlineWeeder(maxInliningNodes,
8859 new InlineWeeder(maxInliningNodes, useMaxInliningNodes, allowLoops, 8086 useMaxInliningNodes, allowLoops, enableUserAssertions);
8860 enableUserAssertions);
8861 ast.FunctionExpression functionExpression = function.node; 8087 ast.FunctionExpression functionExpression = function.node;
8862 weeder.visit(functionExpression.initializers); 8088 weeder.visit(functionExpression.initializers);
8863 weeder.visit(functionExpression.body); 8089 weeder.visit(functionExpression.body);
8864 weeder.visit(functionExpression.asyncModifier); 8090 weeder.visit(functionExpression.asyncModifier);
8865 return !weeder.tooDifficult; 8091 return !weeder.tooDifficult;
8866 } 8092 }
8867 8093
8868 bool registerNode() { 8094 bool registerNode() {
8869 if (!useMaxInliningNodes) return true; 8095 if (!useMaxInliningNodes) return true;
8870 if (nodeCount++ > maxInliningNodes) { 8096 if (nodeCount++ > maxInliningNodes) {
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
8929 tooDifficult = true; 8155 tooDifficult = true;
8930 } 8156 }
8931 8157
8932 void visitRethrow(ast.Rethrow node) { 8158 void visitRethrow(ast.Rethrow node) {
8933 if (!registerNode()) return; 8159 if (!registerNode()) return;
8934 tooDifficult = true; 8160 tooDifficult = true;
8935 } 8161 }
8936 8162
8937 void visitReturn(ast.Return node) { 8163 void visitReturn(ast.Return node) {
8938 if (!registerNode()) return; 8164 if (!registerNode()) return;
8939 if (seenReturn 8165 if (seenReturn || identical(node.beginToken.stringValue, 'native')) {
8940 || identical(node.beginToken.stringValue, 'native')) {
8941 tooDifficult = true; 8166 tooDifficult = true;
8942 return; 8167 return;
8943 } 8168 }
8944 node.visitChildren(this); 8169 node.visitChildren(this);
8945 seenReturn = true; 8170 seenReturn = true;
8946 } 8171 }
8947 8172
8948 void visitThrow(ast.Throw node) { 8173 void visitThrow(ast.Throw node) {
8949 if (!registerNode()) return; 8174 if (!registerNode()) return;
8950 // For now, we don't want to handle throw after a return even if 8175 // For now, we don't want to handle throw after a return even if
(...skipping 19 matching lines...) Expand all
8970 8195
8971 class AstInliningState extends InliningState { 8196 class AstInliningState extends InliningState {
8972 final Local oldReturnLocal; 8197 final Local oldReturnLocal;
8973 final DartType oldReturnType; 8198 final DartType oldReturnType;
8974 final TreeElements oldElements; 8199 final TreeElements oldElements;
8975 final List<HInstruction> oldStack; 8200 final List<HInstruction> oldStack;
8976 final LocalsHandler oldLocalsHandler; 8201 final LocalsHandler oldLocalsHandler;
8977 final bool inTryStatement; 8202 final bool inTryStatement;
8978 final bool allFunctionsCalledOnce; 8203 final bool allFunctionsCalledOnce;
8979 8204
8980 AstInliningState(FunctionElement function, 8205 AstInliningState(
8981 this.oldReturnLocal, 8206 FunctionElement function,
8982 this.oldReturnType, 8207 this.oldReturnLocal,
8983 this.oldElements, 8208 this.oldReturnType,
8984 this.oldStack, 8209 this.oldElements,
8985 this.oldLocalsHandler, 8210 this.oldStack,
8986 this.inTryStatement, 8211 this.oldLocalsHandler,
8987 this.allFunctionsCalledOnce) 8212 this.inTryStatement,
8213 this.allFunctionsCalledOnce)
8988 : super(function); 8214 : super(function);
8989 } 8215 }
8990 8216
8991 class SsaBranch { 8217 class SsaBranch {
8992 final SsaBranchBuilder branchBuilder; 8218 final SsaBranchBuilder branchBuilder;
8993 final HBasicBlock block; 8219 final HBasicBlock block;
8994 LocalsHandler startLocals; 8220 LocalsHandler startLocals;
8995 LocalsHandler exitLocals; 8221 LocalsHandler exitLocals;
8996 SubGraph graph; 8222 SubGraph graph;
8997 8223
8998 SsaBranch(this.branchBuilder) : block = new HBasicBlock(); 8224 SsaBranch(this.branchBuilder) : block = new HBasicBlock();
8999 } 8225 }
9000 8226
9001 class SsaBranchBuilder { 8227 class SsaBranchBuilder {
9002 final SsaBuilder builder; 8228 final SsaBuilder builder;
9003 final ast.Node diagnosticNode; 8229 final ast.Node diagnosticNode;
9004 8230
9005 SsaBranchBuilder(this.builder, [this.diagnosticNode]); 8231 SsaBranchBuilder(this.builder, [this.diagnosticNode]);
9006 8232
9007 Compiler get compiler => builder.compiler; 8233 Compiler get compiler => builder.compiler;
9008 8234
9009 void checkNotAborted() { 8235 void checkNotAborted() {
9010 if (builder.isAborted()) { 8236 if (builder.isAborted()) {
9011 compiler.unimplemented(diagnosticNode, "aborted control flow"); 8237 compiler.unimplemented(diagnosticNode, "aborted control flow");
9012 } 8238 }
9013 } 8239 }
9014 8240
9015 void buildCondition(void visitCondition(), 8241 void buildCondition(
9016 SsaBranch conditionBranch, 8242 void visitCondition(),
9017 SsaBranch thenBranch, 8243 SsaBranch conditionBranch,
9018 SsaBranch elseBranch, 8244 SsaBranch thenBranch,
9019 SourceInformation sourceInformation) { 8245 SsaBranch elseBranch,
8246 SourceInformation sourceInformation) {
9020 startBranch(conditionBranch); 8247 startBranch(conditionBranch);
9021 visitCondition(); 8248 visitCondition();
9022 checkNotAborted(); 8249 checkNotAborted();
9023 assert(identical(builder.current, builder.lastOpenedBlock)); 8250 assert(identical(builder.current, builder.lastOpenedBlock));
9024 HInstruction conditionValue = builder.popBoolified(); 8251 HInstruction conditionValue = builder.popBoolified();
9025 HIf branch = new HIf(conditionValue)..sourceInformation = sourceInformation; 8252 HIf branch = new HIf(conditionValue)..sourceInformation = sourceInformation;
9026 HBasicBlock conditionExitBlock = builder.current; 8253 HBasicBlock conditionExitBlock = builder.current;
9027 builder.close(branch); 8254 builder.close(branch);
9028 conditionBranch.exitLocals = builder.localsHandler; 8255 conditionBranch.exitLocals = builder.localsHandler;
9029 conditionExitBlock.addSuccessor(thenBranch.block); 8256 conditionExitBlock.addSuccessor(thenBranch.block);
9030 conditionExitBlock.addSuccessor(elseBranch.block); 8257 conditionExitBlock.addSuccessor(elseBranch.block);
9031 bool conditionBranchLocalsCanBeReused = 8258 bool conditionBranchLocalsCanBeReused =
9032 mergeLocals(conditionBranch, thenBranch, mayReuseFromLocals: true); 8259 mergeLocals(conditionBranch, thenBranch, mayReuseFromLocals: true);
9033 mergeLocals(conditionBranch, elseBranch, 8260 mergeLocals(conditionBranch, elseBranch,
9034 mayReuseFromLocals: conditionBranchLocalsCanBeReused); 8261 mayReuseFromLocals: conditionBranchLocalsCanBeReused);
9035 8262
9036 conditionBranch.graph = 8263 conditionBranch.graph =
9037 new SubExpression(conditionBranch.block, conditionExitBlock); 8264 new SubExpression(conditionBranch.block, conditionExitBlock);
9038 } 8265 }
9039 8266
9040 /** 8267 /**
9041 * Returns true if the locals of the [fromBranch] may be reused. A [:true:] 8268 * Returns true if the locals of the [fromBranch] may be reused. A [:true:]
9042 * return value implies that [mayReuseFromLocals] was set to [:true:]. 8269 * return value implies that [mayReuseFromLocals] was set to [:true:].
9043 */ 8270 */
9044 bool mergeLocals(SsaBranch fromBranch, SsaBranch toBranch, 8271 bool mergeLocals(SsaBranch fromBranch, SsaBranch toBranch,
9045 {bool mayReuseFromLocals}) { 8272 {bool mayReuseFromLocals}) {
9046 LocalsHandler fromLocals = fromBranch.exitLocals; 8273 LocalsHandler fromLocals = fromBranch.exitLocals;
9047 if (toBranch.startLocals == null) { 8274 if (toBranch.startLocals == null) {
9048 if (mayReuseFromLocals) { 8275 if (mayReuseFromLocals) {
9049 toBranch.startLocals = fromLocals; 8276 toBranch.startLocals = fromLocals;
9050 return false; 8277 return false;
9051 } else { 8278 } else {
9052 toBranch.startLocals = new LocalsHandler.from(fromLocals); 8279 toBranch.startLocals = new LocalsHandler.from(fromLocals);
9053 return true; 8280 return true;
9054 } 8281 }
9055 } else { 8282 } else {
9056 toBranch.startLocals.mergeWith(fromLocals, toBranch.block); 8283 toBranch.startLocals.mergeWith(fromLocals, toBranch.block);
9057 return true; 8284 return true;
9058 } 8285 }
9059 } 8286 }
9060 8287
9061 void startBranch(SsaBranch branch) { 8288 void startBranch(SsaBranch branch) {
9062 builder.graph.addBlock(branch.block); 8289 builder.graph.addBlock(branch.block);
9063 builder.localsHandler = branch.startLocals; 8290 builder.localsHandler = branch.startLocals;
9064 builder.open(branch.block); 8291 builder.open(branch.block);
9065 } 8292 }
9066 8293
9067 HInstruction buildBranch(SsaBranch branch, 8294 HInstruction buildBranch(SsaBranch branch, void visitBranch(),
9068 void visitBranch(), 8295 SsaBranch joinBranch, bool isExpression) {
9069 SsaBranch joinBranch,
9070 bool isExpression) {
9071 startBranch(branch); 8296 startBranch(branch);
9072 visitBranch(); 8297 visitBranch();
9073 branch.graph = new SubGraph(branch.block, builder.lastOpenedBlock); 8298 branch.graph = new SubGraph(branch.block, builder.lastOpenedBlock);
9074 branch.exitLocals = builder.localsHandler; 8299 branch.exitLocals = builder.localsHandler;
9075 if (!builder.isAborted()) { 8300 if (!builder.isAborted()) {
9076 builder.goto(builder.current, joinBranch.block); 8301 builder.goto(builder.current, joinBranch.block);
9077 mergeLocals(branch, joinBranch, mayReuseFromLocals: true); 8302 mergeLocals(branch, joinBranch, mayReuseFromLocals: true);
9078 } 8303 }
9079 if (isExpression) { 8304 if (isExpression) {
9080 checkNotAborted(); 8305 checkNotAborted();
9081 return builder.pop(); 8306 return builder.pop();
9082 } 8307 }
9083 return null; 8308 return null;
9084 } 8309 }
9085 8310
9086 handleIf(void visitCondition(), 8311 handleIf(void visitCondition(), void visitThen(), void visitElse(),
9087 void visitThen(), 8312 {SourceInformation sourceInformation}) {
9088 void visitElse(),
9089 {SourceInformation sourceInformation}) {
9090 if (visitElse == null) { 8313 if (visitElse == null) {
9091 // Make sure to have an else part to avoid a critical edge. A 8314 // Make sure to have an else part to avoid a critical edge. A
9092 // critical edge is an edge that connects a block with multiple 8315 // critical edge is an edge that connects a block with multiple
9093 // successors to a block with multiple predecessors. We avoid 8316 // successors to a block with multiple predecessors. We avoid
9094 // such edges because they prevent inserting copies during code 8317 // such edges because they prevent inserting copies during code
9095 // generation of phi instructions. 8318 // generation of phi instructions.
9096 visitElse = () {}; 8319 visitElse = () {};
9097 } 8320 }
9098 8321
9099 _handleDiamondBranch( 8322 _handleDiamondBranch(visitCondition, visitThen, visitElse,
9100 visitCondition, visitThen, visitElse, isExpression: false, 8323 isExpression: false, sourceInformation: sourceInformation);
9101 sourceInformation: sourceInformation);
9102 } 8324 }
9103 8325
9104 handleConditional(void visitCondition(), 8326 handleConditional(void visitCondition(), void visitThen(), void visitElse()) {
9105 void visitThen(),
9106 void visitElse()) {
9107 assert(visitElse != null); 8327 assert(visitElse != null);
9108 _handleDiamondBranch( 8328 _handleDiamondBranch(visitCondition, visitThen, visitElse,
9109 visitCondition, visitThen, visitElse, isExpression: true); 8329 isExpression: true);
9110 } 8330 }
9111 8331
9112 handleIfNull(void left(), void right()) { 8332 handleIfNull(void left(), void right()) {
9113 // x ?? y is transformed into: x == null ? y : x 8333 // x ?? y is transformed into: x == null ? y : x
9114 HInstruction leftExpression; 8334 HInstruction leftExpression;
9115 handleConditional( 8335 handleConditional(() {
9116 () { 8336 left();
9117 left(); 8337 leftExpression = builder.pop();
9118 leftExpression = builder.pop(); 8338 builder.pushCheckNull(leftExpression);
9119 builder.pushCheckNull(leftExpression); 8339 }, right, () => builder.stack.add(leftExpression));
9120 },
9121 right,
9122 () => builder.stack.add(leftExpression));
9123 } 8340 }
9124 8341
9125 void handleLogicalAndOr(void left(), void right(), {bool isAnd}) { 8342 void handleLogicalAndOr(void left(), void right(), {bool isAnd}) {
9126 // x && y is transformed into: 8343 // x && y is transformed into:
9127 // t0 = boolify(x); 8344 // t0 = boolify(x);
9128 // if (t0) { 8345 // if (t0) {
9129 // t1 = boolify(y); 8346 // t1 = boolify(y);
9130 // } 8347 // }
9131 // result = phi(t1, false); 8348 // result = phi(t1, false);
9132 // 8349 //
(...skipping 17 matching lines...) Expand all
9150 8367
9151 void visitThen() { 8368 void visitThen() {
9152 right(); 8369 right();
9153 boolifiedRight = builder.popBoolified(); 8370 boolifiedRight = builder.popBoolified();
9154 } 8371 }
9155 8372
9156 handleIf(visitCondition, visitThen, null); 8373 handleIf(visitCondition, visitThen, null);
9157 HConstant notIsAnd = 8374 HConstant notIsAnd =
9158 builder.graph.addConstantBool(!isAnd, builder.compiler); 8375 builder.graph.addConstantBool(!isAnd, builder.compiler);
9159 JavaScriptBackend backend = builder.backend; 8376 JavaScriptBackend backend = builder.backend;
9160 HPhi result = new HPhi.manyInputs(null, 8377 HPhi result = new HPhi.manyInputs(
9161 <HInstruction>[boolifiedRight, notIsAnd], 8378 null, <HInstruction>[boolifiedRight, notIsAnd], backend.dynamicType);
9162 backend.dynamicType);
9163 builder.current.addPhi(result); 8379 builder.current.addPhi(result);
9164 builder.stack.add(result); 8380 builder.stack.add(result);
9165 } 8381 }
9166 8382
9167 void handleLogicalAndOrWithLeftNode(ast.Node left, 8383 void handleLogicalAndOrWithLeftNode(ast.Node left, void visitRight(),
9168 void visitRight(), 8384 {bool isAnd}) {
9169 {bool isAnd}) {
9170 // This method is similar to [handleLogicalAndOr] but optimizes the case 8385 // This method is similar to [handleLogicalAndOr] but optimizes the case
9171 // where left is a logical "and" or logical "or". 8386 // where left is a logical "and" or logical "or".
9172 // 8387 //
9173 // For example (x && y) && z is transformed into x && (y && z): 8388 // For example (x && y) && z is transformed into x && (y && z):
9174 // t0 = boolify(x); 8389 // t0 = boolify(x);
9175 // if (t0) { 8390 // if (t0) {
9176 // t1 = boolify(y); 8391 // t1 = boolify(y);
9177 // if (t1) { 8392 // if (t1) {
9178 // t2 = boolify(z); 8393 // t2 = boolify(z);
9179 // } 8394 // }
9180 // t3 = phi(t2, false); 8395 // t3 = phi(t2, false);
9181 // } 8396 // }
9182 // result = phi(t3, false); 8397 // result = phi(t3, false);
9183 8398
9184 ast.Send send = left.asSend(); 8399 ast.Send send = left.asSend();
9185 if (send != null && 8400 if (send != null && (isAnd ? send.isLogicalAnd : send.isLogicalOr)) {
9186 (isAnd ? send.isLogicalAnd : send.isLogicalOr)) {
9187 ast.Node newLeft = send.receiver; 8401 ast.Node newLeft = send.receiver;
9188 Link<ast.Node> link = send.argumentsNode.nodes; 8402 Link<ast.Node> link = send.argumentsNode.nodes;
9189 assert(link.tail.isEmpty); 8403 assert(link.tail.isEmpty);
9190 ast.Node middle = link.head; 8404 ast.Node middle = link.head;
9191 handleLogicalAndOrWithLeftNode( 8405 handleLogicalAndOrWithLeftNode(
9192 newLeft, 8406 newLeft,
9193 () => handleLogicalAndOrWithLeftNode(middle, visitRight, 8407 () =>
9194 isAnd: isAnd), 8408 handleLogicalAndOrWithLeftNode(middle, visitRight, isAnd: isAnd),
9195 isAnd: isAnd); 8409 isAnd: isAnd);
9196 } else { 8410 } else {
9197 handleLogicalAndOr(() => builder.visit(left), visitRight, isAnd: isAnd); 8411 handleLogicalAndOr(() => builder.visit(left), visitRight, isAnd: isAnd);
9198 } 8412 }
9199 } 8413 }
9200 8414
9201 void _handleDiamondBranch(void visitCondition(), 8415 void _handleDiamondBranch(
9202 void visitThen(), 8416 void visitCondition(), void visitThen(), void visitElse(),
9203 void visitElse(), 8417 {bool isExpression, SourceInformation sourceInformation}) {
9204 {bool isExpression,
9205 SourceInformation sourceInformation}) {
9206 SsaBranch conditionBranch = new SsaBranch(this); 8418 SsaBranch conditionBranch = new SsaBranch(this);
9207 SsaBranch thenBranch = new SsaBranch(this); 8419 SsaBranch thenBranch = new SsaBranch(this);
9208 SsaBranch elseBranch = new SsaBranch(this); 8420 SsaBranch elseBranch = new SsaBranch(this);
9209 SsaBranch joinBranch = new SsaBranch(this); 8421 SsaBranch joinBranch = new SsaBranch(this);
9210 8422
9211 conditionBranch.startLocals = builder.localsHandler; 8423 conditionBranch.startLocals = builder.localsHandler;
9212 builder.goto(builder.current, conditionBranch.block); 8424 builder.goto(builder.current, conditionBranch.block);
9213 8425
9214 buildCondition(visitCondition, conditionBranch, thenBranch, elseBranch, 8426 buildCondition(visitCondition, conditionBranch, thenBranch, elseBranch,
9215 sourceInformation); 8427 sourceInformation);
9216 HInstruction thenValue = 8428 HInstruction thenValue =
9217 buildBranch(thenBranch, visitThen, joinBranch, isExpression); 8429 buildBranch(thenBranch, visitThen, joinBranch, isExpression);
9218 HInstruction elseValue = 8430 HInstruction elseValue =
9219 buildBranch(elseBranch, visitElse, joinBranch, isExpression); 8431 buildBranch(elseBranch, visitElse, joinBranch, isExpression);
9220 8432
9221 if (isExpression) { 8433 if (isExpression) {
9222 assert(thenValue != null && elseValue != null); 8434 assert(thenValue != null && elseValue != null);
9223 JavaScriptBackend backend = builder.backend; 8435 JavaScriptBackend backend = builder.backend;
9224 HPhi phi = new HPhi.manyInputs( 8436 HPhi phi = new HPhi.manyInputs(
9225 null, <HInstruction>[thenValue, elseValue], backend.dynamicType); 8437 null, <HInstruction>[thenValue, elseValue], backend.dynamicType);
9226 joinBranch.block.addPhi(phi); 8438 joinBranch.block.addPhi(phi);
9227 builder.stack.add(phi); 8439 builder.stack.add(phi);
9228 } 8440 }
9229 8441
9230 HBasicBlock joinBlock; 8442 HBasicBlock joinBlock;
9231 // If at least one branch did not abort, open the joinBranch. 8443 // If at least one branch did not abort, open the joinBranch.
9232 if (!joinBranch.block.predecessors.isEmpty) { 8444 if (!joinBranch.block.predecessors.isEmpty) {
9233 startBranch(joinBranch); 8445 startBranch(joinBranch);
9234 joinBlock = joinBranch.block; 8446 joinBlock = joinBranch.block;
9235 } 8447 }
9236 8448
9237 HIfBlockInformation info = 8449 HIfBlockInformation info = new HIfBlockInformation(
9238 new HIfBlockInformation( 8450 new HSubExpressionBlockInformation(conditionBranch.graph),
9239 new HSubExpressionBlockInformation(conditionBranch.graph), 8451 new HSubGraphBlockInformation(thenBranch.graph),
9240 new HSubGraphBlockInformation(thenBranch.graph), 8452 new HSubGraphBlockInformation(elseBranch.graph));
9241 new HSubGraphBlockInformation(elseBranch.graph));
9242 8453
9243 HBasicBlock conditionStartBlock = conditionBranch.block; 8454 HBasicBlock conditionStartBlock = conditionBranch.block;
9244 conditionStartBlock.setBlockFlow(info, joinBlock); 8455 conditionStartBlock.setBlockFlow(info, joinBlock);
9245 SubGraph conditionGraph = conditionBranch.graph; 8456 SubGraph conditionGraph = conditionBranch.graph;
9246 HIf branch = conditionGraph.end.last; 8457 HIf branch = conditionGraph.end.last;
9247 assert(branch is HIf); 8458 assert(branch is HIf);
9248 branch.blockInformation = conditionStartBlock.blockFlow; 8459 branch.blockInformation = conditionStartBlock.blockFlow;
9249 } 8460 }
9250 } 8461 }
9251 8462
9252 class TypeBuilder implements DartTypeVisitor<dynamic, SsaBuilder> { 8463 class TypeBuilder implements DartTypeVisitor<dynamic, SsaBuilder> {
9253 final ClassWorld classWorld; 8464 final ClassWorld classWorld;
9254 8465
9255 TypeBuilder(this.classWorld); 8466 TypeBuilder(this.classWorld);
9256 8467
9257 void visit(DartType type, SsaBuilder builder) => type.accept(this, builder); 8468 void visit(DartType type, SsaBuilder builder) => type.accept(this, builder);
9258 8469
9259 void visitVoidType(VoidType type, SsaBuilder builder) { 8470 void visitVoidType(VoidType type, SsaBuilder builder) {
9260 ClassElement cls = builder.backend.helpers.VoidRuntimeType; 8471 ClassElement cls = builder.backend.helpers.VoidRuntimeType;
9261 builder.push(new HVoidType(type, new TypeMask.exact(cls, classWorld))); 8472 builder.push(new HVoidType(type, new TypeMask.exact(cls, classWorld)));
9262 } 8473 }
9263 8474
9264 void visitTypeVariableType(TypeVariableType type, 8475 void visitTypeVariableType(TypeVariableType type, SsaBuilder builder) {
9265 SsaBuilder builder) {
9266 ClassElement cls = builder.backend.helpers.RuntimeType; 8476 ClassElement cls = builder.backend.helpers.RuntimeType;
9267 TypeMask instructionType = new TypeMask.subclass(cls, classWorld); 8477 TypeMask instructionType = new TypeMask.subclass(cls, classWorld);
9268 if (!builder.sourceElement.enclosingElement.isClosure && 8478 if (!builder.sourceElement.enclosingElement.isClosure &&
9269 builder.sourceElement.isInstanceMember) { 8479 builder.sourceElement.isInstanceMember) {
9270 HInstruction receiver = builder.localsHandler.readThis(); 8480 HInstruction receiver = builder.localsHandler.readThis();
9271 builder.push(new HReadTypeVariable(type, receiver, instructionType)); 8481 builder.push(new HReadTypeVariable(type, receiver, instructionType));
9272 } else { 8482 } else {
9273 builder.push( 8483 builder.push(new HReadTypeVariable.noReceiver(
9274 new HReadTypeVariable.noReceiver( 8484 type, builder.addTypeVariableReference(type), instructionType));
9275 type, builder.addTypeVariableReference(type), instructionType));
9276 } 8485 }
9277 } 8486 }
9278 8487
9279 void visitFunctionType(FunctionType type, SsaBuilder builder) { 8488 void visitFunctionType(FunctionType type, SsaBuilder builder) {
9280 type.returnType.accept(this, builder); 8489 type.returnType.accept(this, builder);
9281 HInstruction returnType = builder.pop(); 8490 HInstruction returnType = builder.pop();
9282 List<HInstruction> inputs = <HInstruction>[returnType]; 8491 List<HInstruction> inputs = <HInstruction>[returnType];
9283 8492
9284 for (DartType parameter in type.parameterTypes) { 8493 for (DartType parameter in type.parameterTypes) {
9285 parameter.accept(this, builder); 8494 parameter.accept(this, builder);
9286 inputs.add(builder.pop()); 8495 inputs.add(builder.pop());
9287 } 8496 }
9288 8497
9289 for (DartType parameter in type.optionalParameterTypes) { 8498 for (DartType parameter in type.optionalParameterTypes) {
9290 parameter.accept(this, builder); 8499 parameter.accept(this, builder);
9291 inputs.add(builder.pop()); 8500 inputs.add(builder.pop());
9292 } 8501 }
9293 8502
9294 List<DartType> namedParameterTypes = type.namedParameterTypes; 8503 List<DartType> namedParameterTypes = type.namedParameterTypes;
9295 List<String> names = type.namedParameters; 8504 List<String> names = type.namedParameters;
9296 for (int index = 0; index < names.length; index++) { 8505 for (int index = 0; index < names.length; index++) {
9297 ast.DartString dartString = new ast.DartString.literal(names[index]); 8506 ast.DartString dartString = new ast.DartString.literal(names[index]);
9298 inputs.add( 8507 inputs.add(builder.graph.addConstantString(dartString, builder.compiler));
9299 builder.graph.addConstantString(dartString, builder.compiler));
9300 namedParameterTypes[index].accept(this, builder); 8508 namedParameterTypes[index].accept(this, builder);
9301 inputs.add(builder.pop()); 8509 inputs.add(builder.pop());
9302 } 8510 }
9303 8511
9304 ClassElement cls = builder.backend.helpers.RuntimeFunctionType; 8512 ClassElement cls = builder.backend.helpers.RuntimeFunctionType;
9305 builder.push(new HFunctionType(inputs, type, 8513 builder.push(
9306 new TypeMask.exact(cls, classWorld))); 8514 new HFunctionType(inputs, type, new TypeMask.exact(cls, classWorld)));
9307 } 8515 }
9308 8516
9309 void visitMalformedType(MalformedType type, SsaBuilder builder) { 8517 void visitMalformedType(MalformedType type, SsaBuilder builder) {
9310 visitDynamicType(const DynamicType(), builder); 8518 visitDynamicType(const DynamicType(), builder);
9311 } 8519 }
9312 8520
9313 void visitStatementType(StatementType type, SsaBuilder builder) { 8521 void visitStatementType(StatementType type, SsaBuilder builder) {
9314 throw 'not implemented visitStatementType($type)'; 8522 throw 'not implemented visitStatementType($type)';
9315 } 8523 }
9316 8524
9317 void visitInterfaceType(InterfaceType type, SsaBuilder builder) { 8525 void visitInterfaceType(InterfaceType type, SsaBuilder builder) {
9318 List<HInstruction> inputs = <HInstruction>[]; 8526 List<HInstruction> inputs = <HInstruction>[];
9319 for (DartType typeArgument in type.typeArguments) { 8527 for (DartType typeArgument in type.typeArguments) {
9320 typeArgument.accept(this, builder); 8528 typeArgument.accept(this, builder);
9321 inputs.add(builder.pop()); 8529 inputs.add(builder.pop());
9322 } 8530 }
9323 ClassElement cls; 8531 ClassElement cls;
9324 if (type.typeArguments.isEmpty) { 8532 if (type.typeArguments.isEmpty) {
9325 cls = builder.backend.helpers.RuntimeTypePlain; 8533 cls = builder.backend.helpers.RuntimeTypePlain;
9326 } else { 8534 } else {
9327 cls = builder.backend.helpers.RuntimeTypeGeneric; 8535 cls = builder.backend.helpers.RuntimeTypeGeneric;
9328 } 8536 }
9329 builder.push(new HInterfaceType(inputs, type, 8537 builder.push(
9330 new TypeMask.exact(cls, classWorld))); 8538 new HInterfaceType(inputs, type, new TypeMask.exact(cls, classWorld)));
9331 } 8539 }
9332 8540
9333 void visitTypedefType(TypedefType type, SsaBuilder builder) { 8541 void visitTypedefType(TypedefType type, SsaBuilder builder) {
9334 DartType unaliased = type.unaliased; 8542 DartType unaliased = type.unaliased;
9335 if (unaliased is TypedefType) throw 'unable to unalias $type'; 8543 if (unaliased is TypedefType) throw 'unable to unalias $type';
9336 unaliased.accept(this, builder); 8544 unaliased.accept(this, builder);
9337 } 8545 }
9338 8546
9339 void visitDynamicType(DynamicType type, SsaBuilder builder) { 8547 void visitDynamicType(DynamicType type, SsaBuilder builder) {
9340 JavaScriptBackend backend = builder.compiler.backend; 8548 JavaScriptBackend backend = builder.compiler.backend;
(...skipping 10 matching lines...) Expand all
9351 const _LoopTypeVisitor(); 8559 const _LoopTypeVisitor();
9352 int visitNode(ast.Node node) => HLoopBlockInformation.NOT_A_LOOP; 8560 int visitNode(ast.Node node) => HLoopBlockInformation.NOT_A_LOOP;
9353 int visitWhile(ast.While node) => HLoopBlockInformation.WHILE_LOOP; 8561 int visitWhile(ast.While node) => HLoopBlockInformation.WHILE_LOOP;
9354 int visitFor(ast.For node) => HLoopBlockInformation.FOR_LOOP; 8562 int visitFor(ast.For node) => HLoopBlockInformation.FOR_LOOP;
9355 int visitDoWhile(ast.DoWhile node) => HLoopBlockInformation.DO_WHILE_LOOP; 8563 int visitDoWhile(ast.DoWhile node) => HLoopBlockInformation.DO_WHILE_LOOP;
9356 int visitAsyncForIn(ast.AsyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; 8564 int visitAsyncForIn(ast.AsyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP;
9357 int visitSyncForIn(ast.SyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; 8565 int visitSyncForIn(ast.SyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP;
9358 int visitSwitchStatement(ast.SwitchStatement node) => 8566 int visitSwitchStatement(ast.SwitchStatement node) =>
9359 HLoopBlockInformation.SWITCH_CONTINUE_LOOP; 8567 HLoopBlockInformation.SWITCH_CONTINUE_LOOP;
9360 } 8568 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/source_file_provider.dart ('k') | pkg/compiler/lib/src/ssa/codegen.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698