| 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'; |
| 11 import '../js_backend/native_data.dart'; | 11 import '../js_backend/native_data.dart'; |
| 12 import '../js_backend/interceptor_data.dart'; | 12 import '../js_backend/interceptor_data.dart'; |
| 13 import '../js_model/closure.dart' show JBoxedField, JClosureField; |
| 13 import '../tree/tree.dart' as ast; | 14 import '../tree/tree.dart' as ast; |
| 14 import '../types/types.dart'; | 15 import '../types/types.dart'; |
| 15 import '../world.dart' show ClosedWorld; | 16 import '../world.dart' show ClosedWorld; |
| 16 | 17 |
| 17 import 'graph_builder.dart'; | 18 import 'graph_builder.dart'; |
| 18 import 'nodes.dart'; | 19 import 'nodes.dart'; |
| 19 import 'types.dart'; | 20 import 'types.dart'; |
| 20 | 21 |
| 21 /// Keeps track of locals (including parameters and phis) when building. The | 22 /// Keeps track of locals (including parameters and phis) when building. The |
| 22 /// 'this' reference is treated as parameter and hence handled by this class, | 23 /// 'this' reference is treated as parameter and hence handled by this class, |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 return !redirectionMapping.containsKey(local) && | 297 return !redirectionMapping.containsKey(local) && |
| 297 !scopeInfo.localIsUsedInTryOrSync(local); | 298 !scopeInfo.localIsUsedInTryOrSync(local); |
| 298 } | 299 } |
| 299 | 300 |
| 300 bool isStoredInClosureField(Local local) { | 301 bool isStoredInClosureField(Local local) { |
| 301 assert(local != null); | 302 assert(local != null); |
| 302 if (isAccessedDirectly(local)) return false; | 303 if (isAccessedDirectly(local)) return false; |
| 303 if (scopeInfo is! ClosureRepresentationInfo) return false; | 304 if (scopeInfo is! ClosureRepresentationInfo) return false; |
| 304 FieldEntity redirectTarget = redirectionMapping[local]; | 305 FieldEntity redirectTarget = redirectionMapping[local]; |
| 305 if (redirectTarget == null) return false; | 306 if (redirectTarget == null) return false; |
| 306 return redirectTarget is ClosureFieldElement; | 307 return redirectTarget is ClosureFieldElement || |
| 308 redirectTarget is JClosureField; |
| 307 } | 309 } |
| 308 | 310 |
| 309 bool isBoxed(Local local) { | 311 bool isBoxed(Local local) { |
| 310 if (isAccessedDirectly(local)) return false; | 312 if (isAccessedDirectly(local)) return false; |
| 311 if (isStoredInClosureField(local)) return false; | 313 if (isStoredInClosureField(local)) return false; |
| 312 return redirectionMapping.containsKey(local); | 314 return redirectionMapping.containsKey(local); |
| 313 } | 315 } |
| 314 | 316 |
| 315 bool _isUsedInTryOrGenerator(Local local) { | 317 bool _isUsedInTryOrGenerator(Local local) { |
| 316 return scopeInfo.localIsUsedInTryOrSync(local); | 318 return scopeInfo.localIsUsedInTryOrSync(local); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 335 } | 337 } |
| 336 } | 338 } |
| 337 HInstruction value = directLocals[local]; | 339 HInstruction value = directLocals[local]; |
| 338 if (sourceInformation != null) { | 340 if (sourceInformation != null) { |
| 339 value = new HRef(value, sourceInformation); | 341 value = new HRef(value, sourceInformation); |
| 340 builder.add(value); | 342 builder.add(value); |
| 341 } | 343 } |
| 342 return value; | 344 return value; |
| 343 } else if (isStoredInClosureField(local)) { | 345 } else if (isStoredInClosureField(local)) { |
| 344 ClosureRepresentationInfo closureData = scopeInfo; | 346 ClosureRepresentationInfo closureData = scopeInfo; |
| 345 ClosureFieldElement redirect = redirectionMapping[local]; | 347 FieldEntity redirect = redirectionMapping[local]; |
| 346 HInstruction receiver = readLocal(closureData.closureEntity); | 348 HInstruction receiver = readLocal(closureData.closureEntity); |
| 347 TypeMask type = local is BoxLocal | 349 TypeMask type = local is BoxLocal |
| 348 ? commonMasks.nonNullType | 350 ? commonMasks.nonNullType |
| 349 : getTypeOfCapturedVariable(redirect); | 351 : getTypeOfCapturedVariable(redirect); |
| 350 HInstruction fieldGet = new HFieldGet(redirect, receiver, type); | 352 HInstruction fieldGet = new HFieldGet(redirect, receiver, type); |
| 351 builder.add(fieldGet); | 353 builder.add(fieldGet); |
| 352 return fieldGet..sourceInformation = sourceInformation; | 354 return fieldGet..sourceInformation = sourceInformation; |
| 353 } else if (isBoxed(local)) { | 355 } else if (isBoxed(local)) { |
| 354 BoxFieldElement redirect = redirectionMapping[local]; | 356 FieldEntity redirect = redirectionMapping[local]; |
| 357 BoxLocal localBox; |
| 355 // In the function that declares the captured variable the box is | 358 // In the function that declares the captured variable the box is |
| 356 // accessed as direct local. Inside the nested closure the box is | 359 // accessed as direct local. Inside the nested closure the box is |
| 357 // accessed through a closure-field. | 360 // accessed through a closure-field. |
| 358 // Calling [readLocal] makes sure we generate the correct code to get | 361 // Calling [readLocal] makes sure we generate the correct code to get |
| 359 // the box. | 362 // the box. |
| 360 HInstruction box = readLocal(redirect.box); | 363 if (redirect is BoxFieldElement) { |
| 364 localBox = redirect.box; |
| 365 } else if (redirect is JBoxedField) { |
| 366 localBox = redirect.box; |
| 367 } |
| 368 assert(localBox != null); |
| 369 |
| 370 HInstruction box = readLocal(localBox); |
| 361 HInstruction lookup = | 371 HInstruction lookup = |
| 362 new HFieldGet(redirect, box, getTypeOfCapturedVariable(redirect)); | 372 new HFieldGet(redirect, box, getTypeOfCapturedVariable(redirect)); |
| 363 builder.add(lookup); | 373 builder.add(lookup); |
| 364 return lookup..sourceInformation = sourceInformation; | 374 return lookup..sourceInformation = sourceInformation; |
| 365 } else { | 375 } else { |
| 366 assert(_isUsedInTryOrGenerator(local)); | 376 assert(_isUsedInTryOrGenerator(local)); |
| 367 HLocalValue localValue = getLocal(local); | 377 HLocalValue localValue = getLocal(local); |
| 368 HInstruction instruction = new HLocalGet( | 378 HInstruction instruction = new HLocalGet( |
| 369 local, localValue, commonMasks.dynamicType, sourceInformation); | 379 local, localValue, commonMasks.dynamicType, sourceInformation); |
| 370 builder.add(instruction); | 380 builder.add(instruction); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 409 void updateLocal(Local local, HInstruction value, | 419 void updateLocal(Local local, HInstruction value, |
| 410 {SourceInformation sourceInformation}) { | 420 {SourceInformation sourceInformation}) { |
| 411 if (value is HRef) { | 421 if (value is HRef) { |
| 412 HRef ref = value; | 422 HRef ref = value; |
| 413 value = ref.value; | 423 value = ref.value; |
| 414 } | 424 } |
| 415 assert(!isStoredInClosureField(local)); | 425 assert(!isStoredInClosureField(local)); |
| 416 if (isAccessedDirectly(local)) { | 426 if (isAccessedDirectly(local)) { |
| 417 directLocals[local] = value; | 427 directLocals[local] = value; |
| 418 } else if (isBoxed(local)) { | 428 } else if (isBoxed(local)) { |
| 419 BoxFieldElement redirect = redirectionMapping[local]; | 429 FieldEntity redirect = redirectionMapping[local]; |
| 430 assert(redirect != null); |
| 431 BoxLocal localBox; |
| 432 if (redirect is BoxFieldElement) { |
| 433 localBox = redirect.box; |
| 434 } else if (redirect is JBoxedField) { |
| 435 localBox = redirect.box; |
| 436 } |
| 437 assert(localBox != null); |
| 438 |
| 420 // The box itself could be captured, or be local. A local variable that | 439 // 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. | 440 // 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 | 441 // Inside the closure the box is stored in a closure-field and cannot |
| 423 // be accessed directly. | 442 // be accessed directly. |
| 424 HInstruction box = readLocal(redirect.box); | 443 HInstruction box = readLocal(localBox); |
| 425 builder.add(new HFieldSet(redirect, box, value) | 444 builder.add(new HFieldSet(redirect, box, value) |
| 426 ..sourceInformation = sourceInformation); | 445 ..sourceInformation = sourceInformation); |
| 427 } else { | 446 } else { |
| 428 assert(_isUsedInTryOrGenerator(local)); | 447 assert(_isUsedInTryOrGenerator(local)); |
| 429 HLocalValue localValue = getLocal(local); | 448 HLocalValue localValue = getLocal(local); |
| 430 builder.add(new HLocalSet(local, localValue, value) | 449 builder.add(new HLocalSet(local, localValue, value) |
| 431 ..sourceInformation = sourceInformation); | 450 ..sourceInformation = sourceInformation); |
| 432 } | 451 } |
| 433 } | 452 } |
| 434 | 453 |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 636 // simplicity, we mark the type as an interface type. | 655 // simplicity, we mark the type as an interface type. |
| 637 result = new TypeMask.nonNullSubtype(cls, closedWorld); | 656 result = new TypeMask.nonNullSubtype(cls, closedWorld); |
| 638 } else { | 657 } else { |
| 639 result = new TypeMask.nonNullSubclass(cls, closedWorld); | 658 result = new TypeMask.nonNullSubclass(cls, closedWorld); |
| 640 } | 659 } |
| 641 cachedTypeOfThis = result; | 660 cachedTypeOfThis = result; |
| 642 } | 661 } |
| 643 return result; | 662 return result; |
| 644 } | 663 } |
| 645 | 664 |
| 646 Map<Element, TypeMask> cachedTypesOfCapturedVariables = | 665 Map<FieldEntity, TypeMask> cachedTypesOfCapturedVariables = |
| 647 new Map<Element, TypeMask>(); | 666 new Map<FieldEntity, TypeMask>(); |
| 648 | 667 |
| 649 TypeMask getTypeOfCapturedVariable(FieldElement element) { | 668 TypeMask getTypeOfCapturedVariable(FieldEntity element) { |
| 650 return cachedTypesOfCapturedVariables.putIfAbsent(element, () { | 669 return cachedTypesOfCapturedVariables.putIfAbsent(element, () { |
| 651 return TypeMaskFactory.inferredTypeForMember( | 670 return TypeMaskFactory.inferredTypeForMember( |
| 652 element, _globalInferenceResults); | 671 element, _globalInferenceResults); |
| 653 }); | 672 }); |
| 654 } | 673 } |
| 655 | 674 |
| 656 /// Variables stored in the current activation. These variables are | 675 /// Variables stored in the current activation. These variables are |
| 657 /// being updated in try/catch blocks, and should be | 676 /// being updated in try/catch blocks, and should be |
| 658 /// accessed indirectly through [HLocalGet] and [HLocalSet]. | 677 /// accessed indirectly through [HLocalGet] and [HLocalSet]. |
| 659 Map<Local, HLocalValue> activationVariables = <Local, HLocalValue>{}; | 678 Map<Local, HLocalValue> activationVariables = <Local, HLocalValue>{}; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 673 final MemberEntity memberContext; | 692 final MemberEntity memberContext; |
| 674 | 693 |
| 675 // Avoid slow Object.hashCode. | 694 // Avoid slow Object.hashCode. |
| 676 final int hashCode = _nextHashCode = (_nextHashCode + 1).toUnsigned(30); | 695 final int hashCode = _nextHashCode = (_nextHashCode + 1).toUnsigned(30); |
| 677 static int _nextHashCode = 0; | 696 static int _nextHashCode = 0; |
| 678 | 697 |
| 679 SyntheticLocal(this.name, this.executableContext, this.memberContext); | 698 SyntheticLocal(this.name, this.executableContext, this.memberContext); |
| 680 | 699 |
| 681 toString() => 'SyntheticLocal($name)'; | 700 toString() => 'SyntheticLocal($name)'; |
| 682 } | 701 } |
| OLD | NEW |