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

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

Issue 2721403006: Split NativeData (Closed)
Patch Set: Updated cf. comments. Created 3 years, 9 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 '../compiler.dart' show Compiler;
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/backend_helpers.dart' show BackendHelpers; 13 import '../js_backend/backend_helpers.dart' show BackendHelpers;
14 import '../js_backend/js_backend.dart' show JavaScriptBackend; 14 import '../js_backend/js_backend.dart' show JavaScriptBackend, Namer;
15 import '../js_backend/interceptor_data.dart';
16 import '../js_backend/native_data.dart';
15 import '../universe/world_builder.dart' show CodegenWorldBuilder; 17 import '../universe/world_builder.dart' show CodegenWorldBuilder;
16 18
17 import 'code_emitter_task.dart' show CodeEmitterTask; 19 import 'code_emitter_task.dart' show CodeEmitterTask;
18 import 'model.dart'; 20 import 'model.dart';
19 21
20 class NativeEmitter { 22 class NativeEmitter {
21 final CodeEmitterTask emitterTask; 23 final CodeEmitterTask emitterTask;
22 24
23 // Whether the application contains native classes. 25 // Whether the application contains native classes.
24 bool hasNativeClasses = false; 26 bool hasNativeClasses = false;
(...skipping 12 matching lines...) Expand all
37 NativeEmitter(CodeEmitterTask emitterTask) : this.emitterTask = emitterTask; 39 NativeEmitter(CodeEmitterTask emitterTask) : this.emitterTask = emitterTask;
38 40
39 Compiler get compiler => emitterTask.compiler; 41 Compiler get compiler => emitterTask.compiler;
40 42
41 JavaScriptBackend get backend => compiler.backend; 43 JavaScriptBackend get backend => compiler.backend;
42 44
43 BackendHelpers get helpers => backend.helpers; 45 BackendHelpers get helpers => backend.helpers;
44 46
45 CodegenWorldBuilder get worldBuilder => compiler.codegenWorldBuilder; 47 CodegenWorldBuilder get worldBuilder => compiler.codegenWorldBuilder;
46 48
49 NativeData get nativeData => backend.nativeData;
50
51 InterceptorData get interceptorData => backend.interceptorData;
52
53 Namer get namer => backend.namer;
54
47 /** 55 /**
48 * Prepares native classes for emission. Returns the unneeded classes. 56 * Prepares native classes for emission. Returns the unneeded classes.
49 * 57 *
50 * Removes trivial classes (that can be represented by a super type) and 58 * Removes trivial classes (that can be represented by a super type) and
51 * generates properties that have to be added to classes (native or not). 59 * generates properties that have to be added to classes (native or not).
52 * 60 *
53 * Updates the `nativeLeafTags`, `nativeNonLeafTags` and `nativeExtensions` 61 * Updates the `nativeLeafTags`, `nativeNonLeafTags` and `nativeExtensions`
54 * fields of the given classes. This data must be emitted with the 62 * fields of the given classes. This data must be emitted with the
55 * corresponding classes. 63 * corresponding classes.
56 * 64 *
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 needed = true; 142 needed = true;
135 } else if (interceptorClassesNeededByConstants.contains(classElement)) { 143 } else if (interceptorClassesNeededByConstants.contains(classElement)) {
136 needed = true; 144 needed = true;
137 } else if (classesModifiedByEmitRTISupport.contains(classElement)) { 145 } else if (classesModifiedByEmitRTISupport.contains(classElement)) {
138 // TODO(9556): Remove this test when [emitRuntimeTypeSupport] no longer 146 // TODO(9556): Remove this test when [emitRuntimeTypeSupport] no longer
139 // adds information to a class prototype or constructor. 147 // adds information to a class prototype or constructor.
140 needed = true; 148 needed = true;
141 } else if (extensionPoints.containsKey(cls)) { 149 } else if (extensionPoints.containsKey(cls)) {
142 needed = true; 150 needed = true;
143 } 151 }
144 if (backend.isJsInteropClass(classElement)) { 152 if (nativeData.isJsInteropClass(classElement)) {
145 needed = true; // TODO(jacobr): we don't need all interop classes. 153 needed = true; // TODO(jacobr): we don't need all interop classes.
146 } else if (cls.isNative && 154 } else if (cls.isNative &&
147 backend.nativeData.hasNativeTagsForcedNonLeaf(classElement)) { 155 nativeData.hasNativeTagsForcedNonLeaf(classElement)) {
148 needed = true; 156 needed = true;
149 nonLeafClasses.add(cls); 157 nonLeafClasses.add(cls);
150 } 158 }
151 159
152 if (needed || neededClasses.contains(cls)) { 160 if (needed || neededClasses.contains(cls)) {
153 neededClasses.add(cls); 161 neededClasses.add(cls);
154 neededClasses.add(cls.superclass); 162 neededClasses.add(cls.superclass);
155 nonLeafClasses.add(cls.superclass); 163 nonLeafClasses.add(cls.superclass);
156 } 164 }
157 } 165 }
158 166
159 // Collect all the tags that map to each native class. 167 // Collect all the tags that map to each native class.
160 168
161 Map<Class, Set<String>> leafTags = new Map<Class, Set<String>>(); 169 Map<Class, Set<String>> leafTags = new Map<Class, Set<String>>();
162 Map<Class, Set<String>> nonleafTags = new Map<Class, Set<String>>(); 170 Map<Class, Set<String>> nonleafTags = new Map<Class, Set<String>>();
163 171
164 for (Class cls in classes) { 172 for (Class cls in classes) {
165 if (!cls.isNative) continue; 173 if (!cls.isNative) continue;
166 ClassEntity element = cls.element; 174 ClassEntity element = cls.element;
167 if (backend.isJsInteropClass(element)) continue; 175 if (nativeData.isJsInteropClass(element)) continue;
168 List<String> nativeTags = 176 List<String> nativeTags = nativeData.getNativeTagsOfClass(cls.element);
169 backend.nativeData.getNativeTagsOfClass(cls.element);
170 177
171 if (nonLeafClasses.contains(cls) || extensionPoints.containsKey(cls)) { 178 if (nonLeafClasses.contains(cls) || extensionPoints.containsKey(cls)) {
172 nonleafTags 179 nonleafTags
173 .putIfAbsent(cls, () => new Set<String>()) 180 .putIfAbsent(cls, () => new Set<String>())
174 .addAll(nativeTags); 181 .addAll(nativeTags);
175 } else { 182 } else {
176 Class sufficingInterceptor = cls; 183 Class sufficingInterceptor = cls;
177 while (!neededClasses.contains(sufficingInterceptor)) { 184 while (!neededClasses.contains(sufficingInterceptor)) {
178 sufficingInterceptor = sufficingInterceptor.superclass; 185 sufficingInterceptor = sufficingInterceptor.superclass;
179 } 186 }
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 List<jsAst.Statement> statements = <jsAst.Statement>[]; 313 List<jsAst.Statement> statements = <jsAst.Statement>[];
307 potentiallyConvertDartClosuresToJs(statements, member, stubParameters); 314 potentiallyConvertDartClosuresToJs(statements, member, stubParameters);
308 315
309 String target; 316 String target;
310 jsAst.Expression receiver; 317 jsAst.Expression receiver;
311 List<jsAst.Expression> arguments; 318 List<jsAst.Expression> arguments;
312 319
313 assert(invariant(member, nativeMethods.contains(member))); 320 assert(invariant(member, nativeMethods.contains(member)));
314 // When calling a JS method, we call it with the native name, and only the 321 // When calling a JS method, we call it with the native name, and only the
315 // arguments up until the last one provided. 322 // arguments up until the last one provided.
316 target = backend.nativeData.getFixedBackendName(member); 323 target = nativeData.getFixedBackendName(member);
317 324
318 if (isInterceptedMethod) { 325 if (isInterceptedMethod) {
319 receiver = argumentsBuffer[0]; 326 receiver = argumentsBuffer[0];
320 arguments = argumentsBuffer.sublist( 327 arguments = argumentsBuffer.sublist(
321 1, indexOfLastOptionalArgumentInParameters + 1); 328 1, indexOfLastOptionalArgumentInParameters + 1);
322 } else { 329 } else {
323 // Native methods that are not intercepted must be static. 330 // Native methods that are not intercepted must be static.
324 assert(invariant(member, member.isStatic)); 331 assert(invariant(member, member.isStatic));
325 arguments = argumentsBuffer.sublist( 332 arguments = argumentsBuffer.sublist(
326 0, indexOfLastOptionalArgumentInParameters + 1); 333 0, indexOfLastOptionalArgumentInParameters + 1);
327 if (backend.isJsInteropMethod(member)) { 334 if (nativeData.isJsInteropMethod(member)) {
328 // fixedBackendPath is allowed to have the form foo.bar.baz for 335 // fixedBackendPath is allowed to have the form foo.bar.baz for
329 // interop. This template is uncached to avoid possibly running out of 336 // interop. This template is uncached to avoid possibly running out of
330 // memory when Dart2Js is run in server mode. In reality the risk of 337 // memory when Dart2Js is run in server mode. In reality the risk of
331 // caching these templates causing an issue is very low as each class 338 // caching these templates causing an issue is very low as each class
332 // and library that uses typed JavaScript interop will create only 1 339 // and library that uses typed JavaScript interop will create only 1
333 // unique template. 340 // unique template.
334 receiver = js 341 receiver = js
335 .uncachedExpressionTemplate( 342 .uncachedExpressionTemplate(namer.fixedBackendMethodPath(member))
336 backend.namer.fixedBackendMethodPath(member))
337 .instantiate([]); 343 .instantiate([]);
338 } else { 344 } else {
339 receiver = js('this'); 345 receiver = js('this');
340 } 346 }
341 } 347 }
342 statements 348 statements
343 .add(js.statement('return #.#(#)', [receiver, target, arguments])); 349 .add(js.statement('return #.#(#)', [receiver, target, arguments]));
344 350
345 return statements; 351 return statements;
346 } 352 }
347 353
348 bool isSupertypeOfNativeClass(ClassEntity element) { 354 bool isSupertypeOfNativeClass(ClassEntity element) {
349 if (backend.interceptorData.isMixedIntoInterceptedClass(element)) { 355 if (interceptorData.isMixedIntoInterceptedClass(element)) {
350 return true; 356 return true;
351 } 357 }
352 358
353 return subtypes[element] != null; 359 return subtypes[element] != null;
354 } 360 }
355 361
356 bool requiresNativeIsCheck(ClassEntity element) { 362 bool requiresNativeIsCheck(ClassEntity element) {
357 // TODO(sra): Remove this function. It determines if a native type may 363 // TODO(sra): Remove this function. It determines if a native type may
358 // satisfy a check against [element], in which case an interceptor must be 364 // satisfy a check against [element], in which case an interceptor must be
359 // used. We should also use an interceptor if the check can't be satisfied 365 // used. We should also use an interceptor if the check can't be satisfied
360 // by a native class in case we get a native instance that tries to spoof 366 // by a native class in case we get a native instance that tries to spoof
361 // the type info. i.e the criteria for whether or not to use an interceptor 367 // the type info. i.e the criteria for whether or not to use an interceptor
362 // is whether the receiver can be native, not the type of the test. 368 // is whether the receiver can be native, not the type of the test.
363 ClassEntity cls = element; 369 ClassEntity cls = element;
364 if (backend.nativeData.isNativeOrExtendsNative(cls)) return true; 370 if (nativeData.isNativeOrExtendsNative(cls)) return true;
365 return isSupertypeOfNativeClass(element); 371 return isSupertypeOfNativeClass(element);
366 } 372 }
367 } 373 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698