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

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: 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 863 matching lines...) Expand 10 before | Expand all | Expand 10 after
2308 nativeEmitter.assembleCode(mainBuffer); 2313 nativeEmitter.assembleCode(mainBuffer);
2309 emitMain(mainBuffer); 2314 emitMain(mainBuffer);
2310 mainBuffer.add('function init()$_{\n'); 2315 mainBuffer.add('function init()$_{\n');
2311 mainBuffer.add('$isolateProperties$_=$_{}$N'); 2316 mainBuffer.add('$isolateProperties$_=$_{}$N');
2312 addDefineClassAndFinishClassFunctionsIfNecessary(mainBuffer); 2317 addDefineClassAndFinishClassFunctionsIfNecessary(mainBuffer);
2313 addLazyInitializerFunctionIfNecessary(mainBuffer); 2318 addLazyInitializerFunctionIfNecessary(mainBuffer);
2314 emitFinishIsolateConstructor(mainBuffer); 2319 emitFinishIsolateConstructor(mainBuffer);
2315 mainBuffer.add('}\n'); 2320 mainBuffer.add('}\n');
2316 compiler.assembledCode = mainBuffer.getText(); 2321 compiler.assembledCode = mainBuffer.getText();
2317 2322
2318 if (generateSourceMap) { 2323 if (!deferredBuffer.isEmpty) {
2319 SourceFile compiledFile = new SourceFile(null, compiler.assembledCode); 2324 String code = deferredBuffer.getText();
2320 String sourceMap = buildSourceMap(mainBuffer, compiledFile); 2325 compiler.outputProvider('part', 'js')
2321 compiler.outputProvider('', 'js.map') 2326 ..add(code)
2322 ..add(sourceMap)
2323 ..close(); 2327 ..close();
2328 outputSourceMap(deferredBuffer, compiler.assembledCode, 'part');
2324 } 2329 }
2330
2331 outputSourceMap(mainBuffer, compiler.assembledCode, '');
2325 }); 2332 });
2326 return compiler.assembledCode; 2333 return compiler.assembledCode;
2327 } 2334 }
2328 2335
2329 String buildSourceMap(CodeBuffer buffer, SourceFile compiledFile) { 2336 String buildSourceMap(CodeBuffer buffer, SourceFile compiledFile) {
2330 SourceMapBuilder sourceMapBuilder = new SourceMapBuilder(); 2337 SourceMapBuilder sourceMapBuilder = new SourceMapBuilder();
2331 buffer.forEachSourceLocation(sourceMapBuilder.addMapping); 2338 buffer.forEachSourceLocation(sourceMapBuilder.addMapping);
2332 return sourceMapBuilder.build(compiledFile); 2339 return sourceMapBuilder.build(compiledFile);
2333 } 2340 }
2341
2342 void outputSourceMap(CodeBuffer buffer, String code, String name) {
2343 if (!generateSourceMap) return;
2344 SourceFile compiledFile = new SourceFile(null, compiler.assembledCode);
2345 String sourceMap = buildSourceMap(mainBuffer, compiledFile);
2346 compiler.outputProvider(name, 'js.map')
2347 ..add(sourceMap)
2348 ..close();
2349 }
2350
2351 bool isDeferred(Element element) {
2352 return compiler.deferredLoadTask.isDeferred(element);
2353 }
2334 } 2354 }
2335 2355
2336 const String GENERATED_BY = """ 2356 const String GENERATED_BY = """
2337 // Generated by dart2js, the Dart to JavaScript compiler. 2357 // Generated by dart2js, the Dart to JavaScript compiler.
2338 """; 2358 """;
2339 const String HOOKS_API_USAGE = """ 2359 const String HOOKS_API_USAGE = """
2340 // The code supports the following hooks: 2360 // The code supports the following hooks:
2341 // dartPrint(message) - if this function is defined it is called 2361 // dartPrint(message) - if this function is defined it is called
2342 // instead of the Dart [print] method. 2362 // instead of the Dart [print] method.
2343 // dartMainRunner(main) - if this function is defined, the Dart [main] 2363 // dartMainRunner(main) - if this function is defined, the Dart [main]
2344 // method will not be invoked directly. 2364 // method will not be invoked directly.
2345 // Instead, a closure that will invoke [main] is 2365 // Instead, a closure that will invoke [main] is
2346 // passed to [dartMainRunner]. 2366 // passed to [dartMainRunner].
2347 """; 2367 """;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698