OLD | NEW |
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 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 if (redirectTarget == null) return false; | 302 if (redirectTarget == null) return false; |
303 return redirectTarget is ClosureFieldElement; | 303 return redirectTarget is ClosureFieldElement; |
304 } | 304 } |
305 | 305 |
306 bool isBoxed(Local local) { | 306 bool isBoxed(Local local) { |
307 if (isAccessedDirectly(local)) return false; | 307 if (isAccessedDirectly(local)) return false; |
308 if (isStoredInClosureField(local)) return false; | 308 if (isStoredInClosureField(local)) return false; |
309 return redirectionMapping.containsKey(local); | 309 return redirectionMapping.containsKey(local); |
310 } | 310 } |
311 | 311 |
312 bool isUsedInTryOrGenerator(Local local) { | 312 bool _isUsedInTryOrGenerator(Local local) { |
313 return closureData.variableIsUsedInTryOrSync(local); | 313 return closureData.variableIsUsedInTryOrSync(local); |
314 } | 314 } |
315 | 315 |
316 /// Returns an [HInstruction] for the given element. If the element is | 316 /// Returns an [HInstruction] for the given element. If the element is |
317 /// boxed or stored in a closure then the method generates code to retrieve | 317 /// boxed or stored in a closure then the method generates code to retrieve |
318 /// the value. | 318 /// the value. |
319 HInstruction readLocal(Local local, {SourceInformation sourceInformation}) { | 319 HInstruction readLocal(Local local, {SourceInformation sourceInformation}) { |
320 if (isAccessedDirectly(local)) { | 320 if (isAccessedDirectly(local)) { |
321 if (directLocals[local] == null) { | 321 if (directLocals[local] == null) { |
322 if (local is TypeVariableLocal) { | 322 if (local is TypeVariableLocal) { |
(...skipping 29 matching lines...) Expand all Loading... |
352 // accessed as direct local. Inside the nested closure the box is | 352 // accessed as direct local. Inside the nested closure the box is |
353 // accessed through a closure-field. | 353 // accessed through a closure-field. |
354 // Calling [readLocal] makes sure we generate the correct code to get | 354 // Calling [readLocal] makes sure we generate the correct code to get |
355 // the box. | 355 // the box. |
356 HInstruction box = readLocal(redirect.box); | 356 HInstruction box = readLocal(redirect.box); |
357 HInstruction lookup = | 357 HInstruction lookup = |
358 new HFieldGet(redirect, box, getTypeOfCapturedVariable(redirect)); | 358 new HFieldGet(redirect, box, getTypeOfCapturedVariable(redirect)); |
359 builder.add(lookup); | 359 builder.add(lookup); |
360 return lookup..sourceInformation = sourceInformation; | 360 return lookup..sourceInformation = sourceInformation; |
361 } else { | 361 } else { |
362 assert(isUsedInTryOrGenerator(local)); | 362 assert(_isUsedInTryOrGenerator(local)); |
363 HLocalValue localValue = getLocal(local); | 363 HLocalValue localValue = getLocal(local); |
364 HInstruction instruction = new HLocalGet( | 364 HInstruction instruction = new HLocalGet( |
365 local, localValue, commonMasks.dynamicType, sourceInformation); | 365 local, localValue, commonMasks.dynamicType, sourceInformation); |
366 builder.add(instruction); | 366 builder.add(instruction); |
367 return instruction; | 367 return instruction; |
368 } | 368 } |
369 } | 369 } |
370 | 370 |
371 HInstruction readThis() { | 371 HInstruction readThis() { |
372 HInstruction res = readLocal(closureData.thisLocal); | 372 HInstruction res = readLocal(closureData.thisLocal); |
373 if (res.instructionType == null) { | 373 if (res.instructionType == null) { |
374 res.instructionType = getTypeOfThis(); | 374 res.instructionType = getTypeOfThis(); |
375 } | 375 } |
376 return res; | 376 return res; |
377 } | 377 } |
378 | 378 |
379 HLocalValue getLocal(Local local, {SourceInformation sourceInformation}) { | 379 HLocalValue getLocal(Local local, {SourceInformation sourceInformation}) { |
380 // If the element is a parameter, we already have a | 380 // If the element is a parameter, we already have a |
381 // HParameterValue for it. We cannot create another one because | 381 // HParameterValue for it. We cannot create another one because |
382 // it could then have another name than the real parameter. And | 382 // it could then have another name than the real parameter. And |
383 // the other one would not know it is just a copy of the real | 383 // the other one would not know it is just a copy of the real |
384 // parameter. | 384 // parameter. |
385 if (local is ParameterElement) { | 385 if (builder.parameters.containsKey(local)) { |
386 assert( | |
387 builder.parameters.containsKey(local), | |
388 failedAt(local, | |
389 "No local value for parameter $local in ${builder.parameters}.")); | |
390 return builder.parameters[local]; | 386 return builder.parameters[local]; |
391 } | 387 } |
392 | 388 |
393 return activationVariables.putIfAbsent(local, () { | 389 return activationVariables.putIfAbsent(local, () { |
394 HLocalValue localValue = new HLocalValue(local, commonMasks.nonNullType) | 390 HLocalValue localValue = new HLocalValue(local, commonMasks.nonNullType) |
395 ..sourceInformation = sourceInformation; | 391 ..sourceInformation = sourceInformation; |
396 builder.graph.entry.addAtExit(localValue); | 392 builder.graph.entry.addAtExit(localValue); |
397 return localValue; | 393 return localValue; |
398 }); | 394 }); |
399 } | 395 } |
(...skipping 18 matching lines...) Expand all Loading... |
418 } else if (isBoxed(local)) { | 414 } else if (isBoxed(local)) { |
419 BoxFieldElement redirect = redirectionMapping[local]; | 415 BoxFieldElement redirect = redirectionMapping[local]; |
420 // The box itself could be captured, or be local. A local variable that | 416 // The box itself could be captured, or be local. A local variable that |
421 // is captured will be boxed, but the box itself will be a local. | 417 // is captured will be boxed, but the box itself will be a local. |
422 // Inside the closure the box is stored in a closure-field and cannot | 418 // Inside the closure the box is stored in a closure-field and cannot |
423 // be accessed directly. | 419 // be accessed directly. |
424 HInstruction box = readLocal(redirect.box); | 420 HInstruction box = readLocal(redirect.box); |
425 builder.add(new HFieldSet(redirect, box, value) | 421 builder.add(new HFieldSet(redirect, box, value) |
426 ..sourceInformation = sourceInformation); | 422 ..sourceInformation = sourceInformation); |
427 } else { | 423 } else { |
428 assert(isUsedInTryOrGenerator(local)); | 424 assert(_isUsedInTryOrGenerator(local)); |
429 HLocalValue localValue = getLocal(local); | 425 HLocalValue localValue = getLocal(local); |
430 builder.add(new HLocalSet(local, localValue, value) | 426 builder.add(new HLocalSet(local, localValue, value) |
431 ..sourceInformation = sourceInformation); | 427 ..sourceInformation = sourceInformation); |
432 } | 428 } |
433 } | 429 } |
434 | 430 |
435 /// This function, startLoop, must be called before visiting any children of | 431 /// This function, startLoop, must be called before visiting any children of |
436 /// the loop. In particular it needs to be called before executing the | 432 /// the loop. In particular it needs to be called before executing the |
437 /// initializers. | 433 /// initializers. |
438 /// | 434 /// |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
673 final MemberEntity memberContext; | 669 final MemberEntity memberContext; |
674 | 670 |
675 // Avoid slow Object.hashCode. | 671 // Avoid slow Object.hashCode. |
676 final int hashCode = _nextHashCode = (_nextHashCode + 1).toUnsigned(30); | 672 final int hashCode = _nextHashCode = (_nextHashCode + 1).toUnsigned(30); |
677 static int _nextHashCode = 0; | 673 static int _nextHashCode = 0; |
678 | 674 |
679 SyntheticLocal(this.name, this.executableContext, this.memberContext); | 675 SyntheticLocal(this.name, this.executableContext, this.memberContext); |
680 | 676 |
681 toString() => 'SyntheticLocal($name)'; | 677 toString() => 'SyntheticLocal($name)'; |
682 } | 678 } |
OLD | NEW |