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