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

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

Issue 12033003: Deferred (aka lazy) loading of static functions. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebased Created 7 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 | Annotate | Revision Log
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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 class CodeEmitterTask extends CompilerTask { 52 class CodeEmitterTask extends CompilerTask {
53 bool needsInheritFunction = false; 53 bool needsInheritFunction = false;
54 bool needsDefineClass = false; 54 bool needsDefineClass = false;
55 bool needsClosureClass = false; 55 bool needsClosureClass = false;
56 bool needsLazyInitializer = false; 56 bool needsLazyInitializer = false;
57 final Namer namer; 57 final Namer namer;
58 ConstantEmitter constantEmitter; 58 ConstantEmitter constantEmitter;
59 NativeEmitter nativeEmitter; 59 NativeEmitter nativeEmitter;
60 CodeBuffer boundClosureBuffer; 60 CodeBuffer boundClosureBuffer;
61 CodeBuffer mainBuffer; 61 CodeBuffer mainBuffer;
62 final CodeBuffer deferredBuffer = new CodeBuffer();
62 /** Shorter access to [isolatePropertiesName]. Both here in the code, as 63 /** Shorter access to [isolatePropertiesName]. Both here in the code, as
63 well as in the generated code. */ 64 well as in the generated code. */
64 String isolateProperties; 65 String isolateProperties;
65 String classesCollector; 66 String classesCollector;
66 Set<ClassElement> neededClasses; 67 Set<ClassElement> neededClasses;
67 // TODO(ngeoffray): remove this field. 68 // TODO(ngeoffray): remove this field.
68 Set<ClassElement> instantiatedClasses; 69 Set<ClassElement> instantiatedClasses;
69 70
70 String get _ => compiler.enableMinification ? "" : " "; 71 String get _ => compiler.enableMinification ? "" : " ";
71 String get n => compiler.enableMinification ? "" : "\n"; 72 String get n => compiler.enableMinification ? "" : "\n";
(...skipping 1289 matching lines...) Expand 10 before | Expand all | Expand 10 after
1361 Element member = element.lookupLocalMember(noSuchMethodName); 1362 Element member = element.lookupLocalMember(noSuchMethodName);
1362 if (member == null) continue; 1363 if (member == null) continue;
1363 if (noSuchMethodSelector.applies(member, compiler)) { 1364 if (noSuchMethodSelector.applies(member, compiler)) {
1364 nativeEmitter.handleNoSuchMethod = true; 1365 nativeEmitter.handleNoSuchMethod = true;
1365 break; 1366 break;
1366 } 1367 }
1367 } 1368 }
1368 } 1369 }
1369 1370
1370 for (ClassElement element in sortedClasses) { 1371 for (ClassElement element in sortedClasses) {
1372 if (isDeferred(element)) continue;
1371 generateClass(element, buffer); 1373 generateClass(element, buffer);
1372 } 1374 }
1373 1375
1374 // The closure class could have become necessary because of the generation 1376 // The closure class could have become necessary because of the generation
1375 // of stubs. 1377 // of stubs.
1376 ClassElement closureClass = compiler.closureClass; 1378 ClassElement closureClass = compiler.closureClass;
1377 if (needsClosureClass && !instantiatedClasses.contains(closureClass)) { 1379 if (needsClosureClass && !instantiatedClasses.contains(closureClass)) {
1378 generateClass(closureClass, buffer); 1380 generateClass(closureClass, buffer);
1379 } 1381 }
1380 } 1382 }
1381 1383
1382 void emitFinishClassesInvocationIfNecessary(CodeBuffer buffer) { 1384 void emitFinishClassesInvocationIfNecessary(CodeBuffer buffer) {
1383 if (needsDefineClass) { 1385 if (needsDefineClass) {
1384 buffer.add("$finishClassesName($classesCollector)$N"); 1386 buffer.add("$finishClassesName($classesCollector)$N");
1385 // Reset the map. 1387 // Reset the map.
1386 buffer.add("$classesCollector$_=$_{}$N"); 1388 buffer.add("$classesCollector$_=$_{}$N");
1387 } 1389 }
1388 } 1390 }
1389 1391
1390 void emitStaticFunction(CodeBuffer buffer, 1392 void emitStaticFunction(CodeBuffer buffer,
1391 String name, 1393 String name,
1392 js.Expression functionExpression) { 1394 js.Expression functionExpression) {
1393 js.Expression assignment = 1395 js.Expression assignment =
1394 js.assign(js.use(isolateProperties).dot(name), functionExpression); 1396 js.assign(js.use(isolateProperties).dot(name), functionExpression);
1395 buffer.add(js.prettyPrint(assignment, compiler)); 1397 buffer.add(js.prettyPrint(assignment, compiler));
1396 buffer.add('$N$n'); 1398 buffer.add('$N$n');
1397 } 1399 }
1398 1400
1399 void emitStaticFunctions(CodeBuffer buffer) { 1401 void emitStaticFunctions(CodeBuffer eagerBuffer) {
1400 bool isStaticFunction(Element element) => 1402 bool isStaticFunction(Element element) =>
1401 !element.isInstanceMember() && !element.isField(); 1403 !element.isInstanceMember() && !element.isField();
1402 1404
1403 Iterable<Element> elements = 1405 Iterable<Element> elements =
1404 compiler.codegenWorld.generatedCode.keys.where(isStaticFunction); 1406 compiler.codegenWorld.generatedCode.keys.where(isStaticFunction);
1405 Set<Element> pendingElementsWithBailouts = 1407 Set<Element> pendingElementsWithBailouts =
1406 compiler.codegenWorld.generatedBailoutCode.keys 1408 compiler.codegenWorld.generatedBailoutCode.keys
1407 .where(isStaticFunction) 1409 .where(isStaticFunction)
1408 .toSet(); 1410 .toSet();
1409 1411
1410 for (Element element in Elements.sortedByPosition(elements)) { 1412 for (Element element in Elements.sortedByPosition(elements)) {
1413 CodeBuffer buffer = isDeferred(element) ? deferredBuffer : eagerBuffer;
1411 js.Expression code = compiler.codegenWorld.generatedCode[element]; 1414 js.Expression code = compiler.codegenWorld.generatedCode[element];
1412 emitStaticFunction(buffer, namer.getName(element), code); 1415 emitStaticFunction(buffer, namer.getName(element), code);
1413 js.Expression bailoutCode = 1416 js.Expression bailoutCode =
1414 compiler.codegenWorld.generatedBailoutCode[element]; 1417 compiler.codegenWorld.generatedBailoutCode[element];
1415 if (bailoutCode != null) { 1418 if (bailoutCode != null) {
1416 pendingElementsWithBailouts.remove(element); 1419 pendingElementsWithBailouts.remove(element);
1417 emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode); 1420 emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode);
1418 } 1421 }
1419 } 1422 }
1420 1423
1421 // Is it possible the primary function was inlined but the bailout was not? 1424 // Is it possible the primary function was inlined but the bailout was not?
1422 for (Element element in 1425 for (Element element in
1423 Elements.sortedByPosition(pendingElementsWithBailouts)) { 1426 Elements.sortedByPosition(pendingElementsWithBailouts)) {
1427 CodeBuffer buffer = isDeferred(element) ? deferredBuffer : eagerBuffer;
1424 js.Expression bailoutCode = 1428 js.Expression bailoutCode =
1425 compiler.codegenWorld.generatedBailoutCode[element]; 1429 compiler.codegenWorld.generatedBailoutCode[element];
1426 emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode); 1430 emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode);
1427 } 1431 }
1428 } 1432 }
1429 1433
1430 void emitStaticFunctionGetters(CodeBuffer buffer) { 1434 void emitStaticFunctionGetters(CodeBuffer buffer) {
1431 Set<FunctionElement> functionsNeedingGetter = 1435 Set<FunctionElement> functionsNeedingGetter =
1432 compiler.codegenWorld.staticFunctionsNeedingGetter; 1436 compiler.codegenWorld.staticFunctionsNeedingGetter;
1433 for (FunctionElement element in 1437 for (FunctionElement element in
1434 Elements.sortedByPosition(functionsNeedingGetter)) { 1438 Elements.sortedByPosition(functionsNeedingGetter)) {
1439 if (isDeferred(element)) continue;
1435 // The static function does not have the correct name. Since 1440 // The static function does not have the correct name. Since
1436 // [addParameterStubs] use the name to create its stubs we simply 1441 // [addParameterStubs] use the name to create its stubs we simply
1437 // create a fake element with the correct name. 1442 // create a fake element with the correct name.
1438 // Note: the callElement will not have any enclosingElement. 1443 // Note: the callElement will not have any enclosingElement.
1439 FunctionElement callElement = 1444 FunctionElement callElement =
1440 new ClosureInvocationElement(namer.closureInvocationSelectorName, 1445 new ClosureInvocationElement(namer.closureInvocationSelectorName,
1441 element); 1446 element);
1442 String staticName = namer.getName(element); 1447 String staticName = namer.getName(element);
1443 String invocationName = namer.instanceMethodName(callElement); 1448 String invocationName = namer.instanceMethodName(callElement);
1444 String fieldAccess = '$isolateProperties.$staticName'; 1449 String fieldAccess = '$isolateProperties.$staticName';
(...skipping 870 matching lines...) Expand 10 before | Expand all | Expand 10 after
2315 nativeEmitter.assembleCode(mainBuffer); 2320 nativeEmitter.assembleCode(mainBuffer);
2316 emitMain(mainBuffer); 2321 emitMain(mainBuffer);
2317 mainBuffer.add('function init()$_{\n'); 2322 mainBuffer.add('function init()$_{\n');
2318 mainBuffer.add('$isolateProperties$_=$_{}$N'); 2323 mainBuffer.add('$isolateProperties$_=$_{}$N');
2319 addDefineClassAndFinishClassFunctionsIfNecessary(mainBuffer); 2324 addDefineClassAndFinishClassFunctionsIfNecessary(mainBuffer);
2320 addLazyInitializerFunctionIfNecessary(mainBuffer); 2325 addLazyInitializerFunctionIfNecessary(mainBuffer);
2321 emitFinishIsolateConstructor(mainBuffer); 2326 emitFinishIsolateConstructor(mainBuffer);
2322 mainBuffer.add('}\n'); 2327 mainBuffer.add('}\n');
2323 compiler.assembledCode = mainBuffer.getText(); 2328 compiler.assembledCode = mainBuffer.getText();
2324 2329
2325 if (generateSourceMap) { 2330 if (!deferredBuffer.isEmpty) {
2326 SourceFile compiledFile = new SourceFile(null, compiler.assembledCode); 2331 String code = deferredBuffer.getText();
2327 String sourceMap = buildSourceMap(mainBuffer, compiledFile); 2332 compiler.outputProvider('part', 'js')
2328 compiler.outputProvider('', 'js.map') 2333 ..add(code)
2329 ..add(sourceMap)
2330 ..close(); 2334 ..close();
2335 outputSourceMap(deferredBuffer, compiler.assembledCode, 'part');
2331 } 2336 }
2337
2338 outputSourceMap(mainBuffer, compiler.assembledCode, '');
2332 }); 2339 });
2333 return compiler.assembledCode; 2340 return compiler.assembledCode;
2334 } 2341 }
2335 2342
2336 String buildSourceMap(CodeBuffer buffer, SourceFile compiledFile) { 2343 String buildSourceMap(CodeBuffer buffer, SourceFile compiledFile) {
2337 SourceMapBuilder sourceMapBuilder = new SourceMapBuilder(); 2344 SourceMapBuilder sourceMapBuilder = new SourceMapBuilder();
2338 buffer.forEachSourceLocation(sourceMapBuilder.addMapping); 2345 buffer.forEachSourceLocation(sourceMapBuilder.addMapping);
2339 return sourceMapBuilder.build(compiledFile); 2346 return sourceMapBuilder.build(compiledFile);
2340 } 2347 }
2348
2349 void outputSourceMap(CodeBuffer buffer, String code, String name) {
2350 if (!generateSourceMap) return;
2351 SourceFile compiledFile = new SourceFile(null, compiler.assembledCode);
2352 String sourceMap = buildSourceMap(mainBuffer, compiledFile);
2353 compiler.outputProvider(name, 'js.map')
2354 ..add(sourceMap)
2355 ..close();
2356 }
2357
2358 bool isDeferred(Element element) {
2359 return compiler.deferredLoadTask.isDeferred(element);
2360 }
2341 } 2361 }
2342 2362
2343 const String GENERATED_BY = """ 2363 const String GENERATED_BY = """
2344 // Generated by dart2js, the Dart to JavaScript compiler. 2364 // Generated by dart2js, the Dart to JavaScript compiler.
2345 """; 2365 """;
2346 const String HOOKS_API_USAGE = """ 2366 const String HOOKS_API_USAGE = """
2347 // The code supports the following hooks: 2367 // The code supports the following hooks:
2348 // dartPrint(message) - if this function is defined it is called 2368 // dartPrint(message) - if this function is defined it is called
2349 // instead of the Dart [print] method. 2369 // instead of the Dart [print] method.
2350 // dartMainRunner(main) - if this function is defined, the Dart [main] 2370 // dartMainRunner(main) - if this function is defined, the Dart [main]
2351 // method will not be invoked directly. 2371 // method will not be invoked directly.
2352 // Instead, a closure that will invoke [main] is 2372 // Instead, a closure that will invoke [main] is
2353 // passed to [dartMainRunner]. 2373 // passed to [dartMainRunner].
2354 """; 2374 """;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698