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

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

Issue 2643863005: Use entities in interceptor_stub_generator. (Closed)
Patch Set: Created 3 years, 11 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
« no previous file with comments | « pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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.interceptor_stub_generator; 5 library dart2js.js_emitter.interceptor_stub_generator;
6 6
7 import '../compiler.dart' show Compiler; 7 import '../compiler.dart' show Compiler;
8 import '../constants/values.dart'; 8 import '../constants/values.dart';
9 import '../elements/resolution_types.dart' show ResolutionInterfaceType; 9 import '../elements/entities.dart';
10 import '../elements/elements.dart' show ClassElement, Element; 10 import '../elements/types.dart' show InterfaceType;
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' 14 import '../js_backend/js_backend.dart'
15 show 15 show
16 CustomElementsAnalysis, 16 CustomElementsAnalysis,
17 JavaScriptBackend, 17 JavaScriptBackend,
18 JavaScriptConstantCompiler, 18 JavaScriptConstantCompiler,
19 Namer; 19 Namer;
20 import '../universe/selector.dart' show Selector; 20 import '../universe/selector.dart' show Selector;
21 import '../world.dart' show ClosedWorld; 21 import '../world.dart' show ClosedWorld;
22 22
23 import 'code_emitter_task.dart' show Emitter; 23 import 'code_emitter_task.dart' show Emitter;
24 24
25 class InterceptorStubGenerator { 25 class InterceptorStubGenerator {
26 final Compiler compiler; 26 final Compiler compiler;
27 final Namer namer; 27 final Namer namer;
28 final JavaScriptBackend backend; 28 final JavaScriptBackend backend;
29 final ClosedWorld closedWorld; 29 final ClosedWorld closedWorld;
30 30
31 InterceptorStubGenerator( 31 InterceptorStubGenerator(
32 this.compiler, this.namer, this.backend, this.closedWorld); 32 this.compiler, this.namer, this.backend, this.closedWorld);
33 33
34 Emitter get emitter => backend.emitter.emitter; 34 Emitter get emitter => backend.emitter.emitter;
35 35
36 BackendHelpers get helpers => backend.helpers; 36 BackendHelpers get helpers => backend.helpers;
37 37
38 jsAst.Expression generateGetInterceptorMethod(Set<ClassElement> classes) { 38 jsAst.Expression generateGetInterceptorMethod(Set<ClassEntity> classes) {
39 jsAst.Expression interceptorFor(ClassElement cls) { 39 jsAst.Expression interceptorFor(ClassEntity cls) {
40 return backend.emitter.interceptorPrototypeAccess(cls); 40 return backend.emitter.interceptorPrototypeAccess(cls);
41 } 41 }
42 42
43 /** 43 /**
44 * Build a JavaScrit AST node for doing a type check on 44 * Build a JavaScrit AST node for doing a type check on
45 * [cls]. [cls] must be a non-native interceptor class. 45 * [cls]. [cls] must be a non-native interceptor class.
46 */ 46 */
47 jsAst.Statement buildInterceptorCheck(ClassElement cls) { 47 jsAst.Statement buildInterceptorCheck(ClassEntity cls) {
48 jsAst.Expression condition; 48 jsAst.Expression condition;
49 assert(backend.isInterceptorClass(cls)); 49 assert(backend.isInterceptorClass(cls));
50 if (cls == helpers.jsBoolClass) { 50 if (cls == helpers.jsBoolClass) {
51 condition = js('(typeof receiver) == "boolean"'); 51 condition = js('(typeof receiver) == "boolean"');
52 } else if (cls == helpers.jsIntClass || 52 } else if (cls == helpers.jsIntClass ||
53 cls == helpers.jsDoubleClass || 53 cls == helpers.jsDoubleClass ||
54 cls == helpers.jsNumberClass) { 54 cls == helpers.jsNumberClass) {
55 throw 'internal error'; 55 throw 'internal error';
56 } else if (cls == helpers.jsArrayClass || 56 } else if (cls == helpers.jsArrayClass ||
57 cls == helpers.jsMutableArrayClass || 57 cls == helpers.jsMutableArrayClass ||
(...skipping 14 matching lines...) Expand all
72 bool hasBool = false; 72 bool hasBool = false;
73 bool hasDouble = false; 73 bool hasDouble = false;
74 bool hasInt = false; 74 bool hasInt = false;
75 bool hasNull = false; 75 bool hasNull = false;
76 bool hasNumber = false; 76 bool hasNumber = false;
77 bool hasString = false; 77 bool hasString = false;
78 bool hasNative = false; 78 bool hasNative = false;
79 bool anyNativeClasses = 79 bool anyNativeClasses =
80 compiler.enqueuer.codegen.nativeEnqueuer.hasInstantiatedNativeClasses; 80 compiler.enqueuer.codegen.nativeEnqueuer.hasInstantiatedNativeClasses;
81 81
82 for (ClassElement cls in classes) { 82 for (ClassEntity cls in classes) {
83 if (cls == helpers.jsArrayClass || 83 if (cls == helpers.jsArrayClass ||
84 cls == helpers.jsMutableArrayClass || 84 cls == helpers.jsMutableArrayClass ||
85 cls == helpers.jsFixedArrayClass || 85 cls == helpers.jsFixedArrayClass ||
86 cls == helpers.jsExtendableArrayClass) 86 cls == helpers.jsExtendableArrayClass)
87 hasArray = true; 87 hasArray = true;
88 else if (cls == helpers.jsBoolClass) 88 else if (cls == helpers.jsBoolClass)
89 hasBool = true; 89 hasBool = true;
90 else if (cls == helpers.jsDoubleClass) 90 else if (cls == helpers.jsDoubleClass)
91 hasDouble = true; 91 hasDouble = true;
92 else if (cls == helpers.jsIntClass) 92 else if (cls == helpers.jsIntClass)
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 return #(receiver); 179 return #(receiver);
180 }''', 180 }''',
181 [ 181 [
182 interceptorFor(helpers.jsJavaScriptFunctionClass), 182 interceptorFor(helpers.jsJavaScriptFunctionClass),
183 backend.emitter 183 backend.emitter
184 .constructorAccess(compiler.commonElements.objectClass), 184 .constructorAccess(compiler.commonElements.objectClass),
185 backend.emitter 185 backend.emitter
186 .staticFunctionAccess(helpers.getNativeInterceptorMethod) 186 .staticFunctionAccess(helpers.getNativeInterceptorMethod)
187 ])); 187 ]));
188 } else { 188 } else {
189 ClassElement jsUnknown = helpers.jsUnknownJavaScriptObjectClass; 189 ClassEntity jsUnknown = helpers.jsUnknownJavaScriptObjectClass;
190 if (compiler.codegenWorldBuilder.directlyInstantiatedClasses 190 if (compiler.codegenWorldBuilder.directlyInstantiatedClasses
191 .contains(jsUnknown)) { 191 .contains(jsUnknown)) {
192 statements.add(js.statement('if (!(receiver instanceof #)) return #;', [ 192 statements.add(js.statement('if (!(receiver instanceof #)) return #;', [
193 backend.emitter 193 backend.emitter
194 .constructorAccess(compiler.commonElements.objectClass), 194 .constructorAccess(compiler.commonElements.objectClass),
195 interceptorFor(jsUnknown) 195 interceptorFor(jsUnknown)
196 ])); 196 ]));
197 } 197 }
198 198
199 statements.add(js.statement('return receiver')); 199 statements.add(js.statement('return receiver'));
200 } 200 }
201 201
202 return js('''function(receiver) { #; }''', new jsAst.Block(statements)); 202 return js('''function(receiver) { #; }''', new jsAst.Block(statements));
203 } 203 }
204 204
205 // Returns a statement that takes care of performance critical 205 // Returns a statement that takes care of performance critical
206 // common case for a one-shot interceptor, or null if there is no 206 // common case for a one-shot interceptor, or null if there is no
207 // fast path. 207 // fast path.
208 jsAst.Statement _fastPathForOneShotInterceptor( 208 jsAst.Statement _fastPathForOneShotInterceptor(
209 Selector selector, Set<ClassElement> classes) { 209 Selector selector, Set<ClassEntity> classes) {
210 if (selector.isOperator) { 210 if (selector.isOperator) {
211 String name = selector.name; 211 String name = selector.name;
212 if (name == '==') { 212 if (name == '==') {
213 return js.statement('''{ 213 return js.statement('''{
214 if (receiver == null) return a0 == null; 214 if (receiver == null) return a0 == null;
215 if (typeof receiver != "object") 215 if (typeof receiver != "object")
216 return a0 != null && receiver === a0; 216 return a0 != null && receiver === a0;
217 }'''); 217 }''');
218 } 218 }
219 if (!classes.contains(helpers.jsIntClass) && 219 if (!classes.contains(helpers.jsIntClass) &&
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
331 return receiver[a0] = a1; 331 return receiver[a0] = a1;
332 ''', 332 ''',
333 typeCheck); 333 typeCheck);
334 } 334 }
335 } 335 }
336 return null; 336 return null;
337 } 337 }
338 338
339 jsAst.Expression generateOneShotInterceptor(jsAst.Name name) { 339 jsAst.Expression generateOneShotInterceptor(jsAst.Name name) {
340 Selector selector = backend.oneShotInterceptors[name]; 340 Selector selector = backend.oneShotInterceptors[name];
341 Set<ClassElement> classes = backend.getInterceptedClassesOn(selector.name); 341 Set<ClassEntity> classes = backend.getInterceptedClassesOn(selector.name);
342 jsAst.Name getInterceptorName = namer.nameForGetInterceptor(classes); 342 jsAst.Name getInterceptorName = namer.nameForGetInterceptor(classes);
343 343
344 List<String> parameterNames = <String>[]; 344 List<String> parameterNames = <String>[];
345 parameterNames.add('receiver'); 345 parameterNames.add('receiver');
346 346
347 if (selector.isSetter) { 347 if (selector.isSetter) {
348 parameterNames.add('value'); 348 parameterNames.add('value');
349 } else { 349 } else {
350 for (int i = 0; i < selector.argumentCount; i++) { 350 for (int i = 0; i < selector.argumentCount; i++) {
351 parameterNames.add('a$i'); 351 parameterNames.add('a$i');
(...skipping 21 matching lines...) Expand all
373 // TODO(sra): Perhaps inject a constant instead? 373 // TODO(sra): Perhaps inject a constant instead?
374 CustomElementsAnalysis analysis = backend.customElementsAnalysis; 374 CustomElementsAnalysis analysis = backend.customElementsAnalysis;
375 if (!analysis.needsTable) return null; 375 if (!analysis.needsTable) return null;
376 376
377 List<jsAst.Expression> elements = <jsAst.Expression>[]; 377 List<jsAst.Expression> elements = <jsAst.Expression>[];
378 JavaScriptConstantCompiler handler = backend.constants; 378 JavaScriptConstantCompiler handler = backend.constants;
379 List<ConstantValue> constants = 379 List<ConstantValue> constants =
380 handler.getConstantsForEmission(emitter.compareConstants); 380 handler.getConstantsForEmission(emitter.compareConstants);
381 for (ConstantValue constant in constants) { 381 for (ConstantValue constant in constants) {
382 if (constant is TypeConstantValue && 382 if (constant is TypeConstantValue &&
383 constant.representedType is ResolutionInterfaceType) { 383 constant.representedType is InterfaceType) {
384 ResolutionInterfaceType type = constant.representedType; 384 InterfaceType type = constant.representedType;
385 Element element = type.element; 385 ClassEntity classElement = type.element;
386 if (element is ClassElement) { 386 if (!analysis.needsClass(classElement)) continue;
Siggi Cherem (dart-lang) 2017/01/19 16:48:22 Just to double-check, this `if` was practically in
Johnni Winther 2017/01/20 07:57:04 All [InterfaceType]s point to a [ClassEntity], if
387 ClassElement classElement = element;
388 if (!analysis.needsClass(classElement)) continue;
389 387
390 elements.add(emitter.constantReference(constant)); 388 elements.add(emitter.constantReference(constant));
391 elements.add(backend.emitter.interceptorClassAccess(classElement)); 389 elements.add(backend.emitter.interceptorClassAccess(classElement));
392 390
393 // Create JavaScript Object map for by-name lookup of generative 391 // Create JavaScript Object map for by-name lookup of generative
394 // constructors. For example, the class A has three generative 392 // constructors. For example, the class A has three generative
395 // constructors 393 // constructors
396 // 394 //
397 // class A { 395 // class A {
398 // A() {} 396 // A() {}
399 // A.foo() {} 397 // A.foo() {}
400 // A.bar() {} 398 // A.bar() {}
401 // } 399 // }
402 // 400 //
403 // Which are described by the map 401 // Which are described by the map
404 // 402 //
405 // {"": A.A$, "foo": A.A$foo, "bar": A.A$bar} 403 // {"": A.A$, "foo": A.A$foo, "bar": A.A$bar}
406 // 404 //
407 // We expect most of the time the map will be a singleton. 405 // We expect most of the time the map will be a singleton.
408 var properties = []; 406 var properties = [];
409 for (Element member in analysis.constructors(classElement)) { 407 for (FunctionEntity member in analysis.constructors(classElement)) {
410 properties.add(new jsAst.Property(js.string(member.name), 408 properties.add(new jsAst.Property(js.string(member.name),
411 backend.emitter.staticFunctionAccess(member))); 409 backend.emitter.staticFunctionAccess(member)));
412 } 410 }
413 411
414 var map = new jsAst.ObjectInitializer(properties); 412 var map = new jsAst.ObjectInitializer(properties);
415 elements.add(map); 413 elements.add(map);
416 }
417 } 414 }
418 } 415 }
419 416
420 return new jsAst.ArrayInitializer(elements); 417 return new jsAst.ArrayInitializer(elements);
421 } 418 }
422 } 419 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698