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

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

Issue 2958553002: Sort type tests. (Closed)
Patch Set: Updated cf. comment Created 3 years, 5 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 library dart2js.js_emitter.runtime_type_generator; 5 library dart2js.js_emitter.runtime_type_generator;
6 6
7 import '../closure.dart' 7 import '../closure.dart'
8 show ClosureRepresentationInfo, ClosureFieldElement, ClosureConversionTask; 8 show ClosureRepresentationInfo, ClosureFieldElement, ClosureConversionTask;
9 import '../common.dart'; 9 import '../common.dart';
10 import '../common/names.dart' show Identifiers; 10 import '../common/names.dart' show Identifiers;
11 import '../common_elements.dart' show CommonElements, ElementEnvironment; 11 import '../common_elements.dart' show CommonElements, ElementEnvironment;
12 import '../elements/elements.dart' 12 import '../elements/elements.dart'
13 show ClassElement, MethodElement, MixinApplicationElement; 13 show ClassElement, MethodElement, MixinApplicationElement;
14 import '../elements/entities.dart'; 14 import '../elements/entities.dart';
15 import '../elements/types.dart'; 15 import '../elements/types.dart';
16 import '../js/js.dart' as jsAst; 16 import '../js/js.dart' as jsAst;
17 import '../js/js.dart' show js; 17 import '../js/js.dart' show js;
18 import '../js_backend/js_interop_analysis.dart'; 18 import '../js_backend/js_interop_analysis.dart';
19 import '../js_backend/native_data.dart'; 19 import '../js_backend/native_data.dart';
20 import '../js_backend/namer.dart' show Namer; 20 import '../js_backend/namer.dart' show Namer;
21 import '../js_backend/runtime_types.dart' 21 import '../js_backend/runtime_types.dart'
22 show 22 show
23 RuntimeTypesChecks, 23 RuntimeTypesChecks,
24 RuntimeTypesNeed, 24 RuntimeTypesNeed,
25 RuntimeTypesEncoder, 25 RuntimeTypesEncoder,
26 RuntimeTypesSubstitutions, 26 RuntimeTypesSubstitutions,
27 Substitution, 27 Substitution,
28 TypeCheck, 28 TypeCheck,
29 TypeChecks; 29 TypeChecks;
30 import '../js_emitter/sorter.dart';
30 import '../util/util.dart' show Setlet; 31 import '../util/util.dart' show Setlet;
31 import '../world.dart'; 32 import '../world.dart';
32 33
33 import 'code_emitter_task.dart' show CodeEmitterTask; 34 import 'code_emitter_task.dart' show CodeEmitterTask;
34 import 'type_test_registry.dart' show TypeTestRegistry; 35 import 'type_test_registry.dart' show TypeTestRegistry;
35 36
36 // Function signatures used in the generation of runtime type information. 37 // Function signatures used in the generation of runtime type information.
37 typedef void FunctionTypeSignatureEmitter( 38 typedef void FunctionTypeSignatureEmitter(
38 FunctionEntity method, FunctionType methodType); 39 FunctionEntity method, FunctionType methodType);
39 40
40 typedef void SubstitutionEmitter(ClassEntity element, {bool emitNull}); 41 typedef void SubstitutionEmitter(ClassEntity element, {bool emitNull});
41 42
43 class TypeTest {
44 final jsAst.Name name;
45 final jsAst.Node expression;
46
47 TypeTest(this.name, this.expression);
48 }
49
50 class TypeTests {
51 TypeTest isTest;
52 TypeTest substitution;
53 TypeTest signature;
54 }
55
42 class TypeTestProperties { 56 class TypeTestProperties {
43 /// The index of the function type into the metadata. 57 /// The index of the function type into the metadata.
44 /// 58 ///
45 /// If the class doesn't have a function type this field is `null`. 59 /// If the class doesn't have a function type this field is `null`.
46 /// 60 ///
47 /// If the is tests were generated with `storeFunctionTypeInMetadata` set to 61 /// If the is tests were generated with `storeFunctionTypeInMetadata` set to
48 /// `false`, this field is `null`, and the [properties] contain a property 62 /// `false`, this field is `null`, and the [properties] contain a property
49 /// that encodes the function type. 63 /// that encodes the function type.
50 jsAst.Expression functionTypeIndex; 64 jsAst.Expression functionTypeIndex;
51 65
52 /// The properties that must be installed on the prototype of the 66 /// The properties that must be installed on the prototype of the
53 /// JS constructor of the [ClassEntity] for which the is checks were 67 /// JS constructor of the [ClassEntity] for which the is checks were
54 /// generated. 68 /// generated.
55 final Map<jsAst.Name, jsAst.Node> properties = <jsAst.Name, jsAst.Node>{}; 69 final Map<ClassEntity, TypeTests> _properties = <ClassEntity, TypeTests>{};
70
71 void addIsTest(ClassEntity cls, jsAst.Name name, jsAst.Node expression) {
72 TypeTests typeTests = _properties.putIfAbsent(cls, () => new TypeTests());
73 typeTests.isTest = new TypeTest(name, expression);
74 }
75
76 void addSubstitution(
77 ClassEntity cls, jsAst.Name name, jsAst.Node expression) {
78 TypeTests typeTests = _properties.putIfAbsent(cls, () => new TypeTests());
79 typeTests.substitution = new TypeTest(name, expression);
80 }
81
82 void addSignature(ClassEntity cls, jsAst.Name name, jsAst.Node expression) {
83 TypeTests typeTests = _properties.putIfAbsent(cls, () => new TypeTests());
84 typeTests.signature = new TypeTest(name, expression);
85 }
86
87 void forEachProperty(
88 Sorter sorter, void f(jsAst.Name name, jsAst.Node expression)) {
89 void handleTypeTest(TypeTest typeTest) {
90 if (typeTest == null) return;
91 f(typeTest.name, typeTest.expression);
92 }
93
94 for (ClassEntity cls in sorter.sortClasses(_properties.keys)) {
95 TypeTests typeTests = _properties[cls];
96 handleTypeTest(typeTests.isTest);
97 handleTypeTest(typeTests.substitution);
98 handleTypeTest(typeTests.signature);
99 }
100 }
56 } 101 }
57 102
58 class RuntimeTypeGenerator { 103 class RuntimeTypeGenerator {
59 final ElementEnvironment _elementEnvironment; 104 final ElementEnvironment _elementEnvironment;
60 final CommonElements _commonElements; 105 final CommonElements _commonElements;
61 final DartTypes _types; 106 final DartTypes _types;
62 final ClosedWorld _closedWorld; 107 final ClosedWorld _closedWorld;
63 final ClosureConversionTask _closureDataLookup; 108 final ClosureConversionTask _closureDataLookup;
64 final CodeEmitterTask emitterTask; 109 final CodeEmitterTask emitterTask;
65 final Namer _namer; 110 final Namer _namer;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 failedAt(classElement)); 158 failedAt(classElement));
114 159
115 /// Generates an is-test if the test is not inherited from a superclass 160 /// Generates an is-test if the test is not inherited from a superclass
116 /// This assumes that for every class an is-tests is generated 161 /// This assumes that for every class an is-tests is generated
117 /// dynamically at runtime. We also always generate tests against 162 /// dynamically at runtime. We also always generate tests against
118 /// native classes. 163 /// native classes.
119 /// TODO(herhut): Generate tests for native classes dynamically, as well. 164 /// TODO(herhut): Generate tests for native classes dynamically, as well.
120 void generateIsTest(ClassEntity other) { 165 void generateIsTest(ClassEntity other) {
121 if (_nativeData.isNativeClass(classElement) || 166 if (_nativeData.isNativeClass(classElement) ||
122 !_closedWorld.isSubclassOf(classElement, other)) { 167 !_closedWorld.isSubclassOf(classElement, other)) {
123 result.properties[_namer.operatorIs(other)] = js('1'); 168 result.addIsTest(other, _namer.operatorIs(other), js('1'));
124 } 169 }
125 } 170 }
126 171
127 void generateFunctionTypeSignature( 172 void generateFunctionTypeSignature(
128 FunctionEntity method, FunctionType type) { 173 FunctionEntity method, FunctionType type) {
129 assert(!(method is MethodElement && !method.isImplementation)); 174 assert(!(method is MethodElement && !method.isImplementation));
130 jsAst.Expression thisAccess = new jsAst.This(); 175 jsAst.Expression thisAccess = new jsAst.This();
131 if (!method.isAbstract) { 176 if (!method.isAbstract) {
132 ClosureRepresentationInfo closureData = 177 ClosureRepresentationInfo closureData =
133 _closureDataLookup.getClosureRepresentationInfo(method); 178 _closureDataLookup.getClosureRepresentationInfo(method);
134 if (closureData != null) { 179 if (closureData != null) {
135 ClosureFieldElement thisLocal = closureData.thisFieldEntity; 180 ClosureFieldElement thisLocal = closureData.thisFieldEntity;
136 if (thisLocal != null) { 181 if (thisLocal != null) {
137 jsAst.Name thisName = _namer.instanceFieldPropertyName(thisLocal); 182 jsAst.Name thisName = _namer.instanceFieldPropertyName(thisLocal);
138 thisAccess = js('this.#', thisName); 183 thisAccess = js('this.#', thisName);
139 } 184 }
140 } 185 }
141 } 186 }
142 187
143 if (storeFunctionTypeInMetadata && !type.containsTypeVariables) { 188 if (storeFunctionTypeInMetadata && !type.containsTypeVariables) {
144 result.functionTypeIndex = 189 result.functionTypeIndex =
145 emitterTask.metadataCollector.reifyType(type); 190 emitterTask.metadataCollector.reifyType(type);
146 } else { 191 } else {
147 jsAst.Expression encoding = _rtiEncoder.getSignatureEncoding( 192 jsAst.Expression encoding = _rtiEncoder.getSignatureEncoding(
148 emitterTask.emitter, type, thisAccess); 193 emitterTask.emitter, type, thisAccess);
149 jsAst.Name operatorSignature = _namer.asName(_namer.operatorSignature); 194 jsAst.Name operatorSignature = _namer.asName(_namer.operatorSignature);
150 result.properties[operatorSignature] = encoding; 195 result.addSignature(classElement, operatorSignature, encoding);
151 } 196 }
152 } 197 }
153 198
154 void generateSubstitution(ClassEntity cls, {bool emitNull: false}) { 199 void generateSubstitution(ClassEntity cls, {bool emitNull: false}) {
155 if (!_elementEnvironment.isGenericClass(cls)) return; 200 if (!_elementEnvironment.isGenericClass(cls)) return;
156 jsAst.Expression expression; 201 jsAst.Expression expression;
157 bool needsNativeCheck = 202 bool needsNativeCheck =
158 emitterTask.nativeEmitter.requiresNativeIsCheck(cls); 203 emitterTask.nativeEmitter.requiresNativeIsCheck(cls);
159 Substitution substitution = 204 Substitution substitution =
160 _rtiSubstitutions.getSubstitution(classElement, cls); 205 _rtiSubstitutions.getSubstitution(classElement, cls);
161 if (substitution != null) { 206 if (substitution != null) {
162 expression = 207 expression =
163 _rtiEncoder.getSubstitutionCode(emitterTask.emitter, substitution); 208 _rtiEncoder.getSubstitutionCode(emitterTask.emitter, substitution);
164 } 209 }
165 if (expression == null && (emitNull || needsNativeCheck)) { 210 if (expression == null && (emitNull || needsNativeCheck)) {
166 expression = new jsAst.LiteralNull(); 211 expression = new jsAst.LiteralNull();
167 } 212 }
168 if (expression != null) { 213 if (expression != null) {
169 result.properties[_namer.substitutionName(cls)] = expression; 214 result.addSubstitution(cls, _namer.substitutionName(cls), expression);
170 } 215 }
171 } 216 }
172 217
173 void generateTypeCheck(TypeCheck check) { 218 void generateTypeCheck(TypeCheck check) {
174 ClassEntity checkedClass = check.cls; 219 ClassEntity checkedClass = check.cls;
175 generateIsTest(checkedClass); 220 generateIsTest(checkedClass);
176 Substitution substitution = check.substitution; 221 Substitution substitution = check.substitution;
177 if (substitution != null) { 222 if (substitution != null) {
178 jsAst.Expression body = 223 jsAst.Expression body =
179 _rtiEncoder.getSubstitutionCode(emitterTask.emitter, substitution); 224 _rtiEncoder.getSubstitutionCode(emitterTask.emitter, substitution);
180 result.properties[_namer.substitutionName(checkedClass)] = body; 225 result.addSubstitution(
226 checkedClass, _namer.substitutionName(checkedClass), body);
181 } 227 }
182 } 228 }
183 229
184 _generateIsTestsOn( 230 _generateIsTestsOn(
185 classElement, 231 classElement,
186 generateIsTest, 232 generateIsTest,
187 generateFunctionTypeSignature, 233 generateFunctionTypeSignature,
188 (ClassEntity e, {bool emitNull: false}) => 234 (ClassEntity e, {bool emitNull: false}) =>
189 generateSubstitution(e, emitNull: emitNull), 235 generateSubstitution(e, emitNull: emitNull),
190 generateTypeCheck); 236 generateTypeCheck);
191 237
192 if (classElement == _commonElements.jsJavaScriptFunctionClass) { 238 if (classElement == _commonElements.jsJavaScriptFunctionClass) {
193 var type = _jsInteropAnalysis.buildJsFunctionType(); 239 var type = _jsInteropAnalysis.buildJsFunctionType();
194 if (type != null) { 240 if (type != null) {
195 jsAst.Expression thisAccess = new jsAst.This(); 241 jsAst.Expression thisAccess = new jsAst.This();
196 jsAst.Expression encoding = _rtiEncoder.getSignatureEncoding( 242 jsAst.Expression encoding = _rtiEncoder.getSignatureEncoding(
197 emitterTask.emitter, type, thisAccess); 243 emitterTask.emitter, type, thisAccess);
198 jsAst.Name operatorSignature = _namer.asName(_namer.operatorSignature); 244 jsAst.Name operatorSignature = _namer.asName(_namer.operatorSignature);
199 result.properties[operatorSignature] = encoding; 245 result.addSignature(classElement, operatorSignature, encoding);
200 } 246 }
201 } 247 }
202 return result; 248 return result;
203 } 249 }
204 250
205 /** 251 /**
206 * Generate "is tests" for [cls] itself, and the "is tests" for the 252 * Generate "is tests" for [cls] itself, and the "is tests" for the
207 * classes it implements and type argument substitution functions for these 253 * classes it implements and type argument substitution functions for these
208 * tests. We don't need to add the "is tests" of the super class because 254 * tests. We don't need to add the "is tests" of the super class because
209 * they will be inherited at runtime, but we may need to generate the 255 * they will be inherited at runtime, but we may need to generate the
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 389
344 // We need to also emit "is checks" for the superclass and its supertypes. 390 // We need to also emit "is checks" for the superclass and its supertypes.
345 ClassEntity superclass = _elementEnvironment.getSuperClass(cls); 391 ClassEntity superclass = _elementEnvironment.getSuperClass(cls);
346 if (superclass != null) { 392 if (superclass != null) {
347 tryEmitTest(superclass); 393 tryEmitTest(superclass);
348 _generateInterfacesIsTests( 394 _generateInterfacesIsTests(
349 superclass, generateIsTest, generateSubstitution, alreadyGenerated); 395 superclass, generateIsTest, generateSubstitution, alreadyGenerated);
350 } 396 }
351 } 397 }
352 } 398 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698