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

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

Issue 2301293002: kernel -> ssa: implement if-statements (Closed)
Patch Set: add visitNot 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(
205 TypeMaskFactory.inferredTypeForElement(parameterElement, compiler)); 205 parameterElement,
206 TypeMaskFactory.inferredTypeForElement(
207 parameterElement, _compiler));
206 builder.parameters[parameterElement] = parameter; 208 builder.parameters[parameterElement] = parameter;
207 directLocals[parameterElement] = parameter; 209 directLocals[parameterElement] = parameter;
208 }); 210 });
209 } 211 }
210 212
211 enterScope(node, element); 213 enterScope(node, element);
212 214
213 // If the freeVariableMapping is not empty, then this function was a 215 // If the freeVariableMapping is not empty, then this function was a
214 // nested closure that captures variables. Redirect the captured 216 // nested closure that captures variables. Redirect the captured
215 // variables to fields in the closure. 217 // variables to fields in the closure.
216 closureData.forEachFreeVariable((Local from, CapturedVariable to) { 218 closureData.forEachFreeVariable((Local from, CapturedVariable to) {
217 redirectElement(from, to); 219 redirectElement(from, to);
218 }); 220 });
219 JavaScriptBackend backend = compiler.backend; 221 JavaScriptBackend backend = _compiler.backend;
220 if (closureData.isClosure) { 222 if (closureData.isClosure) {
221 // Inside closure redirect references to itself to [:this:]. 223 // Inside closure redirect references to itself to [:this:].
222 HThis thisInstruction = 224 HThis thisInstruction =
223 new HThis(closureData.thisLocal, backend.nonNullType); 225 new HThis(closureData.thisLocal, backend.nonNullType);
224 builder.graph.thisInstruction = thisInstruction; 226 builder.graph.thisInstruction = thisInstruction;
225 builder.graph.entry.addAtEntry(thisInstruction); 227 builder.graph.entry.addAtEntry(thisInstruction);
226 updateLocal(closureData.closureElement, thisInstruction); 228 updateLocal(closureData.closureElement, thisInstruction);
227 } else if (element.isInstanceMember) { 229 } else if (element.isInstanceMember) {
228 // Once closures have been mapped to classes their instance members might 230 // Once closures have been mapped to classes their instance members might
229 // not have any thisElement if the closure was created inside a static 231 // not have any thisElement if the closure was created inside a static
(...skipping 28 matching lines...) Expand all
258 } 260 }
259 if (isInterceptorClass) { 261 if (isInterceptorClass) {
260 // Only use the extra parameter in intercepted classes. 262 // Only use the extra parameter in intercepted classes.
261 directLocals[closureData.thisLocal] = value; 263 directLocals[closureData.thisLocal] = value;
262 } 264 }
263 } else if (isNativeUpgradeFactory) { 265 } else if (isNativeUpgradeFactory) {
264 SyntheticLocal parameter = 266 SyntheticLocal parameter =
265 new SyntheticLocal('receiver', executableContext); 267 new SyntheticLocal('receiver', executableContext);
266 // Unlike `this`, receiver is nullable since direct calls to generative 268 // Unlike `this`, receiver is nullable since direct calls to generative
267 // constructor call the constructor with `null`. 269 // constructor call the constructor with `null`.
268 ClassWorld classWorld = compiler.world; 270 ClassWorld classWorld = _compiler.world;
269 HParameterValue value = 271 HParameterValue value =
270 new HParameterValue(parameter, new TypeMask.exact(cls, classWorld)); 272 new HParameterValue(parameter, new TypeMask.exact(cls, classWorld));
271 builder.graph.explicitReceiverParameter = value; 273 builder.graph.explicitReceiverParameter = value;
272 builder.graph.entry.addAtEntry(value); 274 builder.graph.entry.addAtEntry(value);
273 } 275 }
274 } 276 }
275 277
276 /// Returns true if the local can be accessed directly. Boxed variables or 278 /// Returns true if the local can be accessed directly. Boxed variables or
277 /// captured variables that are stored in the closure-field return [:false:]. 279 /// captured variables that are stored in the closure-field return [:false:].
278 bool isAccessedDirectly(Local local) { 280 bool isAccessedDirectly(Local local) {
(...skipping 20 matching lines...) Expand all
299 return closureData.variablesUsedInTryOrGenerator.contains(local); 301 return closureData.variablesUsedInTryOrGenerator.contains(local);
300 } 302 }
301 303
302 /// Returns an [HInstruction] for the given element. If the element is 304 /// 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 305 /// boxed or stored in a closure then the method generates code to retrieve
304 /// the value. 306 /// the value.
305 HInstruction readLocal(Local local, {SourceInformation sourceInformation}) { 307 HInstruction readLocal(Local local, {SourceInformation sourceInformation}) {
306 if (isAccessedDirectly(local)) { 308 if (isAccessedDirectly(local)) {
307 if (directLocals[local] == null) { 309 if (directLocals[local] == null) {
308 if (local is TypeVariableElement) { 310 if (local is TypeVariableElement) {
309 compiler.reporter.internalError(compiler.currentElement, 311 _compiler.reporter.internalError(_compiler.currentElement,
310 "Runtime type information not available for $local."); 312 "Runtime type information not available for $local.");
311 } else { 313 } else {
312 compiler.reporter.internalError( 314 _compiler.reporter.internalError(
313 local, "Cannot find value $local in ${directLocals.keys}."); 315 local, "Cannot find value $local in ${directLocals.keys}.");
314 } 316 }
315 } 317 }
316 HInstruction value = directLocals[local]; 318 HInstruction value = directLocals[local];
317 if (sourceInformation != null) { 319 if (sourceInformation != null) {
318 value = new HRef(value, sourceInformation); 320 value = new HRef(value, sourceInformation);
319 builder.add(value); 321 builder.add(value);
320 } 322 }
321 return value; 323 return value;
322 } else if (isStoredInClosureField(local)) { 324 } else if (isStoredInClosureField(local)) {
323 ClosureFieldElement redirect = redirectionMapping[local]; 325 ClosureFieldElement redirect = redirectionMapping[local];
324 HInstruction receiver = readLocal(closureData.closureElement); 326 HInstruction receiver = readLocal(closureData.closureElement);
325 TypeMask type = local is BoxLocal 327 TypeMask type = local is BoxLocal
326 ? (compiler.backend as JavaScriptBackend).nonNullType 328 ? (_compiler.backend as JavaScriptBackend).nonNullType
327 : getTypeOfCapturedVariable(redirect); 329 : getTypeOfCapturedVariable(redirect);
328 HInstruction fieldGet = new HFieldGet(redirect, receiver, type); 330 HInstruction fieldGet = new HFieldGet(redirect, receiver, type);
329 builder.add(fieldGet); 331 builder.add(fieldGet);
330 return fieldGet..sourceInformation = sourceInformation; 332 return fieldGet..sourceInformation = sourceInformation;
331 } else if (isBoxed(local)) { 333 } else if (isBoxed(local)) {
332 BoxFieldElement redirect = redirectionMapping[local]; 334 BoxFieldElement redirect = redirectionMapping[local];
333 // In the function that declares the captured variable the box is 335 // In the function that declares the captured variable the box is
334 // accessed as direct local. Inside the nested closure the box is 336 // accessed as direct local. Inside the nested closure the box is
335 // accessed through a closure-field. 337 // accessed through a closure-field.
336 // Calling [readLocal] makes sure we generate the correct code to get 338 // Calling [readLocal] makes sure we generate the correct code to get
337 // the box. 339 // the box.
338 HInstruction box = readLocal(redirect.box); 340 HInstruction box = readLocal(redirect.box);
339 HInstruction lookup = 341 HInstruction lookup =
340 new HFieldGet(redirect, box, getTypeOfCapturedVariable(redirect)); 342 new HFieldGet(redirect, box, getTypeOfCapturedVariable(redirect));
341 builder.add(lookup); 343 builder.add(lookup);
342 return lookup..sourceInformation = sourceInformation; 344 return lookup..sourceInformation = sourceInformation;
343 } else { 345 } else {
344 assert(isUsedInTryOrGenerator(local)); 346 assert(isUsedInTryOrGenerator(local));
345 HLocalValue localValue = getLocal(local); 347 HLocalValue localValue = getLocal(local);
346 HInstruction instruction = new HLocalGet( 348 HInstruction instruction = new HLocalGet(
347 local, 349 local,
348 localValue, 350 localValue,
349 (compiler.backend as JavaScriptBackend).dynamicType, 351 (_compiler.backend as JavaScriptBackend).dynamicType,
350 sourceInformation); 352 sourceInformation);
351 builder.add(instruction); 353 builder.add(instruction);
352 return instruction; 354 return instruction;
353 } 355 }
354 } 356 }
355 357
356 HInstruction readThis() { 358 HInstruction readThis() {
357 HInstruction res = readLocal(closureData.thisLocal); 359 HInstruction res = readLocal(closureData.thisLocal);
358 if (res.instructionType == null) { 360 if (res.instructionType == null) {
359 res.instructionType = getTypeOfThis(); 361 res.instructionType = getTypeOfThis();
360 } 362 }
361 return res; 363 return res;
362 } 364 }
363 365
364 HLocalValue getLocal(Local local, {SourceInformation sourceInformation}) { 366 HLocalValue getLocal(Local local, {SourceInformation sourceInformation}) {
365 // If the element is a parameter, we already have a 367 // If the element is a parameter, we already have a
366 // HParameterValue for it. We cannot create another one because 368 // HParameterValue for it. We cannot create another one because
367 // it could then have another name than the real parameter. And 369 // 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 370 // the other one would not know it is just a copy of the real
369 // parameter. 371 // parameter.
370 if (local is ParameterElement) { 372 if (local is ParameterElement) {
371 assert(invariant(local, builder.parameters.containsKey(local), 373 assert(invariant(local, builder.parameters.containsKey(local),
372 message: "No local value for parameter $local in " 374 message: "No local value for parameter $local in "
373 "${builder.parameters}.")); 375 "${builder.parameters}."));
374 return builder.parameters[local]; 376 return builder.parameters[local];
375 } 377 }
376 378
377 return activationVariables.putIfAbsent(local, () { 379 return activationVariables.putIfAbsent(local, () {
378 JavaScriptBackend backend = compiler.backend; 380 JavaScriptBackend backend = _compiler.backend;
379 HLocalValue localValue = new HLocalValue(local, backend.nonNullType) 381 HLocalValue localValue = new HLocalValue(local, backend.nonNullType)
380 ..sourceInformation = sourceInformation; 382 ..sourceInformation = sourceInformation;
381 builder.graph.entry.addAtExit(localValue); 383 builder.graph.entry.addAtExit(localValue);
382 return localValue; 384 return localValue;
383 }); 385 });
384 } 386 }
385 387
386 Local getTypeVariableAsLocal(TypeVariableType type) { 388 Local getTypeVariableAsLocal(TypeVariableType type) {
387 return typeVariableLocals.putIfAbsent(type, () { 389 return typeVariableLocals.putIfAbsent(type, () {
388 return new TypeVariableLocal(type, executableContext); 390 return new TypeVariableLocal(type, executableContext);
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 } 475 }
474 } 476 }
475 477
476 /// Create phis at the loop entry for local variables (ready for the values 478 /// 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. 479 /// from the back edge). Populate the phis with the current values.
478 void beginLoopHeader(HBasicBlock loopEntry) { 480 void beginLoopHeader(HBasicBlock loopEntry) {
479 // Create a copy because we modify the map while iterating over it. 481 // Create a copy because we modify the map while iterating over it.
480 Map<Local, HInstruction> savedDirectLocals = 482 Map<Local, HInstruction> savedDirectLocals =
481 new Map<Local, HInstruction>.from(directLocals); 483 new Map<Local, HInstruction>.from(directLocals);
482 484
483 JavaScriptBackend backend = compiler.backend; 485 JavaScriptBackend backend = _compiler.backend;
484 // Create phis for all elements in the definitions environment. 486 // Create phis for all elements in the definitions environment.
485 savedDirectLocals.forEach((Local local, HInstruction instruction) { 487 savedDirectLocals.forEach((Local local, HInstruction instruction) {
486 if (isAccessedDirectly(local)) { 488 if (isAccessedDirectly(local)) {
487 // We know 'this' cannot be modified. 489 // We know 'this' cannot be modified.
488 if (local != closureData.thisLocal) { 490 if (local != closureData.thisLocal) {
489 HPhi phi = 491 HPhi phi =
490 new HPhi.singleInput(local, instruction, backend.dynamicType); 492 new HPhi.singleInput(local, instruction, backend.dynamicType);
491 loopEntry.addPhi(phi); 493 loopEntry.addPhi(phi);
492 directLocals[local] = phi; 494 directLocals[local] = phi;
493 } else { 495 } else {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
537 /// there is a conflict. 539 /// there is a conflict.
538 /// If a phi node is necessary, it will use this handler's instruction as the 540 /// 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. 541 /// first input, and the otherLocals instruction as the second.
540 void mergeWith(LocalsHandler otherLocals, HBasicBlock joinBlock) { 542 void mergeWith(LocalsHandler otherLocals, HBasicBlock joinBlock) {
541 // If an element is in one map but not the other we can safely 543 // 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 544 // ignore it. It means that a variable was declared in the
543 // block. Since variable declarations are scoped the declared 545 // block. Since variable declarations are scoped the declared
544 // variable cannot be alive outside the block. Note: this is only 546 // variable cannot be alive outside the block. Note: this is only
545 // true for nodes where we do joins. 547 // true for nodes where we do joins.
546 Map<Local, HInstruction> joinedLocals = new Map<Local, HInstruction>(); 548 Map<Local, HInstruction> joinedLocals = new Map<Local, HInstruction>();
547 JavaScriptBackend backend = compiler.backend; 549 JavaScriptBackend backend = _compiler.backend;
548 otherLocals.directLocals.forEach((Local local, HInstruction instruction) { 550 otherLocals.directLocals.forEach((Local local, HInstruction instruction) {
549 // We know 'this' cannot be modified. 551 // We know 'this' cannot be modified.
550 if (local == closureData.thisLocal) { 552 if (local == closureData.thisLocal) {
551 assert(directLocals[local] == instruction); 553 assert(directLocals[local] == instruction);
552 joinedLocals[local] = instruction; 554 joinedLocals[local] = instruction;
553 } else { 555 } else {
554 HInstruction mine = directLocals[local]; 556 HInstruction mine = directLocals[local];
555 if (mine == null) return; 557 if (mine == null) return;
556 if (identical(instruction, mine)) { 558 if (identical(instruction, mine)) {
557 joinedLocals[local] = instruction; 559 joinedLocals[local] = instruction;
(...skipping 12 matching lines...) Expand all
570 /// localsHandlers into a new one using phis. The new localsHandler is 572 /// 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 573 /// 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 574 /// 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. 575 /// exclude local values from the result when they are no longer in scope.
574 LocalsHandler mergeMultiple( 576 LocalsHandler mergeMultiple(
575 List<LocalsHandler> localsHandlers, HBasicBlock joinBlock) { 577 List<LocalsHandler> localsHandlers, HBasicBlock joinBlock) {
576 assert(localsHandlers.length > 0); 578 assert(localsHandlers.length > 0);
577 if (localsHandlers.length == 1) return localsHandlers[0]; 579 if (localsHandlers.length == 1) return localsHandlers[0];
578 Map<Local, HInstruction> joinedLocals = new Map<Local, HInstruction>(); 580 Map<Local, HInstruction> joinedLocals = new Map<Local, HInstruction>();
579 HInstruction thisValue = null; 581 HInstruction thisValue = null;
580 JavaScriptBackend backend = compiler.backend; 582 JavaScriptBackend backend = _compiler.backend;
581 directLocals.forEach((Local local, HInstruction instruction) { 583 directLocals.forEach((Local local, HInstruction instruction) {
582 if (local != closureData.thisLocal) { 584 if (local != closureData.thisLocal) {
583 HPhi phi = new HPhi.noInputs(local, backend.dynamicType); 585 HPhi phi = new HPhi.noInputs(local, backend.dynamicType);
584 joinedLocals[local] = phi; 586 joinedLocals[local] = phi;
585 joinBlock.addPhi(phi); 587 joinBlock.addPhi(phi);
586 } else { 588 } else {
587 // We know that "this" never changes, if it's there. 589 // We know that "this" never changes, if it's there.
588 // Save it for later. While merging, there is no phi for "this", 590 // 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. 591 // so we don't have to special case it in the merge loop.
590 thisValue = instruction; 592 thisValue = instruction;
(...skipping 25 matching lines...) Expand all
616 return this; 618 return this;
617 } 619 }
618 620
619 TypeMask cachedTypeOfThis; 621 TypeMask cachedTypeOfThis;
620 622
621 TypeMask getTypeOfThis() { 623 TypeMask getTypeOfThis() {
622 TypeMask result = cachedTypeOfThis; 624 TypeMask result = cachedTypeOfThis;
623 if (result == null) { 625 if (result == null) {
624 ThisLocal local = closureData.thisLocal; 626 ThisLocal local = closureData.thisLocal;
625 ClassElement cls = local.enclosingClass; 627 ClassElement cls = local.enclosingClass;
626 ClassWorld classWorld = compiler.world; 628 ClassWorld classWorld = _compiler.world;
627 if (classWorld.isUsedAsMixin(cls)) { 629 if (classWorld.isUsedAsMixin(cls)) {
628 // If the enclosing class is used as a mixin, [:this:] can be 630 // If the enclosing class is used as a mixin, [:this:] can be
629 // of the class that mixins the enclosing class. These two 631 // of the class that mixins the enclosing class. These two
630 // classes do not have a subclass relationship, so, for 632 // classes do not have a subclass relationship, so, for
631 // simplicity, we mark the type as an interface type. 633 // simplicity, we mark the type as an interface type.
632 result = new TypeMask.nonNullSubtype(cls.declaration, compiler.world); 634 result = new TypeMask.nonNullSubtype(cls.declaration, _compiler.world);
633 } else { 635 } else {
634 result = new TypeMask.nonNullSubclass(cls.declaration, compiler.world); 636 result = new TypeMask.nonNullSubclass(cls.declaration, _compiler.world);
635 } 637 }
636 cachedTypeOfThis = result; 638 cachedTypeOfThis = result;
637 } 639 }
638 return result; 640 return result;
639 } 641 }
640 642
641 Map<Element, TypeMask> cachedTypesOfCapturedVariables = 643 Map<Element, TypeMask> cachedTypesOfCapturedVariables =
642 new Map<Element, TypeMask>(); 644 new Map<Element, TypeMask>();
643 645
644 TypeMask getTypeOfCapturedVariable(Element element) { 646 TypeMask getTypeOfCapturedVariable(Element element) {
645 assert(element.isField); 647 assert(element.isField);
646 return cachedTypesOfCapturedVariables.putIfAbsent(element, () { 648 return cachedTypesOfCapturedVariables.putIfAbsent(element, () {
647 return TypeMaskFactory.inferredTypeForElement(element, compiler); 649 return TypeMaskFactory.inferredTypeForElement(element, _compiler);
648 }); 650 });
649 } 651 }
650 652
651 /// Variables stored in the current activation. These variables are 653 /// Variables stored in the current activation. These variables are
652 /// being updated in try/catch blocks, and should be 654 /// being updated in try/catch blocks, and should be
653 /// accessed indirectly through [HLocalGet] and [HLocalSet]. 655 /// accessed indirectly through [HLocalGet] and [HLocalSet].
654 Map<Local, HLocalValue> activationVariables = <Local, HLocalValue>{}; 656 Map<Local, HLocalValue> activationVariables = <Local, HLocalValue>{};
655 } 657 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/ssa/graph_builder.dart ('k') | pkg/compiler/lib/src/ssa/ssa_branch_builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698