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

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

Issue 2818463002: Remove Compiler and JavaScriptBackend from interceptor_stub_generator. (Closed)
Patch Set: Created 3 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
« no previous file with comments | « pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.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.program_builder; 5 library dart2js.js_emitter.program_builder;
6 6
7 import '../../closure.dart' show ClosureFieldElement; 7 import '../../closure.dart' show ClosureFieldElement;
8 import '../../common.dart'; 8 import '../../common.dart';
9 import '../../common/names.dart' show Names, Selectors; 9 import '../../common/names.dart' show Names, Selectors;
10 import '../../compiler.dart' show Compiler; 10 import '../../compiler.dart' show Compiler;
(...skipping 24 matching lines...) Expand all
35 import '../../js/js.dart' as js; 35 import '../../js/js.dart' as js;
36 import '../../js_backend/backend.dart' 36 import '../../js_backend/backend.dart'
37 show 37 show
38 JavaScriptBackend, 38 JavaScriptBackend,
39 RuntimeTypesEncoder, 39 RuntimeTypesEncoder,
40 RuntimeTypesNeed, 40 RuntimeTypesNeed,
41 SuperMemberData; 41 SuperMemberData;
42 import '../../js_backend/backend_usage.dart'; 42 import '../../js_backend/backend_usage.dart';
43 import '../../js_backend/constant_handler_javascript.dart' 43 import '../../js_backend/constant_handler_javascript.dart'
44 show JavaScriptConstantCompiler; 44 show JavaScriptConstantCompiler;
45 import '../../js_backend/custom_elements_analysis.dart';
45 import '../../js_backend/namer.dart' show Namer, StringBackedName; 46 import '../../js_backend/namer.dart' show Namer, StringBackedName;
46 import '../../js_backend/native_data.dart'; 47 import '../../js_backend/native_data.dart';
47 import '../../js_backend/interceptor_data.dart'; 48 import '../../js_backend/interceptor_data.dart';
48 import '../../js_backend/mirrors_data.dart'; 49 import '../../js_backend/mirrors_data.dart';
49 import '../../native/enqueue.dart' show NativeCodegenEnqueuer; 50 import '../../native/enqueue.dart' show NativeCodegenEnqueuer;
50 import '../../options.dart'; 51 import '../../options.dart';
51 import '../../universe/selector.dart' show Selector; 52 import '../../universe/selector.dart' show Selector;
52 import '../../universe/world_builder.dart' 53 import '../../universe/world_builder.dart'
53 show CodegenWorldBuilder, SelectorConstraints; 54 show CodegenWorldBuilder, SelectorConstraints;
54 import '../../world.dart' show ClosedWorld; 55 import '../../world.dart' show ClosedWorld;
(...skipping 11 matching lines...) Expand all
66 import '../model.dart'; 67 import '../model.dart';
67 68
68 part 'collector.dart'; 69 part 'collector.dart';
69 part 'field_visitor.dart'; 70 part 'field_visitor.dart';
70 part 'registry.dart'; 71 part 'registry.dart';
71 72
72 /// Builds a self-contained representation of the program that can then be 73 /// Builds a self-contained representation of the program that can then be
73 /// emitted more easily by the individual emitters. 74 /// emitted more easily by the individual emitters.
74 class ProgramBuilder { 75 class ProgramBuilder {
75 final Compiler _compiler; 76 final Compiler _compiler;
76 final Namer namer; 77 final Namer _namer;
77 final CodeEmitterTask _task; 78 final CodeEmitterTask _task;
78 final ClosedWorld closedWorld; 79 final ClosedWorld _closedWorld;
79 80
80 /// Contains the collected information the program builder used to build 81 /// Contains the collected information the program builder used to build
81 /// the model. 82 /// the model.
82 // The collector will be filled on the first call to `buildProgram`. 83 // The collector will be filled on the first call to `buildProgram`.
83 // It is stored and publicly exposed for backwards compatibility. New code 84 // It is stored and publicly exposed for backwards compatibility. New code
84 // (and in particular new emitters) should not use it. 85 // (and in particular new emitters) should not use it.
85 final Collector collector; 86 final Collector collector;
86 87
87 final Registry _registry; 88 final Registry _registry;
88 89
89 /// True if the program should store function types in the metadata. 90 /// True if the program should store function types in the metadata.
90 bool _storeFunctionTypesInMetadata = false; 91 bool _storeFunctionTypesInMetadata = false;
91 92
92 ProgramBuilder(Compiler compiler, Namer namer, this._task, Emitter emitter, 93 ProgramBuilder(Compiler compiler, Namer _namer, this._task, Emitter emitter,
93 ClosedWorld closedWorld, Set<ClassElement> rtiNeededClasses) 94 ClosedWorld closedWorld, Set<ClassElement> rtiNeededClasses)
94 : this._compiler = compiler, 95 : this._compiler = compiler,
95 this.namer = namer, 96 this._namer = _namer,
96 this.closedWorld = closedWorld, 97 this._closedWorld = closedWorld,
97 this.collector = new Collector( 98 this.collector = new Collector(
98 compiler, namer, closedWorld, rtiNeededClasses, emitter), 99 compiler, _namer, closedWorld, rtiNeededClasses, emitter),
99 this._registry = new Registry(compiler); 100 this._registry = new Registry(compiler);
100 101
101 JavaScriptBackend get _backend => _compiler.backend; 102 JavaScriptBackend get _backend => _compiler.backend;
102 CodegenWorldBuilder get _worldBuilder => _compiler.codegenWorldBuilder; 103 CodegenWorldBuilder get _worldBuilder => _compiler.codegenWorldBuilder;
103 DeferredLoadTask get _deferredLoadTask => _compiler.deferredLoadTask; 104 DeferredLoadTask get _deferredLoadTask => _compiler.deferredLoadTask;
104 Types get _types => _compiler.types; 105 Types get _types => _compiler.types;
105 CommonElements get _commonElements => _compiler.commonElements; 106 CommonElements get _commonElements => _compiler.commonElements;
106 CompilerOptions get _options => _compiler.options; 107 CompilerOptions get _options => _compiler.options;
107 NativeCodegenEnqueuer get _nativeCodegenEnqueuer => 108 NativeCodegenEnqueuer get _nativeCodegenEnqueuer =>
108 _backend.nativeCodegenEnqueuer; 109 _backend.nativeCodegenEnqueuer;
109 Namer get _namer => _backend.namer;
110 BackendUsage get _backendUsage => _backend.backendUsage; 110 BackendUsage get _backendUsage => _backend.backendUsage;
111 CodeEmitterTask get _emitter => _backend.emitter; 111 CodeEmitterTask get _emitter => _backend.emitter;
112 JavaScriptConstantCompiler get _constantHandler => _backend.constants; 112 JavaScriptConstantCompiler get _constantHandler => _backend.constants;
113 NativeData get _nativeData => _backend.nativeData; 113 NativeData get _nativeData => _backend.nativeData;
114 RuntimeTypesNeed get _rtiNeed => _backend.rtiNeed; 114 RuntimeTypesNeed get _rtiNeed => _backend.rtiNeed;
115 MirrorsData get _mirrorsData => _backend.mirrorsData; 115 MirrorsData get _mirrorsData => _backend.mirrorsData;
116 InterceptorData get _interceptorData => _backend.interceptorData; 116 InterceptorData get _interceptorData => _backend.interceptorData;
117 SuperMemberData get _superMemberData => _backend.superMemberData; 117 SuperMemberData get _superMemberData => _backend.superMemberData;
118 RuntimeTypesEncoder get _rtiEncoder => _backend.rtiEncoder; 118 RuntimeTypesEncoder get _rtiEncoder => _backend.rtiEncoder;
119 OneShotInterceptorData get _oneShotInterceptorData => 119 OneShotInterceptorData get _oneShotInterceptorData =>
120 _backend.oneShotInterceptorData; 120 _backend.oneShotInterceptorData;
121 CustomElementsCodegenAnalysis get _customElementsCodegenAnalysis =>
122 _backend.customElementsCodegenAnalysis;
121 123
122 /// Mapping from [ClassElement] to constructed [Class]. We need this to 124 /// Mapping from [ClassElement] to constructed [Class]. We need this to
123 /// update the superclass in the [Class]. 125 /// update the superclass in the [Class].
124 final Map<ClassElement, Class> _classes = <ClassElement, Class>{}; 126 final Map<ClassElement, Class> _classes = <ClassElement, Class>{};
125 127
126 /// Mapping from [OutputUnit] to constructed [Fragment]. We need this to 128 /// Mapping from [OutputUnit] to constructed [Fragment]. We need this to
127 /// generate the deferredLoadingMap (to know which hunks to load). 129 /// generate the deferredLoadingMap (to know which hunks to load).
128 final Map<OutputUnit, Fragment> _outputs = <OutputUnit, Fragment>{}; 130 final Map<OutputUnit, Fragment> _outputs = <OutputUnit, Fragment>{};
129 131
130 /// Mapping from [ConstantValue] to constructed [Constant]. We need this to 132 /// Mapping from [ConstantValue] to constructed [Constant]. We need this to
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 _deferredLoadTask.hunksToLoad 235 _deferredLoadTask.hunksToLoad
234 .forEach((String loadId, List<OutputUnit> outputUnits) { 236 .forEach((String loadId, List<OutputUnit> outputUnits) {
235 loadMap[loadId] = outputUnits 237 loadMap[loadId] = outputUnits
236 .map((OutputUnit unit) => _outputs[unit]) 238 .map((OutputUnit unit) => _outputs[unit])
237 .toList(growable: false); 239 .toList(growable: false);
238 }); 240 });
239 return loadMap; 241 return loadMap;
240 } 242 }
241 243
242 js.Expression _buildTypeToInterceptorMap() { 244 js.Expression _buildTypeToInterceptorMap() {
243 InterceptorStubGenerator stubGenerator = 245 InterceptorStubGenerator stubGenerator = new InterceptorStubGenerator(
244 new InterceptorStubGenerator(_compiler, namer, _backend, closedWorld); 246 _options,
247 _commonElements,
248 _emitter,
249 _nativeCodegenEnqueuer,
250 _constantHandler,
251 _namer,
252 _nativeData,
253 _interceptorData,
254 _oneShotInterceptorData,
255 _customElementsCodegenAnalysis,
256 _worldBuilder,
257 _closedWorld);
245 return stubGenerator.generateTypeToInterceptorMap(); 258 return stubGenerator.generateTypeToInterceptorMap();
246 } 259 }
247 260
248 MainFragment _buildMainFragment(LibrariesMap librariesMap) { 261 MainFragment _buildMainFragment(LibrariesMap librariesMap) {
249 // Construct the main output from the libraries and the registered holders. 262 // Construct the main output from the libraries and the registered holders.
250 MainFragment result = new MainFragment( 263 MainFragment result = new MainFragment(
251 librariesMap.outputUnit, 264 librariesMap.outputUnit,
252 "", // The empty string is the name for the main output file. 265 "", // The empty string is the name for the main output file.
253 _buildInvokeMain(), 266 _buildInvokeMain(),
254 _buildLibraries(librariesMap), 267 _buildLibraries(librariesMap),
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 if (staticNonFinalFields == null) return const <StaticField>[]; 308 if (staticNonFinalFields == null) return const <StaticField>[];
296 309
297 return staticNonFinalFields.map(_buildStaticField).toList(growable: false); 310 return staticNonFinalFields.map(_buildStaticField).toList(growable: false);
298 } 311 }
299 312
300 StaticField _buildStaticField(FieldElement element) { 313 StaticField _buildStaticField(FieldElement element) {
301 ConstantValue initialValue = 314 ConstantValue initialValue =
302 _constantHandler.getConstantValue(element.constant); 315 _constantHandler.getConstantValue(element.constant);
303 // TODO(zarah): The holder should not be registered during building of 316 // TODO(zarah): The holder should not be registered during building of
304 // a static field. 317 // a static field.
305 _registry.registerHolder(namer.globalObjectForConstant(initialValue), 318 _registry.registerHolder(_namer.globalObjectForConstant(initialValue),
306 isConstantsHolder: true); 319 isConstantsHolder: true);
307 js.Expression code = _task.emitter.constantReference(initialValue); 320 js.Expression code = _task.emitter.constantReference(initialValue);
308 js.Name name = namer.globalPropertyName(element); 321 js.Name name = _namer.globalPropertyName(element);
309 bool isFinal = false; 322 bool isFinal = false;
310 bool isLazy = false; 323 bool isLazy = false;
311 324
312 // TODO(floitsch): we shouldn't update the registry in the middle of 325 // TODO(floitsch): we shouldn't update the registry in the middle of
313 // building a static field. (Note that the static-state holder was 326 // building a static field. (Note that the static-state holder was
314 // already registered earlier, and that we just call the register to get 327 // already registered earlier, and that we just call the register to get
315 // the holder-instance. 328 // the holder-instance.
316 return new StaticField( 329 return new StaticField(
317 element, name, _registerStaticStateHolder(), code, isFinal, isLazy); 330 element, name, _registerStaticStateHolder(), code, isFinal, isLazy);
318 } 331 }
(...skipping 12 matching lines...) Expand all
331 .toList(growable: false); 344 .toList(growable: false);
332 } 345 }
333 346
334 StaticField _buildLazyField(FieldElement element) { 347 StaticField _buildLazyField(FieldElement element) {
335 js.Expression code = _backend.generatedCode[element]; 348 js.Expression code = _backend.generatedCode[element];
336 // The code is null if we ended up not needing the lazily 349 // The code is null if we ended up not needing the lazily
337 // initialized field after all because of constant folding 350 // initialized field after all because of constant folding
338 // before code generation. 351 // before code generation.
339 if (code == null) return null; 352 if (code == null) return null;
340 353
341 js.Name name = namer.globalPropertyName(element); 354 js.Name name = _namer.globalPropertyName(element);
342 bool isFinal = element.isFinal; 355 bool isFinal = element.isFinal;
343 bool isLazy = true; 356 bool isLazy = true;
344 // TODO(floitsch): we shouldn't update the registry in the middle of 357 // TODO(floitsch): we shouldn't update the registry in the middle of
345 // building a static field. (Note that the static-state holder was 358 // building a static field. (Note that the static-state holder was
346 // already registered earlier, and that we just call the register to get 359 // already registered earlier, and that we just call the register to get
347 // the holder-instance. 360 // the holder-instance.
348 return new StaticField( 361 return new StaticField(
349 element, name, _registerStaticStateHolder(), code, isFinal, isLazy); 362 element, name, _registerStaticStateHolder(), code, isFinal, isLazy);
350 } 363 }
351 364
352 List<Library> _buildLibraries(LibrariesMap librariesMap) { 365 List<Library> _buildLibraries(LibrariesMap librariesMap) {
353 List<Library> libraries = new List<Library>(librariesMap.length); 366 List<Library> libraries = new List<Library>(librariesMap.length);
354 int count = 0; 367 int count = 0;
355 librariesMap.forEach((LibraryElement library, List<Element> elements) { 368 librariesMap.forEach((LibraryElement library, List<Element> elements) {
356 libraries[count++] = _buildLibrary(library, elements); 369 libraries[count++] = _buildLibrary(library, elements);
357 }); 370 });
358 return libraries; 371 return libraries;
359 } 372 }
360 373
361 void _addJsInteropStubs(LibrariesMap librariesMap) { 374 void _addJsInteropStubs(LibrariesMap librariesMap) {
362 if (_classes.containsKey(_commonElements.objectClass)) { 375 if (_classes.containsKey(_commonElements.objectClass)) {
363 var toStringInvocation = namer.invocationName(Selectors.toString_); 376 var toStringInvocation = _namer.invocationName(Selectors.toString_);
364 // TODO(jacobr): register toString as used so that it is always accessible 377 // TODO(jacobr): register toString as used so that it is always accessible
365 // from JavaScript. 378 // from JavaScript.
366 _classes[_commonElements.objectClass].callStubs.add(_buildStubMethod( 379 _classes[_commonElements.objectClass].callStubs.add(_buildStubMethod(
367 new StringBackedName("toString"), 380 new StringBackedName("toString"),
368 js.js('function() { return this.#(this) }', toStringInvocation))); 381 js.js('function() { return this.#(this) }', toStringInvocation)));
369 } 382 }
370 383
371 // We add all members from classes marked with isJsInterop to the base 384 // We add all members from classes marked with isJsInterop to the base
372 // Interceptor class with implementations that directly call the 385 // Interceptor class with implementations that directly call the
373 // corresponding JavaScript member. We do not attempt to bind this when 386 // corresponding JavaScript member. We do not attempt to bind this when
374 // tearing off JavaScript methods as we cannot distinguish between calling 387 // tearing off JavaScript methods as we cannot distinguish between calling
375 // a regular getter that returns a JavaScript function and tearing off 388 // a regular getter that returns a JavaScript function and tearing off
376 // a method in the case where there exist multiple JavaScript classes 389 // a method in the case where there exist multiple JavaScript classes
377 // that conflict on whether the member is a getter or a method. 390 // that conflict on whether the member is a getter or a method.
378 var interceptorClass = _classes[_commonElements.jsJavaScriptObjectClass]; 391 var interceptorClass = _classes[_commonElements.jsJavaScriptObjectClass];
379 var stubNames = new Set<String>(); 392 var stubNames = new Set<String>();
380 librariesMap.forEach((LibraryElement library, List<Element> elements) { 393 librariesMap.forEach((LibraryElement library, List<Element> elements) {
381 for (Element e in elements) { 394 for (Element e in elements) {
382 if (e is ClassElement && _nativeData.isJsInteropClass(e)) { 395 if (e is ClassElement && _nativeData.isJsInteropClass(e)) {
383 e.declaration.forEachMember((_, Element member) { 396 e.declaration.forEachMember((_, Element member) {
384 var jsName = _nativeData.computeUnescapedJSInteropName(member.name); 397 var jsName = _nativeData.computeUnescapedJSInteropName(member.name);
385 if (!member.isInstanceMember) return; 398 if (!member.isInstanceMember) return;
386 if (member.isGetter || member.isField || member.isFunction) { 399 if (member.isGetter || member.isField || member.isFunction) {
387 var selectors = 400 var selectors =
388 _worldBuilder.getterInvocationsByName(member.name); 401 _worldBuilder.getterInvocationsByName(member.name);
389 if (selectors != null && !selectors.isEmpty) { 402 if (selectors != null && !selectors.isEmpty) {
390 for (var selector in selectors.keys) { 403 for (var selector in selectors.keys) {
391 var stubName = namer.invocationName(selector); 404 var stubName = _namer.invocationName(selector);
392 if (stubNames.add(stubName.key)) { 405 if (stubNames.add(stubName.key)) {
393 interceptorClass.callStubs.add(_buildStubMethod(stubName, 406 interceptorClass.callStubs.add(_buildStubMethod(stubName,
394 js.js('function(obj) { return obj.# }', [jsName]), 407 js.js('function(obj) { return obj.# }', [jsName]),
395 element: member)); 408 element: member));
396 } 409 }
397 } 410 }
398 } 411 }
399 } 412 }
400 413
401 if (member.isSetter || (member.isField && !member.isConst)) { 414 if (member.isSetter || (member.isField && !member.isConst)) {
402 var selectors = 415 var selectors =
403 _worldBuilder.setterInvocationsByName(member.name); 416 _worldBuilder.setterInvocationsByName(member.name);
404 if (selectors != null && !selectors.isEmpty) { 417 if (selectors != null && !selectors.isEmpty) {
405 var stubName = namer.setterForElement(member); 418 var stubName = _namer.setterForElement(member);
406 if (stubNames.add(stubName.key)) { 419 if (stubNames.add(stubName.key)) {
407 interceptorClass.callStubs.add(_buildStubMethod(stubName, 420 interceptorClass.callStubs.add(_buildStubMethod(stubName,
408 js.js('function(obj, v) { return obj.# = v }', [jsName]), 421 js.js('function(obj, v) { return obj.# = v }', [jsName]),
409 element: member)); 422 element: member));
410 } 423 }
411 } 424 }
412 } 425 }
413 426
414 // Generating stubs for direct calls and stubs for call-through 427 // Generating stubs for direct calls and stubs for call-through
415 // of getters that happen to be functions. 428 // of getters that happen to be functions.
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
460 // may want to map named arguments to an object literal containing 473 // may want to map named arguments to an object literal containing
461 // all named arguments. 474 // all named arguments.
462 if (selectors != null && !selectors.isEmpty) { 475 if (selectors != null && !selectors.isEmpty) {
463 for (var selector in selectors.keys) { 476 for (var selector in selectors.keys) {
464 // Check whether the arity matches this member. 477 // Check whether the arity matches this member.
465 var argumentCount = selector.argumentCount; 478 var argumentCount = selector.argumentCount;
466 // JS interop does not support named arguments. 479 // JS interop does not support named arguments.
467 if (selector.namedArgumentCount > 0) continue; 480 if (selector.namedArgumentCount > 0) continue;
468 if (argumentCount < minArgs) continue; 481 if (argumentCount < minArgs) continue;
469 if (argumentCount > maxArgs) continue; 482 if (argumentCount > maxArgs) continue;
470 var stubName = namer.invocationName(selector); 483 var stubName = _namer.invocationName(selector);
471 if (!stubNames.add(stubName.key)) continue; 484 if (!stubNames.add(stubName.key)) continue;
472 var parameters = 485 var parameters =
473 new List<String>.generate(argumentCount, (i) => 'p$i'); 486 new List<String>.generate(argumentCount, (i) => 'p$i');
474 487
475 // We intentionally generate the same stub method for direct 488 // We intentionally generate the same stub method for direct
476 // calls and call-throughs of getters so that calling a 489 // calls and call-throughs of getters so that calling a
477 // getter that returns a function behaves the same as calling 490 // getter that returns a function behaves the same as calling
478 // a method. This is helpful as many typed JavaScript APIs 491 // a method. This is helpful as many typed JavaScript APIs
479 // specify member functions with getters that return 492 // specify member functions with getters that return
480 // functions. The behavior of this solution matches JavaScript 493 // functions. The behavior of this solution matches JavaScript
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
530 if (_nativeData.isJsInteropClass(element)) { 543 if (_nativeData.isJsInteropClass(element)) {
531 // TODO(jacobr): check whether the class has any active static fields 544 // TODO(jacobr): check whether the class has any active static fields
532 // if it does not we can suppress it completely. 545 // if it does not we can suppress it completely.
533 onlyForRti = true; 546 onlyForRti = true;
534 } 547 }
535 548
536 List<Method> methods = []; 549 List<Method> methods = [];
537 List<StubMethod> callStubs = <StubMethod>[]; 550 List<StubMethod> callStubs = <StubMethod>[];
538 551
539 ClassStubGenerator classStubGenerator = new ClassStubGenerator( 552 ClassStubGenerator classStubGenerator = new ClassStubGenerator(
540 namer, _backend, _worldBuilder, closedWorld, 553 _namer, _backend, _worldBuilder, _closedWorld,
541 enableMinification: _options.enableMinification); 554 enableMinification: _options.enableMinification);
542 RuntimeTypeGenerator runtimeTypeGenerator = 555 RuntimeTypeGenerator runtimeTypeGenerator =
543 new RuntimeTypeGenerator(_compiler, _task, namer); 556 new RuntimeTypeGenerator(_compiler, _task, _namer);
544 557
545 void visitMember(ClassElement enclosing, MemberElement member) { 558 void visitMember(ClassElement enclosing, MemberElement member) {
546 assert(invariant(element, member.isDeclaration)); 559 assert(invariant(element, member.isDeclaration));
547 assert(invariant(element, element == enclosing)); 560 assert(invariant(element, element == enclosing));
548 561
549 if (Elements.isNonAbstractInstanceMember(member)) { 562 if (Elements.isNonAbstractInstanceMember(member)) {
550 // TODO(herhut): Remove once _buildMethod can no longer return null. 563 // TODO(herhut): Remove once _buildMethod can no longer return null.
551 Method method = _buildMethod(member); 564 Method method = _buildMethod(member);
552 if (method != null) methods.add(method); 565 if (method != null) methods.add(method);
553 } 566 }
(...skipping 23 matching lines...) Expand all
577 _symbolsMap[name] = selectorName; 590 _symbolsMap[name] = selectorName;
578 } 591 }
579 noSuchMethodStubs.add( 592 noSuchMethodStubs.add(
580 classStubGenerator.generateStubForNoSuchMethod(name, selector)); 593 classStubGenerator.generateStubForNoSuchMethod(name, selector));
581 }); 594 });
582 } 595 }
583 596
584 if (element == _commonElements.closureClass) { 597 if (element == _commonElements.closureClass) {
585 // We add a special getter here to allow for tearing off a closure from 598 // We add a special getter here to allow for tearing off a closure from
586 // itself. 599 // itself.
587 js.Name name = namer.getterForMember(Names.call); 600 js.Name name = _namer.getterForMember(Names.call);
588 js.Fun function = js.js('function() { return this; }'); 601 js.Fun function = js.js('function() { return this; }');
589 callStubs.add(_buildStubMethod(name, function)); 602 callStubs.add(_buildStubMethod(name, function));
590 } 603 }
591 604
592 ClassElement implementation = element.implementation; 605 ClassElement implementation = element.implementation;
593 606
594 // MixinApplications run through the members of their mixin. Here, we are 607 // MixinApplications run through the members of their mixin. Here, we are
595 // only interested in direct members. 608 // only interested in direct members.
596 if (!onlyForRti && !element.isMixinApplication) { 609 if (!onlyForRti && !element.isMixinApplication) {
597 implementation.forEachMember(visitMember, includeBackendMembers: true); 610 implementation.forEachMember(visitMember, includeBackendMembers: true);
(...skipping 19 matching lines...) Expand all
617 .isChecks 630 .isChecks
618 .add(_buildStubMethod(name, code)); 631 .add(_buildStubMethod(name, code));
619 }); 632 });
620 } else { 633 } else {
621 for (Field field in instanceFields) { 634 for (Field field in instanceFields) {
622 if (field.needsCheckedSetter) { 635 if (field.needsCheckedSetter) {
623 assert(!field.needsUncheckedSetter); 636 assert(!field.needsUncheckedSetter);
624 FieldElement element = field.element; 637 FieldElement element = field.element;
625 js.Expression code = _backend.generatedCode[element]; 638 js.Expression code = _backend.generatedCode[element];
626 assert(code != null); 639 assert(code != null);
627 js.Name name = namer.deriveSetterName(field.accessorName); 640 js.Name name = _namer.deriveSetterName(field.accessorName);
628 checkedSetters.add(_buildStubMethod(name, code, element: element)); 641 checkedSetters.add(_buildStubMethod(name, code, element: element));
629 } 642 }
630 } 643 }
631 644
632 typeTests.properties.forEach((js.Name name, js.Node code) { 645 typeTests.properties.forEach((js.Name name, js.Node code) {
633 isChecks.add(_buildStubMethod(name, code)); 646 isChecks.add(_buildStubMethod(name, code));
634 }); 647 });
635 } 648 }
636 649
637 js.Name name = namer.className(element); 650 js.Name name = _namer.className(element);
638 String holderName = namer.globalObjectFor(element); 651 String holderName = _namer.globalObjectFor(element);
639 // TODO(floitsch): we shouldn't update the registry in the middle of 652 // TODO(floitsch): we shouldn't update the registry in the middle of
640 // building a class. 653 // building a class.
641 Holder holder = _registry.registerHolder(holderName); 654 Holder holder = _registry.registerHolder(holderName);
642 bool isInstantiated = !_nativeData.isJsInteropClass(element) && 655 bool isInstantiated = !_nativeData.isJsInteropClass(element) &&
643 _worldBuilder.directlyInstantiatedClasses.contains(element); 656 _worldBuilder.directlyInstantiatedClasses.contains(element);
644 657
645 Class result; 658 Class result;
646 if (element.isMixinApplication && !onlyForRti) { 659 if (element.isMixinApplication && !onlyForRti) {
647 assert(!_nativeData.isNativeClass(element)); 660 assert(!_nativeData.isNativeClass(element));
648 assert(methods.isEmpty); 661 assert(methods.isEmpty);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
685 bool _methodNeedsStubs(FunctionElement method) { 698 bool _methodNeedsStubs(FunctionElement method) {
686 return !method.functionSignature.optionalParameters.isEmpty; 699 return !method.functionSignature.optionalParameters.isEmpty;
687 } 700 }
688 701
689 bool _methodCanBeReflected(MethodElement method) { 702 bool _methodCanBeReflected(MethodElement method) {
690 return _mirrorsData.isMemberAccessibleByReflection(method); 703 return _mirrorsData.isMemberAccessibleByReflection(method);
691 } 704 }
692 705
693 bool _methodCanBeApplied(FunctionElement method) { 706 bool _methodCanBeApplied(FunctionElement method) {
694 return _backendUsage.isFunctionApplyUsed && 707 return _backendUsage.isFunctionApplyUsed &&
695 closedWorld.getMightBePassedToApply(method); 708 _closedWorld.getMightBePassedToApply(method);
696 } 709 }
697 710
698 /* Map | List */ _computeParameterDefaultValues(FunctionSignature signature) { 711 /* Map | List */ _computeParameterDefaultValues(FunctionSignature signature) {
699 var /* Map | List */ optionalParameterDefaultValues; 712 var /* Map | List */ optionalParameterDefaultValues;
700 if (signature.optionalParametersAreNamed) { 713 if (signature.optionalParametersAreNamed) {
701 optionalParameterDefaultValues = new Map<String, ConstantValue>(); 714 optionalParameterDefaultValues = new Map<String, ConstantValue>();
702 signature.forEachOptionalParameter((ParameterElement parameter) { 715 signature.forEachOptionalParameter((ParameterElement parameter) {
703 ConstantValue def = 716 ConstantValue def =
704 _constantHandler.getConstantValue(parameter.constant); 717 _constantHandler.getConstantValue(parameter.constant);
705 optionalParameterDefaultValues[parameter.name] = def; 718 optionalParameterDefaultValues[parameter.name] = def;
706 }); 719 });
707 } else { 720 } else {
708 optionalParameterDefaultValues = <ConstantValue>[]; 721 optionalParameterDefaultValues = <ConstantValue>[];
709 signature.forEachOptionalParameter((ParameterElement parameter) { 722 signature.forEachOptionalParameter((ParameterElement parameter) {
710 ConstantValue def = 723 ConstantValue def =
711 _constantHandler.getConstantValue(parameter.constant); 724 _constantHandler.getConstantValue(parameter.constant);
712 optionalParameterDefaultValues.add(def); 725 optionalParameterDefaultValues.add(def);
713 }); 726 });
714 } 727 }
715 return optionalParameterDefaultValues; 728 return optionalParameterDefaultValues;
716 } 729 }
717 730
718 DartMethod _buildMethod(MethodElement element) { 731 DartMethod _buildMethod(MethodElement element) {
719 assert(element.isDeclaration); 732 assert(element.isDeclaration);
720 js.Name name = namer.methodPropertyName(element); 733 js.Name name = _namer.methodPropertyName(element);
721 js.Expression code = _backend.generatedCode[element]; 734 js.Expression code = _backend.generatedCode[element];
722 735
723 // TODO(kasperl): Figure out under which conditions code is null. 736 // TODO(kasperl): Figure out under which conditions code is null.
724 if (code == null) return null; 737 if (code == null) return null;
725 738
726 bool canTearOff = false; 739 bool canTearOff = false;
727 js.Name tearOffName; 740 js.Name tearOffName;
728 bool isClosureCallMethod = false; 741 bool isClosureCallMethod = false;
729 bool isNotApplyTarget = !element.isFunction || element.isAccessor; 742 bool isNotApplyTarget = !element.isFunction || element.isAccessor;
730 743
731 bool canBeReflected = _methodCanBeReflected(element); 744 bool canBeReflected = _methodCanBeReflected(element);
732 bool canBeApplied = _methodCanBeApplied(element); 745 bool canBeApplied = _methodCanBeApplied(element);
733 746
734 js.Name aliasName = _superMemberData.isAliasedSuperMember(element) 747 js.Name aliasName = _superMemberData.isAliasedSuperMember(element)
735 ? namer.aliasedSuperMemberPropertyName(element) 748 ? _namer.aliasedSuperMemberPropertyName(element)
736 : null; 749 : null;
737 750
738 if (isNotApplyTarget) { 751 if (isNotApplyTarget) {
739 canTearOff = false; 752 canTearOff = false;
740 } else { 753 } else {
741 if (element.enclosingClass.isClosure) { 754 if (element.enclosingClass.isClosure) {
742 canTearOff = false; 755 canTearOff = false;
743 isClosureCallMethod = true; 756 isClosureCallMethod = true;
744 } else { 757 } else {
745 // Careful with operators. 758 // Careful with operators.
746 canTearOff = _worldBuilder.hasInvokedGetter(element, closedWorld) || 759 canTearOff = _worldBuilder.hasInvokedGetter(element, _closedWorld) ||
747 (canBeReflected && !element.isOperator); 760 (canBeReflected && !element.isOperator);
748 assert(canTearOff || 761 assert(canTearOff ||
749 !_worldBuilder.methodsNeedingSuperGetter.contains(element)); 762 !_worldBuilder.methodsNeedingSuperGetter.contains(element));
750 tearOffName = namer.getterForElement(element); 763 tearOffName = _namer.getterForElement(element);
751 } 764 }
752 } 765 }
753 766
754 if (canTearOff) { 767 if (canTearOff) {
755 assert(invariant(element, !element.isGenerativeConstructor)); 768 assert(invariant(element, !element.isGenerativeConstructor));
756 assert(invariant(element, !element.isGenerativeConstructorBody)); 769 assert(invariant(element, !element.isGenerativeConstructorBody));
757 assert(invariant(element, !element.isConstructor)); 770 assert(invariant(element, !element.isConstructor));
758 } 771 }
759 772
760 js.Name callName = null; 773 js.Name callName = null;
761 if (canTearOff) { 774 if (canTearOff) {
762 Selector callSelector = 775 Selector callSelector =
763 new Selector.fromElement(element).toCallSelector(); 776 new Selector.fromElement(element).toCallSelector();
764 callName = namer.invocationName(callSelector); 777 callName = _namer.invocationName(callSelector);
765 } 778 }
766 779
767 ResolutionDartType memberType; 780 ResolutionDartType memberType;
768 if (element.isGenerativeConstructorBody) { 781 if (element.isGenerativeConstructorBody) {
769 // TODO(herhut): Why does this need to be normalized away? We never need 782 // TODO(herhut): Why does this need to be normalized away? We never need
770 // this information anyway as they cannot be torn off or 783 // this information anyway as they cannot be torn off or
771 // reflected. 784 // reflected.
772 var body = element; 785 var body = element;
773 memberType = body.constructor.type; 786 memberType = body.constructor.type;
774 } else { 787 } else {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
813 return _emitter.metadataCollector 826 return _emitter.metadataCollector
814 .reifyTypeForOutputUnit(type, outputUnit); 827 .reifyTypeForOutputUnit(type, outputUnit);
815 } 828 }
816 } 829 }
817 830
818 List<ParameterStubMethod> _generateParameterStubs( 831 List<ParameterStubMethod> _generateParameterStubs(
819 MethodElement element, bool canTearOff) { 832 MethodElement element, bool canTearOff) {
820 if (!_methodNeedsStubs(element)) return const <ParameterStubMethod>[]; 833 if (!_methodNeedsStubs(element)) return const <ParameterStubMethod>[];
821 834
822 ParameterStubGenerator generator = 835 ParameterStubGenerator generator =
823 new ParameterStubGenerator(_compiler, namer, _backend, closedWorld); 836 new ParameterStubGenerator(_compiler, _namer, _backend, _closedWorld);
824 return generator.generateParameterStubs(element, canTearOff: canTearOff); 837 return generator.generateParameterStubs(element, canTearOff: canTearOff);
825 } 838 }
826 839
827 /// Builds a stub method. 840 /// Builds a stub method.
828 /// 841 ///
829 /// Stub methods may have an element that can be used for code-size 842 /// Stub methods may have an element that can be used for code-size
830 /// attribution. 843 /// attribution.
831 Method _buildStubMethod(js.Name name, js.Expression code, 844 Method _buildStubMethod(js.Name name, js.Expression code,
832 {MemberElement element}) { 845 {MemberElement element}) {
833 return new StubMethod(name, code, element: element); 846 return new StubMethod(name, code, element: element);
834 } 847 }
835 848
836 // The getInterceptor methods directly access the prototype of classes. 849 // The getInterceptor methods directly access the prototype of classes.
837 // We must evaluate these classes eagerly so that the prototype is 850 // We must evaluate these classes eagerly so that the prototype is
838 // accessible. 851 // accessible.
839 void _markEagerInterceptorClasses() { 852 void _markEagerInterceptorClasses() {
840 Iterable<js.Name> names = 853 Iterable<js.Name> names =
841 _oneShotInterceptorData.specializedGetInterceptorNames; 854 _oneShotInterceptorData.specializedGetInterceptorNames;
842 for (js.Name name in names) { 855 for (js.Name name in names) {
843 for (ClassElement element 856 for (ClassElement element
844 in _oneShotInterceptorData.getSpecializedGetInterceptorsFor(name)) { 857 in _oneShotInterceptorData.getSpecializedGetInterceptorsFor(name)) {
845 Class cls = _classes[element]; 858 Class cls = _classes[element];
846 if (cls != null) cls.isEager = true; 859 if (cls != null) cls.isEager = true;
847 } 860 }
848 } 861 }
849 } 862 }
850 863
851 Iterable<StaticStubMethod> _generateGetInterceptorMethods() { 864 Iterable<StaticStubMethod> _generateGetInterceptorMethods() {
852 InterceptorStubGenerator stubGenerator = 865 InterceptorStubGenerator stubGenerator = new InterceptorStubGenerator(
853 new InterceptorStubGenerator(_compiler, namer, _backend, closedWorld); 866 _options,
867 _commonElements,
868 _emitter,
869 _nativeCodegenEnqueuer,
870 _constantHandler,
871 _namer,
872 _nativeData,
873 _interceptorData,
874 _oneShotInterceptorData,
875 _customElementsCodegenAnalysis,
876 _worldBuilder,
877 _closedWorld);
854 878
855 String holderName = 879 String holderName =
856 namer.globalObjectForLibrary(_commonElements.interceptorsLibrary); 880 _namer.globalObjectForLibrary(_commonElements.interceptorsLibrary);
857 // TODO(floitsch): we shouldn't update the registry in the middle of 881 // TODO(floitsch): we shouldn't update the registry in the middle of
858 // generating the interceptor methods. 882 // generating the interceptor methods.
859 Holder holder = _registry.registerHolder(holderName); 883 Holder holder = _registry.registerHolder(holderName);
860 884
861 Iterable<js.Name> names = 885 Iterable<js.Name> names =
862 _oneShotInterceptorData.specializedGetInterceptorNames; 886 _oneShotInterceptorData.specializedGetInterceptorNames;
863 return names.map((js.Name name) { 887 return names.map((js.Name name) {
864 Set<ClassEntity> classes = 888 Set<ClassEntity> classes =
865 _oneShotInterceptorData.getSpecializedGetInterceptorsFor(name); 889 _oneShotInterceptorData.getSpecializedGetInterceptorsFor(name);
866 js.Expression code = stubGenerator.generateGetInterceptorMethod(classes); 890 js.Expression code = stubGenerator.generateGetInterceptorMethod(classes);
867 return new StaticStubMethod(name, holder, code); 891 return new StaticStubMethod(name, holder, code);
868 }); 892 });
869 } 893 }
870 894
871 List<Field> _buildFields(Element holder, 895 List<Field> _buildFields(Element holder,
872 {bool visitStatics, bool isHolderInterceptedClass: false}) { 896 {bool visitStatics, bool isHolderInterceptedClass: false}) {
873 List<Field> fields = <Field>[]; 897 List<Field> fields = <Field>[];
874 new FieldVisitor(_compiler, namer, closedWorld) 898 new FieldVisitor(_compiler, _namer, _closedWorld)
875 .visitFields(holder, visitStatics, (FieldElement field, 899 .visitFields(holder, visitStatics, (FieldElement field,
876 js.Name name, 900 js.Name name,
877 js.Name accessorName, 901 js.Name accessorName,
878 bool needsGetter, 902 bool needsGetter,
879 bool needsSetter, 903 bool needsSetter,
880 bool needsCheckedSetter) { 904 bool needsCheckedSetter) {
881 assert(invariant(field, field.isDeclaration)); 905 assert(invariant(field, field.isDeclaration));
882 906
883 int getterFlags = 0; 907 int getterFlags = 0;
884 if (needsGetter) { 908 if (needsGetter) {
(...skipping 25 matching lines...) Expand all
910 } 934 }
911 935
912 fields.add(new Field(field, name, accessorName, getterFlags, setterFlags, 936 fields.add(new Field(field, name, accessorName, getterFlags, setterFlags,
913 needsCheckedSetter)); 937 needsCheckedSetter));
914 }); 938 });
915 939
916 return fields; 940 return fields;
917 } 941 }
918 942
919 Iterable<StaticStubMethod> _generateOneShotInterceptors() { 943 Iterable<StaticStubMethod> _generateOneShotInterceptors() {
920 InterceptorStubGenerator stubGenerator = 944 InterceptorStubGenerator stubGenerator = new InterceptorStubGenerator(
921 new InterceptorStubGenerator(_compiler, namer, _backend, closedWorld); 945 _options,
946 _commonElements,
947 _emitter,
948 _nativeCodegenEnqueuer,
949 _constantHandler,
950 _namer,
951 _nativeData,
952 _interceptorData,
953 _oneShotInterceptorData,
954 _customElementsCodegenAnalysis,
955 _worldBuilder,
956 _closedWorld);
922 957
923 String holderName = 958 String holderName =
924 namer.globalObjectForLibrary(_commonElements.interceptorsLibrary); 959 _namer.globalObjectForLibrary(_commonElements.interceptorsLibrary);
925 // TODO(floitsch): we shouldn't update the registry in the middle of 960 // TODO(floitsch): we shouldn't update the registry in the middle of
926 // generating the interceptor methods. 961 // generating the interceptor methods.
927 Holder holder = _registry.registerHolder(holderName); 962 Holder holder = _registry.registerHolder(holderName);
928 963
929 List<js.Name> names = _oneShotInterceptorData.oneShotInterceptorNames; 964 List<js.Name> names = _oneShotInterceptorData.oneShotInterceptorNames;
930 return names.map((js.Name name) { 965 return names.map((js.Name name) {
931 js.Expression code = stubGenerator.generateOneShotInterceptor(name); 966 js.Expression code = stubGenerator.generateOneShotInterceptor(name);
932 return new StaticStubMethod(name, holder, code); 967 return new StaticStubMethod(name, holder, code);
933 }); 968 });
934 } 969 }
935 970
936 StaticDartMethod _buildStaticMethod(MethodElement element) { 971 StaticDartMethod _buildStaticMethod(MethodElement element) {
937 js.Name name = namer.methodPropertyName(element); 972 js.Name name = _namer.methodPropertyName(element);
938 String holder = namer.globalObjectFor(element); 973 String holder = _namer.globalObjectFor(element);
939 js.Expression code = _backend.generatedCode[element]; 974 js.Expression code = _backend.generatedCode[element];
940 975
941 bool isApplyTarget = !element.isConstructor && !element.isAccessor; 976 bool isApplyTarget = !element.isConstructor && !element.isAccessor;
942 bool canBeApplied = _methodCanBeApplied(element); 977 bool canBeApplied = _methodCanBeApplied(element);
943 bool canBeReflected = _methodCanBeReflected(element); 978 bool canBeReflected = _methodCanBeReflected(element);
944 979
945 bool needsTearOff = isApplyTarget && 980 bool needsTearOff = isApplyTarget &&
946 (canBeReflected || 981 (canBeReflected ||
947 _worldBuilder.staticFunctionsNeedingGetter.contains(element)); 982 _worldBuilder.staticFunctionsNeedingGetter.contains(element));
948 983
949 js.Name tearOffName = 984 js.Name tearOffName =
950 needsTearOff ? namer.staticClosureName(element) : null; 985 needsTearOff ? _namer.staticClosureName(element) : null;
951 986
952 js.Name callName = null; 987 js.Name callName = null;
953 if (needsTearOff) { 988 if (needsTearOff) {
954 Selector callSelector = 989 Selector callSelector =
955 new Selector.fromElement(element).toCallSelector(); 990 new Selector.fromElement(element).toCallSelector();
956 callName = namer.invocationName(callSelector); 991 callName = _namer.invocationName(callSelector);
957 } 992 }
958 js.Expression functionType; 993 js.Expression functionType;
959 ResolutionDartType type = element.type; 994 ResolutionDartType type = element.type;
960 if (needsTearOff || canBeReflected) { 995 if (needsTearOff || canBeReflected) {
961 OutputUnit outputUnit = _deferredLoadTask.outputUnitForElement(element); 996 OutputUnit outputUnit = _deferredLoadTask.outputUnitForElement(element);
962 functionType = _generateFunctionType(type, outputUnit); 997 functionType = _generateFunctionType(type, outputUnit);
963 } 998 }
964 999
965 int requiredParameterCount; 1000 int requiredParameterCount;
966 var /* List | Map */ optionalParameterDefaultValues; 1001 var /* List | Map */ optionalParameterDefaultValues;
(...skipping 17 matching lines...) Expand all
984 functionType: functionType); 1019 functionType: functionType);
985 } 1020 }
986 1021
987 void _registerConstants( 1022 void _registerConstants(
988 OutputUnit outputUnit, Iterable<ConstantValue> constantValues) { 1023 OutputUnit outputUnit, Iterable<ConstantValue> constantValues) {
989 // `constantValues` is null if an outputUnit doesn't contain any constants. 1024 // `constantValues` is null if an outputUnit doesn't contain any constants.
990 if (constantValues == null) return; 1025 if (constantValues == null) return;
991 for (ConstantValue constantValue in constantValues) { 1026 for (ConstantValue constantValue in constantValues) {
992 _registry.registerConstant(outputUnit, constantValue); 1027 _registry.registerConstant(outputUnit, constantValue);
993 assert(!_constants.containsKey(constantValue)); 1028 assert(!_constants.containsKey(constantValue));
994 js.Name name = namer.constantName(constantValue); 1029 js.Name name = _namer.constantName(constantValue);
995 String constantObject = namer.globalObjectForConstant(constantValue); 1030 String constantObject = _namer.globalObjectForConstant(constantValue);
996 Holder holder = 1031 Holder holder =
997 _registry.registerHolder(constantObject, isConstantsHolder: true); 1032 _registry.registerHolder(constantObject, isConstantsHolder: true);
998 Constant constant = new Constant(name, holder, constantValue); 1033 Constant constant = new Constant(name, holder, constantValue);
999 _constants[constantValue] = constant; 1034 _constants[constantValue] = constant;
1000 } 1035 }
1001 } 1036 }
1002 1037
1003 Holder _registerStaticStateHolder() { 1038 Holder _registerStaticStateHolder() {
1004 return _registry.registerHolder(namer.staticStateHolder, 1039 return _registry.registerHolder(_namer.staticStateHolder,
1005 isStaticStateHolder: true); 1040 isStaticStateHolder: true);
1006 } 1041 }
1007 } 1042 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698