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

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

Issue 2949293002: Add ScopeInfo class for variable information that doesn't actually involve closures. (Closed)
Patch Set: . Created 3 years, 6 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/ssa/builder_kernel.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 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 '../elements/elements.dart'; 7 import '../elements/elements.dart';
8 import '../elements/entities.dart'; 8 import '../elements/entities.dart';
9 import '../elements/types.dart'; 9 import '../elements/types.dart';
10 import '../io/source_information.dart'; 10 import '../io/source_information.dart';
(...skipping 14 matching lines...) Expand all
25 /// The values of locals that can be directly accessed (without redirections 25 /// The values of locals that can be directly accessed (without redirections
26 /// to boxes or closure-fields). 26 /// to boxes or closure-fields).
27 /// 27 ///
28 /// [directLocals] is iterated, so it is "insertion ordered" to make the 28 /// [directLocals] is iterated, so it is "insertion ordered" to make the
29 /// iteration order a function only of insertions and not a function of 29 /// iteration order a function only of insertions and not a function of
30 /// e.g. Element hash codes. I'd prefer to use a SortedMap but some elements 30 /// e.g. Element hash codes. I'd prefer to use a SortedMap but some elements
31 /// don't have source locations for [Elements.compareByPosition]. 31 /// don't have source locations for [Elements.compareByPosition].
32 Map<Local, HInstruction> directLocals = new Map<Local, HInstruction>(); 32 Map<Local, HInstruction> directLocals = new Map<Local, HInstruction>();
33 Map<Local, FieldEntity> redirectionMapping = new Map<Local, FieldEntity>(); 33 Map<Local, FieldEntity> redirectionMapping = new Map<Local, FieldEntity>();
34 final GraphBuilder builder; 34 final GraphBuilder builder;
35 ClosureRepresentationInfo closureData; 35 ScopeInfo scopeInfo;
36 Map<TypeVariableType, TypeVariableLocal> typeVariableLocals = 36 Map<TypeVariableType, TypeVariableLocal> typeVariableLocals =
37 new Map<TypeVariableType, TypeVariableLocal>(); 37 new Map<TypeVariableType, TypeVariableLocal>();
38 final Entity executableContext; 38 final Entity executableContext;
39 final MemberEntity memberContext; 39 final MemberEntity memberContext;
40 40
41 /// The class that defines the current type environment or null if no type 41 /// The class that defines the current type environment or null if no type
42 /// variables are in scope. 42 /// variables are in scope.
43 final ClassEntity contextClass; 43 final ClassEntity contextClass;
44 44
45 /// The type of the current instance, if concrete. 45 /// The type of the current instance, if concrete.
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 /// copy the [directLocals], since the other fields can be shared 106 /// copy the [directLocals], since the other fields can be shared
107 /// throughout the AST visit. 107 /// throughout the AST visit.
108 LocalsHandler.from(LocalsHandler other) 108 LocalsHandler.from(LocalsHandler other)
109 : directLocals = new Map<Local, HInstruction>.from(other.directLocals), 109 : directLocals = new Map<Local, HInstruction>.from(other.directLocals),
110 redirectionMapping = other.redirectionMapping, 110 redirectionMapping = other.redirectionMapping,
111 executableContext = other.executableContext, 111 executableContext = other.executableContext,
112 memberContext = other.memberContext, 112 memberContext = other.memberContext,
113 contextClass = other.contextClass, 113 contextClass = other.contextClass,
114 instanceType = other.instanceType, 114 instanceType = other.instanceType,
115 builder = other.builder, 115 builder = other.builder,
116 closureData = other.closureData, 116 scopeInfo = other.scopeInfo,
117 _nativeData = other._nativeData, 117 _nativeData = other._nativeData,
118 _interceptorData = other._interceptorData, 118 _interceptorData = other._interceptorData,
119 activationVariables = other.activationVariables, 119 activationVariables = other.activationVariables,
120 cachedTypeOfThis = other.cachedTypeOfThis, 120 cachedTypeOfThis = other.cachedTypeOfThis,
121 cachedTypesOfCapturedVariables = other.cachedTypesOfCapturedVariables; 121 cachedTypesOfCapturedVariables = other.cachedTypesOfCapturedVariables;
122 122
123 /// Redirects accesses from element [from] to element [to]. The [to] element 123 /// Redirects accesses from element [from] to element [to]. The [to] element
124 /// must be a boxed variable or a variable that is stored in a closure-field. 124 /// must be a boxed variable or a variable that is stored in a closure-field.
125 void redirectElement(Local from, FieldEntity to) { 125 void redirectElement(Local from, FieldEntity to) {
126 assert(redirectionMapping[from] == null); 126 assert(redirectionMapping[from] == null);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 HInstruction oldValue = readLocal(boxedVariable); 190 HInstruction oldValue = readLocal(boxedVariable);
191 updateLocal(boxElement, newBox); 191 updateLocal(boxElement, newBox);
192 updateLocal(boxedVariable, oldValue); 192 updateLocal(boxedVariable, oldValue);
193 } 193 }
194 updateLocal(boxElement, newBox); 194 updateLocal(boxElement, newBox);
195 } 195 }
196 196
197 /// Documentation wanted -- johnniwinther 197 /// Documentation wanted -- johnniwinther
198 /// 198 ///
199 /// Invariant: [function] must be an implementation element. 199 /// Invariant: [function] must be an implementation element.
200 void startFunction( 200 void startFunction(MemberEntity element, ScopeInfo scopeInfo,
201 MemberEntity element, 201 ClosureAnalysisInfo scopeData, Map<Local, TypeMask> parameters,
202 ClosureRepresentationInfo closureData,
203 ClosureAnalysisInfo scopeData,
204 Map<Local, TypeMask> parameters,
205 {bool isGenerativeConstructorBody}) { 202 {bool isGenerativeConstructorBody}) {
206 assert(!(element is MemberElement && !element.isImplementation), 203 assert(!(element is MemberElement && !element.isImplementation),
207 failedAt(element)); 204 failedAt(element));
208 this.closureData = closureData; 205 this.scopeInfo = scopeInfo;
209 206
210 parameters.forEach((Local local, TypeMask typeMask) { 207 parameters.forEach((Local local, TypeMask typeMask) {
211 if (isGenerativeConstructorBody) { 208 if (isGenerativeConstructorBody) {
212 if (scopeData.isCaptured(local)) { 209 if (scopeData.isCaptured(local)) {
213 // The parameter will be a field in the box passed as the 210 // The parameter will be a field in the box passed as the
214 // last parameter. So no need to have it. 211 // last parameter. So no need to have it.
215 return; 212 return;
216 } 213 }
217 } 214 }
218 HInstruction parameter = builder.addParameter(local, typeMask); 215 HInstruction parameter = builder.addParameter(local, typeMask);
219 builder.parameters[local] = parameter; 216 builder.parameters[local] = parameter;
220 directLocals[local] = parameter; 217 directLocals[local] = parameter;
221 }); 218 });
222 219
223 enterScope(scopeData, 220 enterScope(scopeData,
224 forGenerativeConstructorBody: isGenerativeConstructorBody); 221 forGenerativeConstructorBody: isGenerativeConstructorBody);
225 222
226 if (closureData.isClosure) { 223 // When we remove the element model, we can just use the first check
224 // (because the underlying elements won't all be *both* ScopeInfos and
225 // ClosureRepresentationInfos).
226 if (scopeInfo is ClosureRepresentationInfo && scopeInfo.isClosure) {
227 ClosureRepresentationInfo closureData = scopeInfo;
227 // If the freeVariableMapping is not empty, then this function was a 228 // If the freeVariableMapping is not empty, then this function was a
228 // nested closure that captures variables. Redirect the captured 229 // nested closure that captures variables. Redirect the captured
229 // variables to fields in the closure. 230 // variables to fields in the closure.
230 closureData.forEachFreeVariable((Local from, FieldEntity to) { 231 closureData.forEachFreeVariable((Local from, FieldEntity to) {
231 redirectElement(from, to); 232 redirectElement(from, to);
232 }); 233 });
233 // Inside closure redirect references to itself to [:this:]. 234 // Inside closure redirect references to itself to [:this:].
234 HThis thisInstruction = 235 HThis thisInstruction =
235 new HThis(closureData.thisLocal, commonMasks.nonNullType); 236 new HThis(closureData.thisLocal, commonMasks.nonNullType);
236 builder.graph.thisInstruction = thisInstruction; 237 builder.graph.thisInstruction = thisInstruction;
237 builder.graph.entry.addAtEntry(thisInstruction); 238 builder.graph.entry.addAtEntry(thisInstruction);
238 updateLocal(closureData.closureEntity, thisInstruction); 239 updateLocal(closureData.closureEntity, thisInstruction);
239 } else if (element.isInstanceMember) { 240 } else if (element.isInstanceMember) {
240 // Once closures have been mapped to classes their instance members might 241 // Once closures have been mapped to classes their instance members might
241 // not have any thisElement if the closure was created inside a static 242 // not have any thisElement if the closure was created inside a static
242 // context. 243 // context.
243 HThis thisInstruction = new HThis(closureData.thisLocal, getTypeOfThis()); 244 HThis thisInstruction = new HThis(scopeInfo.thisLocal, getTypeOfThis());
244 builder.graph.thisInstruction = thisInstruction; 245 builder.graph.thisInstruction = thisInstruction;
245 builder.graph.entry.addAtEntry(thisInstruction); 246 builder.graph.entry.addAtEntry(thisInstruction);
246 directLocals[closureData.thisLocal] = thisInstruction; 247 directLocals[scopeInfo.thisLocal] = thisInstruction;
247 } 248 }
248 249
249 // If this method is an intercepted method, add the extra 250 // If this method is an intercepted method, add the extra
250 // parameter to it, that is the actual receiver for intercepted 251 // parameter to it, that is the actual receiver for intercepted
251 // classes, or the same as [:this:] for non-intercepted classes. 252 // classes, or the same as [:this:] for non-intercepted classes.
252 ClassEntity cls = element.enclosingClass; 253 ClassEntity cls = element.enclosingClass;
253 254
254 // When the class extends a native class, the instance is pre-constructed 255 // When the class extends a native class, the instance is pre-constructed
255 // and passed to the generative constructor factory function as a parameter. 256 // and passed to the generative constructor factory function as a parameter.
256 // Instead of allocating and initializing the object, the constructor 257 // Instead of allocating and initializing the object, the constructor
257 // 'upgrades' the native subclass object by initializing the Dart fields. 258 // 'upgrades' the native subclass object by initializing the Dart fields.
258 bool isNativeUpgradeFactory = element is ConstructorEntity && 259 bool isNativeUpgradeFactory = element is ConstructorEntity &&
259 element.isGenerativeConstructor && 260 element.isGenerativeConstructor &&
260 _nativeData.isNativeOrExtendsNative(cls); 261 _nativeData.isNativeOrExtendsNative(cls);
261 if (_interceptorData.isInterceptedMethod(element)) { 262 if (_interceptorData.isInterceptedMethod(element)) {
262 bool isInterceptedClass = _interceptorData.isInterceptedClass(cls); 263 bool isInterceptedClass = _interceptorData.isInterceptedClass(cls);
263 String name = isInterceptedClass ? 'receiver' : '_'; 264 String name = isInterceptedClass ? 'receiver' : '_';
264 SyntheticLocal parameter = createLocal(name); 265 SyntheticLocal parameter = createLocal(name);
265 HParameterValue value = new HParameterValue(parameter, getTypeOfThis()); 266 HParameterValue value = new HParameterValue(parameter, getTypeOfThis());
266 builder.graph.explicitReceiverParameter = value; 267 builder.graph.explicitReceiverParameter = value;
267 builder.graph.entry.addAfter(directLocals[closureData.thisLocal], value); 268 builder.graph.entry.addAfter(directLocals[scopeInfo.thisLocal], value);
268 if (builder.lastAddedParameter == null) { 269 if (builder.lastAddedParameter == null) {
269 // If this is the first parameter inserted, make sure it stays first. 270 // If this is the first parameter inserted, make sure it stays first.
270 builder.lastAddedParameter = value; 271 builder.lastAddedParameter = value;
271 } 272 }
272 if (isInterceptedClass) { 273 if (isInterceptedClass) {
273 // Only use the extra parameter in intercepted classes. 274 // Only use the extra parameter in intercepted classes.
274 directLocals[closureData.thisLocal] = value; 275 directLocals[scopeInfo.thisLocal] = value;
275 } 276 }
276 } else if (isNativeUpgradeFactory) { 277 } else if (isNativeUpgradeFactory) {
277 SyntheticLocal parameter = createLocal('receiver'); 278 SyntheticLocal parameter = createLocal('receiver');
278 // Unlike `this`, receiver is nullable since direct calls to generative 279 // Unlike `this`, receiver is nullable since direct calls to generative
279 // constructor call the constructor with `null`. 280 // constructor call the constructor with `null`.
280 HParameterValue value = 281 HParameterValue value =
281 new HParameterValue(parameter, new TypeMask.exact(cls, closedWorld)); 282 new HParameterValue(parameter, new TypeMask.exact(cls, closedWorld));
282 builder.graph.explicitReceiverParameter = value; 283 builder.graph.explicitReceiverParameter = value;
283 builder.graph.entry.addAtEntry(value); 284 builder.graph.entry.addAtEntry(value);
284 if (builder.lastAddedParameter == null) { 285 if (builder.lastAddedParameter == null) {
285 // If this is the first parameter inserted, make sure it stays first. 286 // If this is the first parameter inserted, make sure it stays first.
286 builder.lastAddedParameter = value; 287 builder.lastAddedParameter = value;
287 } 288 }
288 } 289 }
289 } 290 }
290 291
291 /// Returns true if the local can be accessed directly. Boxed variables or 292 /// Returns true if the local can be accessed directly. Boxed variables or
292 /// captured variables that are stored in the closure-field return [:false:]. 293 /// captured variables that are stored in the closure-field return [:false:].
293 bool isAccessedDirectly(Local local) { 294 bool isAccessedDirectly(Local local) {
294 assert(local != null); 295 assert(local != null);
295 return !redirectionMapping.containsKey(local) && 296 return !redirectionMapping.containsKey(local) &&
296 !closureData.variableIsUsedInTryOrSync(local); 297 !scopeInfo.variableIsUsedInTryOrSync(local);
297 } 298 }
298 299
299 bool isStoredInClosureField(Local local) { 300 bool isStoredInClosureField(Local local) {
300 assert(local != null); 301 assert(local != null);
301 if (isAccessedDirectly(local)) return false; 302 if (isAccessedDirectly(local)) return false;
303 if (scopeInfo is! ClosureRepresentationInfo) return false;
302 FieldEntity redirectTarget = redirectionMapping[local]; 304 FieldEntity redirectTarget = redirectionMapping[local];
303 if (redirectTarget == null) return false; 305 if (redirectTarget == null) return false;
304 return redirectTarget is ClosureFieldElement; 306 return redirectTarget is ClosureFieldElement;
305 } 307 }
306 308
307 bool isBoxed(Local local) { 309 bool isBoxed(Local local) {
308 if (isAccessedDirectly(local)) return false; 310 if (isAccessedDirectly(local)) return false;
309 if (isStoredInClosureField(local)) return false; 311 if (isStoredInClosureField(local)) return false;
310 return redirectionMapping.containsKey(local); 312 return redirectionMapping.containsKey(local);
311 } 313 }
312 314
313 bool _isUsedInTryOrGenerator(Local local) { 315 bool _isUsedInTryOrGenerator(Local local) {
314 return closureData.variableIsUsedInTryOrSync(local); 316 return scopeInfo.variableIsUsedInTryOrSync(local);
315 } 317 }
316 318
317 /// Returns an [HInstruction] for the given element. If the element is 319 /// Returns an [HInstruction] for the given element. If the element is
318 /// boxed or stored in a closure then the method generates code to retrieve 320 /// boxed or stored in a closure then the method generates code to retrieve
319 /// the value. 321 /// the value.
320 HInstruction readLocal(Local local, {SourceInformation sourceInformation}) { 322 HInstruction readLocal(Local local, {SourceInformation sourceInformation}) {
321 if (isAccessedDirectly(local)) { 323 if (isAccessedDirectly(local)) {
322 if (directLocals[local] == null) { 324 if (directLocals[local] == null) {
323 if (local is TypeVariableLocal) { 325 if (local is TypeVariableLocal) {
324 throw new SpannableAssertionFailure( 326 throw new SpannableAssertionFailure(
325 CURRENT_ELEMENT_SPANNABLE, 327 CURRENT_ELEMENT_SPANNABLE,
326 "Runtime type information not available for $local " 328 "Runtime type information not available for $local "
327 "in $executableContext."); 329 "in $executableContext.");
328 } else { 330 } else {
329 throw new SpannableAssertionFailure( 331 throw new SpannableAssertionFailure(
330 local, 332 local,
331 "Cannot find value $local in ${directLocals.keys} for " 333 "Cannot find value $local in ${directLocals.keys} for "
332 "$executableContext."); 334 "$executableContext.");
333 } 335 }
334 } 336 }
335 HInstruction value = directLocals[local]; 337 HInstruction value = directLocals[local];
336 if (sourceInformation != null) { 338 if (sourceInformation != null) {
337 value = new HRef(value, sourceInformation); 339 value = new HRef(value, sourceInformation);
338 builder.add(value); 340 builder.add(value);
339 } 341 }
340 return value; 342 return value;
341 } else if (isStoredInClosureField(local)) { 343 } else if (isStoredInClosureField(local)) {
344 ClosureRepresentationInfo closureData = scopeInfo;
342 ClosureFieldElement redirect = redirectionMapping[local]; 345 ClosureFieldElement redirect = redirectionMapping[local];
343 HInstruction receiver = readLocal(closureData.closureEntity); 346 HInstruction receiver = readLocal(closureData.closureEntity);
344 TypeMask type = local is BoxLocal 347 TypeMask type = local is BoxLocal
345 ? commonMasks.nonNullType 348 ? commonMasks.nonNullType
346 : getTypeOfCapturedVariable(redirect); 349 : getTypeOfCapturedVariable(redirect);
347 HInstruction fieldGet = new HFieldGet(redirect, receiver, type); 350 HInstruction fieldGet = new HFieldGet(redirect, receiver, type);
348 builder.add(fieldGet); 351 builder.add(fieldGet);
349 return fieldGet..sourceInformation = sourceInformation; 352 return fieldGet..sourceInformation = sourceInformation;
350 } else if (isBoxed(local)) { 353 } else if (isBoxed(local)) {
351 BoxFieldElement redirect = redirectionMapping[local]; 354 BoxFieldElement redirect = redirectionMapping[local];
(...skipping 11 matching lines...) Expand all
363 assert(_isUsedInTryOrGenerator(local)); 366 assert(_isUsedInTryOrGenerator(local));
364 HLocalValue localValue = getLocal(local); 367 HLocalValue localValue = getLocal(local);
365 HInstruction instruction = new HLocalGet( 368 HInstruction instruction = new HLocalGet(
366 local, localValue, commonMasks.dynamicType, sourceInformation); 369 local, localValue, commonMasks.dynamicType, sourceInformation);
367 builder.add(instruction); 370 builder.add(instruction);
368 return instruction; 371 return instruction;
369 } 372 }
370 } 373 }
371 374
372 HInstruction readThis() { 375 HInstruction readThis() {
373 HInstruction res = readLocal(closureData.thisLocal); 376 HInstruction res = readLocal(scopeInfo.thisLocal);
374 if (res.instructionType == null) { 377 if (res.instructionType == null) {
375 res.instructionType = getTypeOfThis(); 378 res.instructionType = getTypeOfThis();
376 } 379 }
377 return res; 380 return res;
378 } 381 }
379 382
380 HLocalValue getLocal(Local local, {SourceInformation sourceInformation}) { 383 HLocalValue getLocal(Local local, {SourceInformation sourceInformation}) {
381 // If the element is a parameter, we already have a 384 // If the element is a parameter, we already have a
382 // HParameterValue for it. We cannot create another one because 385 // HParameterValue for it. We cannot create another one because
383 // it could then have another name than the real parameter. And 386 // it could then have another name than the real parameter. And
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
487 /// from the back edge). Populate the phis with the current values. 490 /// from the back edge). Populate the phis with the current values.
488 void beginLoopHeader(HBasicBlock loopEntry) { 491 void beginLoopHeader(HBasicBlock loopEntry) {
489 // Create a copy because we modify the map while iterating over it. 492 // Create a copy because we modify the map while iterating over it.
490 Map<Local, HInstruction> savedDirectLocals = 493 Map<Local, HInstruction> savedDirectLocals =
491 new Map<Local, HInstruction>.from(directLocals); 494 new Map<Local, HInstruction>.from(directLocals);
492 495
493 // Create phis for all elements in the definitions environment. 496 // Create phis for all elements in the definitions environment.
494 savedDirectLocals.forEach((Local local, HInstruction instruction) { 497 savedDirectLocals.forEach((Local local, HInstruction instruction) {
495 if (isAccessedDirectly(local)) { 498 if (isAccessedDirectly(local)) {
496 // We know 'this' cannot be modified. 499 // We know 'this' cannot be modified.
497 if (local != closureData.thisLocal) { 500 if (local != scopeInfo.thisLocal) {
498 HPhi phi = 501 HPhi phi =
499 new HPhi.singleInput(local, instruction, commonMasks.dynamicType); 502 new HPhi.singleInput(local, instruction, commonMasks.dynamicType);
500 loopEntry.addPhi(phi); 503 loopEntry.addPhi(phi);
501 directLocals[local] = phi; 504 directLocals[local] = phi;
502 } else { 505 } else {
503 directLocals[local] = instruction; 506 directLocals[local] = instruction;
504 } 507 }
505 } 508 }
506 }); 509 });
507 } 510 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
544 /// first input, and the otherLocals instruction as the second. 547 /// first input, and the otherLocals instruction as the second.
545 void mergeWith(LocalsHandler otherLocals, HBasicBlock joinBlock) { 548 void mergeWith(LocalsHandler otherLocals, HBasicBlock joinBlock) {
546 // If an element is in one map but not the other we can safely 549 // If an element is in one map but not the other we can safely
547 // ignore it. It means that a variable was declared in the 550 // ignore it. It means that a variable was declared in the
548 // block. Since variable declarations are scoped the declared 551 // block. Since variable declarations are scoped the declared
549 // variable cannot be alive outside the block. Note: this is only 552 // variable cannot be alive outside the block. Note: this is only
550 // true for nodes where we do joins. 553 // true for nodes where we do joins.
551 Map<Local, HInstruction> joinedLocals = new Map<Local, HInstruction>(); 554 Map<Local, HInstruction> joinedLocals = new Map<Local, HInstruction>();
552 otherLocals.directLocals.forEach((Local local, HInstruction instruction) { 555 otherLocals.directLocals.forEach((Local local, HInstruction instruction) {
553 // We know 'this' cannot be modified. 556 // We know 'this' cannot be modified.
554 if (local == closureData.thisLocal) { 557 if (local == scopeInfo.thisLocal) {
555 assert(directLocals[local] == instruction); 558 assert(directLocals[local] == instruction);
556 joinedLocals[local] = instruction; 559 joinedLocals[local] = instruction;
557 } else { 560 } else {
558 HInstruction mine = directLocals[local]; 561 HInstruction mine = directLocals[local];
559 if (mine == null) return; 562 if (mine == null) return;
560 if (identical(instruction, mine)) { 563 if (identical(instruction, mine)) {
561 joinedLocals[local] = instruction; 564 joinedLocals[local] = instruction;
562 } else { 565 } else {
563 HInstruction phi = new HPhi.manyInputs(local, 566 HInstruction phi = new HPhi.manyInputs(local,
564 <HInstruction>[mine, instruction], commonMasks.dynamicType); 567 <HInstruction>[mine, instruction], commonMasks.dynamicType);
(...skipping 10 matching lines...) Expand all
575 /// returned. Unless it is also in the list, the current localsHandler is not 578 /// returned. Unless it is also in the list, the current localsHandler is not
576 /// used for its values, only for its declared variables. This is a way to 579 /// used for its values, only for its declared variables. This is a way to
577 /// exclude local values from the result when they are no longer in scope. 580 /// exclude local values from the result when they are no longer in scope.
578 LocalsHandler mergeMultiple( 581 LocalsHandler mergeMultiple(
579 List<LocalsHandler> localsHandlers, HBasicBlock joinBlock) { 582 List<LocalsHandler> localsHandlers, HBasicBlock joinBlock) {
580 assert(localsHandlers.length > 0); 583 assert(localsHandlers.length > 0);
581 if (localsHandlers.length == 1) return localsHandlers.single; 584 if (localsHandlers.length == 1) return localsHandlers.single;
582 Map<Local, HInstruction> joinedLocals = new Map<Local, HInstruction>(); 585 Map<Local, HInstruction> joinedLocals = new Map<Local, HInstruction>();
583 HInstruction thisValue = null; 586 HInstruction thisValue = null;
584 directLocals.forEach((Local local, HInstruction instruction) { 587 directLocals.forEach((Local local, HInstruction instruction) {
585 if (local != closureData.thisLocal) { 588 if (local != scopeInfo.thisLocal) {
586 HPhi phi = new HPhi.noInputs(local, commonMasks.dynamicType); 589 HPhi phi = new HPhi.noInputs(local, commonMasks.dynamicType);
587 joinedLocals[local] = phi; 590 joinedLocals[local] = phi;
588 joinBlock.addPhi(phi); 591 joinBlock.addPhi(phi);
589 } else { 592 } else {
590 // We know that "this" never changes, if it's there. 593 // We know that "this" never changes, if it's there.
591 // Save it for later. While merging, there is no phi for "this", 594 // Save it for later. While merging, there is no phi for "this",
592 // so we don't have to special case it in the merge loop. 595 // so we don't have to special case it in the merge loop.
593 thisValue = instruction; 596 thisValue = instruction;
594 } 597 }
595 }); 598 });
596 for (LocalsHandler handler in localsHandlers) { 599 for (LocalsHandler handler in localsHandlers) {
597 handler.directLocals.forEach((Local local, HInstruction instruction) { 600 handler.directLocals.forEach((Local local, HInstruction instruction) {
598 HPhi phi = joinedLocals[local]; 601 HPhi phi = joinedLocals[local];
599 if (phi != null) { 602 if (phi != null) {
600 phi.addInput(instruction); 603 phi.addInput(instruction);
601 } 604 }
602 }); 605 });
603 } 606 }
604 if (thisValue != null) { 607 if (thisValue != null) {
605 // If there was a "this" for the scope, add it to the new locals. 608 // If there was a "this" for the scope, add it to the new locals.
606 joinedLocals[closureData.thisLocal] = thisValue; 609 joinedLocals[scopeInfo.thisLocal] = thisValue;
607 } 610 }
608 611
609 // Remove locals that are not in all handlers. 612 // Remove locals that are not in all handlers.
610 directLocals = new Map<Local, HInstruction>(); 613 directLocals = new Map<Local, HInstruction>();
611 joinedLocals.forEach((Local local, HInstruction instruction) { 614 joinedLocals.forEach((Local local, HInstruction instruction) {
612 if (local != closureData.thisLocal && 615 if (local != scopeInfo.thisLocal &&
613 instruction.inputs.length != localsHandlers.length) { 616 instruction.inputs.length != localsHandlers.length) {
614 joinBlock.removePhi(instruction); 617 joinBlock.removePhi(instruction);
615 } else { 618 } else {
616 directLocals[local] = instruction; 619 directLocals[local] = instruction;
617 } 620 }
618 }); 621 });
619 return this; 622 return this;
620 } 623 }
621 624
622 TypeMask cachedTypeOfThis; 625 TypeMask cachedTypeOfThis;
623 626
624 TypeMask getTypeOfThis() { 627 TypeMask getTypeOfThis() {
625 TypeMask result = cachedTypeOfThis; 628 TypeMask result = cachedTypeOfThis;
626 if (result == null) { 629 if (result == null) {
627 ThisLocal local = closureData.thisLocal; 630 ThisLocal local = scopeInfo.thisLocal;
628 ClassEntity cls = local.enclosingClass; 631 ClassEntity cls = local.enclosingClass;
629 if (closedWorld.isUsedAsMixin(cls)) { 632 if (closedWorld.isUsedAsMixin(cls)) {
630 // If the enclosing class is used as a mixin, [:this:] can be 633 // If the enclosing class is used as a mixin, [:this:] can be
631 // of the class that mixins the enclosing class. These two 634 // of the class that mixins the enclosing class. These two
632 // classes do not have a subclass relationship, so, for 635 // classes do not have a subclass relationship, so, for
633 // simplicity, we mark the type as an interface type. 636 // simplicity, we mark the type as an interface type.
634 result = new TypeMask.nonNullSubtype(cls, closedWorld); 637 result = new TypeMask.nonNullSubtype(cls, closedWorld);
635 } else { 638 } else {
636 result = new TypeMask.nonNullSubclass(cls, closedWorld); 639 result = new TypeMask.nonNullSubclass(cls, closedWorld);
637 } 640 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
670 final MemberEntity memberContext; 673 final MemberEntity memberContext;
671 674
672 // Avoid slow Object.hashCode. 675 // Avoid slow Object.hashCode.
673 final int hashCode = _nextHashCode = (_nextHashCode + 1).toUnsigned(30); 676 final int hashCode = _nextHashCode = (_nextHashCode + 1).toUnsigned(30);
674 static int _nextHashCode = 0; 677 static int _nextHashCode = 0;
675 678
676 SyntheticLocal(this.name, this.executableContext, this.memberContext); 679 SyntheticLocal(this.name, this.executableContext, this.memberContext);
677 680
678 toString() => 'SyntheticLocal($name)'; 681 toString() => 'SyntheticLocal($name)';
679 } 682 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/ssa/builder_kernel.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698