OLD | NEW |
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 14 matching lines...) Expand all Loading... |
25 GetterElement, | 25 GetterElement, |
26 LibraryElement, | 26 LibraryElement, |
27 MemberElement, | 27 MemberElement, |
28 MethodElement, | 28 MethodElement, |
29 ParameterElement, | 29 ParameterElement, |
30 TypedefElement, | 30 TypedefElement, |
31 VariableElement; | 31 VariableElement; |
32 import '../../elements/entities.dart'; | 32 import '../../elements/entities.dart'; |
33 import '../../elements/types.dart' show DartType; | 33 import '../../elements/types.dart' show DartType; |
34 import '../../js/js.dart' as js; | 34 import '../../js/js.dart' as js; |
35 import '../../js_backend/backend_helpers.dart' show BackendHelpers; | |
36 import '../../js_backend/js_backend.dart' | 35 import '../../js_backend/js_backend.dart' |
37 show Namer, JavaScriptBackend, JavaScriptConstantCompiler, StringBackedName; | 36 show Namer, JavaScriptBackend, JavaScriptConstantCompiler, StringBackedName; |
38 import '../../universe/selector.dart' show Selector; | 37 import '../../universe/selector.dart' show Selector; |
39 import '../../universe/world_builder.dart' | 38 import '../../universe/world_builder.dart' |
40 show CodegenWorldBuilder, SelectorConstraints; | 39 show CodegenWorldBuilder, SelectorConstraints; |
41 import '../../world.dart' show ClosedWorld; | 40 import '../../world.dart' show ClosedWorld; |
42 import '../js_emitter.dart' | 41 import '../js_emitter.dart' |
43 show | 42 show |
44 ClassStubGenerator, | 43 ClassStubGenerator, |
45 CodeEmitterTask, | 44 CodeEmitterTask, |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 ProgramBuilder(Compiler compiler, Namer namer, this._task, Emitter emitter, | 78 ProgramBuilder(Compiler compiler, Namer namer, this._task, Emitter emitter, |
80 ClosedWorld closedWorld, Set<ClassElement> rtiNeededClasses) | 79 ClosedWorld closedWorld, Set<ClassElement> rtiNeededClasses) |
81 : this._compiler = compiler, | 80 : this._compiler = compiler, |
82 this.namer = namer, | 81 this.namer = namer, |
83 this.closedWorld = closedWorld, | 82 this.closedWorld = closedWorld, |
84 this.collector = new Collector( | 83 this.collector = new Collector( |
85 compiler, namer, closedWorld, rtiNeededClasses, emitter), | 84 compiler, namer, closedWorld, rtiNeededClasses, emitter), |
86 this._registry = new Registry(compiler); | 85 this._registry = new Registry(compiler); |
87 | 86 |
88 JavaScriptBackend get backend => _compiler.backend; | 87 JavaScriptBackend get backend => _compiler.backend; |
89 BackendHelpers get helpers => backend.helpers; | |
90 CodegenWorldBuilder get worldBuilder => _compiler.codegenWorldBuilder; | 88 CodegenWorldBuilder get worldBuilder => _compiler.codegenWorldBuilder; |
91 | 89 |
92 /// Mapping from [ClassElement] to constructed [Class]. We need this to | 90 /// Mapping from [ClassElement] to constructed [Class]. We need this to |
93 /// update the superclass in the [Class]. | 91 /// update the superclass in the [Class]. |
94 final Map<ClassElement, Class> _classes = <ClassElement, Class>{}; | 92 final Map<ClassElement, Class> _classes = <ClassElement, Class>{}; |
95 | 93 |
96 /// Mapping from [OutputUnit] to constructed [Fragment]. We need this to | 94 /// Mapping from [OutputUnit] to constructed [Fragment]. We need this to |
97 /// generate the deferredLoadingMap (to know which hunks to load). | 95 /// generate the deferredLoadingMap (to know which hunks to load). |
98 final Map<OutputUnit, Fragment> _outputs = <OutputUnit, Fragment>{}; | 96 final Map<OutputUnit, Fragment> _outputs = <OutputUnit, Fragment>{}; |
99 | 97 |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
340 js.js('function() { return this.#(this) }', toStringInvocation))); | 338 js.js('function() { return this.#(this) }', toStringInvocation))); |
341 } | 339 } |
342 | 340 |
343 // We add all members from classes marked with isJsInterop to the base | 341 // We add all members from classes marked with isJsInterop to the base |
344 // Interceptor class with implementations that directly call the | 342 // Interceptor class with implementations that directly call the |
345 // corresponding JavaScript member. We do not attempt to bind this when | 343 // corresponding JavaScript member. We do not attempt to bind this when |
346 // tearing off JavaScript methods as we cannot distinguish between calling | 344 // tearing off JavaScript methods as we cannot distinguish between calling |
347 // a regular getter that returns a JavaScript function and tearing off | 345 // a regular getter that returns a JavaScript function and tearing off |
348 // a method in the case where there exist multiple JavaScript classes | 346 // a method in the case where there exist multiple JavaScript classes |
349 // that conflict on whether the member is a getter or a method. | 347 // that conflict on whether the member is a getter or a method. |
350 var interceptorClass = _classes[helpers.jsJavaScriptObjectClass]; | 348 var interceptorClass = |
| 349 _classes[_compiler.commonElements.jsJavaScriptObjectClass]; |
351 var stubNames = new Set<String>(); | 350 var stubNames = new Set<String>(); |
352 librariesMap.forEach((LibraryElement library, List<Element> elements) { | 351 librariesMap.forEach((LibraryElement library, List<Element> elements) { |
353 for (Element e in elements) { | 352 for (Element e in elements) { |
354 if (e is ClassElement && backend.nativeData.isJsInteropClass(e)) { | 353 if (e is ClassElement && backend.nativeData.isJsInteropClass(e)) { |
355 e.declaration.forEachMember((_, Element member) { | 354 e.declaration.forEachMember((_, Element member) { |
356 var jsName = | 355 var jsName = |
357 backend.nativeData.computeUnescapedJSInteropName(member.name); | 356 backend.nativeData.computeUnescapedJSInteropName(member.name); |
358 if (!member.isInstanceMember) return; | 357 if (!member.isInstanceMember) return; |
359 if (member.isGetter || member.isField || member.isFunction) { | 358 if (member.isGetter || member.isField || member.isFunction) { |
360 var selectors = worldBuilder.getterInvocationsByName(member.name); | 359 var selectors = worldBuilder.getterInvocationsByName(member.name); |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
468 // Note that a library-element may have multiple [Library]s, if it is split | 467 // Note that a library-element may have multiple [Library]s, if it is split |
469 // into multiple output units. | 468 // into multiple output units. |
470 Library _buildLibrary(LibraryElement library, List<Element> elements) { | 469 Library _buildLibrary(LibraryElement library, List<Element> elements) { |
471 String uri = library.canonicalUri.toString(); | 470 String uri = library.canonicalUri.toString(); |
472 | 471 |
473 List<StaticMethod> statics = elements | 472 List<StaticMethod> statics = elements |
474 .where((e) => e is FunctionElement) | 473 .where((e) => e is FunctionElement) |
475 .map(_buildStaticMethod) | 474 .map(_buildStaticMethod) |
476 .toList(); | 475 .toList(); |
477 | 476 |
478 if (library == helpers.interceptorsLibrary) { | 477 if (library == _compiler.commonElements.interceptorsLibrary) { |
479 statics.addAll(_generateGetInterceptorMethods()); | 478 statics.addAll(_generateGetInterceptorMethods()); |
480 statics.addAll(_generateOneShotInterceptors()); | 479 statics.addAll(_generateOneShotInterceptors()); |
481 } | 480 } |
482 | 481 |
483 List<Class> classes = elements | 482 List<Class> classes = elements |
484 .where((e) => e is ClassElement) | 483 .where((e) => e is ClassElement) |
485 .map((ClassElement classElement) => _classes[classElement]) | 484 .map((ClassElement classElement) => _classes[classElement]) |
486 .where((Class cls) => | 485 .where((Class cls) => |
487 !cls.isNative || !_unneededNativeClasses.contains(cls)) | 486 !cls.isNative || !_unneededNativeClasses.contains(cls)) |
488 .toList(growable: false); | 487 .toList(growable: false); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
545 String selectorName = selector.name; | 544 String selectorName = selector.name; |
546 if (selector.isSetter) selectorName = "$selectorName="; | 545 if (selector.isSetter) selectorName = "$selectorName="; |
547 if (backend.mirrorsData.symbolsUsed.contains(selectorName)) { | 546 if (backend.mirrorsData.symbolsUsed.contains(selectorName)) { |
548 _symbolsMap[name] = selectorName; | 547 _symbolsMap[name] = selectorName; |
549 } | 548 } |
550 noSuchMethodStubs.add( | 549 noSuchMethodStubs.add( |
551 classStubGenerator.generateStubForNoSuchMethod(name, selector)); | 550 classStubGenerator.generateStubForNoSuchMethod(name, selector)); |
552 }); | 551 }); |
553 } | 552 } |
554 | 553 |
555 if (element == helpers.closureClass) { | 554 if (element == _compiler.commonElements.closureClass) { |
556 // We add a special getter here to allow for tearing off a closure from | 555 // We add a special getter here to allow for tearing off a closure from |
557 // itself. | 556 // itself. |
558 js.Name name = namer.getterForMember(Names.call); | 557 js.Name name = namer.getterForMember(Names.call); |
559 js.Fun function = js.js('function() { return this; }'); | 558 js.Fun function = js.js('function() { return this; }'); |
560 callStubs.add(_buildStubMethod(name, function)); | 559 callStubs.add(_buildStubMethod(name, function)); |
561 } | 560 } |
562 | 561 |
563 ClassElement implementation = element.implementation; | 562 ClassElement implementation = element.implementation; |
564 | 563 |
565 // MixinApplications run through the members of their mixin. Here, we are | 564 // MixinApplications run through the members of their mixin. Here, we are |
(...skipping 12 matching lines...) Expand all Loading... |
578 : _buildFields(element, | 577 : _buildFields(element, |
579 visitStatics: true, isHolderInterceptedClass: isInterceptedClass); | 578 visitStatics: true, isHolderInterceptedClass: isInterceptedClass); |
580 | 579 |
581 TypeTestProperties typeTests = runtimeTypeGenerator.generateIsTests(element, | 580 TypeTestProperties typeTests = runtimeTypeGenerator.generateIsTests(element, |
582 storeFunctionTypeInMetadata: _storeFunctionTypesInMetadata); | 581 storeFunctionTypeInMetadata: _storeFunctionTypesInMetadata); |
583 | 582 |
584 List<StubMethod> checkedSetters = <StubMethod>[]; | 583 List<StubMethod> checkedSetters = <StubMethod>[]; |
585 List<StubMethod> isChecks = <StubMethod>[]; | 584 List<StubMethod> isChecks = <StubMethod>[]; |
586 if (backend.nativeData.isJsInteropClass(element)) { | 585 if (backend.nativeData.isJsInteropClass(element)) { |
587 typeTests.properties.forEach((js.Name name, js.Node code) { | 586 typeTests.properties.forEach((js.Name name, js.Node code) { |
588 _classes[helpers.jsInterceptorClass] | 587 _classes[_compiler.commonElements.jsInterceptorClass] |
589 .isChecks | 588 .isChecks |
590 .add(_buildStubMethod(name, code)); | 589 .add(_buildStubMethod(name, code)); |
591 }); | 590 }); |
592 } else { | 591 } else { |
593 for (Field field in instanceFields) { | 592 for (Field field in instanceFields) { |
594 if (field.needsCheckedSetter) { | 593 if (field.needsCheckedSetter) { |
595 assert(!field.needsUncheckedSetter); | 594 assert(!field.needsUncheckedSetter); |
596 FieldElement element = field.element; | 595 FieldElement element = field.element; |
597 js.Expression code = backend.generatedCode[element]; | 596 js.Expression code = backend.generatedCode[element]; |
598 assert(code != null); | 597 assert(code != null); |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
817 Class cls = _classes[element]; | 816 Class cls = _classes[element]; |
818 if (cls != null) cls.isEager = true; | 817 if (cls != null) cls.isEager = true; |
819 } | 818 } |
820 } | 819 } |
821 } | 820 } |
822 | 821 |
823 Iterable<StaticStubMethod> _generateGetInterceptorMethods() { | 822 Iterable<StaticStubMethod> _generateGetInterceptorMethods() { |
824 InterceptorStubGenerator stubGenerator = | 823 InterceptorStubGenerator stubGenerator = |
825 new InterceptorStubGenerator(_compiler, namer, backend, closedWorld); | 824 new InterceptorStubGenerator(_compiler, namer, backend, closedWorld); |
826 | 825 |
827 String holderName = | 826 String holderName = namer |
828 namer.globalObjectForLibrary(helpers.interceptorsLibrary); | 827 .globalObjectForLibrary(_compiler.commonElements.interceptorsLibrary); |
829 // TODO(floitsch): we shouldn't update the registry in the middle of | 828 // TODO(floitsch): we shouldn't update the registry in the middle of |
830 // generating the interceptor methods. | 829 // generating the interceptor methods. |
831 Holder holder = _registry.registerHolder(holderName); | 830 Holder holder = _registry.registerHolder(holderName); |
832 | 831 |
833 Iterable<js.Name> names = | 832 Iterable<js.Name> names = |
834 backend.oneShotInterceptorData.specializedGetInterceptorNames; | 833 backend.oneShotInterceptorData.specializedGetInterceptorNames; |
835 return names.map((js.Name name) { | 834 return names.map((js.Name name) { |
836 Set<ClassEntity> classes = | 835 Set<ClassEntity> classes = |
837 backend.oneShotInterceptorData.getSpecializedGetInterceptorsFor(name); | 836 backend.oneShotInterceptorData.getSpecializedGetInterceptorsFor(name); |
838 js.Expression code = stubGenerator.generateGetInterceptorMethod(classes); | 837 js.Expression code = stubGenerator.generateGetInterceptorMethod(classes); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
885 needsCheckedSetter)); | 884 needsCheckedSetter)); |
886 }); | 885 }); |
887 | 886 |
888 return fields; | 887 return fields; |
889 } | 888 } |
890 | 889 |
891 Iterable<StaticStubMethod> _generateOneShotInterceptors() { | 890 Iterable<StaticStubMethod> _generateOneShotInterceptors() { |
892 InterceptorStubGenerator stubGenerator = | 891 InterceptorStubGenerator stubGenerator = |
893 new InterceptorStubGenerator(_compiler, namer, backend, closedWorld); | 892 new InterceptorStubGenerator(_compiler, namer, backend, closedWorld); |
894 | 893 |
895 String holderName = | 894 String holderName = namer |
896 namer.globalObjectForLibrary(helpers.interceptorsLibrary); | 895 .globalObjectForLibrary(_compiler.commonElements.interceptorsLibrary); |
897 // TODO(floitsch): we shouldn't update the registry in the middle of | 896 // TODO(floitsch): we shouldn't update the registry in the middle of |
898 // generating the interceptor methods. | 897 // generating the interceptor methods. |
899 Holder holder = _registry.registerHolder(holderName); | 898 Holder holder = _registry.registerHolder(holderName); |
900 | 899 |
901 List<js.Name> names = | 900 List<js.Name> names = |
902 backend.oneShotInterceptorData.oneShotInterceptorNames; | 901 backend.oneShotInterceptorData.oneShotInterceptorNames; |
903 return names.map((js.Name name) { | 902 return names.map((js.Name name) { |
904 js.Expression code = stubGenerator.generateOneShotInterceptor(name); | 903 js.Expression code = stubGenerator.generateOneShotInterceptor(name); |
905 return new StaticStubMethod(name, holder, code); | 904 return new StaticStubMethod(name, holder, code); |
906 }); | 905 }); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
972 Constant constant = new Constant(name, holder, constantValue); | 971 Constant constant = new Constant(name, holder, constantValue); |
973 _constants[constantValue] = constant; | 972 _constants[constantValue] = constant; |
974 } | 973 } |
975 } | 974 } |
976 | 975 |
977 Holder _registerStaticStateHolder() { | 976 Holder _registerStaticStateHolder() { |
978 return _registry.registerHolder(namer.staticStateHolder, | 977 return _registry.registerHolder(namer.staticStateHolder, |
979 isStaticStateHolder: true); | 978 isStaticStateHolder: true); |
980 } | 979 } |
981 } | 980 } |
OLD | NEW |