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

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

Issue 2668233002: Remove code supporting incremental compilation in dart2js (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 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.full_emitter; 5 library dart2js.js_emitter.full_emitter;
6 6
7 import 'dart:collection' show HashMap; 7 import 'dart:collection' show HashMap;
8 import 'dart:convert'; 8 import 'dart:convert';
9 9
10 import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames; 10 import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames;
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
103 Map<OutputUnit, List<VariableElement>> outputStaticNonFinalFieldLists; 103 Map<OutputUnit, List<VariableElement>> outputStaticNonFinalFieldLists;
104 Map<OutputUnit, Set<LibraryElement>> outputLibraryLists; 104 Map<OutputUnit, Set<LibraryElement>> outputLibraryLists;
105 List<TypedefElement> typedefsNeededForReflection; 105 List<TypedefElement> typedefsNeededForReflection;
106 106
107 final ContainerBuilder containerBuilder = new ContainerBuilder(); 107 final ContainerBuilder containerBuilder = new ContainerBuilder();
108 final ClassEmitter classEmitter; 108 final ClassEmitter classEmitter;
109 final NsmEmitter nsmEmitter; 109 final NsmEmitter nsmEmitter;
110 final InterceptorEmitter interceptorEmitter; 110 final InterceptorEmitter interceptorEmitter;
111 111
112 // TODO(johnniwinther): Wrap these fields in a caching strategy. 112 // TODO(johnniwinther): Wrap these fields in a caching strategy.
113 final Set<ConstantValue> cachedEmittedConstants;
114 final List<jsAst.Statement> cachedEmittedConstantsAst = <jsAst.Statement>[]; 113 final List<jsAst.Statement> cachedEmittedConstantsAst = <jsAst.Statement>[];
115 final Map<Element, ClassBuilder> cachedClassBuilders;
116 final Set<Element> cachedElements;
117 114
118 bool needsClassSupport = false; 115 bool needsClassSupport = false;
119 bool needsMixinSupport = false; 116 bool needsMixinSupport = false;
120 bool needsLazyInitializer = false; 117 bool needsLazyInitializer = false;
121 118
122 /// True if [ContainerBuilder.addMemberMethodFromInfo] used "structured info", 119 /// True if [ContainerBuilder.addMemberMethodFromInfo] used "structured info",
123 /// that is, some function was needed for reflection, had stubs, or had a 120 /// that is, some function was needed for reflection, had stubs, or had a
124 /// super alias. 121 /// super alias.
125 bool needsStructuredMemberInfo = false; 122 bool needsStructuredMemberInfo = false;
126 123
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 // this map. 170 // this map.
174 final Map<Fragment, Map<Element, ClassBuilder>> elementDescriptors = 171 final Map<Fragment, Map<Element, ClassBuilder>> elementDescriptors =
175 new Map<Fragment, Map<Element, ClassBuilder>>(); 172 new Map<Fragment, Map<Element, ClassBuilder>>();
176 173
177 final bool generateSourceMap; 174 final bool generateSourceMap;
178 175
179 Emitter(Compiler compiler, Namer namer, ClosedWorld closedWorld, 176 Emitter(Compiler compiler, Namer namer, ClosedWorld closedWorld,
180 this.generateSourceMap, this.task) 177 this.generateSourceMap, this.task)
181 : this.compiler = compiler, 178 : this.compiler = compiler,
182 this.namer = namer, 179 this.namer = namer,
183 cachedEmittedConstants = compiler.cacheStrategy.newSet(),
184 cachedClassBuilders = compiler.cacheStrategy.newMap(),
185 cachedElements = compiler.cacheStrategy.newSet(),
186 classEmitter = new ClassEmitter(closedWorld), 180 classEmitter = new ClassEmitter(closedWorld),
187 interceptorEmitter = new InterceptorEmitter(closedWorld), 181 interceptorEmitter = new InterceptorEmitter(closedWorld),
188 nsmEmitter = new NsmEmitter(closedWorld) { 182 nsmEmitter = new NsmEmitter(closedWorld) {
189 constantEmitter = new ConstantEmitter( 183 constantEmitter = new ConstantEmitter(
190 compiler, namer, this.constantReference, constantListGenerator); 184 compiler, namer, this.constantReference, constantListGenerator);
191 containerBuilder.emitter = this; 185 containerBuilder.emitter = this;
192 classEmitter.emitter = this; 186 classEmitter.emitter = this;
193 nsmEmitter.emitter = this; 187 nsmEmitter.emitter = this;
194 interceptorEmitter.emitter = this; 188 interceptorEmitter.emitter = this;
195 if (compiler.options.hasIncrementalSupport) {
196 // Much like a scout, an incremental compiler is always prepared. For
197 // mixins, classes, and lazy statics, at least.
198 needsClassSupport = true;
199 needsMixinSupport = true;
200 needsLazyInitializer = true;
201 needsStructuredMemberInfo = true;
202 }
203 } 189 }
204 190
205 DiagnosticReporter get reporter => compiler.reporter; 191 DiagnosticReporter get reporter => compiler.reporter;
206 192
207 List<jsAst.Node> cspPrecompiledFunctionFor(OutputUnit outputUnit) { 193 List<jsAst.Node> cspPrecompiledFunctionFor(OutputUnit outputUnit) {
208 return _cspPrecompiledFunctions.putIfAbsent( 194 return _cspPrecompiledFunctions.putIfAbsent(
209 outputUnit, () => new List<jsAst.Node>()); 195 outputUnit, () => new List<jsAst.Node>());
210 } 196 }
211 197
212 List<jsAst.Expression> cspPrecompiledConstructorNamesFor( 198 List<jsAst.Expression> cspPrecompiledConstructorNamesFor(
213 OutputUnit outputUnit) { 199 OutputUnit outputUnit) {
214 return _cspPrecompiledConstructorNames.putIfAbsent( 200 return _cspPrecompiledConstructorNames.putIfAbsent(
215 outputUnit, () => new List<jsAst.Expression>()); 201 outputUnit, () => new List<jsAst.Expression>());
216 } 202 }
217 203
218 /// Erases the precompiled information for csp mode for all output units.
219 /// Used by the incremental compiler.
220 void clearCspPrecompiledNodes() {
221 _cspPrecompiledFunctions.clear();
222 _cspPrecompiledConstructorNames.clear();
223 }
224
225 @override 204 @override
226 bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) { 205 bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) {
227 if (constant.isFunction) return true; // Already emitted. 206 if (constant.isFunction) return true; // Already emitted.
228 if (constant.isPrimitive) return true; // Inlined. 207 if (constant.isPrimitive) return true; // Inlined.
229 if (constant.isDummy) return true; // Inlined. 208 if (constant.isDummy) return true; // Inlined.
230 // The name is null when the constant is already a JS constant. 209 // The name is null when the constant is already a JS constant.
231 // TODO(floitsch): every constant should be registered, so that we can 210 // TODO(floitsch): every constant should be registered, so that we can
232 // share the ones that take up too much space (like some strings). 211 // share the ones that take up too much space (like some strings).
233 if (namer.constantName(constant) == null) return true; 212 if (namer.constantName(constant) == null) return true;
234 return false; 213 return false;
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after
589 }); 568 });
590 } else { 569 } else {
591 return js.comment("Constructors are generated at runtime."); 570 return js.comment("Constructors are generated at runtime.");
592 } 571 }
593 } 572 }
594 573
595 void assembleClass( 574 void assembleClass(
596 Class cls, ClassBuilder enclosingBuilder, Fragment fragment) { 575 Class cls, ClassBuilder enclosingBuilder, Fragment fragment) {
597 ClassElement classElement = cls.element; 576 ClassElement classElement = cls.element;
598 reporter.withCurrentElement(classElement, () { 577 reporter.withCurrentElement(classElement, () {
599 if (compiler.options.hasIncrementalSupport) { 578 classEmitter.emitClass(cls, enclosingBuilder, fragment);
600 ClassBuilder cachedBuilder =
601 cachedClassBuilders.putIfAbsent(classElement, () {
602 ClassBuilder builder = new ClassBuilder.forClass(classElement, namer);
603 classEmitter.emitClass(cls, builder, fragment);
604 return builder;
605 });
606 invariant(classElement, cachedBuilder.fields.isEmpty);
607 invariant(classElement, cachedBuilder.superName == null);
608 invariant(classElement, cachedBuilder.functionType == null);
609 invariant(classElement, cachedBuilder.fieldMetadata == null);
610 enclosingBuilder.properties.addAll(cachedBuilder.properties);
611 } else {
612 classEmitter.emitClass(cls, enclosingBuilder, fragment);
613 }
614 }); 579 });
615 } 580 }
616 581
617 void assembleStaticFunctions( 582 void assembleStaticFunctions(
618 Iterable<Method> staticFunctions, Fragment fragment) { 583 Iterable<Method> staticFunctions, Fragment fragment) {
619 if (staticFunctions == null) return; 584 if (staticFunctions == null) return;
620 585
621 for (Method method in staticFunctions) { 586 for (Method method in staticFunctions) {
622 MethodElement element = method.element; 587 MethodElement element = method.element;
623 // We need to filter out null-elements for the interceptors. 588 // We need to filter out null-elements for the interceptors.
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
734 if (!compiler.options.enableMinification) { 699 if (!compiler.options.enableMinification) {
735 laziesInfo.add(js.quoteName(field.name)); 700 laziesInfo.add(js.quoteName(field.name));
736 } 701 }
737 if (!isMainFragment) { 702 if (!isMainFragment) {
738 laziesInfo.add(js('#', field.holder.name)); 703 laziesInfo.add(js('#', field.holder.name));
739 } 704 }
740 } 705 }
741 return laziesInfo; 706 return laziesInfo;
742 } 707 }
743 708
744 // TODO(sra): Remove this unused function.
745 jsAst.Expression buildLazilyInitializedStaticField(VariableElement element,
746 {String isolateProperties}) {
747 jsAst.Expression code = backend.generatedCode[element];
748 // The code is null if we ended up not needing the lazily
749 // initialized field after all because of constant folding
750 // before code generation.
751 if (code == null) return null;
752 // The code only computes the initial value. We build the lazy-check
753 // here:
754 // lazyInitializer(fieldName, getterName, initial, name, prototype);
755 // The name is used for error reporting. The 'initial' must be a
756 // closure that constructs the initial value.
757 if (isolateProperties != null) {
758 // This is currently only used in incremental compilation to patch
759 // in new lazy values.
760 return js('#(#,#,#,#,#)', [
761 js(lazyInitializerName),
762 js.quoteName(namer.globalPropertyName(element)),
763 js.quoteName(namer.lazyInitializerName(element)),
764 code,
765 js.string(element.name),
766 isolateProperties
767 ]);
768 }
769
770 if (compiler.options.enableMinification) {
771 return js('#(#,#,#)', [
772 js(lazyInitializerName),
773 js.quoteName(namer.globalPropertyName(element)),
774 js.quoteName(namer.lazyInitializerName(element)),
775 code
776 ]);
777 } else {
778 return js('#(#,#,#,#)', [
779 js(lazyInitializerName),
780 js.quoteName(namer.globalPropertyName(element)),
781 js.quoteName(namer.lazyInitializerName(element)),
782 code,
783 js.string(element.name)
784 ]);
785 }
786 }
787
788 jsAst.Statement buildMetadata(Program program, OutputUnit outputUnit) { 709 jsAst.Statement buildMetadata(Program program, OutputUnit outputUnit) {
789 List<jsAst.Statement> parts = <jsAst.Statement>[]; 710 List<jsAst.Statement> parts = <jsAst.Statement>[];
790 711
791 jsAst.Expression types = program.metadataTypesForOutputUnit(outputUnit); 712 jsAst.Expression types = program.metadataTypesForOutputUnit(outputUnit);
792 713
793 if (outputUnit == compiler.deferredLoadTask.mainOutputUnit) { 714 if (outputUnit == compiler.deferredLoadTask.mainOutputUnit) {
794 jsAst.Expression metadataAccess = 715 jsAst.Expression metadataAccess =
795 generateEmbeddedGlobalAccess(embeddedNames.METADATA); 716 generateEmbeddedGlobalAccess(embeddedNames.METADATA);
796 jsAst.Expression typesAccess = 717 jsAst.Expression typesAccess =
797 generateEmbeddedGlobalAccess(embeddedNames.TYPES); 718 generateEmbeddedGlobalAccess(embeddedNames.TYPES);
798 719
799 parts 720 parts
800 ..add(js.statement('# = #;', [metadataAccess, program.metadata])) 721 ..add(js.statement('# = #;', [metadataAccess, program.metadata]))
801 ..add(js.statement('# = #;', [typesAccess, types])); 722 ..add(js.statement('# = #;', [typesAccess, types]));
802 } else if (types != null) { 723 } else if (types != null) {
803 parts.add(js.statement('var ${namer.deferredTypesName} = #;', types)); 724 parts.add(js.statement('var ${namer.deferredTypesName} = #;', types));
804 } 725 }
805 return new jsAst.Block(parts); 726 return new jsAst.Block(parts);
806 } 727 }
807 728
808 jsAst.Statement buildCompileTimeConstants(List<Constant> constants, 729 jsAst.Statement buildCompileTimeConstants(List<Constant> constants,
809 {bool isMainFragment}) { 730 {bool isMainFragment}) {
810 assert(isMainFragment != null); 731 assert(isMainFragment != null);
811 732
812 if (constants.isEmpty) return js.comment("No constants in program."); 733 if (constants.isEmpty) return js.comment("No constants in program.");
813 List<jsAst.Statement> parts = <jsAst.Statement>[]; 734 List<jsAst.Statement> parts = <jsAst.Statement>[];
814 if (compiler.options.hasIncrementalSupport && isMainFragment) {
815 parts = cachedEmittedConstantsAst;
816 }
817 for (Constant constant in constants) { 735 for (Constant constant in constants) {
818 ConstantValue constantValue = constant.value; 736 ConstantValue constantValue = constant.value;
819 if (compiler.options.hasIncrementalSupport && isMainFragment) {
820 if (cachedEmittedConstants.contains(constantValue)) continue;
821 cachedEmittedConstants.add(constantValue);
822 }
823 parts.add(buildConstantInitializer(constantValue)); 737 parts.add(buildConstantInitializer(constantValue));
824 } 738 }
825 739
826 return new jsAst.Block(parts); 740 return new jsAst.Block(parts);
827 } 741 }
828 742
829 jsAst.Statement buildConstantInitializer(ConstantValue constant) { 743 jsAst.Statement buildConstantInitializer(ConstantValue constant) {
830 jsAst.Name name = namer.constantName(constant); 744 jsAst.Name name = namer.constantName(constant);
831 jsAst.Statement initializer = js.statement('#.# = #', [ 745 jsAst.Statement initializer = js.statement('#.# = #', [
832 namer.globalObjectForConstant(constant), 746 namer.globalObjectForConstant(constant),
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
1010 } 924 }
1011 } 925 }
1012 Isolate.prototype = oldIsolate.prototype; 926 Isolate.prototype = oldIsolate.prototype;
1013 Isolate.prototype.constructor = Isolate; 927 Isolate.prototype.constructor = Isolate;
1014 Isolate.#isolatePropertiesName = isolateProperties; 928 Isolate.#isolatePropertiesName = isolateProperties;
1015 if (#outputContainsConstantList) { 929 if (#outputContainsConstantList) {
1016 Isolate.#makeConstListProperty = oldIsolate.#makeConstListProperty; 930 Isolate.#makeConstListProperty = oldIsolate.#makeConstListProperty;
1017 } 931 }
1018 Isolate.#functionThatReturnsNullProperty = 932 Isolate.#functionThatReturnsNullProperty =
1019 oldIsolate.#functionThatReturnsNullProperty; 933 oldIsolate.#functionThatReturnsNullProperty;
1020 if (#hasIncrementalSupport) {
1021 Isolate.#lazyInitializerProperty =
1022 oldIsolate.#lazyInitializerProperty;
1023 }
1024 return Isolate; 934 return Isolate;
1025 } 935 }
1026 936
1027 }''', 937 }''',
1028 { 938 {
1029 'allClasses': allClassesAccess, 939 'allClasses': allClassesAccess,
1030 'getTypeFromName': getTypeFromNameAccess, 940 'getTypeFromName': getTypeFromNameAccess,
1031 'interceptorsByTag': interceptorsByTagAccess, 941 'interceptorsByTag': interceptorsByTagAccess,
1032 'leafTags': leafTagsAccess, 942 'leafTags': leafTagsAccess,
1033 'finishedClasses': finishedClassesAccess, 943 'finishedClasses': finishedClassesAccess,
1034 'needsLazyInitializer': needsLazyInitializer, 944 'needsLazyInitializer': needsLazyInitializer,
1035 'lazies': laziesAccess, 945 'lazies': laziesAccess,
1036 'cyclicThrow': cyclicThrow, 946 'cyclicThrow': cyclicThrow,
1037 'isolatePropertiesName': namer.isolatePropertiesName, 947 'isolatePropertiesName': namer.isolatePropertiesName,
1038 'outputContainsConstantList': outputContainsConstantList, 948 'outputContainsConstantList': outputContainsConstantList,
1039 'makeConstListProperty': makeConstListProperty, 949 'makeConstListProperty': makeConstListProperty,
1040 'functionThatReturnsNullProperty': 950 'functionThatReturnsNullProperty':
1041 backend.rtiEncoder.getFunctionThatReturnsNullName, 951 backend.rtiEncoder.getFunctionThatReturnsNullName,
1042 'hasIncrementalSupport': compiler.options.hasIncrementalSupport,
1043 'lazyInitializerProperty': lazyInitializerProperty,
1044 }); 952 });
1045 } 953 }
1046 954
1047 jsAst.Statement buildConvertToFastObjectFunction() { 955 jsAst.Statement buildConvertToFastObjectFunction() {
1048 List<jsAst.Statement> debugCode = <jsAst.Statement>[]; 956 List<jsAst.Statement> debugCode = <jsAst.Statement>[];
1049 if (DEBUG_FAST_OBJECTS) { 957 if (DEBUG_FAST_OBJECTS) {
1050 debugCode.add(js.statement(r''' 958 debugCode.add(js.statement(r'''
1051 // The following only works on V8 when run with option 959 // The following only works on V8 when run with option
1052 // "--allow-natives-syntax". We use'new Function' because the 960 // "--allow-natives-syntax". We use'new Function' because the
1053 // miniparser does not understand V8 native syntax. 961 // miniparser does not understand V8 native syntax.
(...skipping 27 matching lines...) Expand all
1081 // mode. 989 // mode.
1082 properties.__MAGIC_SLOW_PROPERTY = 1; 990 properties.__MAGIC_SLOW_PROPERTY = 1;
1083 delete properties.__MAGIC_SLOW_PROPERTY; 991 delete properties.__MAGIC_SLOW_PROPERTY;
1084 return properties; 992 return properties;
1085 }'''); 993 }''');
1086 } 994 }
1087 995
1088 jsAst.Statement buildSupportsDirectProtoAccess() { 996 jsAst.Statement buildSupportsDirectProtoAccess() {
1089 jsAst.Statement supportsDirectProtoAccess; 997 jsAst.Statement supportsDirectProtoAccess;
1090 998
1091 if (compiler.options.hasIncrementalSupport) { 999 supportsDirectProtoAccess = js.statement(r'''
1092 supportsDirectProtoAccess = js.statement(r''' 1000 var supportsDirectProtoAccess = (function () {
1093 var supportsDirectProtoAccess = false; 1001 var cls = function () {};
1094 '''); 1002 cls.prototype = {'p': {}};
1095 } else { 1003 var object = new cls();
1096 supportsDirectProtoAccess = js.statement(r''' 1004 if (!(object.__proto__ && object.__proto__.p === cls.prototype.p))
1097 var supportsDirectProtoAccess = (function () { 1005 return false;
1098 var cls = function () {};
1099 cls.prototype = {'p': {}};
1100 var object = new cls();
1101 if (!(object.__proto__ && object.__proto__.p === cls.prototype.p))
1102 return false;
1103
1104 try {
1105 // Are we running on a platform where the performance is good?
1106 // (i.e. Chrome or d8).
1107 1006
1108 // Chrome userAgent? 1007 try {
1109 if (typeof navigator != "undefined" && 1008 // Are we running on a platform where the performance is good?
1110 typeof navigator.userAgent == "string" && 1009 // (i.e. Chrome or d8).
1111 navigator.userAgent.indexOf("Chrome/") >= 0) return true;
1112 1010
1113 // d8 version() looks like "N.N.N.N", jsshell version() like "N". 1011 // Chrome userAgent?
1114 if (typeof version == "function" && 1012 if (typeof navigator != "undefined" &&
1115 version.length == 0) { 1013 typeof navigator.userAgent == "string" &&
1116 var v = version(); 1014 navigator.userAgent.indexOf("Chrome/") >= 0) return true;
1117 if (/^\d+\.\d+\.\d+\.\d+$/.test(v)) return true; 1015
1118 } 1016 // d8 version() looks like "N.N.N.N", jsshell version() like "N".
1119 } catch(_) {} 1017 if (typeof version == "function" &&
1120 1018 version.length == 0) {
1121 return false; 1019 var v = version();
1122 })(); 1020 if (/^\d+\.\d+\.\d+\.\d+$/.test(v)) return true;
1123 '''); 1021 }
1124 } 1022 } catch(_) {}
1023
1024 return false;
1025 })();
1026 ''');
1125 1027
1126 return supportsDirectProtoAccess; 1028 return supportsDirectProtoAccess;
1127 } 1029 }
1128 1030
1129 jsAst.Expression generateLibraryDescriptor( 1031 jsAst.Expression generateLibraryDescriptor(
1130 LibraryElement library, Fragment fragment) { 1032 LibraryElement library, Fragment fragment) {
1131 var uri = ""; 1033 var uri = "";
1132 if (!compiler.options.enableMinification || backend.mustPreserveUris) { 1034 if (!compiler.options.enableMinification || backend.mustPreserveUris) {
1133 uri = library.canonicalUri; 1035 uri = library.canonicalUri;
1134 if (uri.scheme == 'file' && compiler.options.outputUri != null) { 1036 if (uri.scheme == 'file' && compiler.options.outputUri != null) {
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
1372 jsAst.Expression mangledGlobalNamesAccess = 1274 jsAst.Expression mangledGlobalNamesAccess =
1373 generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES); 1275 generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES);
1374 jsAst.ObjectInitializer map = new jsAst.ObjectInitializer(properties); 1276 jsAst.ObjectInitializer map = new jsAst.ObjectInitializer(properties);
1375 parts.add(js.statement('# = #', [mangledGlobalNamesAccess, map])); 1277 parts.add(js.statement('# = #', [mangledGlobalNamesAccess, map]));
1376 } 1278 }
1377 1279
1378 return new jsAst.Block(parts); 1280 return new jsAst.Block(parts);
1379 } 1281 }
1380 1282
1381 void checkEverythingEmitted(Iterable<Element> elements) { 1283 void checkEverythingEmitted(Iterable<Element> elements) {
1382 List<Element> pendingStatics; 1284 List<Element> pendingStatics =
1383 if (!compiler.options.hasIncrementalSupport) { 1285 Elements.sortedByPosition(elements.where((e) => !e.isLibrary));
1384 pendingStatics =
1385 Elements.sortedByPosition(elements.where((e) => !e.isLibrary));
1386 1286
1387 pendingStatics.forEach((element) => reporter.reportInfo( 1287 pendingStatics.forEach((element) => reporter.reportInfo(
1388 element, MessageKind.GENERIC, {'text': 'Pending statics.'})); 1288 element, MessageKind.GENERIC, {'text': 'Pending statics.'}));
1389 }
1390 1289
1391 if (pendingStatics != null && !pendingStatics.isEmpty) { 1290 if (pendingStatics != null && !pendingStatics.isEmpty) {
1392 reporter.internalError( 1291 reporter.internalError(
1393 pendingStatics.first, 'Pending statics (see above).'); 1292 pendingStatics.first, 'Pending statics (see above).');
1394 } 1293 }
1395 } 1294 }
1396 1295
1397 void assembleLibrary(Library library, Fragment fragment) { 1296 void assembleLibrary(Library library, Fragment fragment) {
1398 LibraryElement libraryElement = library.element; 1297 LibraryElement libraryElement = library.element;
1399 1298
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1458 } 1357 }
1459 1358
1460 if (descriptors.isNotEmpty) { 1359 if (descriptors.isNotEmpty) {
1461 List<Element> remainingLibraries = 1360 List<Element> remainingLibraries =
1462 descriptors.keys.where((Element e) => e is LibraryElement).toList(); 1361 descriptors.keys.where((Element e) => e is LibraryElement).toList();
1463 1362
1464 // The remaining descriptors are only accessible through reflection. 1363 // The remaining descriptors are only accessible through reflection.
1465 // The program builder does not collect libraries that only 1364 // The program builder does not collect libraries that only
1466 // contain typedefs that are used for reflection. 1365 // contain typedefs that are used for reflection.
1467 for (LibraryElement element in remainingLibraries) { 1366 for (LibraryElement element in remainingLibraries) {
1468 assert(element is LibraryElement || 1367 assert(element is LibraryElement);
1469 compiler.options.hasIncrementalSupport);
1470 if (element is LibraryElement) { 1368 if (element is LibraryElement) {
1471 parts.add(generateLibraryDescriptor(element, mainFragment)); 1369 parts.add(generateLibraryDescriptor(element, mainFragment));
1472 descriptors.remove(element); 1370 descriptors.remove(element);
1473 } 1371 }
1474 } 1372 }
1475 } 1373 }
1476 jsAst.ArrayInitializer descriptorsAst = new jsAst.ArrayInitializer(parts); 1374 jsAst.ArrayInitializer descriptorsAst = new jsAst.ArrayInitializer(parts);
1477 1375
1478 // Using a named function here produces easier to read stack traces in 1376 // Using a named function here produces easier to read stack traces in
1479 // Chrome/V8. 1377 // Chrome/V8.
1480 statements.add(js.statement( 1378 statements.add(js.statement(
1481 """ 1379 """
1482 (function() { 1380 (function() {
1483 // No renaming in the top-level function to save the locals for the 1381 // No renaming in the top-level function to save the locals for the
1484 // nested context where they will be used more. We have to put the 1382 // nested context where they will be used more. We have to put the
1485 // comment into a hole as the parser strips out comments right away. 1383 // comment into a hole as the parser strips out comments right away.
1486 #disableVariableRenaming; 1384 #disableVariableRenaming;
1487 #supportsDirectProtoAccess; 1385 #supportsDirectProtoAccess;
1488 1386
1489 if (#hasIncrementalSupport) {
1490 #helper = #helper || Object.create(null);
1491 #helper.patch = function(a) { eval(a)};
1492 #helper.schemaChange = #schemaChange;
1493 #helper.addMethod = #addMethod;
1494 #helper.extractStubs =
1495 function(array, name, isStatic, originalDescriptor) {
1496 var descriptor = Object.create(null);
1497 this.addStubs(descriptor, array, name, isStatic, []);
1498 return descriptor;
1499 };
1500 }
1501
1502 if (#isProgramSplit) { 1387 if (#isProgramSplit) {
1503 /// We collect all the global state, so it can be passed to the 1388 /// We collect all the global state, so it can be passed to the
1504 /// initializer of deferred files. 1389 /// initializer of deferred files.
1505 var #globalsHolder = Object.create(null) 1390 var #globalsHolder = Object.create(null)
1506 } 1391 }
1507 1392
1508 // [map] returns an object that V8 shouldn't try to optimize with a 1393 // [map] returns an object that V8 shouldn't try to optimize with a
1509 // hidden class. This prevents a potential performance problem where V8 1394 // hidden class. This prevents a potential performance problem where V8
1510 // tries to build a hidden class for an object used as a hashMap. 1395 // tries to build a hidden class for an object used as a hashMap.
1511 // It requires fewer characters to declare a variable as a parameter than 1396 // It requires fewer characters to declare a variable as a parameter than
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1584 #convertGlobalObjectsToFastObjects; 1469 #convertGlobalObjectsToFastObjects;
1585 #debugFastObjects; 1470 #debugFastObjects;
1586 1471
1587 #init; 1472 #init;
1588 1473
1589 #main; 1474 #main;
1590 })(); 1475 })();
1591 """, 1476 """,
1592 { 1477 {
1593 "disableVariableRenaming": js.comment("/* ::norenaming:: */"), 1478 "disableVariableRenaming": js.comment("/* ::norenaming:: */"),
1594 "hasIncrementalSupport": compiler.options.hasIncrementalSupport,
1595 "helper": js('this.#', [namer.incrementalHelperName]),
1596 "schemaChange": buildSchemaChangeFunction(),
1597 "addMethod": buildIncrementalAddMethod(),
1598 "isProgramSplit": isProgramSplit, 1479 "isProgramSplit": isProgramSplit,
1599 "supportsDirectProtoAccess": buildSupportsDirectProtoAccess(), 1480 "supportsDirectProtoAccess": buildSupportsDirectProtoAccess(),
1600 "globalsHolder": globalsHolder, 1481 "globalsHolder": globalsHolder,
1601 "globalObjectSetup": buildGlobalObjectSetup(isProgramSplit), 1482 "globalObjectSetup": buildGlobalObjectSetup(isProgramSplit),
1602 "isolateName": namer.isolateName, 1483 "isolateName": namer.isolateName,
1603 "isolatePropertiesName": js(isolatePropertiesName), 1484 "isolatePropertiesName": js(isolatePropertiesName),
1604 "initName": initName, 1485 "initName": initName,
1605 "functionThatReturnsNull": buildFunctionThatReturnsNull(), 1486 "functionThatReturnsNull": buildFunctionThatReturnsNull(),
1606 "mangledNames": buildMangledNames(), 1487 "mangledNames": buildMangledNames(),
1607 "setupProgram": 1488 "setupProgram":
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1663 } 1544 }
1664 1545
1665 mainOutput.close(); 1546 mainOutput.close();
1666 1547
1667 if (generateSourceMap) { 1548 if (generateSourceMap) {
1668 outputSourceMap(mainOutput, lineColumnCollector, '', 1549 outputSourceMap(mainOutput, lineColumnCollector, '',
1669 compiler.options.sourceMapUri, compiler.options.outputUri); 1550 compiler.options.sourceMapUri, compiler.options.outputUri);
1670 } 1551 }
1671 } 1552 }
1672 1553
1673 /// Used by incremental compilation to patch up the prototype of
1674 /// [oldConstructor] for use as prototype of [newConstructor].
1675 jsAst.Fun buildSchemaChangeFunction() {
1676 if (!compiler.options.hasIncrementalSupport) return null;
1677 return js('''
1678 function(newConstructor, oldConstructor, superclass) {
1679 // Invariant: newConstructor.prototype has no interesting properties besides
1680 // generated accessors. These are copied to oldPrototype which will be
1681 // updated by other incremental changes.
1682 if (superclass != null) {
1683 this.inheritFrom(newConstructor, superclass);
1684 }
1685 var oldPrototype = oldConstructor.prototype;
1686 var newPrototype = newConstructor.prototype;
1687 var hasOwnProperty = Object.prototype.hasOwnProperty;
1688 for (var property in newPrototype) {
1689 if (hasOwnProperty.call(newPrototype, property)) {
1690 // Copy generated accessors.
1691 oldPrototype[property] = newPrototype[property];
1692 }
1693 }
1694 oldPrototype.__proto__ = newConstructor.prototype.__proto__;
1695 oldPrototype.constructor = newConstructor;
1696 newConstructor.prototype = oldPrototype;
1697 return newConstructor;
1698 }''');
1699 }
1700
1701 /// Used by incremental compilation to patch up an object ([holder]) with a
1702 /// new (or updated) method. [arrayOrFunction] is either the new method, or
1703 /// an array containing the method (see
1704 /// [ContainerBuilder.addMemberMethodFromInfo]). [name] is the name of the
1705 /// new method. [isStatic] tells if method is static (or
1706 /// top-level). [globalFunctionsAccess] is a reference to
1707 /// [embeddedNames.GLOBAL_FUNCTIONS].
1708 jsAst.Fun buildIncrementalAddMethod() {
1709 if (!compiler.options.hasIncrementalSupport) return null;
1710 return js(r"""
1711 function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) {
1712 var arrayOrFunction = originalDescriptor[name];
1713 var method;
1714 if (arrayOrFunction.constructor === Array) {
1715 var existing = holder[name];
1716 var array = arrayOrFunction;
1717
1718 // Each method may have a number of stubs associated. For example, if an
1719 // instance method supports multiple arguments, a stub for each matching
1720 // selector. There is also a getter stub for tear-off getters. For example,
1721 // an instance method foo([a]) may have the following stubs: foo$0, foo$1,
1722 // and get$foo (here exemplified using unminified names).
1723 // [extractStubs] returns a JavaScript object whose own properties
1724 // corresponds to the stubs.
1725 var descriptor =
1726 this.extractStubs(array, name, isStatic, originalDescriptor);
1727 method = descriptor[name];
1728
1729 // Iterate through the properties of descriptor and copy the stubs to the
1730 // existing holder (for instance methods, a prototype).
1731 for (var property in descriptor) {
1732 if (!Object.prototype.hasOwnProperty.call(descriptor, property)) continue;
1733 var stub = descriptor[property];
1734 var existingStub = holder[property];
1735 if (stub === method || !existingStub || !stub.$getterStub) {
1736 // Not replacing an existing getter stub.
1737 holder[property] = stub;
1738 continue;
1739 }
1740 if (!stub.$getterStub) {
1741 var error = new Error('Unexpected stub.');
1742 error.stub = stub;
1743 throw error;
1744 }
1745
1746 // Existing getter stubs need special treatment as they may already have
1747 // been called and produced a closure.
1748 this.pendingStubs = this.pendingStubs || [];
1749 // It isn't safe to invoke the stub yet.
1750 this.pendingStubs.push((function(holder, stub, existingStub, existing,
1751 method) {
1752 return function() {
1753 var receiver = isStatic ? holder : new holder.constructor();
1754 // Invoke the existing stub to obtain the tear-off closure.
1755 existingStub = existingStub.call(receiver);
1756 // Invoke the new stub to create a tear-off closure we can use as a
1757 // prototype.
1758 stub = stub.call(receiver);
1759
1760 // Copy the properties from the new tear-off's prototype to the
1761 // prototype of the existing tear-off.
1762 var newProto = stub.constructor.prototype;
1763 var existingProto = existingStub.constructor.prototype;
1764 for (var stubProperty in newProto) {
1765 if (!Object.prototype.hasOwnProperty.call(newProto, stubProperty))
1766 continue;
1767 existingProto[stubProperty] = newProto[stubProperty];
1768 }
1769
1770 // Update all the existing stub's references to [existing] to
1771 // [method]. Instance tear-offs are call-by-name, so this isn't
1772 // necessary for those.
1773 if (!isStatic) return;
1774 for (var reference in existingStub) {
1775 if (existingStub[reference] === existing) {
1776 existingStub[reference] = method;
1777 }
1778 }
1779 }
1780 })(holder, stub, existingStub, existing, method));
1781 }
1782 } else {
1783 method = arrayOrFunction;
1784 holder[name] = method;
1785 }
1786 if (isStatic) globalFunctionsAccess[name] = method;
1787 }""");
1788 }
1789
1790 Map<OutputUnit, jsAst.Expression> buildDescriptorsForOutputUnits( 1554 Map<OutputUnit, jsAst.Expression> buildDescriptorsForOutputUnits(
1791 Program program) { 1555 Program program) {
1792 Map<OutputUnit, jsAst.Expression> outputs = 1556 Map<OutputUnit, jsAst.Expression> outputs =
1793 new Map<OutputUnit, jsAst.Expression>(); 1557 new Map<OutputUnit, jsAst.Expression>();
1794 1558
1795 for (Fragment fragment in program.deferredFragments) { 1559 for (Fragment fragment in program.deferredFragments) {
1796 OutputUnit outputUnit = fragment.outputUnit; 1560 OutputUnit outputUnit = fragment.outputUnit;
1797 1561
1798 Map<Element, ClassBuilder> descriptors = elementDescriptors[fragment]; 1562 Map<Element, ClassBuilder> descriptors = elementDescriptors[fragment];
1799 1563
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after
2171 // Json does not support comments, so we embed the explanation in the 1935 // Json does not support comments, so we embed the explanation in the
2172 // data. 1936 // data.
2173 mapping["_comment"] = "This mapping shows which compiled `.js` files are " 1937 mapping["_comment"] = "This mapping shows which compiled `.js` files are "
2174 "needed for a given deferred library import."; 1938 "needed for a given deferred library import.";
2175 mapping.addAll(compiler.deferredLoadTask.computeDeferredMap()); 1939 mapping.addAll(compiler.deferredLoadTask.computeDeferredMap());
2176 compiler.outputProvider( 1940 compiler.outputProvider(
2177 compiler.options.deferredMapUri.path, 'deferred_map') 1941 compiler.options.deferredMapUri.path, 'deferred_map')
2178 ..add(const JsonEncoder.withIndent(" ").convert(mapping)) 1942 ..add(const JsonEncoder.withIndent(" ").convert(mapping))
2179 ..close(); 1943 ..close();
2180 } 1944 }
2181
2182 void invalidateCaches() {
2183 if (!compiler.options.hasIncrementalSupport) return;
2184 if (cachedElements.isEmpty) return;
2185 for (Element element in backend.codegenEnqueuer.newlyEnqueuedElements) {
2186 if (element.isInstanceMember) {
2187 cachedClassBuilders.remove(element.enclosingClass);
2188 }
2189 }
2190 }
2191 } 1945 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698