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 '../js_emitter.dart' show | 7 import '../js_emitter.dart' show |
8 ClassStubGenerator, | 8 ClassStubGenerator, |
9 CodeEmitterTask, | 9 CodeEmitterTask, |
10 computeMixinClass, | 10 computeMixinClass, |
(...skipping 27 matching lines...) Expand all Loading... |
38 FieldElement, | 38 FieldElement, |
39 FunctionElement, | 39 FunctionElement, |
40 FunctionSignature, | 40 FunctionSignature, |
41 LibraryElement, | 41 LibraryElement, |
42 MethodElement, | 42 MethodElement, |
43 Name, | 43 Name, |
44 ParameterElement, | 44 ParameterElement, |
45 TypedefElement, | 45 TypedefElement, |
46 VariableElement; | 46 VariableElement; |
47 import '../../js/js.dart' as js; | 47 import '../../js/js.dart' as js; |
| 48 import '../../js_backend/backend_helpers.dart' show |
| 49 BackendHelpers; |
48 import '../../js_backend/js_backend.dart' show | 50 import '../../js_backend/js_backend.dart' show |
49 Namer, | 51 Namer, |
50 JavaScriptBackend, | 52 JavaScriptBackend, |
51 JavaScriptConstantCompiler, | 53 JavaScriptConstantCompiler, |
52 StringBackedName; | 54 StringBackedName; |
53 import '../../universe/selector.dart' show | 55 import '../../universe/selector.dart' show |
54 Selector; | 56 Selector; |
55 import '../../universe/universe.dart' show | 57 import '../../universe/universe.dart' show |
56 Universe, | 58 Universe, |
57 SelectorConstraints; | 59 SelectorConstraints; |
(...skipping 29 matching lines...) Expand all Loading... |
87 this._task, | 89 this._task, |
88 Emitter emitter, | 90 Emitter emitter, |
89 Set<ClassElement> rtiNeededClasses) | 91 Set<ClassElement> rtiNeededClasses) |
90 : this._compiler = compiler, | 92 : this._compiler = compiler, |
91 this.namer = namer, | 93 this.namer = namer, |
92 this.collector = | 94 this.collector = |
93 new Collector(compiler, namer, rtiNeededClasses, emitter), | 95 new Collector(compiler, namer, rtiNeededClasses, emitter), |
94 this._registry = new Registry(compiler); | 96 this._registry = new Registry(compiler); |
95 | 97 |
96 JavaScriptBackend get backend => _compiler.backend; | 98 JavaScriptBackend get backend => _compiler.backend; |
| 99 BackendHelpers get helpers => backend.helpers; |
97 Universe get universe => _compiler.codegenWorld; | 100 Universe get universe => _compiler.codegenWorld; |
98 | 101 |
99 /// Mapping from [ClassElement] to constructed [Class]. We need this to | 102 /// Mapping from [ClassElement] to constructed [Class]. We need this to |
100 /// update the superclass in the [Class]. | 103 /// update the superclass in the [Class]. |
101 final Map<ClassElement, Class> _classes = <ClassElement, Class>{}; | 104 final Map<ClassElement, Class> _classes = <ClassElement, Class>{}; |
102 | 105 |
103 /// Mapping from [OutputUnit] to constructed [Fragment]. We need this to | 106 /// Mapping from [OutputUnit] to constructed [Fragment]. We need this to |
104 /// generate the deferredLoadingMap (to know which hunks to load). | 107 /// generate the deferredLoadingMap (to know which hunks to load). |
105 final Map<OutputUnit, Fragment> _outputs = <OutputUnit, Fragment>{}; | 108 final Map<OutputUnit, Fragment> _outputs = <OutputUnit, Fragment>{}; |
106 | 109 |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
358 js.js('function() { return this.#(this) }', toStringInvocation))); | 361 js.js('function() { return this.#(this) }', toStringInvocation))); |
359 } | 362 } |
360 | 363 |
361 // We add all members from classes marked with isJsInterop to the base | 364 // We add all members from classes marked with isJsInterop to the base |
362 // Interceptor class with implementations that directly call the | 365 // Interceptor class with implementations that directly call the |
363 // corresponding JavaScript member. We do not attempt to bind this when | 366 // corresponding JavaScript member. We do not attempt to bind this when |
364 // tearing off JavaScript methods as we cannot distinguish between calling | 367 // tearing off JavaScript methods as we cannot distinguish between calling |
365 // a regular getter that returns a JavaScript function and tearing off | 368 // a regular getter that returns a JavaScript function and tearing off |
366 // a method in the case where there exist multiple JavaScript classes | 369 // a method in the case where there exist multiple JavaScript classes |
367 // that conflict on whether the member is a getter or a method. | 370 // that conflict on whether the member is a getter or a method. |
368 var interceptorClass = _classes[backend.jsJavaScriptObjectClass]; | 371 var interceptorClass = _classes[helpers.jsJavaScriptObjectClass]; |
369 var stubNames = new Set<String>(); | 372 var stubNames = new Set<String>(); |
370 librariesMap.forEach((LibraryElement library, List<Element> elements) { | 373 librariesMap.forEach((LibraryElement library, List<Element> elements) { |
371 for (Element e in elements) { | 374 for (Element e in elements) { |
372 if (e is ClassElement && backend.isJsInterop(e)) { | 375 if (e is ClassElement && backend.isJsInterop(e)) { |
373 e.declaration.forEachMember((_, Element member) { | 376 e.declaration.forEachMember((_, Element member) { |
374 if (!member.isInstanceMember) return; | 377 if (!member.isInstanceMember) return; |
375 if (member.isGetter || member.isField || member.isFunction) { | 378 if (member.isGetter || member.isField || member.isFunction) { |
376 var selectors = | 379 var selectors = |
377 _compiler.codegenWorld.getterInvocationsByName(member.name); | 380 _compiler.codegenWorld.getterInvocationsByName(member.name); |
378 if (selectors != null && !selectors.isEmpty) { | 381 if (selectors != null && !selectors.isEmpty) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
442 // Note that a library-element may have multiple [Library]s, if it is split | 445 // Note that a library-element may have multiple [Library]s, if it is split |
443 // into multiple output units. | 446 // into multiple output units. |
444 Library _buildLibrary(LibraryElement library, List<Element> elements) { | 447 Library _buildLibrary(LibraryElement library, List<Element> elements) { |
445 String uri = library.canonicalUri.toString(); | 448 String uri = library.canonicalUri.toString(); |
446 | 449 |
447 List<StaticMethod> statics = elements | 450 List<StaticMethod> statics = elements |
448 .where((e) => e is FunctionElement) | 451 .where((e) => e is FunctionElement) |
449 .map(_buildStaticMethod) | 452 .map(_buildStaticMethod) |
450 .toList(); | 453 .toList(); |
451 | 454 |
452 if (library == backend.interceptorsLibrary) { | 455 if (library == helpers.interceptorsLibrary) { |
453 statics.addAll(_generateGetInterceptorMethods()); | 456 statics.addAll(_generateGetInterceptorMethods()); |
454 statics.addAll(_generateOneShotInterceptors()); | 457 statics.addAll(_generateOneShotInterceptors()); |
455 } | 458 } |
456 | 459 |
457 List<Class> classes = elements | 460 List<Class> classes = elements |
458 .where((e) => e is ClassElement) | 461 .where((e) => e is ClassElement) |
459 .map((ClassElement classElement) => _classes[classElement]) | 462 .map((ClassElement classElement) => _classes[classElement]) |
460 .where((Class cls) => | 463 .where((Class cls) => |
461 !cls.isNative || !_unneededNativeClasses.contains(cls)) | 464 !cls.isNative || !_unneededNativeClasses.contains(cls)) |
462 .toList(growable: false); | 465 .toList(growable: false); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
537 if (selector.isSetter) selectorName = "$selectorName="; | 540 if (selector.isSetter) selectorName = "$selectorName="; |
538 if (backend.symbolsUsed.contains(selectorName)) { | 541 if (backend.symbolsUsed.contains(selectorName)) { |
539 _symbolsMap[name] = selectorName; | 542 _symbolsMap[name] = selectorName; |
540 } | 543 } |
541 noSuchMethodStubs | 544 noSuchMethodStubs |
542 .add(classStubGenerator.generateStubForNoSuchMethod(name, | 545 .add(classStubGenerator.generateStubForNoSuchMethod(name, |
543 selector)); | 546 selector)); |
544 }); | 547 }); |
545 } | 548 } |
546 | 549 |
547 if (element == backend.closureClass) { | 550 if (element == helpers.closureClass) { |
548 // We add a special getter here to allow for tearing off a closure from | 551 // We add a special getter here to allow for tearing off a closure from |
549 // itself. | 552 // itself. |
550 js.Name name = namer.getterForMember(Names.call); | 553 js.Name name = namer.getterForMember(Names.call); |
551 js.Fun function = js.js('function() { return this; }'); | 554 js.Fun function = js.js('function() { return this; }'); |
552 callStubs.add(_buildStubMethod(name, function)); | 555 callStubs.add(_buildStubMethod(name, function)); |
553 } | 556 } |
554 | 557 |
555 ClassElement implementation = element.implementation; | 558 ClassElement implementation = element.implementation; |
556 | 559 |
557 // MixinApplications run through the members of their mixin. Here, we are | 560 // MixinApplications run through the members of their mixin. Here, we are |
558 // only interested in direct members. | 561 // only interested in direct members. |
559 if (!onlyForRti && !element.isMixinApplication) { | 562 if (!onlyForRti && !element.isMixinApplication) { |
560 implementation.forEachMember(visitMember, includeBackendMembers: true); | 563 implementation.forEachMember(visitMember, includeBackendMembers: true); |
561 } | 564 } |
562 | 565 |
563 List<Field> instanceFields = | 566 List<Field> instanceFields = |
564 onlyForRti ? const <Field>[] : _buildFields(element, false); | 567 onlyForRti ? const <Field>[] : _buildFields(element, false); |
565 List<Field> staticFieldsForReflection = | 568 List<Field> staticFieldsForReflection = |
566 onlyForRti ? const <Field>[] : _buildFields(element, true); | 569 onlyForRti ? const <Field>[] : _buildFields(element, true); |
567 | 570 |
568 TypeTestProperties typeTests = | 571 TypeTestProperties typeTests = |
569 runtimeTypeGenerator.generateIsTests( | 572 runtimeTypeGenerator.generateIsTests( |
570 element, | 573 element, |
571 storeFunctionTypeInMetadata: _storeFunctionTypesInMetadata); | 574 storeFunctionTypeInMetadata: _storeFunctionTypesInMetadata); |
572 | 575 |
573 List<StubMethod> checkedSetters = <StubMethod>[]; | 576 List<StubMethod> checkedSetters = <StubMethod>[]; |
574 List<StubMethod> isChecks = <StubMethod>[]; | 577 List<StubMethod> isChecks = <StubMethod>[]; |
575 if (backend.isJsInterop(element)) { | 578 if (backend.isJsInterop(element)) { |
576 typeTests.properties.forEach((js.Name name, js.Node code) { | 579 typeTests.properties.forEach((js.Name name, js.Node code) { |
577 _classes[backend.jsInterceptorClass].isChecks.add( | 580 _classes[helpers.jsInterceptorClass].isChecks.add( |
578 _buildStubMethod(name, code)); | 581 _buildStubMethod(name, code)); |
579 }); | 582 }); |
580 } else { | 583 } else { |
581 for (Field field in instanceFields) { | 584 for (Field field in instanceFields) { |
582 if (field.needsCheckedSetter) { | 585 if (field.needsCheckedSetter) { |
583 assert(!field.needsUncheckedSetter); | 586 assert(!field.needsUncheckedSetter); |
584 Element element = field.element; | 587 Element element = field.element; |
585 js.Expression code = backend.generatedCode[element]; | 588 js.Expression code = backend.generatedCode[element]; |
586 assert(code != null); | 589 assert(code != null); |
587 js.Name name = namer.deriveSetterName(field.accessorName); | 590 js.Name name = namer.deriveSetterName(field.accessorName); |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
807 Class cls = _classes[element]; | 810 Class cls = _classes[element]; |
808 if (cls != null) cls.isEager = true; | 811 if (cls != null) cls.isEager = true; |
809 } | 812 } |
810 } | 813 } |
811 } | 814 } |
812 | 815 |
813 Iterable<StaticStubMethod> _generateGetInterceptorMethods() { | 816 Iterable<StaticStubMethod> _generateGetInterceptorMethods() { |
814 InterceptorStubGenerator stubGenerator = | 817 InterceptorStubGenerator stubGenerator = |
815 new InterceptorStubGenerator(_compiler, namer, backend); | 818 new InterceptorStubGenerator(_compiler, namer, backend); |
816 | 819 |
817 String holderName = namer.globalObjectFor(backend.interceptorsLibrary); | 820 String holderName = namer.globalObjectFor(helpers.interceptorsLibrary); |
818 // TODO(floitsch): we shouldn't update the registry in the middle of | 821 // TODO(floitsch): we shouldn't update the registry in the middle of |
819 // generating the interceptor methods. | 822 // generating the interceptor methods. |
820 Holder holder = _registry.registerHolder(holderName); | 823 Holder holder = _registry.registerHolder(holderName); |
821 | 824 |
822 Map<js.Name, Set<ClassElement>> specializedGetInterceptors = | 825 Map<js.Name, Set<ClassElement>> specializedGetInterceptors = |
823 backend.specializedGetInterceptors; | 826 backend.specializedGetInterceptors; |
824 List<js.Name> names = specializedGetInterceptors.keys.toList()..sort(); | 827 List<js.Name> names = specializedGetInterceptors.keys.toList()..sort(); |
825 return names.map((js.Name name) { | 828 return names.map((js.Name name) { |
826 Set<ClassElement> classes = specializedGetInterceptors[name]; | 829 Set<ClassElement> classes = specializedGetInterceptors[name]; |
827 js.Expression code = stubGenerator.generateGetInterceptorMethod(classes); | 830 js.Expression code = stubGenerator.generateGetInterceptorMethod(classes); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
872 needsCheckedSetter)); | 875 needsCheckedSetter)); |
873 }); | 876 }); |
874 | 877 |
875 return fields; | 878 return fields; |
876 } | 879 } |
877 | 880 |
878 Iterable<StaticStubMethod> _generateOneShotInterceptors() { | 881 Iterable<StaticStubMethod> _generateOneShotInterceptors() { |
879 InterceptorStubGenerator stubGenerator = | 882 InterceptorStubGenerator stubGenerator = |
880 new InterceptorStubGenerator(_compiler, namer, backend); | 883 new InterceptorStubGenerator(_compiler, namer, backend); |
881 | 884 |
882 String holderName = namer.globalObjectFor(backend.interceptorsLibrary); | 885 String holderName = namer.globalObjectFor(helpers.interceptorsLibrary); |
883 // TODO(floitsch): we shouldn't update the registry in the middle of | 886 // TODO(floitsch): we shouldn't update the registry in the middle of |
884 // generating the interceptor methods. | 887 // generating the interceptor methods. |
885 Holder holder = _registry.registerHolder(holderName); | 888 Holder holder = _registry.registerHolder(holderName); |
886 | 889 |
887 List<js.Name> names = backend.oneShotInterceptors.keys.toList()..sort(); | 890 List<js.Name> names = backend.oneShotInterceptors.keys.toList()..sort(); |
888 return names.map((js.Name name) { | 891 return names.map((js.Name name) { |
889 js.Expression code = stubGenerator.generateOneShotInterceptor(name); | 892 js.Expression code = stubGenerator.generateOneShotInterceptor(name); |
890 return new StaticStubMethod(name, holder, code); | 893 return new StaticStubMethod(name, holder, code); |
891 }); | 894 }); |
892 } | 895 } |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
961 Constant constant = new Constant(name, holder, constantValue); | 964 Constant constant = new Constant(name, holder, constantValue); |
962 _constants[constantValue] = constant; | 965 _constants[constantValue] = constant; |
963 } | 966 } |
964 } | 967 } |
965 | 968 |
966 Holder _registerStaticStateHolder() { | 969 Holder _registerStaticStateHolder() { |
967 return _registry.registerHolder( | 970 return _registry.registerHolder( |
968 namer.staticStateHolder, isStaticStateHolder: true); | 971 namer.staticStateHolder, isStaticStateHolder: true); |
969 } | 972 } |
970 } | 973 } |
OLD | NEW |