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

Side by Side Diff: dart/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart

Issue 16580014: Don't create part.js when there is no deferred loading. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 6 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | dart/tests/compiler/dart2js/unneeded_part_js_test.dart » ('j') | 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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 part of js_backend; 5 part of js_backend;
6 6
7 /** 7 /**
8 * A function element that represents a closure call. The signature is copied 8 * A function element that represents a closure call. The signature is copied
9 * from the given element. 9 * from the given element.
10 */ 10 */
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 */ 56 */
57 class CodeEmitterTask extends CompilerTask { 57 class CodeEmitterTask extends CompilerTask {
58 bool needsInheritFunction = false; 58 bool needsInheritFunction = false;
59 bool needsDefineClass = false; 59 bool needsDefineClass = false;
60 bool needsMixinSupport = false; 60 bool needsMixinSupport = false;
61 bool needsLazyInitializer = false; 61 bool needsLazyInitializer = false;
62 final Namer namer; 62 final Namer namer;
63 ConstantEmitter constantEmitter; 63 ConstantEmitter constantEmitter;
64 NativeEmitter nativeEmitter; 64 NativeEmitter nativeEmitter;
65 CodeBuffer mainBuffer; 65 CodeBuffer mainBuffer;
66 final CodeBuffer deferredBuffer = new CodeBuffer(); 66 final CodeBuffer deferredLibraries = new CodeBuffer();
67 final CodeBuffer deferredConstants = new CodeBuffer();
67 /** Shorter access to [isolatePropertiesName]. Both here in the code, as 68 /** Shorter access to [isolatePropertiesName]. Both here in the code, as
68 well as in the generated code. */ 69 well as in the generated code. */
69 String isolateProperties; 70 String isolateProperties;
70 String classesCollector; 71 String classesCollector;
71 final Set<ClassElement> neededClasses = new Set<ClassElement>(); 72 final Set<ClassElement> neededClasses = new Set<ClassElement>();
72 final List<ClassElement> regularClasses = <ClassElement>[]; 73 final List<ClassElement> regularClasses = <ClassElement>[];
73 final List<ClassElement> deferredClasses = <ClassElement>[]; 74 final List<ClassElement> deferredClasses = <ClassElement>[];
74 final List<ClassElement> nativeClasses = <ClassElement>[]; 75 final List<ClassElement> nativeClasses = <ClassElement>[];
75 final List<Selector> trivialNsmHandlers = <Selector>[]; 76 final List<Selector> trivialNsmHandlers = <Selector>[];
76 final Map<String, String> mangledFieldNames = <String, String>{}; 77 final Map<String, String> mangledFieldNames = <String, String>{};
(...skipping 1817 matching lines...) Expand 10 before | Expand all | Expand 10 after
1894 emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode); 1895 emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode);
1895 } 1896 }
1896 } 1897 }
1897 1898
1898 final Map<Element, Element> staticGetters = new Map<Element, Element>(); 1899 final Map<Element, Element> staticGetters = new Map<Element, Element>();
1899 1900
1900 void emitStaticFunctionGetters(CodeBuffer eagerBuffer) { 1901 void emitStaticFunctionGetters(CodeBuffer eagerBuffer) {
1901 for (FunctionElement element in 1902 for (FunctionElement element in
1902 Elements.sortedByPosition(staticGetters.keys)) { 1903 Elements.sortedByPosition(staticGetters.keys)) {
1903 Element closure = staticGetters[element]; 1904 Element closure = staticGetters[element];
1904 // TODO(ahe): This should be emitted as a constant. Currently, 1905 CodeBuffer buffer = isDeferred(element) ? deferredConstants : eagerBuffer;
1905 // this breaks deferred loading.
1906 CodeBuffer buffer = eagerBuffer;
1907 String closureClass = namer.isolateAccess(closure); 1906 String closureClass = namer.isolateAccess(closure);
1908 String name = namer.getStaticClosureName(element); 1907 String name = namer.getStaticClosureName(element);
1909 String staticName = namer.getName(element); 1908 String staticName = namer.getName(element);
1910 1909
1911 String closureName = namer.getStaticClosureName(element); 1910 String closureName = namer.getStaticClosureName(element);
1912 jsAst.Node assignment = js('$isolateProperties.$name = ' 1911 jsAst.Node assignment = js('$isolateProperties.$name = '
1913 'new $closureClass($isolateProperties.$staticName, "$closureName")'); 1912 'new $closureClass($isolateProperties.$staticName, "$closureName")');
1914 buffer.write(jsAst.prettyPrint(assignment, compiler)); 1913 buffer.write(jsAst.prettyPrint(assignment, compiler));
1915 buffer.write('$N'); 1914 buffer.write('$N');
1916 } 1915 }
(...skipping 1203 matching lines...) Expand 10 before | Expand all | Expand 10 after
3120 mainBuffer.write( 3119 mainBuffer.write(
3121 jsAst.prettyPrint( 3120 jsAst.prettyPrint(
3122 js('init.mangledNames = #', map).toStatement(), compiler)); 3121 js('init.mangledNames = #', map).toStatement(), compiler));
3123 if (compiler.enableMinification) { 3122 if (compiler.enableMinification) {
3124 mainBuffer.write(';'); 3123 mainBuffer.write(';');
3125 } 3124 }
3126 } 3125 }
3127 mainBuffer 3126 mainBuffer
3128 ..write(getReflectionDataParser()) 3127 ..write(getReflectionDataParser())
3129 ..write('([$n'); 3128 ..write('([$n');
3130 emitDeferredPreambleWhenEmpty(deferredBuffer);
3131 deferredBuffer.add('\$\$$_=$_{};$n');
3132 3129
3133 deferredBuffer
3134 ..write(getReflectionDataParser())
3135 ..write('([$n');
3136 var sortedLibraries = Elements.sortedByPosition(libraryBuffers.keys); 3130 var sortedLibraries = Elements.sortedByPosition(libraryBuffers.keys);
3137 for (LibraryElement library in sortedLibraries) { 3131 for (LibraryElement library in sortedLibraries) {
3138 List<CodeBuffer> buffers = libraryBuffers[library]; 3132 List<CodeBuffer> buffers = libraryBuffers[library];
3139 var buffer = buffers[0]; 3133 var buffer = buffers[0];
3140 var uri = library.canonicalUri; 3134 var uri = library.canonicalUri;
3141 if (uri.scheme == 'file' && compiler.sourceMapUri != null) { 3135 if (uri.scheme == 'file' && compiler.sourceMapUri != null) {
3142 // TODO(ahe): It is a hack to use compiler.sourceMapUri 3136 // TODO(ahe): It is a hack to use compiler.sourceMapUri
3143 // here. It should be relative to the main JavaScript 3137 // here. It should be relative to the main JavaScript
3144 // output file. 3138 // output file.
3145 uri = relativize( 3139 uri = relativize(
3146 compiler.sourceMapUri, library.canonicalUri, false); 3140 compiler.sourceMapUri, library.canonicalUri, false);
3147 } 3141 }
3148 if (buffer != null) { 3142 if (buffer != null) {
3149 var metadata = buildMetadataFunction(library); 3143 var metadata = buildMetadataFunction(library);
3150 mainBuffer 3144 mainBuffer
3151 ..write('["${library.getLibraryOrScriptName()}",$_') 3145 ..write('["${library.getLibraryOrScriptName()}",$_')
3152 ..write('"${uri}",$_') 3146 ..write('"${uri}",$_')
3153 ..write(metadata == null 3147 ..write(metadata == null
3154 ? "" : jsAst.prettyPrint(metadata, compiler)) 3148 ? "" : jsAst.prettyPrint(metadata, compiler))
3155 ..write(',$_') 3149 ..write(',$_')
3156 ..write('{$n') 3150 ..write('{$n')
3157 ..addBuffer(buffer) 3151 ..addBuffer(buffer)
3158 ..write('}],$n'); 3152 ..write('}],$n');
3159 } 3153 }
3160 buffer = buffers[1]; 3154 buffer = buffers[1];
3161 if (buffer != null) { 3155 if (buffer != null) {
3162 deferredBuffer 3156 deferredLibraries
3163 ..write('["${library.getLibraryOrScriptName()}",$_') 3157 ..write('["${library.getLibraryOrScriptName()}",$_')
3164 ..write('"${uri}",$_') 3158 ..write('"${uri}",$_')
3165 ..write('[],$_') 3159 ..write('[],$_')
3166 ..write('{$n') 3160 ..write('{$n')
3167 ..addBuffer(buffer) 3161 ..addBuffer(buffer)
3168 ..write('}],$n'); 3162 ..write('}],$n');
3169 } 3163 }
3170 libraryBuffers[library] = const []; 3164 libraryBuffers[library] = const [];
3171 } 3165 }
3172 mainBuffer.write('])$N'); 3166 mainBuffer.write('])$N');
3173 3167
3174 deferredBuffer.write('])$N');
3175 if (!deferredClasses.isEmpty) {
3176 deferredBuffer.add('$finishClassesName(\$\$,'
3177 '$_${namer.CURRENT_ISOLATE},'
3178 '$_$isolatePropertiesName)$N');
3179 }
3180
3181 // Reset the map.
3182 deferredBuffer.add("\$\$$_=${_}null$N$n");
3183 emitFinishClassesInvocationIfNecessary(mainBuffer); 3168 emitFinishClassesInvocationIfNecessary(mainBuffer);
3184 classesCollector = oldClassesCollector; 3169 classesCollector = oldClassesCollector;
3185 } 3170 }
3186 3171
3187 emitStaticFunctionGetters(mainBuffer); 3172 emitStaticFunctionGetters(mainBuffer);
3188 3173
3189 emitRuntimeTypeSupport(mainBuffer); 3174 emitRuntimeTypeSupport(mainBuffer);
3190 emitCompileTimeConstants(mainBuffer); 3175 emitCompileTimeConstants(mainBuffer);
3191 // Static field initializations require the classes and compile-time 3176 // Static field initializations require the classes and compile-time
3192 // constants to be set up. 3177 // constants to be set up.
(...skipping 13 matching lines...) Expand all
3206 3191
3207 emitFinishIsolateConstructorInvocation(mainBuffer); 3192 emitFinishIsolateConstructorInvocation(mainBuffer);
3208 mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_=' 3193 mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_='
3209 '${_}new ${namer.isolateName}()$N'); 3194 '${_}new ${namer.isolateName}()$N');
3210 3195
3211 emitMain(mainBuffer); 3196 emitMain(mainBuffer);
3212 emitInitFunction(mainBuffer); 3197 emitInitFunction(mainBuffer);
3213 compiler.assembledCode = mainBuffer.getText(); 3198 compiler.assembledCode = mainBuffer.getText();
3214 outputSourceMap(mainBuffer, compiler.assembledCode, ''); 3199 outputSourceMap(mainBuffer, compiler.assembledCode, '');
3215 3200
3216 emitDeferredCode(deferredBuffer); 3201 emitDeferredCode();
3217 3202
3218 }); 3203 });
3219 return compiler.assembledCode; 3204 return compiler.assembledCode;
3220 } 3205 }
3221 3206
3222 final Map<LibraryElement, List<CodeBuffer>> libraryBuffers = 3207 final Map<LibraryElement, List<CodeBuffer>> libraryBuffers =
3223 new Map<LibraryElement, List<CodeBuffer>>(); 3208 new Map<LibraryElement, List<CodeBuffer>>();
3224 3209
3225 CodeBuffer bufferForElement(Element element, CodeBuffer eagerBuffer) { 3210 CodeBuffer bufferForElement(Element element, CodeBuffer eagerBuffer) {
3226 LibraryElement library = element.getLibrary(); 3211 LibraryElement library = element.getLibrary();
3227 List<CodeBuffer> buffers = libraryBuffers.putIfAbsent( 3212 List<CodeBuffer> buffers = libraryBuffers.putIfAbsent(
3228 library, () => <CodeBuffer>[null, null]); 3213 library, () => <CodeBuffer>[null, null]);
3229 bool deferred = isDeferred(element); 3214 bool deferred = isDeferred(element);
3230 int index = deferred ? 1 : 0; 3215 int index = deferred ? 1 : 0;
3231 CodeBuffer buffer = buffers[index]; 3216 CodeBuffer buffer = buffers[index];
3232 if (buffer == null) { 3217 if (buffer == null) {
3233 buffer = buffers[index] = new CodeBuffer(); 3218 buffer = buffers[index] = new CodeBuffer();
3234 } 3219 }
3235 return buffer; 3220 return buffer;
3236 } 3221 }
3237 3222
3238 bool firstDeferredConstant = true;
3239
3240 /** 3223 /**
3241 * Returns the appropriate buffer for [constant]. If [constant] is 3224 * Returns the appropriate buffer for [constant]. If [constant] is
3242 * itself an instance of a deferred type (or built from constants 3225 * itself an instance of a deferred type (or built from constants
3243 * that are instances of deferred types) attempting to use 3226 * that are instances of deferred types) attempting to use
3244 * [constant] before the deferred type has been loaded will not 3227 * [constant] before the deferred type has been loaded will not
3245 * work, and [constant] itself must be deferred. 3228 * work, and [constant] itself must be deferred.
3246 */ 3229 */
3247 CodeBuffer bufferForConstant(Constant constant, CodeBuffer eagerBuffer) { 3230 CodeBuffer bufferForConstant(Constant constant, CodeBuffer eagerBuffer) {
3248 var queue = new Queue()..add(constant); 3231 var queue = new Queue()..add(constant);
3249 while (!queue.isEmpty) { 3232 while (!queue.isEmpty) {
3250 constant = queue.removeFirst(); 3233 constant = queue.removeFirst();
3251 if (isDeferred(constant.computeType(compiler).element)) { 3234 if (isDeferred(constant.computeType(compiler).element)) {
3252 emitDeferredPreambleWhenEmpty(deferredBuffer); 3235 return deferredConstants;
3253 if (firstDeferredConstant) {
3254 deferredBuffer.write(
3255 '${namer.CURRENT_ISOLATE}$_=${_}old${namer.CURRENT_ISOLATE}$N');
3256 deferredBuffer.write(
3257 'old${namer.CURRENT_ISOLATE}$_=${_}${namer.CURRENT_ISOLATE}$N');
3258 }
3259 firstDeferredConstant = false;
3260 return deferredBuffer;
3261 } 3236 }
3262 queue.addAll(constant.getDependencies()); 3237 queue.addAll(constant.getDependencies());
3263 } 3238 }
3264 return eagerBuffer; 3239 return eagerBuffer;
3265 } 3240 }
3266 3241
3267 void emitDeferredCode(CodeBuffer buffer) {
3268 if (buffer.isEmpty) return;
3269 3242
3270 buffer.write(n);
3271 3243
3272 buffer.write( 3244 void emitDeferredCode() {
3273 '${namer.CURRENT_ISOLATE}$_=${_}old${namer.CURRENT_ISOLATE}$N'); 3245 if (deferredLibraries.isEmpty && deferredConstants.isEmpty) return;
3246
3247 var oldClassesCollector = classesCollector;
3248 classesCollector = r"$$";
3249
3250 // It does not make sense to defer constants if there are no
3251 // deferred elements.
3252 assert(!deferredLibraries.isEmpty);
3253
3254 var buffer = new CodeBuffer()
3255 ..write(buildGeneratedBy())
3256 ..write('var old${namer.CURRENT_ISOLATE}$_='
3257 '$_${namer.CURRENT_ISOLATE}$N'
3258 // TODO(ahe): This defines a lot of properties on the
3259 // Isolate.prototype object. We know this will turn it into a
3260 // slow object in V8, so instead we should do something similar
3261 // to Isolate.$finishIsolateConstructor.
3262 '${namer.CURRENT_ISOLATE}$_='
3263 '$_${namer.isolateName}.prototype$N$n'
3264 // The classesCollector object ($$).
3265 '$classesCollector$_=$_{};$n')
3266 ..write(getReflectionDataParser())
3267 ..write('([$n')
3268 ..addBuffer(deferredLibraries)
3269 ..write('])$N');
3270
3271 if (!deferredClasses.isEmpty) {
3272 buffer.add('$finishClassesName($classesCollector,$_${namer.CURRENT_ISOLATE },'
kasperl 2013/06/10 07:27:47 Long line.
ahe 2013/06/10 07:32:36 Done.
3273 '$_$isolatePropertiesName)$N');
3274 }
3275
3276 buffer
kasperl 2013/06/10 07:27:47 I prefer having .write on the same line as buffer.
ahe 2013/06/10 07:32:36 Done.
3277 // Reset the classesCollector ($$).
3278 .write('$classesCollector$_=${_}null$N$n'
3279 '${namer.CURRENT_ISOLATE}$_=${_}old${namer.CURRENT_ISOLATE}$N');
3280
3281 classesCollector = oldClassesCollector;
3282
3283 if (!deferredConstants.isEmpty) {
3284 buffer.addBuffer(deferredConstants);
3285 }
3274 3286
3275 String code = buffer.getText(); 3287 String code = buffer.getText();
3276 compiler.outputProvider('part', 'js') 3288 compiler.outputProvider('part', 'js')
3277 ..add(code) 3289 ..add(code)
3278 ..close(); 3290 ..close();
3279 outputSourceMap(buffer, compiler.assembledCode, 'part'); 3291 outputSourceMap(buffer, compiler.assembledCode, 'part');
3280 } 3292 }
3281 3293
3282 void emitDeferredPreambleWhenEmpty(CodeBuffer buffer) {
3283 if (!buffer.isEmpty) return;
3284
3285 buffer.write(buildGeneratedBy());
3286
3287 buffer.write('var old${namer.CURRENT_ISOLATE}$_='
3288 '$_${namer.CURRENT_ISOLATE}$N');
3289
3290 // TODO(ahe): This defines a lot of properties on the
3291 // Isolate.prototype object. We know this will turn it into a
3292 // slow object in V8, so instead we should do something similar to
3293 // Isolate.$finishIsolateConstructor.
3294 buffer.write('${namer.CURRENT_ISOLATE}$_='
3295 '$_${namer.isolateName}.prototype$N$n');
3296 }
3297
3298 String buildGeneratedBy() { 3294 String buildGeneratedBy() {
3299 var suffix = ''; 3295 var suffix = '';
3300 if (compiler.hasBuildId) suffix = ' version: ${compiler.buildId}'; 3296 if (compiler.hasBuildId) suffix = ' version: ${compiler.buildId}';
3301 return '// Generated by dart2js, the Dart to JavaScript compiler$suffix.\n'; 3297 return '// Generated by dart2js, the Dart to JavaScript compiler$suffix.\n';
3302 } 3298 }
3303 3299
3304 String buildSourceMap(CodeBuffer buffer, SourceFile compiledFile) { 3300 String buildSourceMap(CodeBuffer buffer, SourceFile compiledFile) {
3305 SourceMapBuilder sourceMapBuilder = 3301 SourceMapBuilder sourceMapBuilder =
3306 new SourceMapBuilder(compiler.sourceMapUri); 3302 new SourceMapBuilder(compiler.sourceMapUri);
3307 buffer.forEachSourceLocation(sourceMapBuilder.addMapping); 3303 buffer.forEachSourceLocation(sourceMapBuilder.addMapping);
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
3386 3382
3387 const String HOOKS_API_USAGE = """ 3383 const String HOOKS_API_USAGE = """
3388 // The code supports the following hooks: 3384 // The code supports the following hooks:
3389 // dartPrint(message) - if this function is defined it is called 3385 // dartPrint(message) - if this function is defined it is called
3390 // instead of the Dart [print] method. 3386 // instead of the Dart [print] method.
3391 // dartMainRunner(main) - if this function is defined, the Dart [main] 3387 // dartMainRunner(main) - if this function is defined, the Dart [main]
3392 // method will not be invoked directly. 3388 // method will not be invoked directly.
3393 // Instead, a closure that will invoke [main] is 3389 // Instead, a closure that will invoke [main] is
3394 // passed to [dartMainRunner]. 3390 // passed to [dartMainRunner].
3395 """; 3391 """;
OLDNEW
« no previous file with comments | « no previous file | dart/tests/compiler/dart2js/unneeded_part_js_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698