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

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

Issue 2872613003: Pass data objects directly to NativeEmitter (Closed)
Patch Set: Cleanup Created 3 years, 7 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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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.native_emitter; 5 library dart2js.js_emitter.native_emitter;
6 6
7 import '../common.dart'; 7 import '../common.dart';
8 import '../compiler.dart' show Compiler; 8 import '../common_elements.dart' show CommonElements;
9 import '../elements/types.dart' show DartType, FunctionType; 9 import '../elements/types.dart' show DartType, FunctionType;
10 import '../elements/entities.dart'; 10 import '../elements/entities.dart';
11 import '../js/js.dart' as jsAst; 11 import '../js/js.dart' as jsAst;
12 import '../js/js.dart' show js; 12 import '../js/js.dart' show js;
13 import '../js_backend/js_backend.dart' show JavaScriptBackend, Namer;
14 import '../js_backend/interceptor_data.dart'; 13 import '../js_backend/interceptor_data.dart';
15 import '../js_backend/native_data.dart'; 14 import '../js_backend/native_data.dart';
15 import '../native/enqueue.dart' show NativeCodegenEnqueuer;
16 import '../universe/world_builder.dart' show CodegenWorldBuilder; 16 import '../universe/world_builder.dart' show CodegenWorldBuilder;
17 import '../world.dart' show ClosedWorld;
17 18
18 import 'code_emitter_task.dart' show CodeEmitterTask; 19 import 'code_emitter_task.dart' show CodeEmitterTask;
19 import 'model.dart'; 20 import 'model.dart';
20 21
21 class NativeEmitter { 22 class NativeEmitter {
22 final CodeEmitterTask emitterTask; 23 final CodeEmitterTask _emitterTask;
23 final NativeData nativeData; 24 final ClosedWorld _closedWorld;
24 final InterceptorData interceptorData; 25 final CodegenWorldBuilder _worldBuilder;
26 final NativeCodegenEnqueuer _nativeCodegenEnqueuer;
25 27
26 // Whether the application contains native classes. 28 // Whether the application contains native classes.
27 bool hasNativeClasses = false; 29 bool hasNativeClasses = false;
28 30
29 // Caches the native subtypes of a native class. 31 // Caches the native subtypes of a native class.
30 Map<ClassEntity, List<ClassEntity>> subtypes = 32 Map<ClassEntity, List<ClassEntity>> subtypes =
31 <ClassEntity, List<ClassEntity>>{}; 33 <ClassEntity, List<ClassEntity>>{};
32 34
33 // Caches the direct native subtypes of a native class. 35 // Caches the direct native subtypes of a native class.
34 Map<ClassEntity, List<ClassEntity>> directSubtypes = 36 Map<ClassEntity, List<ClassEntity>> directSubtypes =
35 <ClassEntity, List<ClassEntity>>{}; 37 <ClassEntity, List<ClassEntity>>{};
36 38
37 // Caches the methods that have a native body. 39 // Caches the methods that have a native body.
38 Set<FunctionEntity> nativeMethods = new Set<FunctionEntity>(); 40 Set<FunctionEntity> nativeMethods = new Set<FunctionEntity>();
39 41
40 NativeEmitter(this.emitterTask, this.nativeData, this.interceptorData); 42 NativeEmitter(this._emitterTask, this._closedWorld, this._worldBuilder,
43 this._nativeCodegenEnqueuer);
41 44
42 Compiler get compiler => emitterTask.compiler; 45 CommonElements get _commonElements => _closedWorld.commonElements;
43 46 NativeData get _nativeData => _closedWorld.nativeData;
44 JavaScriptBackend get backend => compiler.backend; 47 InterceptorData get _interceptorData => _closedWorld.interceptorData;
45
46 CodegenWorldBuilder get worldBuilder => compiler.codegenWorldBuilder;
47
48 Namer get namer => backend.namer;
49 48
50 /** 49 /**
51 * Prepares native classes for emission. Returns the unneeded classes. 50 * Prepares native classes for emission. Returns the unneeded classes.
52 * 51 *
53 * Removes trivial classes (that can be represented by a super type) and 52 * Removes trivial classes (that can be represented by a super type) and
54 * generates properties that have to be added to classes (native or not). 53 * generates properties that have to be added to classes (native or not).
55 * 54 *
56 * Updates the `nativeLeafTags`, `nativeNonLeafTags` and `nativeExtensions` 55 * Updates the `nativeLeafTags`, `nativeNonLeafTags` and `nativeExtensions`
57 * fields of the given classes. This data must be emitted with the 56 * fields of the given classes. This data must be emitted with the
58 * corresponding classes. 57 * corresponding classes.
(...skipping 29 matching lines...) Expand all
88 // Compute a pre-order traversal of the subclass forest. We actually want a 87 // Compute a pre-order traversal of the subclass forest. We actually want a
89 // post-order traversal but it is easier to compute the pre-order and use it 88 // post-order traversal but it is easier to compute the pre-order and use it
90 // in reverse. 89 // in reverse.
91 List<Class> preOrder = <Class>[]; 90 List<Class> preOrder = <Class>[];
92 Set<Class> seen = new Set<Class>(); 91 Set<Class> seen = new Set<Class>();
93 92
94 Class objectClass = null; 93 Class objectClass = null;
95 Class jsInterceptorClass = null; 94 Class jsInterceptorClass = null;
96 95
97 void walk(Class cls) { 96 void walk(Class cls) {
98 if (cls.element == compiler.commonElements.objectClass) { 97 if (cls.element == _commonElements.objectClass) {
99 objectClass = cls; 98 objectClass = cls;
100 return; 99 return;
101 } 100 }
102 if (cls.element == compiler.commonElements.jsInterceptorClass) { 101 if (cls.element == _commonElements.jsInterceptorClass) {
103 jsInterceptorClass = cls; 102 jsInterceptorClass = cls;
104 return; 103 return;
105 } 104 }
106 if (seen.contains(cls)) return; 105 if (seen.contains(cls)) return;
107 seen.add(cls); 106 seen.add(cls);
108 walk(cls.superclass); 107 walk(cls.superclass);
109 preOrder.add(cls); 108 preOrder.add(cls);
110 } 109 }
111 110
112 classes.forEach(walk); 111 classes.forEach(walk);
(...skipping 24 matching lines...) Expand all
137 needed = true; 136 needed = true;
138 } else if (interceptorClassesNeededByConstants.contains(classElement)) { 137 } else if (interceptorClassesNeededByConstants.contains(classElement)) {
139 needed = true; 138 needed = true;
140 } else if (classesModifiedByEmitRTISupport.contains(classElement)) { 139 } else if (classesModifiedByEmitRTISupport.contains(classElement)) {
141 // TODO(9556): Remove this test when [emitRuntimeTypeSupport] no longer 140 // TODO(9556): Remove this test when [emitRuntimeTypeSupport] no longer
142 // adds information to a class prototype or constructor. 141 // adds information to a class prototype or constructor.
143 needed = true; 142 needed = true;
144 } else if (extensionPoints.containsKey(cls)) { 143 } else if (extensionPoints.containsKey(cls)) {
145 needed = true; 144 needed = true;
146 } 145 }
147 if (nativeData.isJsInteropClass(classElement)) { 146 if (_nativeData.isJsInteropClass(classElement)) {
148 needed = true; // TODO(jacobr): we don't need all interop classes. 147 needed = true; // TODO(jacobr): we don't need all interop classes.
149 } else if (cls.isNative && 148 } else if (cls.isNative &&
150 nativeData.hasNativeTagsForcedNonLeaf(classElement)) { 149 _nativeData.hasNativeTagsForcedNonLeaf(classElement)) {
151 needed = true; 150 needed = true;
152 nonLeafClasses.add(cls); 151 nonLeafClasses.add(cls);
153 } 152 }
154 153
155 if (needed || neededClasses.contains(cls)) { 154 if (needed || neededClasses.contains(cls)) {
156 neededClasses.add(cls); 155 neededClasses.add(cls);
157 neededClasses.add(cls.superclass); 156 neededClasses.add(cls.superclass);
158 nonLeafClasses.add(cls.superclass); 157 nonLeafClasses.add(cls.superclass);
159 } 158 }
160 } 159 }
161 160
162 // Collect all the tags that map to each native class. 161 // Collect all the tags that map to each native class.
163 162
164 Map<Class, Set<String>> leafTags = new Map<Class, Set<String>>(); 163 Map<Class, Set<String>> leafTags = new Map<Class, Set<String>>();
165 Map<Class, Set<String>> nonleafTags = new Map<Class, Set<String>>(); 164 Map<Class, Set<String>> nonleafTags = new Map<Class, Set<String>>();
166 165
167 for (Class cls in classes) { 166 for (Class cls in classes) {
168 if (!cls.isNative) continue; 167 if (!cls.isNative) continue;
169 ClassEntity element = cls.element; 168 ClassEntity element = cls.element;
170 if (nativeData.isJsInteropClass(element)) continue; 169 if (_nativeData.isJsInteropClass(element)) continue;
171 List<String> nativeTags = nativeData.getNativeTagsOfClass(cls.element); 170 List<String> nativeTags = _nativeData.getNativeTagsOfClass(cls.element);
172 171
173 if (nonLeafClasses.contains(cls) || extensionPoints.containsKey(cls)) { 172 if (nonLeafClasses.contains(cls) || extensionPoints.containsKey(cls)) {
174 nonleafTags 173 nonleafTags
175 .putIfAbsent(cls, () => new Set<String>()) 174 .putIfAbsent(cls, () => new Set<String>())
176 .addAll(nativeTags); 175 .addAll(nativeTags);
177 } else { 176 } else {
178 Class sufficingInterceptor = cls; 177 Class sufficingInterceptor = cls;
179 while (!neededClasses.contains(sufficingInterceptor)) { 178 while (!neededClasses.contains(sufficingInterceptor)) {
180 sufficingInterceptor = sufficingInterceptor.superclass; 179 sufficingInterceptor = sufficingInterceptor.superclass;
181 } 180 }
(...skipping 14 matching lines...) Expand all
196 cls.nativeLeafTags = leafTags[cls].toList(growable: false); 195 cls.nativeLeafTags = leafTags[cls].toList(growable: false);
197 } 196 }
198 if (nonleafTags[cls] != null) { 197 if (nonleafTags[cls] != null) {
199 cls.nativeNonLeafTags = nonleafTags[cls].toList(growable: false); 198 cls.nativeNonLeafTags = nonleafTags[cls].toList(growable: false);
200 } 199 }
201 cls.nativeExtensions = extensionPoints[cls]; 200 cls.nativeExtensions = extensionPoints[cls];
202 } 201 }
203 202
204 // Add properties containing the information needed to construct maps used 203 // Add properties containing the information needed to construct maps used
205 // by getNativeInterceptor and custom elements. 204 // by getNativeInterceptor and custom elements.
206 if (backend.nativeCodegenEnqueuer.hasInstantiatedNativeClasses) { 205 if (_nativeCodegenEnqueuer.hasInstantiatedNativeClasses) {
207 fillNativeInfo(jsInterceptorClass); 206 fillNativeInfo(jsInterceptorClass);
208 for (Class cls in classes) { 207 for (Class cls in classes) {
209 if (!cls.isNative || neededClasses.contains(cls)) { 208 if (!cls.isNative || neededClasses.contains(cls)) {
210 fillNativeInfo(cls); 209 fillNativeInfo(cls);
211 } 210 }
212 } 211 }
213 } 212 }
214 213
215 // TODO(sra): Issue #13731- this is commented out as part of custom 214 // TODO(sra): Issue #13731- this is commented out as part of custom
216 // element constructor work. 215 // element constructor work.
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 258
260 return cls.methods.isEmpty && 259 return cls.methods.isEmpty &&
261 cls.isChecks.isEmpty && 260 cls.isChecks.isEmpty &&
262 cls.callStubs.isEmpty && 261 cls.callStubs.isEmpty &&
263 !cls.superclass.isMixinApplication && 262 !cls.superclass.isMixinApplication &&
264 !cls.fields.any(needsAccessor); 263 !cls.fields.any(needsAccessor);
265 } 264 }
266 265
267 void potentiallyConvertDartClosuresToJs(List<jsAst.Statement> statements, 266 void potentiallyConvertDartClosuresToJs(List<jsAst.Statement> statements,
268 FunctionEntity member, List<jsAst.Parameter> stubParameters) { 267 FunctionEntity member, List<jsAst.Parameter> stubParameters) {
269 FunctionEntity converter = compiler.commonElements.closureConverter; 268 FunctionEntity converter = _commonElements.closureConverter;
270 jsAst.Expression closureConverter = 269 jsAst.Expression closureConverter =
271 emitterTask.staticFunctionAccess(converter); 270 _emitterTask.staticFunctionAccess(converter);
272 worldBuilder.forEachParameter(member, (DartType type, String name) { 271 _worldBuilder.forEachParameter(member, (DartType type, String name) {
273 // If [name] is not in [stubParameters], then the parameter is an optional 272 // If [name] is not in [stubParameters], then the parameter is an optional
274 // parameter that was not provided for this stub. 273 // parameter that was not provided for this stub.
275 for (jsAst.Parameter stubParameter in stubParameters) { 274 for (jsAst.Parameter stubParameter in stubParameters) {
276 if (stubParameter.name == name) { 275 if (stubParameter.name == name) {
277 type = type.unaliased; 276 type = type.unaliased;
278 if (type.isFunctionType) { 277 if (type.isFunctionType) {
279 // The parameter type is a function type either directly or through 278 // The parameter type is a function type either directly or through
280 // typedef(s). 279 // typedef(s).
281 FunctionType functionType = type; 280 FunctionType functionType = type;
282 int arity = functionType.parameterTypes.length; 281 int arity = functionType.parameterTypes.length;
(...skipping 25 matching lines...) Expand all
308 List<jsAst.Statement> statements = <jsAst.Statement>[]; 307 List<jsAst.Statement> statements = <jsAst.Statement>[];
309 potentiallyConvertDartClosuresToJs(statements, member, stubParameters); 308 potentiallyConvertDartClosuresToJs(statements, member, stubParameters);
310 309
311 String target; 310 String target;
312 jsAst.Expression receiver; 311 jsAst.Expression receiver;
313 List<jsAst.Expression> arguments; 312 List<jsAst.Expression> arguments;
314 313
315 assert(invariant(member, nativeMethods.contains(member))); 314 assert(invariant(member, nativeMethods.contains(member)));
316 // When calling a JS method, we call it with the native name, and only the 315 // When calling a JS method, we call it with the native name, and only the
317 // arguments up until the last one provided. 316 // arguments up until the last one provided.
318 target = nativeData.getFixedBackendName(member); 317 target = _nativeData.getFixedBackendName(member);
319 318
320 if (isInterceptedMethod) { 319 if (isInterceptedMethod) {
321 receiver = argumentsBuffer[0]; 320 receiver = argumentsBuffer[0];
322 arguments = argumentsBuffer.sublist( 321 arguments = argumentsBuffer.sublist(
323 1, indexOfLastOptionalArgumentInParameters + 1); 322 1, indexOfLastOptionalArgumentInParameters + 1);
324 } else { 323 } else {
325 // Native methods that are not intercepted must be static. 324 // Native methods that are not intercepted must be static.
326 assert(invariant(member, member.isStatic)); 325 assert(invariant(member, member.isStatic));
327 arguments = argumentsBuffer.sublist( 326 arguments = argumentsBuffer.sublist(
328 0, indexOfLastOptionalArgumentInParameters + 1); 327 0, indexOfLastOptionalArgumentInParameters + 1);
329 if (nativeData.isJsInteropMember(member)) { 328 if (_nativeData.isJsInteropMember(member)) {
330 // fixedBackendPath is allowed to have the form foo.bar.baz for 329 // fixedBackendPath is allowed to have the form foo.bar.baz for
331 // interop. This template is uncached to avoid possibly running out of 330 // interop. This template is uncached to avoid possibly running out of
332 // memory when Dart2Js is run in server mode. In reality the risk of 331 // memory when Dart2Js is run in server mode. In reality the risk of
333 // caching these templates causing an issue is very low as each class 332 // caching these templates causing an issue is very low as each class
334 // and library that uses typed JavaScript interop will create only 1 333 // and library that uses typed JavaScript interop will create only 1
335 // unique template. 334 // unique template.
336 receiver = js 335 receiver = js
337 .uncachedExpressionTemplate( 336 .uncachedExpressionTemplate(
338 nativeData.getFixedBackendMethodPath(member)) 337 _nativeData.getFixedBackendMethodPath(member))
339 .instantiate([]); 338 .instantiate([]);
340 } else { 339 } else {
341 receiver = js('this'); 340 receiver = js('this');
342 } 341 }
343 } 342 }
344 statements 343 statements
345 .add(js.statement('return #.#(#)', [receiver, target, arguments])); 344 .add(js.statement('return #.#(#)', [receiver, target, arguments]));
346 345
347 return statements; 346 return statements;
348 } 347 }
349 348
350 bool isSupertypeOfNativeClass(ClassEntity element) { 349 bool isSupertypeOfNativeClass(ClassEntity element) {
351 if (interceptorData.isMixedIntoInterceptedClass(element)) { 350 if (_interceptorData.isMixedIntoInterceptedClass(element)) {
352 return true; 351 return true;
353 } 352 }
354 353
355 return subtypes[element] != null; 354 return subtypes[element] != null;
356 } 355 }
357 356
358 bool requiresNativeIsCheck(ClassEntity element) { 357 bool requiresNativeIsCheck(ClassEntity element) {
359 // TODO(sra): Remove this function. It determines if a native type may 358 // TODO(sra): Remove this function. It determines if a native type may
360 // satisfy a check against [element], in which case an interceptor must be 359 // satisfy a check against [element], in which case an interceptor must be
361 // used. We should also use an interceptor if the check can't be satisfied 360 // used. We should also use an interceptor if the check can't be satisfied
362 // by a native class in case we get a native instance that tries to spoof 361 // by a native class in case we get a native instance that tries to spoof
363 // the type info. i.e the criteria for whether or not to use an interceptor 362 // the type info. i.e the criteria for whether or not to use an interceptor
364 // is whether the receiver can be native, not the type of the test. 363 // is whether the receiver can be native, not the type of the test.
365 ClassEntity cls = element; 364 ClassEntity cls = element;
366 if (nativeData.isNativeOrExtendsNative(cls)) return true; 365 if (_nativeData.isNativeOrExtendsNative(cls)) return true;
367 return isSupertypeOfNativeClass(element); 366 return isSupertypeOfNativeClass(element);
368 } 367 }
369 } 368 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698