Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(218)

Side by Side Diff: pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart

Issue 1859343004: dartfmt pkg/compiler (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 part of dart2js.js_emitter; 5 part of dart2js.js_emitter;
6 6
7 // Function signatures used in the generation of runtime type information. 7 // Function signatures used in the generation of runtime type information.
8 typedef void FunctionTypeSignatureEmitter(Element method, 8 typedef void FunctionTypeSignatureEmitter(
9 FunctionType methodType); 9 Element method, FunctionType methodType);
10 10
11 typedef void SubstitutionEmitter(Element element, {bool emitNull}); 11 typedef void SubstitutionEmitter(Element element, {bool emitNull});
12 12
13 class TypeTestProperties { 13 class TypeTestProperties {
14 /// The index of the function type into the metadata. 14 /// The index of the function type into the metadata.
15 /// 15 ///
16 /// If the class doesn't have a function type this field is `null`. 16 /// If the class doesn't have a function type this field is `null`.
17 /// 17 ///
18 /// If the is tests were generated with `storeFunctionTypeInMetadata` set to 18 /// If the is tests were generated with `storeFunctionTypeInMetadata` set to
19 /// `false`, this field is `null`, and the [properties] contain a property 19 /// `false`, this field is `null`, and the [properties] contain a property
(...skipping 10 matching lines...) Expand all
30 final Compiler compiler; 30 final Compiler compiler;
31 final CodeEmitterTask emitterTask; 31 final CodeEmitterTask emitterTask;
32 final Namer namer; 32 final Namer namer;
33 33
34 RuntimeTypeGenerator(this.compiler, this.emitterTask, this.namer); 34 RuntimeTypeGenerator(this.compiler, this.emitterTask, this.namer);
35 35
36 JavaScriptBackend get backend => compiler.backend; 36 JavaScriptBackend get backend => compiler.backend;
37 TypeTestRegistry get typeTestRegistry => emitterTask.typeTestRegistry; 37 TypeTestRegistry get typeTestRegistry => emitterTask.typeTestRegistry;
38 CoreClasses get coreClasses => compiler.coreClasses; 38 CoreClasses get coreClasses => compiler.coreClasses;
39 39
40 Set<ClassElement> get checkedClasses => 40 Set<ClassElement> get checkedClasses => typeTestRegistry.checkedClasses;
41 typeTestRegistry.checkedClasses;
42 41
43 Iterable<ClassElement> get classesUsingTypeVariableTests => 42 Iterable<ClassElement> get classesUsingTypeVariableTests =>
44 typeTestRegistry.classesUsingTypeVariableTests; 43 typeTestRegistry.classesUsingTypeVariableTests;
45 44
46 Set<FunctionType> get checkedFunctionTypes => 45 Set<FunctionType> get checkedFunctionTypes =>
47 typeTestRegistry.checkedFunctionTypes; 46 typeTestRegistry.checkedFunctionTypes;
48 47
49 /// Generates all properties necessary for is-checks on the [classElement]. 48 /// Generates all properties necessary for is-checks on the [classElement].
50 /// 49 ///
51 /// Returns an instance of [TypeTestProperties] that contains the properties 50 /// Returns an instance of [TypeTestProperties] that contains the properties
52 /// that must be installed on the prototype of the JS constructor of the 51 /// that must be installed on the prototype of the JS constructor of the
53 /// [classElement]. 52 /// [classElement].
54 /// 53 ///
55 /// If [storeFunctionTypeInMetadata] is `true`, stores the reified function 54 /// If [storeFunctionTypeInMetadata] is `true`, stores the reified function
56 /// type (if class has one) in the metadata object and stores its index in 55 /// type (if class has one) in the metadata object and stores its index in
57 /// the result. This is only possible for function types that do not contain 56 /// the result. This is only possible for function types that do not contain
58 /// type variables. 57 /// type variables.
59 TypeTestProperties generateIsTests( 58 TypeTestProperties generateIsTests(ClassElement classElement,
60 ClassElement classElement, 59 {bool storeFunctionTypeInMetadata: true}) {
61 { bool storeFunctionTypeInMetadata: true}) {
62 assert(invariant(classElement, classElement.isDeclaration)); 60 assert(invariant(classElement, classElement.isDeclaration));
63 61
64 TypeTestProperties result = new TypeTestProperties(); 62 TypeTestProperties result = new TypeTestProperties();
65 63
66 /// Generates an is-test if the test is not inherited from a superclass 64 /// Generates an is-test if the test is not inherited from a superclass
67 /// This assumes that for every class an is-tests is generated 65 /// This assumes that for every class an is-tests is generated
68 /// dynamically at runtime. We also always generate tests against 66 /// dynamically at runtime. We also always generate tests against
69 /// native classes. 67 /// native classes.
70 /// TODO(herhut): Generate tests for native classes dynamically, as well. 68 /// TODO(herhut): Generate tests for native classes dynamically, as well.
71 void generateIsTest(Element other) { 69 void generateIsTest(Element other) {
72 if (backend.isNative(classElement) || 70 if (backend.isNative(classElement) || !classElement.isSubclassOf(other)) {
73 !classElement.isSubclassOf(other)) {
74 result.properties[namer.operatorIs(other)] = js('1'); 71 result.properties[namer.operatorIs(other)] = js('1');
75 } 72 }
76 } 73 }
77 74
78 void generateFunctionTypeSignature(FunctionElement method, 75 void generateFunctionTypeSignature(
79 FunctionType type) { 76 FunctionElement method, FunctionType type) {
80 assert(method.isImplementation); 77 assert(method.isImplementation);
81 jsAst.Expression thisAccess = new jsAst.This(); 78 jsAst.Expression thisAccess = new jsAst.This();
82 ClosureClassMap closureData = 79 ClosureClassMap closureData =
83 compiler.closureToClassMapper.closureMappingCache[method.node]; 80 compiler.closureToClassMapper.closureMappingCache[method.node];
84 if (closureData != null) { 81 if (closureData != null) {
85 ClosureFieldElement thisLocal = 82 ClosureFieldElement thisLocal =
86 closureData.freeVariableMap[closureData.thisLocal]; 83 closureData.freeVariableMap[closureData.thisLocal];
87 if (thisLocal != null) { 84 if (thisLocal != null) {
88 jsAst.Name thisName = namer.instanceFieldPropertyName(thisLocal); 85 jsAst.Name thisName = namer.instanceFieldPropertyName(thisLocal);
89 thisAccess = js('this.#', thisName); 86 thisAccess = js('this.#', thisName);
90 } 87 }
91 } 88 }
92 89
93 if (storeFunctionTypeInMetadata && !type.containsTypeVariables) { 90 if (storeFunctionTypeInMetadata && !type.containsTypeVariables) {
94 result.functionTypeIndex = 91 result.functionTypeIndex =
95 emitterTask.metadataCollector.reifyType(type); 92 emitterTask.metadataCollector.reifyType(type);
96 } else { 93 } else {
97 RuntimeTypesEncoder rtiEncoder = backend.rtiEncoder; 94 RuntimeTypesEncoder rtiEncoder = backend.rtiEncoder;
98 jsAst.Expression encoding = 95 jsAst.Expression encoding =
99 rtiEncoder.getSignatureEncoding(type, thisAccess); 96 rtiEncoder.getSignatureEncoding(type, thisAccess);
100 jsAst.Name operatorSignature = 97 jsAst.Name operatorSignature = namer.asName(namer.operatorSignature);
101 namer.asName(namer.operatorSignature);
102 result.properties[operatorSignature] = encoding; 98 result.properties[operatorSignature] = encoding;
103 } 99 }
104 } 100 }
105 101
106 void generateSubstitution(ClassElement cls, {bool emitNull: false}) { 102 void generateSubstitution(ClassElement cls, {bool emitNull: false}) {
107 if (cls.typeVariables.isEmpty) return; 103 if (cls.typeVariables.isEmpty) return;
108 RuntimeTypes rti = backend.rti; 104 RuntimeTypes rti = backend.rti;
109 RuntimeTypesEncoder rtiEncoder = backend.rtiEncoder; 105 RuntimeTypesEncoder rtiEncoder = backend.rtiEncoder;
110 jsAst.Expression expression; 106 jsAst.Expression expression;
111 bool needsNativeCheck = 107 bool needsNativeCheck =
(...skipping 15 matching lines...) Expand all
127 generateIsTest(checkedClass); 123 generateIsTest(checkedClass);
128 Substitution substitution = check.substitution; 124 Substitution substitution = check.substitution;
129 if (substitution != null) { 125 if (substitution != null) {
130 jsAst.Expression body = 126 jsAst.Expression body =
131 backend.rtiEncoder.getSubstitutionCode(substitution); 127 backend.rtiEncoder.getSubstitutionCode(substitution);
132 result.properties[namer.substitutionName(checkedClass)] = body; 128 result.properties[namer.substitutionName(checkedClass)] = body;
133 } 129 }
134 } 130 }
135 131
136 _generateIsTestsOn(classElement, generateIsTest, 132 _generateIsTestsOn(classElement, generateIsTest,
137 generateFunctionTypeSignature, 133 generateFunctionTypeSignature, generateSubstitution, generateTypeCheck);
138 generateSubstitution,
139 generateTypeCheck);
140 134
141 return result; 135 return result;
142 } 136 }
143 137
144 /** 138 /**
145 * Generate "is tests" for [cls] itself, and the "is tests" for the 139 * Generate "is tests" for [cls] itself, and the "is tests" for the
146 * classes it implements and type argument substitution functions for these 140 * classes it implements and type argument substitution functions for these
147 * tests. We don't need to add the "is tests" of the super class because 141 * tests. We don't need to add the "is tests" of the super class because
148 * they will be inherited at runtime, but we may need to generate the 142 * they will be inherited at runtime, but we may need to generate the
149 * substitutions, because they may have changed. 143 * substitutions, because they may have changed.
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
204 198
205 if (classesUsingTypeVariableTests.contains(superclass) || 199 if (classesUsingTypeVariableTests.contains(superclass) ||
206 checkedClasses.contains(superclass)) { 200 checkedClasses.contains(superclass)) {
207 // Generate substitution. If no substitution is necessary, emit 201 // Generate substitution. If no substitution is necessary, emit
208 // `null` to overwrite a (possibly) existing substitution from the 202 // `null` to overwrite a (possibly) existing substitution from the
209 // super classes. 203 // super classes.
210 generateSubstitution(superclass, emitNull: true); 204 generateSubstitution(superclass, emitNull: true);
211 } 205 }
212 } 206 }
213 207
214 void emitNothing(_, {emitNull}) {}; 208 void emitNothing(_, {emitNull}) {}
209 ;
215 210
216 generateSubstitution = emitNothing; 211 generateSubstitution = emitNothing;
217 } 212 }
218 213
219 // A class that defines a `call` method implicitly implements 214 // A class that defines a `call` method implicitly implements
220 // [Function] and needs checks for all typedefs that are used in is-checks. 215 // [Function] and needs checks for all typedefs that are used in is-checks.
221 if (checkedClasses.contains(coreClasses.functionClass) || 216 if (checkedClasses.contains(coreClasses.functionClass) ||
222 checkedFunctionTypes.isNotEmpty) { 217 checkedFunctionTypes.isNotEmpty) {
223 Element call = cls.lookupLocalMember(Identifiers.call); 218 Element call = cls.lookupLocalMember(Identifiers.call);
224 if (call == null) { 219 if (call == null) {
225 // If [cls] is a closure, it has a synthetic call operator method. 220 // If [cls] is a closure, it has a synthetic call operator method.
226 call = cls.lookupBackendMember(Identifiers.call); 221 call = cls.lookupBackendMember(Identifiers.call);
227 } 222 }
228 if (call != null && call.isFunction) { 223 if (call != null && call.isFunction) {
229 FunctionElement callFunction = call; 224 FunctionElement callFunction = call;
230 // A superclass might already implement the Function interface. In such 225 // A superclass might already implement the Function interface. In such
231 // a case, we can avoid emiting the is test here. 226 // a case, we can avoid emiting the is test here.
232 if (!cls.superclass.implementsFunction(coreClasses)) { 227 if (!cls.superclass.implementsFunction(coreClasses)) {
233 _generateInterfacesIsTests(coreClasses.functionClass, 228 _generateInterfacesIsTests(coreClasses.functionClass, generateIsTest,
234 generateIsTest, 229 generateSubstitution, generated);
235 generateSubstitution,
236 generated);
237 } 230 }
238 FunctionType callType = callFunction.computeType(compiler.resolution); 231 FunctionType callType = callFunction.computeType(compiler.resolution);
239 generateFunctionTypeSignature(callFunction, callType); 232 generateFunctionTypeSignature(callFunction, callType);
240 } 233 }
241 } 234 }
242 235
243 for (DartType interfaceType in cls.interfaces) { 236 for (DartType interfaceType in cls.interfaces) {
244 _generateInterfacesIsTests(interfaceType.element, generateIsTest, 237 _generateInterfacesIsTests(interfaceType.element, generateIsTest,
245 generateSubstitution, generated); 238 generateSubstitution, generated);
246 } 239 }
247 } 240 }
248 241
249 /** 242 /**
250 * Generate "is tests" where [cls] is being implemented. 243 * Generate "is tests" where [cls] is being implemented.
251 */ 244 */
252 void _generateInterfacesIsTests(ClassElement cls, 245 void _generateInterfacesIsTests(
253 void generateIsTest(ClassElement element), 246 ClassElement cls,
254 SubstitutionEmitter generateSubstitution, 247 void generateIsTest(ClassElement element),
255 Set<Element> alreadyGenerated) { 248 SubstitutionEmitter generateSubstitution,
249 Set<Element> alreadyGenerated) {
256 void tryEmitTest(ClassElement check) { 250 void tryEmitTest(ClassElement check) {
257 if (!alreadyGenerated.contains(check) && checkedClasses.contains(check)) { 251 if (!alreadyGenerated.contains(check) && checkedClasses.contains(check)) {
258 alreadyGenerated.add(check); 252 alreadyGenerated.add(check);
259 generateIsTest(check); 253 generateIsTest(check);
260 generateSubstitution(check); 254 generateSubstitution(check);
261 } 255 }
262 }; 256 }
257 ;
263 258
264 tryEmitTest(cls); 259 tryEmitTest(cls);
265 260
266 for (DartType interfaceType in cls.interfaces) { 261 for (DartType interfaceType in cls.interfaces) {
267 Element element = interfaceType.element; 262 Element element = interfaceType.element;
268 tryEmitTest(element); 263 tryEmitTest(element);
269 _generateInterfacesIsTests(element, generateIsTest, generateSubstitution, 264 _generateInterfacesIsTests(
270 alreadyGenerated); 265 element, generateIsTest, generateSubstitution, alreadyGenerated);
271 } 266 }
272 267
273 // We need to also emit "is checks" for the superclass and its supertypes. 268 // We need to also emit "is checks" for the superclass and its supertypes.
274 ClassElement superclass = cls.superclass; 269 ClassElement superclass = cls.superclass;
275 if (superclass != null) { 270 if (superclass != null) {
276 tryEmitTest(superclass); 271 tryEmitTest(superclass);
277 _generateInterfacesIsTests(superclass, generateIsTest, 272 _generateInterfacesIsTests(
278 generateSubstitution, alreadyGenerated); 273 superclass, generateIsTest, generateSubstitution, alreadyGenerated);
279 } 274 }
280 } 275 }
281 276
282 List<StubMethod> generateTypeVariableReaderStubs(ClassElement classElement) { 277 List<StubMethod> generateTypeVariableReaderStubs(ClassElement classElement) {
283 List<StubMethod> stubs = <StubMethod>[]; 278 List<StubMethod> stubs = <StubMethod>[];
284 ClassElement superclass = classElement; 279 ClassElement superclass = classElement;
285 while (superclass != null) { 280 while (superclass != null) {
286 for (TypeVariableType parameter in superclass.typeVariables) { 281 for (TypeVariableType parameter in superclass.typeVariables) {
287 if (backend.emitter.readTypeVariables.contains(parameter.element)) { 282 if (backend.emitter.readTypeVariables.contains(parameter.element)) {
288 stubs.add( 283 stubs.add(
289 _generateTypeVariableReader(classElement, parameter.element)); 284 _generateTypeVariableReader(classElement, parameter.element));
290 }
291 } 285 }
292 superclass = superclass.superclass;
293 } 286 }
287 superclass = superclass.superclass;
288 }
294 289
295 return stubs; 290 return stubs;
296 } 291 }
297 292
298 StubMethod _generateTypeVariableReader(ClassElement cls, 293 StubMethod _generateTypeVariableReader(
299 TypeVariableElement element) { 294 ClassElement cls, TypeVariableElement element) {
300 jsAst.Name name = namer.nameForReadTypeVariable(element); 295 jsAst.Name name = namer.nameForReadTypeVariable(element);
301 int index = element.index; 296 int index = element.index;
302 jsAst.Expression computeTypeVariable; 297 jsAst.Expression computeTypeVariable;
303 298
304 Substitution substitution = 299 Substitution substitution =
305 backend.rti.getSubstitution(cls, element.typeDeclaration); 300 backend.rti.getSubstitution(cls, element.typeDeclaration);
306 if (substitution != null) { 301 if (substitution != null) {
307 computeTypeVariable = 302 computeTypeVariable = js(
308 js(r'#.apply(null, this.$builtinTypeInfo)', 303 r'#.apply(null, this.$builtinTypeInfo)',
309 backend.rtiEncoder.getSubstitutionCodeForVariable( 304 backend.rtiEncoder
310 substitution, index)); 305 .getSubstitutionCodeForVariable(substitution, index));
311 } else { 306 } else {
312 // TODO(ahe): These can be generated dynamically. 307 // TODO(ahe): These can be generated dynamically.
313 computeTypeVariable = 308 computeTypeVariable = js(
314 js(r'this.$builtinTypeInfo && this.$builtinTypeInfo[#]', 309 r'this.$builtinTypeInfo && this.$builtinTypeInfo[#]',
315 js.number(index)); 310 js.number(index));
316 } 311 }
317 jsAst.Expression convertRtiToRuntimeType = backend.emitter 312 jsAst.Expression convertRtiToRuntimeType = backend.emitter
318 .staticFunctionAccess(backend.helpers.convertRtiToRuntimeType); 313 .staticFunctionAccess(backend.helpers.convertRtiToRuntimeType);
319 314
320 return new StubMethod(name, 315 return new StubMethod(
321 js('function () { return #(#) }', 316 name,
322 [convertRtiToRuntimeType, computeTypeVariable])); 317 js('function () { return #(#) }',
318 [convertRtiToRuntimeType, computeTypeVariable]));
323 } 319 }
324 } 320 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698