| 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 |