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 |