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

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

Issue 2301293002: kernel -> ssa: implement if-statements (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, 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 '../closure.dart'; 5 import '../closure.dart';
6 import '../common.dart'; 6 import '../common.dart';
7 import '../compiler.dart' show Compiler; 7 import '../compiler.dart' show Compiler;
8 import '../dart_types.dart'; 8 import '../dart_types.dart';
9 import '../elements/elements.dart'; 9 import '../elements/elements.dart';
10 import '../io/source_information.dart'; 10 import '../io/source_information.dart';
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 /// } 54 /// }
55 /// main() { 55 /// main() {
56 /// new Foo<String>('foo'); 56 /// new Foo<String>('foo');
57 /// } 57 /// }
58 /// 58 ///
59 /// [instanceType] is not used if it contains type variables, since these 59 /// [instanceType] is not used if it contains type variables, since these
60 /// might not be in scope or from the current instance. 60 /// might not be in scope or from the current instance.
61 /// 61 ///
62 final InterfaceType instanceType; 62 final InterfaceType instanceType;
63 63
64 final Compiler compiler; 64 final Compiler _compiler;
65 65
66 LocalsHandler(this.builder, this.executableContext, 66 LocalsHandler(this.builder, this.executableContext,
67 InterfaceType instanceType, this.compiler) 67 InterfaceType instanceType, this._compiler)
68 : this.instanceType = 68 : this.instanceType =
69 instanceType == null || instanceType.containsTypeVariables 69 instanceType == null || instanceType.containsTypeVariables
70 ? null 70 ? null
71 : instanceType; 71 : instanceType;
72 72
73 /// Substituted type variables occurring in [type] into the context of 73 /// Substituted type variables occurring in [type] into the context of
74 /// [contextClass]. 74 /// [contextClass].
75 DartType substInContext(DartType type) { 75 DartType substInContext(DartType type) {
76 if (contextClass != null) { 76 if (contextClass != null) {
77 ClassElement typeContext = Types.getClassContext(type); 77 ClassElement typeContext = Types.getClassContext(type);
(...skipping 10 matching lines...) Expand all
88 /// Creates a new [LocalsHandler] based on [other]. We only need to 88 /// Creates a new [LocalsHandler] based on [other]. We only need to
89 /// copy the [directLocals], since the other fields can be shared 89 /// copy the [directLocals], since the other fields can be shared
90 /// throughout the AST visit. 90 /// throughout the AST visit.
91 LocalsHandler.from(LocalsHandler other) 91 LocalsHandler.from(LocalsHandler other)
92 : directLocals = new Map<Local, HInstruction>.from(other.directLocals), 92 : directLocals = new Map<Local, HInstruction>.from(other.directLocals),
93 redirectionMapping = other.redirectionMapping, 93 redirectionMapping = other.redirectionMapping,
94 executableContext = other.executableContext, 94 executableContext = other.executableContext,
95 instanceType = other.instanceType, 95 instanceType = other.instanceType,
96 builder = other.builder, 96 builder = other.builder,
97 closureData = other.closureData, 97 closureData = other.closureData,
98 compiler = other.compiler, 98 _compiler = other._compiler,
99 activationVariables = other.activationVariables, 99 activationVariables = other.activationVariables,
100 cachedTypeOfThis = other.cachedTypeOfThis, 100 cachedTypeOfThis = other.cachedTypeOfThis,
101 cachedTypesOfCapturedVariables = other.cachedTypesOfCapturedVariables; 101 cachedTypesOfCapturedVariables = other.cachedTypesOfCapturedVariables;
102 102
103 /// Redirects accesses from element [from] to element [to]. The [to] element 103 /// Redirects accesses from element [from] to element [to]. The [to] element
104 /// must be a boxed variable or a variable that is stored in a closure-field. 104 /// must be a boxed variable or a variable that is stored in a closure-field.
105 void redirectElement(Local from, CapturedVariable to) { 105 void redirectElement(Local from, CapturedVariable to) {
106 assert(redirectionMapping[from] == null); 106 assert(redirectionMapping[from] == null);
107 redirectionMapping[from] = to; 107 redirectionMapping[from] = to;
108 assert(isStoredInClosureField(from) || isBoxed(from)); 108 assert(isStoredInClosureField(from) || isBoxed(from));
109 } 109 }
110 110
111 HInstruction createBox() { 111 HInstruction createBox() {
112 // TODO(floitsch): Clean up this hack. Should we create a box-object by 112 // TODO(floitsch): Clean up this hack. Should we create a box-object by
113 // just creating an empty object literal? 113 // just creating an empty object literal?
114 JavaScriptBackend backend = compiler.backend; 114 JavaScriptBackend backend = _compiler.backend;
115 HInstruction box = new HForeignCode( 115 HInstruction box = new HForeignCode(
116 js.js.parseForeignJS('{}'), backend.nonNullType, <HInstruction>[], 116 js.js.parseForeignJS('{}'), backend.nonNullType, <HInstruction>[],
117 nativeBehavior: native.NativeBehavior.PURE_ALLOCATION); 117 nativeBehavior: native.NativeBehavior.PURE_ALLOCATION);
118 builder.add(box); 118 builder.add(box);
119 return box; 119 return box;
120 } 120 }
121 121
122 /// If the scope (function or loop) [node] has captured variables then this 122 /// If the scope (function or loop) [node] has captured variables then this
123 /// method creates a box and sets up the redirections. 123 /// method creates a box and sets up the redirections.
124 void enterScope(ast.Node node, Element element) { 124 void enterScope(ast.Node node, Element element) {
125 // See if any variable in the top-scope of the function is captured. If yes 125 // See if any variable in the top-scope of the function is captured. If yes
126 // we need to create a box-object. 126 // we need to create a box-object.
127 ClosureScope scopeData = closureData.capturingScopes[node]; 127 ClosureScope scopeData = closureData.capturingScopes[node];
128 if (scopeData == null) return; 128 if (scopeData == null) return;
129 HInstruction box; 129 HInstruction box;
130 // The scope has captured variables. 130 // The scope has captured variables.
131 if (element != null && element.isGenerativeConstructorBody) { 131 if (element != null && element.isGenerativeConstructorBody) {
132 // The box is passed as a parameter to a generative 132 // The box is passed as a parameter to a generative
133 // constructor body. 133 // constructor body.
134 JavaScriptBackend backend = compiler.backend; 134 JavaScriptBackend backend = _compiler.backend;
135 box = builder.addParameter(scopeData.boxElement, backend.nonNullType); 135 box = builder.addParameter(scopeData.boxElement, backend.nonNullType);
136 } else { 136 } else {
137 box = createBox(); 137 box = createBox();
138 } 138 }
139 // Add the box to the known locals. 139 // Add the box to the known locals.
140 directLocals[scopeData.boxElement] = box; 140 directLocals[scopeData.boxElement] = box;
141 // Make sure that accesses to the boxed locals go into the box. We also 141 // Make sure that accesses to the boxed locals go into the box. We also
142 // need to make sure that parameters are copied into the box if necessary. 142 // need to make sure that parameters are copied into the box if necessary.
143 scopeData.forEachCapturedVariable( 143 scopeData.forEachCapturedVariable(
144 (LocalVariableElement from, BoxFieldElement to) { 144 (LocalVariableElement from, BoxFieldElement to) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 updateLocal(boxedVariable, oldValue); 178 updateLocal(boxedVariable, oldValue);
179 } 179 }
180 updateLocal(boxElement, newBox); 180 updateLocal(boxElement, newBox);
181 } 181 }
182 182
183 /// Documentation wanted -- johnniwinther 183 /// Documentation wanted -- johnniwinther
184 /// 184 ///
185 /// Invariant: [function] must be an implementation element. 185 /// Invariant: [function] must be an implementation element.
186 void startFunction(AstElement element, ast.Node node) { 186 void startFunction(AstElement element, ast.Node node) {
187 assert(invariant(element, element.isImplementation)); 187 assert(invariant(element, element.isImplementation));
188 closureData = compiler.closureToClassMapper 188 closureData = _compiler.closureToClassMapper
189 .computeClosureToClassMapping(element.resolvedAst); 189 .computeClosureToClassMapping(element.resolvedAst);
190 190
191 if (element is FunctionElement) { 191 if (element is FunctionElement) {
192 FunctionElement functionElement = element; 192 FunctionElement functionElement = element;
193 FunctionSignature params = functionElement.functionSignature; 193 FunctionSignature params = functionElement.functionSignature;
194 ClosureScope scopeData = closureData.capturingScopes[node]; 194 ClosureScope scopeData = closureData.capturingScopes[node];
195 params.orderedForEachParameter((ParameterElement parameterElement) { 195 params.orderedForEachParameter((ParameterElement parameterElement) {
196 if (element.isGenerativeConstructorBody) { 196 if (element.isGenerativeConstructorBody) {
197 if (scopeData != null && 197 if (scopeData != null &&
198 scopeData.isCapturedVariable(parameterElement)) { 198 scopeData.isCapturedVariable(parameterElement)) {
199 // The parameter will be a field in the box passed as the 199 // The parameter will be a field in the box passed as the
200 // last parameter. So no need to have it. 200 // last parameter. So no need to have it.
201 return; 201 return;
202 } 202 }
203 } 203 }
204 HInstruction parameter = builder.addParameter(parameterElement, 204 HInstruction parameter = builder.addParameter(parameterElement,
205 TypeMaskFactory.inferredTypeForElement(parameterElement, compiler)); 205 TypeMaskFactory.inferredTypeForElement(parameterElement, _compiler)) ;
206 builder.parameters[parameterElement] = parameter; 206 builder.parameters[parameterElement] = parameter;
207 directLocals[parameterElement] = parameter; 207 directLocals[parameterElement] = parameter;
208 }); 208 });
209 } 209 }
210 210
211 enterScope(node, element); 211 enterScope(node, element);
212 212
213 // If the freeVariableMapping is not empty, then this function was a 213 // If the freeVariableMapping is not empty, then this function was a
214 // nested closure that captures variables. Redirect the captured 214 // nested closure that captures variables. Redirect the captured
215 // variables to fields in the closure. 215 // variables to fields in the closure.
216 closureData.forEachFreeVariable((Local from, CapturedVariable to) { 216 closureData.forEachFreeVariable((Local from, CapturedVariable to) {
217 redirectElement(from, to); 217 redirectElement(from, to);
218 }); 218 });
219 JavaScriptBackend backend = compiler.backend; 219 JavaScriptBackend backend = _compiler.backend;
220 if (closureData.isClosure) { 220 if (closureData.isClosure) {
221 // Inside closure redirect references to itself to [:this:]. 221 // Inside closure redirect references to itself to [:this:].
222 HThis thisInstruction = 222 HThis thisInstruction =
223 new HThis(closureData.thisLocal, backend.nonNullType); 223 new HThis(closureData.thisLocal, backend.nonNullType);
224 builder.graph.thisInstruction = thisInstruction; 224 builder.graph.thisInstruction = thisInstruction;
225 builder.graph.entry.addAtEntry(thisInstruction); 225 builder.graph.entry.addAtEntry(thisInstruction);
226 updateLocal(closureData.closureElement, thisInstruction); 226 updateLocal(closureData.closureElement, thisInstruction);
227 } else if (element.isInstanceMember) { 227 } else if (element.isInstanceMember) {
228 // Once closures have been mapped to classes their instance members might 228 // Once closures have been mapped to classes their instance members might
229 // not have any thisElement if the closure was created inside a static 229 // not have any thisElement if the closure was created inside a static
(...skipping 28 matching lines...) Expand all
258 } 258 }
259 if (isInterceptorClass) { 259 if (isInterceptorClass) {
260 // Only use the extra parameter in intercepted classes. 260 // Only use the extra parameter in intercepted classes.
261 directLocals[closureData.thisLocal] = value; 261 directLocals[closureData.thisLocal] = value;
262 } 262 }
263 } else if (isNativeUpgradeFactory) { 263 } else if (isNativeUpgradeFactory) {
264 SyntheticLocal parameter = 264 SyntheticLocal parameter =
265 new SyntheticLocal('receiver', executableContext); 265 new SyntheticLocal('receiver', executableContext);
266 // Unlike `this`, receiver is nullable since direct calls to generative 266 // Unlike `this`, receiver is nullable since direct calls to generative
267 // constructor call the constructor with `null`. 267 // constructor call the constructor with `null`.
268 ClassWorld classWorld = compiler.world; 268 ClassWorld classWorld = _compiler.world;
269 HParameterValue value = 269 HParameterValue value =
270 new HParameterValue(parameter, new TypeMask.exact(cls, classWorld)); 270 new HParameterValue(parameter, new TypeMask.exact(cls, classWorld));
271 builder.graph.explicitReceiverParameter = value; 271 builder.graph.explicitReceiverParameter = value;
272 builder.graph.entry.addAtEntry(value); 272 builder.graph.entry.addAtEntry(value);
273 } 273 }
274 } 274 }
275 275
276 /// Returns true if the local can be accessed directly. Boxed variables or 276 /// Returns true if the local can be accessed directly. Boxed variables or
277 /// captured variables that are stored in the closure-field return [:false:]. 277 /// captured variables that are stored in the closure-field return [:false:].
278 bool isAccessedDirectly(Local local) { 278 bool isAccessedDirectly(Local local) {
(...skipping 20 matching lines...) Expand all
299 return closureData.variablesUsedInTryOrGenerator.contains(local); 299 return closureData.variablesUsedInTryOrGenerator.contains(local);
300 } 300 }
301 301
302 /// Returns an [HInstruction] for the given element. If the element is 302 /// Returns an [HInstruction] for the given element. If the element is
303 /// boxed or stored in a closure then the method generates code to retrieve 303 /// boxed or stored in a closure then the method generates code to retrieve
304 /// the value. 304 /// the value.
305 HInstruction readLocal(Local local, {SourceInformation sourceInformation}) { 305 HInstruction readLocal(Local local, {SourceInformation sourceInformation}) {
306 if (isAccessedDirectly(local)) { 306 if (isAccessedDirectly(local)) {
307 if (directLocals[local] == null) { 307 if (directLocals[local] == null) {
308 if (local is TypeVariableElement) { 308 if (local is TypeVariableElement) {
309 compiler.reporter.internalError(compiler.currentElement, 309 _compiler.reporter.internalError(_compiler.currentElement,
310 "Runtime type information not available for $local."); 310 "Runtime type information not available for $local.");
311 } else { 311 } else {
312 compiler.reporter.internalError( 312 _compiler.reporter.internalError(
313 local, "Cannot find value $local in ${directLocals.keys}."); 313 local, "Cannot find value $local in ${directLocals.keys}.");
314 } 314 }
315 } 315 }
316 HInstruction value = directLocals[local]; 316 HInstruction value = directLocals[local];
317 if (sourceInformation != null) { 317 if (sourceInformation != null) {
318 value = new HRef(value, sourceInformation); 318 value = new HRef(value, sourceInformation);
319 builder.add(value); 319 builder.add(value);
320 } 320 }
321 return value; 321 return value;
322 } else if (isStoredInClosureField(local)) { 322 } else if (isStoredInClosureField(local)) {
323 ClosureFieldElement redirect = redirectionMapping[local]; 323 ClosureFieldElement redirect = redirectionMapping[local];
324 HInstruction receiver = readLocal(closureData.closureElement); 324 HInstruction receiver = readLocal(closureData.closureElement);
325 TypeMask type = local is BoxLocal 325 TypeMask type = local is BoxLocal
326 ? (compiler.backend as JavaScriptBackend).nonNullType 326 ? (_compiler.backend as JavaScriptBackend).nonNullType
327 : getTypeOfCapturedVariable(redirect); 327 : getTypeOfCapturedVariable(redirect);
328 HInstruction fieldGet = new HFieldGet(redirect, receiver, type); 328 HInstruction fieldGet = new HFieldGet(redirect, receiver, type);
329 builder.add(fieldGet); 329 builder.add(fieldGet);
330 return fieldGet..sourceInformation = sourceInformation; 330 return fieldGet..sourceInformation = sourceInformation;
331 } else if (isBoxed(local)) { 331 } else if (isBoxed(local)) {
332 BoxFieldElement redirect = redirectionMapping[local]; 332 BoxFieldElement redirect = redirectionMapping[local];
333 // In the function that declares the captured variable the box is 333 // In the function that declares the captured variable the box is
334 // accessed as direct local. Inside the nested closure the box is 334 // accessed as direct local. Inside the nested closure the box is
335 // accessed through a closure-field. 335 // accessed through a closure-field.
336 // Calling [readLocal] makes sure we generate the correct code to get 336 // Calling [readLocal] makes sure we generate the correct code to get
337 // the box. 337 // the box.
338 HInstruction box = readLocal(redirect.box); 338 HInstruction box = readLocal(redirect.box);
339 HInstruction lookup = 339 HInstruction lookup =
340 new HFieldGet(redirect, box, getTypeOfCapturedVariable(redirect)); 340 new HFieldGet(redirect, box, getTypeOfCapturedVariable(redirect));
341 builder.add(lookup); 341 builder.add(lookup);
342 return lookup..sourceInformation = sourceInformation; 342 return lookup..sourceInformation = sourceInformation;
343 } else { 343 } else {
344 assert(isUsedInTryOrGenerator(local)); 344 assert(isUsedInTryOrGenerator(local));
345 HLocalValue localValue = getLocal(local); 345 HLocalValue localValue = getLocal(local);
346 HInstruction instruction = new HLocalGet( 346 HInstruction instruction = new HLocalGet(
347 local, 347 local,
348 localValue, 348 localValue,
349 (compiler.backend as JavaScriptBackend).dynamicType, 349 (_compiler.backend as JavaScriptBackend).dynamicType,
350 sourceInformation); 350 sourceInformation);
351 builder.add(instruction); 351 builder.add(instruction);
352 return instruction; 352 return instruction;
353 } 353 }
354 } 354 }
355 355
356 HInstruction readThis() { 356 HInstruction readThis() {
357 HInstruction res = readLocal(closureData.thisLocal); 357 HInstruction res = readLocal(closureData.thisLocal);
358 if (res.instructionType == null) { 358 if (res.instructionType == null) {
359 res.instructionType = getTypeOfThis(); 359 res.instructionType = getTypeOfThis();
360 } 360 }
361 return res; 361 return res;
362 } 362 }
363 363
364 HLocalValue getLocal(Local local, {SourceInformation sourceInformation}) { 364 HLocalValue getLocal(Local local, {SourceInformation sourceInformation}) {
365 // If the element is a parameter, we already have a 365 // If the element is a parameter, we already have a
366 // HParameterValue for it. We cannot create another one because 366 // HParameterValue for it. We cannot create another one because
367 // it could then have another name than the real parameter. And 367 // it could then have another name than the real parameter. And
368 // the other one would not know it is just a copy of the real 368 // the other one would not know it is just a copy of the real
369 // parameter. 369 // parameter.
370 if (local is ParameterElement) { 370 if (local is ParameterElement) {
371 assert(invariant(local, builder.parameters.containsKey(local), 371 assert(invariant(local, builder.parameters.containsKey(local),
372 message: "No local value for parameter $local in " 372 message: "No local value for parameter $local in "
373 "${builder.parameters}.")); 373 "${builder.parameters}."));
374 return builder.parameters[local]; 374 return builder.parameters[local];
375 } 375 }
376 376
377 return activationVariables.putIfAbsent(local, () { 377 return activationVariables.putIfAbsent(local, () {
378 JavaScriptBackend backend = compiler.backend; 378 JavaScriptBackend backend = _compiler.backend;
379 HLocalValue localValue = new HLocalValue(local, backend.nonNullType) 379 HLocalValue localValue = new HLocalValue(local, backend.nonNullType)
380 ..sourceInformation = sourceInformation; 380 ..sourceInformation = sourceInformation;
381 builder.graph.entry.addAtExit(localValue); 381 builder.graph.entry.addAtExit(localValue);
382 return localValue; 382 return localValue;
383 }); 383 });
384 } 384 }
385 385
386 Local getTypeVariableAsLocal(TypeVariableType type) { 386 Local getTypeVariableAsLocal(TypeVariableType type) {
387 return typeVariableLocals.putIfAbsent(type, () { 387 return typeVariableLocals.putIfAbsent(type, () {
388 return new TypeVariableLocal(type, executableContext); 388 return new TypeVariableLocal(type, executableContext);
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 } 473 }
474 } 474 }
475 475
476 /// Create phis at the loop entry for local variables (ready for the values 476 /// Create phis at the loop entry for local variables (ready for the values
477 /// from the back edge). Populate the phis with the current values. 477 /// from the back edge). Populate the phis with the current values.
478 void beginLoopHeader(HBasicBlock loopEntry) { 478 void beginLoopHeader(HBasicBlock loopEntry) {
479 // Create a copy because we modify the map while iterating over it. 479 // Create a copy because we modify the map while iterating over it.
480 Map<Local, HInstruction> savedDirectLocals = 480 Map<Local, HInstruction> savedDirectLocals =
481 new Map<Local, HInstruction>.from(directLocals); 481 new Map<Local, HInstruction>.from(directLocals);
482 482
483 JavaScriptBackend backend = compiler.backend; 483 JavaScriptBackend backend = _compiler.backend;
484 // Create phis for all elements in the definitions environment. 484 // Create phis for all elements in the definitions environment.
485 savedDirectLocals.forEach((Local local, HInstruction instruction) { 485 savedDirectLocals.forEach((Local local, HInstruction instruction) {
486 if (isAccessedDirectly(local)) { 486 if (isAccessedDirectly(local)) {
487 // We know 'this' cannot be modified. 487 // We know 'this' cannot be modified.
488 if (local != closureData.thisLocal) { 488 if (local != closureData.thisLocal) {
489 HPhi phi = 489 HPhi phi =
490 new HPhi.singleInput(local, instruction, backend.dynamicType); 490 new HPhi.singleInput(local, instruction, backend.dynamicType);
491 loopEntry.addPhi(phi); 491 loopEntry.addPhi(phi);
492 directLocals[local] = phi; 492 directLocals[local] = phi;
493 } else { 493 } else {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
537 /// there is a conflict. 537 /// there is a conflict.
538 /// If a phi node is necessary, it will use this handler's instruction as the 538 /// If a phi node is necessary, it will use this handler's instruction as the
539 /// first input, and the otherLocals instruction as the second. 539 /// first input, and the otherLocals instruction as the second.
540 void mergeWith(LocalsHandler otherLocals, HBasicBlock joinBlock) { 540 void mergeWith(LocalsHandler otherLocals, HBasicBlock joinBlock) {
541 // If an element is in one map but not the other we can safely 541 // If an element is in one map but not the other we can safely
542 // ignore it. It means that a variable was declared in the 542 // ignore it. It means that a variable was declared in the
543 // block. Since variable declarations are scoped the declared 543 // block. Since variable declarations are scoped the declared
544 // variable cannot be alive outside the block. Note: this is only 544 // variable cannot be alive outside the block. Note: this is only
545 // true for nodes where we do joins. 545 // true for nodes where we do joins.
546 Map<Local, HInstruction> joinedLocals = new Map<Local, HInstruction>(); 546 Map<Local, HInstruction> joinedLocals = new Map<Local, HInstruction>();
547 JavaScriptBackend backend = compiler.backend; 547 JavaScriptBackend backend = _compiler.backend;
548 otherLocals.directLocals.forEach((Local local, HInstruction instruction) { 548 otherLocals.directLocals.forEach((Local local, HInstruction instruction) {
549 // We know 'this' cannot be modified. 549 // We know 'this' cannot be modified.
550 if (local == closureData.thisLocal) { 550 if (local == closureData.thisLocal) {
551 assert(directLocals[local] == instruction); 551 assert(directLocals[local] == instruction);
552 joinedLocals[local] = instruction; 552 joinedLocals[local] = instruction;
553 } else { 553 } else {
554 HInstruction mine = directLocals[local]; 554 HInstruction mine = directLocals[local];
555 if (mine == null) return; 555 if (mine == null) return;
556 if (identical(instruction, mine)) { 556 if (identical(instruction, mine)) {
557 joinedLocals[local] = instruction; 557 joinedLocals[local] = instruction;
(...skipping 12 matching lines...) Expand all
570 /// localsHandlers into a new one using phis. The new localsHandler is 570 /// localsHandlers into a new one using phis. The new localsHandler is
571 /// returned. Unless it is also in the list, the current localsHandler is not 571 /// returned. Unless it is also in the list, the current localsHandler is not
572 /// used for its values, only for its declared variables. This is a way to 572 /// used for its values, only for its declared variables. This is a way to
573 /// exclude local values from the result when they are no longer in scope. 573 /// exclude local values from the result when they are no longer in scope.
574 LocalsHandler mergeMultiple( 574 LocalsHandler mergeMultiple(
575 List<LocalsHandler> localsHandlers, HBasicBlock joinBlock) { 575 List<LocalsHandler> localsHandlers, HBasicBlock joinBlock) {
576 assert(localsHandlers.length > 0); 576 assert(localsHandlers.length > 0);
577 if (localsHandlers.length == 1) return localsHandlers[0]; 577 if (localsHandlers.length == 1) return localsHandlers[0];
578 Map<Local, HInstruction> joinedLocals = new Map<Local, HInstruction>(); 578 Map<Local, HInstruction> joinedLocals = new Map<Local, HInstruction>();
579 HInstruction thisValue = null; 579 HInstruction thisValue = null;
580 JavaScriptBackend backend = compiler.backend; 580 JavaScriptBackend backend = _compiler.backend;
581 directLocals.forEach((Local local, HInstruction instruction) { 581 directLocals.forEach((Local local, HInstruction instruction) {
582 if (local != closureData.thisLocal) { 582 if (local != closureData.thisLocal) {
583 HPhi phi = new HPhi.noInputs(local, backend.dynamicType); 583 HPhi phi = new HPhi.noInputs(local, backend.dynamicType);
584 joinedLocals[local] = phi; 584 joinedLocals[local] = phi;
585 joinBlock.addPhi(phi); 585 joinBlock.addPhi(phi);
586 } else { 586 } else {
587 // We know that "this" never changes, if it's there. 587 // We know that "this" never changes, if it's there.
588 // Save it for later. While merging, there is no phi for "this", 588 // Save it for later. While merging, there is no phi for "this",
589 // so we don't have to special case it in the merge loop. 589 // so we don't have to special case it in the merge loop.
590 thisValue = instruction; 590 thisValue = instruction;
(...skipping 25 matching lines...) Expand all
616 return this; 616 return this;
617 } 617 }
618 618
619 TypeMask cachedTypeOfThis; 619 TypeMask cachedTypeOfThis;
620 620
621 TypeMask getTypeOfThis() { 621 TypeMask getTypeOfThis() {
622 TypeMask result = cachedTypeOfThis; 622 TypeMask result = cachedTypeOfThis;
623 if (result == null) { 623 if (result == null) {
624 ThisLocal local = closureData.thisLocal; 624 ThisLocal local = closureData.thisLocal;
625 ClassElement cls = local.enclosingClass; 625 ClassElement cls = local.enclosingClass;
626 ClassWorld classWorld = compiler.world; 626 ClassWorld classWorld = _compiler.world;
627 if (classWorld.isUsedAsMixin(cls)) { 627 if (classWorld.isUsedAsMixin(cls)) {
628 // If the enclosing class is used as a mixin, [:this:] can be 628 // If the enclosing class is used as a mixin, [:this:] can be
629 // of the class that mixins the enclosing class. These two 629 // of the class that mixins the enclosing class. These two
630 // classes do not have a subclass relationship, so, for 630 // classes do not have a subclass relationship, so, for
631 // simplicity, we mark the type as an interface type. 631 // simplicity, we mark the type as an interface type.
632 result = new TypeMask.nonNullSubtype(cls.declaration, compiler.world); 632 result = new TypeMask.nonNullSubtype(cls.declaration, _compiler.world);
633 } else { 633 } else {
634 result = new TypeMask.nonNullSubclass(cls.declaration, compiler.world); 634 result = new TypeMask.nonNullSubclass(cls.declaration, _compiler.world);
635 } 635 }
636 cachedTypeOfThis = result; 636 cachedTypeOfThis = result;
637 } 637 }
638 return result; 638 return result;
639 } 639 }
640 640
641 Map<Element, TypeMask> cachedTypesOfCapturedVariables = 641 Map<Element, TypeMask> cachedTypesOfCapturedVariables =
642 new Map<Element, TypeMask>(); 642 new Map<Element, TypeMask>();
643 643
644 TypeMask getTypeOfCapturedVariable(Element element) { 644 TypeMask getTypeOfCapturedVariable(Element element) {
645 assert(element.isField); 645 assert(element.isField);
646 return cachedTypesOfCapturedVariables.putIfAbsent(element, () { 646 return cachedTypesOfCapturedVariables.putIfAbsent(element, () {
647 return TypeMaskFactory.inferredTypeForElement(element, compiler); 647 return TypeMaskFactory.inferredTypeForElement(element, _compiler);
648 }); 648 });
649 } 649 }
650 650
651 /// Variables stored in the current activation. These variables are 651 /// Variables stored in the current activation. These variables are
652 /// being updated in try/catch blocks, and should be 652 /// being updated in try/catch blocks, and should be
653 /// accessed indirectly through [HLocalGet] and [HLocalSet]. 653 /// accessed indirectly through [HLocalGet] and [HLocalSet].
654 Map<Local, HLocalValue> activationVariables = <Local, HLocalValue>{}; 654 Map<Local, HLocalValue> activationVariables = <Local, HLocalValue>{};
655 } 655 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698