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/resolution_types.dart'; | 7 import '../elements/resolution_types.dart'; |
8 import '../elements/elements.dart'; | 8 import '../elements/elements.dart'; |
9 import '../elements/entities.dart'; | 9 import '../elements/entities.dart'; |
10 import '../io/source_information.dart'; | 10 import '../io/source_information.dart'; |
(...skipping 18 matching lines...) Expand all Loading... |
29 /// iteration order a function only of insertions and not a function of | 29 /// iteration order a function only of insertions and not a function of |
30 /// e.g. Element hash codes. I'd prefer to use a SortedMap but some elements | 30 /// e.g. Element hash codes. I'd prefer to use a SortedMap but some elements |
31 /// don't have source locations for [Elements.compareByPosition]. | 31 /// don't have source locations for [Elements.compareByPosition]. |
32 Map<Local, HInstruction> directLocals = new Map<Local, HInstruction>(); | 32 Map<Local, HInstruction> directLocals = new Map<Local, HInstruction>(); |
33 Map<Local, CapturedVariable> redirectionMapping = | 33 Map<Local, CapturedVariable> redirectionMapping = |
34 new Map<Local, CapturedVariable>(); | 34 new Map<Local, CapturedVariable>(); |
35 final GraphBuilder builder; | 35 final GraphBuilder builder; |
36 ClosureClassMap closureData; | 36 ClosureClassMap closureData; |
37 Map<ResolutionTypeVariableType, TypeVariableLocal> typeVariableLocals = | 37 Map<ResolutionTypeVariableType, TypeVariableLocal> typeVariableLocals = |
38 new Map<ResolutionTypeVariableType, TypeVariableLocal>(); | 38 new Map<ResolutionTypeVariableType, TypeVariableLocal>(); |
39 final ExecutableElement executableContext; | 39 final Entity executableContext; |
| 40 final MemberEntity memberContext; |
40 | 41 |
41 /// The class that defines the current type environment or null if no type | 42 /// The class that defines the current type environment or null if no type |
42 /// variables are in scope. | 43 /// variables are in scope. |
43 ClassElement get contextClass => executableContext.contextClass; | 44 final ClassElement contextClass; |
44 | 45 |
45 /// The type of the current instance, if concrete. | 46 /// The type of the current instance, if concrete. |
46 /// | 47 /// |
47 /// This allows for handling fixed type argument in case of inlining. For | 48 /// This allows for handling fixed type argument in case of inlining. For |
48 /// instance, checking `'foo'` against `String` instead of `T` in `main`: | 49 /// instance, checking `'foo'` against `String` instead of `T` in `main`: |
49 /// | 50 /// |
50 /// class Foo<T> { | 51 /// class Foo<T> { |
51 /// T field; | 52 /// T field; |
52 /// Foo(this.field); | 53 /// Foo(this.field); |
53 /// } | 54 /// } |
54 /// main() { | 55 /// main() { |
55 /// new Foo<String>('foo'); | 56 /// new Foo<String>('foo'); |
56 /// } | 57 /// } |
57 /// | 58 /// |
58 /// [instanceType] is not used if it contains type variables, since these | 59 /// [instanceType] is not used if it contains type variables, since these |
59 /// might not be in scope or from the current instance. | 60 /// might not be in scope or from the current instance. |
60 /// | 61 /// |
61 final ResolutionInterfaceType instanceType; | 62 final ResolutionInterfaceType instanceType; |
62 | 63 |
63 final NativeData _nativeData; | 64 final NativeData _nativeData; |
64 | 65 |
65 final InterceptorData _interceptorData; | 66 final InterceptorData _interceptorData; |
66 | 67 |
67 LocalsHandler( | 68 LocalsHandler( |
68 this.builder, | 69 this.builder, |
69 this.executableContext, | 70 this.executableContext, |
| 71 this.memberContext, |
| 72 this.contextClass, |
70 ResolutionInterfaceType instanceType, | 73 ResolutionInterfaceType instanceType, |
71 this._nativeData, | 74 this._nativeData, |
72 this._interceptorData) | 75 this._interceptorData) |
73 : this.instanceType = | 76 : this.instanceType = |
74 instanceType == null || instanceType.containsTypeVariables | 77 instanceType == null || instanceType.containsTypeVariables |
75 ? null | 78 ? null |
76 : instanceType; | 79 : instanceType; |
77 | 80 |
78 ClosedWorld get closedWorld => builder.closedWorld; | 81 ClosedWorld get closedWorld => builder.closedWorld; |
79 | 82 |
(...skipping 19 matching lines...) Expand all Loading... |
99 return type; | 102 return type; |
100 } | 103 } |
101 | 104 |
102 /// Creates a new [LocalsHandler] based on [other]. We only need to | 105 /// Creates a new [LocalsHandler] based on [other]. We only need to |
103 /// copy the [directLocals], since the other fields can be shared | 106 /// copy the [directLocals], since the other fields can be shared |
104 /// throughout the AST visit. | 107 /// throughout the AST visit. |
105 LocalsHandler.from(LocalsHandler other) | 108 LocalsHandler.from(LocalsHandler other) |
106 : directLocals = new Map<Local, HInstruction>.from(other.directLocals), | 109 : directLocals = new Map<Local, HInstruction>.from(other.directLocals), |
107 redirectionMapping = other.redirectionMapping, | 110 redirectionMapping = other.redirectionMapping, |
108 executableContext = other.executableContext, | 111 executableContext = other.executableContext, |
| 112 memberContext = other.memberContext, |
| 113 contextClass = other.contextClass, |
109 instanceType = other.instanceType, | 114 instanceType = other.instanceType, |
110 builder = other.builder, | 115 builder = other.builder, |
111 closureData = other.closureData, | 116 closureData = other.closureData, |
112 _nativeData = other._nativeData, | 117 _nativeData = other._nativeData, |
113 _interceptorData = other._interceptorData, | 118 _interceptorData = other._interceptorData, |
114 activationVariables = other.activationVariables, | 119 activationVariables = other.activationVariables, |
115 cachedTypeOfThis = other.cachedTypeOfThis, | 120 cachedTypeOfThis = other.cachedTypeOfThis, |
116 cachedTypesOfCapturedVariables = other.cachedTypesOfCapturedVariables; | 121 cachedTypesOfCapturedVariables = other.cachedTypesOfCapturedVariables; |
117 | 122 |
118 /// Redirects accesses from element [from] to element [to]. The [to] element | 123 /// Redirects accesses from element [from] to element [to]. The [to] element |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 // When the class extends a native class, the instance is pre-constructed | 257 // When the class extends a native class, the instance is pre-constructed |
253 // and passed to the generative constructor factory function as a parameter. | 258 // and passed to the generative constructor factory function as a parameter. |
254 // Instead of allocating and initializing the object, the constructor | 259 // Instead of allocating and initializing the object, the constructor |
255 // 'upgrades' the native subclass object by initializing the Dart fields. | 260 // 'upgrades' the native subclass object by initializing the Dart fields. |
256 bool isNativeUpgradeFactory = element.isGenerativeConstructor && | 261 bool isNativeUpgradeFactory = element.isGenerativeConstructor && |
257 _nativeData.isNativeOrExtendsNative(cls); | 262 _nativeData.isNativeOrExtendsNative(cls); |
258 if (_interceptorData.isInterceptedMethod(element)) { | 263 if (_interceptorData.isInterceptedMethod(element)) { |
259 bool isInterceptedClass = | 264 bool isInterceptedClass = |
260 _interceptorData.isInterceptedClass(cls.declaration); | 265 _interceptorData.isInterceptedClass(cls.declaration); |
261 String name = isInterceptedClass ? 'receiver' : '_'; | 266 String name = isInterceptedClass ? 'receiver' : '_'; |
262 SyntheticLocal parameter = new SyntheticLocal(name, executableContext); | 267 SyntheticLocal parameter = createLocal(name); |
263 HParameterValue value = new HParameterValue(parameter, getTypeOfThis()); | 268 HParameterValue value = new HParameterValue(parameter, getTypeOfThis()); |
264 builder.graph.explicitReceiverParameter = value; | 269 builder.graph.explicitReceiverParameter = value; |
265 builder.graph.entry.addAfter(directLocals[closureData.thisLocal], value); | 270 builder.graph.entry.addAfter(directLocals[closureData.thisLocal], value); |
266 if (builder.lastAddedParameter == null) { | 271 if (builder.lastAddedParameter == null) { |
267 // If this is the first parameter inserted, make sure it stays first. | 272 // If this is the first parameter inserted, make sure it stays first. |
268 builder.lastAddedParameter = value; | 273 builder.lastAddedParameter = value; |
269 } | 274 } |
270 if (isInterceptedClass) { | 275 if (isInterceptedClass) { |
271 // Only use the extra parameter in intercepted classes. | 276 // Only use the extra parameter in intercepted classes. |
272 directLocals[closureData.thisLocal] = value; | 277 directLocals[closureData.thisLocal] = value; |
273 } | 278 } |
274 } else if (isNativeUpgradeFactory) { | 279 } else if (isNativeUpgradeFactory) { |
275 SyntheticLocal parameter = | 280 SyntheticLocal parameter = createLocal('receiver'); |
276 new SyntheticLocal('receiver', executableContext); | |
277 // Unlike `this`, receiver is nullable since direct calls to generative | 281 // Unlike `this`, receiver is nullable since direct calls to generative |
278 // constructor call the constructor with `null`. | 282 // constructor call the constructor with `null`. |
279 HParameterValue value = | 283 HParameterValue value = |
280 new HParameterValue(parameter, new TypeMask.exact(cls, closedWorld)); | 284 new HParameterValue(parameter, new TypeMask.exact(cls, closedWorld)); |
281 builder.graph.explicitReceiverParameter = value; | 285 builder.graph.explicitReceiverParameter = value; |
282 builder.graph.entry.addAtEntry(value); | 286 builder.graph.entry.addAtEntry(value); |
283 if (builder.lastAddedParameter == null) { | 287 if (builder.lastAddedParameter == null) { |
284 // If this is the first parameter inserted, make sure it stays first. | 288 // If this is the first parameter inserted, make sure it stays first. |
285 builder.lastAddedParameter = value; | 289 builder.lastAddedParameter = value; |
286 } | 290 } |
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
651 return cachedTypesOfCapturedVariables.putIfAbsent(element, () { | 655 return cachedTypesOfCapturedVariables.putIfAbsent(element, () { |
652 return TypeMaskFactory.inferredTypeForMember( | 656 return TypeMaskFactory.inferredTypeForMember( |
653 element, _globalInferenceResults); | 657 element, _globalInferenceResults); |
654 }); | 658 }); |
655 } | 659 } |
656 | 660 |
657 /// Variables stored in the current activation. These variables are | 661 /// Variables stored in the current activation. These variables are |
658 /// being updated in try/catch blocks, and should be | 662 /// being updated in try/catch blocks, and should be |
659 /// accessed indirectly through [HLocalGet] and [HLocalSet]. | 663 /// accessed indirectly through [HLocalGet] and [HLocalSet]. |
660 Map<Local, HLocalValue> activationVariables = <Local, HLocalValue>{}; | 664 Map<Local, HLocalValue> activationVariables = <Local, HLocalValue>{}; |
| 665 |
| 666 SyntheticLocal createLocal(String name) { |
| 667 return new SyntheticLocal(name, executableContext, memberContext); |
| 668 } |
661 } | 669 } |
662 | 670 |
663 /// A synthetic local variable only used with the SSA graph. | 671 /// A synthetic local variable only used with the SSA graph. |
664 /// | 672 /// |
665 /// For instance used for holding return value of function or the exception of a | 673 /// For instance used for holding return value of function or the exception of a |
666 /// try-catch statement. | 674 /// try-catch statement. |
667 class SyntheticLocal extends Local { | 675 class SyntheticLocal extends Local { |
668 final String name; | 676 final String name; |
669 final ExecutableElement executableContext; | 677 final Entity executableContext; |
| 678 final MemberEntity memberContext; |
670 | 679 |
671 // Avoid slow Object.hashCode. | 680 // Avoid slow Object.hashCode. |
672 final int hashCode = _nextHashCode = (_nextHashCode + 1).toUnsigned(30); | 681 final int hashCode = _nextHashCode = (_nextHashCode + 1).toUnsigned(30); |
673 static int _nextHashCode = 0; | 682 static int _nextHashCode = 0; |
674 | 683 |
675 SyntheticLocal(this.name, this.executableContext); | 684 SyntheticLocal(this.name, this.executableContext, this.memberContext); |
676 | |
677 @override | |
678 MemberElement get memberContext => executableContext.memberContext; | |
679 | 685 |
680 toString() => 'SyntheticLocal($name)'; | 686 toString() => 'SyntheticLocal($name)'; |
681 } | 687 } |
OLD | NEW |