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

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

Issue 974803002: Defer addStubs to class instantiation time. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebased and fixes. Created 5 years, 9 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) 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 part of dart2js.js_emitter; 5 part of dart2js.js_emitter;
6 6
7 7
8 class OldEmitter implements Emitter { 8 class OldEmitter implements Emitter {
9 final Compiler compiler; 9 final Compiler compiler;
10 final CodeEmitterTask task; 10 final CodeEmitterTask task;
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 374
375 for (var i = 0; i < fields.length; i++) { 375 for (var i = 0; i < fields.length; i++) {
376 if(i != 0) str += ", "; 376 if(i != 0) str += ", ";
377 377
378 var field = generateAccessor(fields[i], accessors, name); 378 var field = generateAccessor(fields[i], accessors, name);
379 if (#hasIsolateSupport) { fieldNames += "'" + field + "',"; } 379 if (#hasIsolateSupport) { fieldNames += "'" + field + "',"; }
380 var parameter = "p_" + field; 380 var parameter = "p_" + field;
381 str += parameter; 381 str += parameter;
382 body += ("this." + field + " = " + parameter + ";\n"); 382 body += ("this." + field + " = " + parameter + ";\n");
383 } 383 }
384 if (supportsDirectProtoAccess) {
385 body += "this." + #deferredAction + "();";
386 }
384 str += ") {\n" + body + "}\n"; 387 str += ") {\n" + body + "}\n";
385 str += name + ".builtin$cls=\"" + name + "\";\n"; 388 str += name + ".builtin$cls=\"" + name + "\";\n";
386 str += "$desc=$collectedClasses." + name + "[1];\n"; 389 str += "$desc=$collectedClasses." + name + "[1];\n";
387 str += name + ".prototype = $desc;\n"; 390 str += name + ".prototype = $desc;\n";
388 if (typeof defineClass.name != "string") { 391 if (typeof defineClass.name != "string") {
389 str += name + ".name=\"" + name + "\";\n"; 392 str += name + ".name=\"" + name + "\";\n";
390 } 393 }
391 if (#hasIsolateSupport) { 394 if (#hasIsolateSupport) {
392 str += name + "." + #fieldNamesProperty + "=[" + fieldNames 395 str += name + "." + #fieldNamesProperty + "=[" + fieldNames
393 + "];\n"; 396 + "];\n";
394 } 397 }
395 str += accessors.join(""); 398 str += accessors.join("");
396 399
397 return str; 400 return str;
398 }''', { 'hasIsolateSupport': hasIsolateSupport, 401 }''', { 'deferredAction': js.string(namer.deferredAction),
402 'hasIsolateSupport': hasIsolateSupport,
399 'fieldNamesProperty': js.string(fieldNamesProperty)}); 403 'fieldNamesProperty': js.string(fieldNamesProperty)});
400 404
401 // Declare a function called "generateAccessor". This is used in 405 // Declare a function called "generateAccessor". This is used in
402 // defineClassFunction. 406 // defineClassFunction.
403 List result = <jsAst.Node>[ 407 List result = <jsAst.Node>[
404 generateAccessorFunction, 408 generateAccessorFunction,
405 new jsAst.FunctionDeclaration( 409 new jsAst.FunctionDeclaration(
406 new jsAst.VariableDeclaration('defineClass'), defineClass) ]; 410 new jsAst.VariableDeclaration('defineClass'), defineClass) ];
407 411
408 if (compiler.hasIncrementalSupport) { 412 if (compiler.hasIncrementalSupport) {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
462 466
463 return result; 467 return result;
464 } 468 }
465 469
466 /** Needs defineClass to be defined. */ 470 /** Needs defineClass to be defined. */
467 jsAst.Expression buildInheritFrom() { 471 jsAst.Expression buildInheritFrom() {
468 jsAst.Expression result = js(r""" 472 jsAst.Expression result = js(r"""
469 // If the browser supports changing the prototype via __proto__, we make 473 // If the browser supports changing the prototype via __proto__, we make
470 // use of that feature. Otherwise, we copy the properties into a new 474 // use of that feature. Otherwise, we copy the properties into a new
471 // constructor. 475 // constructor.
472 (function () { 476 supportsDirectProtoAccess ?
473 var cls = function () {};
474 cls.prototype = {'p': {}};
475 var object = new cls();
476 return object.__proto__ &&
477 object.__proto__.p === cls.prototype.p;
478 })() ?
479 function(constructor, superConstructor) { 477 function(constructor, superConstructor) {
480 var prototype = constructor.prototype; 478 var prototype = constructor.prototype;
481 prototype.__proto__ = superConstructor.prototype; 479 prototype.__proto__ = superConstructor.prototype;
482 // Use a function for `true` here, as functions are stored in the 480 // Use a function for `true` here, as functions are stored in the
483 // hidden class and not as properties in the object. 481 // hidden class and not as properties in the object.
484 prototype.constructor = constructor; 482 prototype.constructor = constructor;
485 prototype[#operatorIsPrefix + constructor.name] = constructor; 483 prototype[#operatorIsPrefix + constructor.name] = constructor;
486 return convertToFastObject(prototype); 484 return convertToFastObject(prototype);
487 } : 485 } :
488 function() { 486 function() {
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
568 // class. The minifier together with noSuchMethod can put methods on 566 // class. The minifier together with noSuchMethod can put methods on
569 // the Object.prototype object, and they show through here, so we check 567 // the Object.prototype object, and they show through here, so we check
570 // that we have a string. 568 // that we have a string.
571 if (!superclass || typeof superclass != "string") { 569 if (!superclass || typeof superclass != "string") {
572 // Inlined special case of InheritFrom here for performance reasons. 570 // Inlined special case of InheritFrom here for performance reasons.
573 // Fix up the the Dart Object class' prototype. 571 // Fix up the the Dart Object class' prototype.
574 var constructor = allClasses[cls]; 572 var constructor = allClasses[cls];
575 var prototype = constructor.prototype; 573 var prototype = constructor.prototype;
576 prototype.constructor = constructor; 574 prototype.constructor = constructor;
577 prototype.#isObject = constructor; 575 prototype.#isObject = constructor;
576 prototype.#deferredAction = #markerFun;
578 return; 577 return;
579 } 578 }
580 finishClass(superclass); 579 finishClass(superclass);
581 var superConstructor = allClasses[superclass]; 580 var superConstructor = allClasses[superclass];
582 581
583 if (!superConstructor) 582 if (!superConstructor) {
584 superConstructor = existingIsolateProperties[superclass]; 583 superConstructor = existingIsolateProperties[superclass];
584 }
585 585
586 var constructor = allClasses[cls]; 586 var constructor = allClasses[cls];
587 var prototype = inheritFrom(constructor, superConstructor); 587 var prototype = inheritFrom(constructor, superConstructor);
588 588
589 if (#needsNativeSupport) 589 if (#needsNativeSupport) {
590 if (Object.prototype.hasOwnProperty.call(prototype, $specProperty)) 590 if (Object.prototype.hasOwnProperty.call(prototype, $specProperty)) {
591 #nativeInfoHandler 591 #nativeInfoHandler;
592 // As native classes can come into existence without a constructor
593 // call, we have to ensure that the class has been fully
594 // initialized.
595 if (constructor.prototype.#deferredAction)
596 finishAddStubsHelper(constructor.prototype);
597 }
598 }
599 // Interceptors (or rather their prototypes) are also used without
600 // first instantiating them first.
601 if (prototype.#isInterceptorClass &&
602 constructor.prototype.#deferredAction) {
603 finishAddStubsHelper(constructor.prototype);
604 }
592 } 605 }
593 }''', {'finishedClassesAccess': finishedClassesAccess, 606 }''', {'deferredAction': namer.deferredAction,
607 'finishedClassesAccess': finishedClassesAccess,
608 'markerFun': markerFun,
594 'needsMixinSupport': needsMixinSupport, 609 'needsMixinSupport': needsMixinSupport,
595 'needsNativeSupport': needsNativeSupport, 610 'needsNativeSupport': needsNativeSupport,
596 'nativeInfoHandler': nativeInfoHandler, 611 'nativeInfoHandler': nativeInfoHandler,
612 'isInterceptorClass': namer.operatorIs(backend.jsInterceptorClass),
597 'isObject' : namer.operatorIs(compiler.objectClass) }); 613 'isObject' : namer.operatorIs(compiler.objectClass) });
598 } 614 }
599 615
600 void emitFinishIsolateConstructorInvocation(CodeOutput output) { 616 void emitFinishIsolateConstructorInvocation(CodeOutput output) {
601 String isolate = namer.isolateName; 617 String isolate = namer.isolateName;
602 output.add("$isolate = $finishIsolateConstructorName($isolate)$N"); 618 output.add("$isolate = $finishIsolateConstructorName($isolate)$N");
603 } 619 }
604 620
605 /// In minified mode we want to keep the name for the most common core types. 621 /// In minified mode we want to keep the name for the most common core types.
606 bool _isNativeTypeNeedingReflectionName(Element element) { 622 bool _isNativeTypeNeedingReflectionName(Element element) {
(...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after
1110 'hasIncrementalSupport': compiler.hasIncrementalSupport, 1126 'hasIncrementalSupport': compiler.hasIncrementalSupport,
1111 'lazyInitializerProperty': lazyInitializerProperty,}); 1127 'lazyInitializerProperty': lazyInitializerProperty,});
1112 1128
1113 output.addBuffer( 1129 output.addBuffer(
1114 jsAst.prettyPrint(decl, compiler, monitor: compiler.dumpInfoTask)); 1130 jsAst.prettyPrint(decl, compiler, monitor: compiler.dumpInfoTask));
1115 if (compiler.enableMinification) { 1131 if (compiler.enableMinification) {
1116 output.add('\n'); 1132 output.add('\n');
1117 } 1133 }
1118 } 1134 }
1119 1135
1136 String get markerFun => backend.namer.internalGlobal('markerFun');
1137
1138 void emitMarkerFun(CodeOutput output) {
1139 jsAst.Statement markerFunStmt = js.statement('''
1140 // This function is used to mark the end of the inheritance chain so that
1141 // finishAddStubsHelper knows where to stop searching for deferred work.
1142 // We have to put it at the top level so that we only get one instance of
1143 // it even if we call parseReflectionData multiple times, e.g., due to
1144 // deferred loading.
1145 function #() {}''', markerFun);
1146 output.addBuffer(jsAst.prettyPrint(markerFunStmt, compiler));
1147 output.add(N);
1148 }
1149
1120 void emitConvertToFastObjectFunction(CodeOutput output) { 1150 void emitConvertToFastObjectFunction(CodeOutput output) {
1121 List<jsAst.Statement> debugCode = <jsAst.Statement>[]; 1151 List<jsAst.Statement> debugCode = <jsAst.Statement>[];
1122 if (DEBUG_FAST_OBJECTS) { 1152 if (DEBUG_FAST_OBJECTS) {
1123 debugCode.add(js.statement(r''' 1153 debugCode.add(js.statement(r'''
1124 // The following only works on V8 when run with option 1154 // The following only works on V8 when run with option
1125 // "--allow-natives-syntax". We use'new Function' because the 1155 // "--allow-natives-syntax". We use'new Function' because the
1126 // miniparser does not understand V8 native syntax. 1156 // miniparser does not understand V8 native syntax.
1127 if (typeof print === "function") { 1157 if (typeof print === "function") {
1128 var HasFastProperties = 1158 var HasFastProperties =
1129 new Function("a", "return %HasFastProperties(a)"); 1159 new Function("a", "return %HasFastProperties(a)");
(...skipping 25 matching lines...) Expand all
1155 // mode. 1185 // mode.
1156 properties.__MAGIC_SLOW_PROPERTY = 1; 1186 properties.__MAGIC_SLOW_PROPERTY = 1;
1157 delete properties.__MAGIC_SLOW_PROPERTY; 1187 delete properties.__MAGIC_SLOW_PROPERTY;
1158 return properties; 1188 return properties;
1159 }'''); 1189 }''');
1160 1190
1161 output.addBuffer(jsAst.prettyPrint(convertToSlowObject, compiler)); 1191 output.addBuffer(jsAst.prettyPrint(convertToSlowObject, compiler));
1162 output.add(N); 1192 output.add(N);
1163 } 1193 }
1164 1194
1195 void emitSupportsDirectProtoAccess(CodeOutput output) {
1196 jsAst.Statement supportsDirectProtoAccess = js.statement(r'''
1197 var supportsDirectProtoAccess = (function () {
1198 var cls = function () {};
1199 cls.prototype = {'p': {}};
1200 var object = new cls();
1201 return object.__proto__ &&
1202 object.__proto__.p === cls.prototype.p;
1203 })();
1204 ''');
1205
1206 output.addBuffer(jsAst.prettyPrint(supportsDirectProtoAccess, compiler));
1207 output.add(N);
1208 }
1209
1165 void writeLibraryDescriptor(CodeOutput output, LibraryElement library) { 1210 void writeLibraryDescriptor(CodeOutput output, LibraryElement library) {
1166 var uri = ""; 1211 var uri = "";
1167 if (!compiler.enableMinification || backend.mustPreserveUris) { 1212 if (!compiler.enableMinification || backend.mustPreserveUris) {
1168 uri = library.canonicalUri; 1213 uri = library.canonicalUri;
1169 if (uri.scheme == 'file' && compiler.outputUri != null) { 1214 if (uri.scheme == 'file' && compiler.outputUri != null) {
1170 uri = relativize(compiler.outputUri, library.canonicalUri, false); 1215 uri = relativize(compiler.outputUri, library.canonicalUri, false);
1171 } 1216 }
1172 } 1217 }
1173 ClassBuilder descriptor = elementDescriptors[library]; 1218 ClassBuilder descriptor = elementDescriptors[library];
1174 if (descriptor == null) { 1219 if (descriptor == null) {
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
1383 /// The semicolon is important in minified mode, without it the 1428 /// The semicolon is important in minified mode, without it the
1384 /// following parenthesis looks like a call to the object literal. 1429 /// following parenthesis looks like a call to the object literal.
1385 mainOutput.add( 1430 mainOutput.add(
1386 'self.${deferredInitializers} = self.${deferredInitializers} || ' 1431 'self.${deferredInitializers} = self.${deferredInitializers} || '
1387 'Object.create(null);$n'); 1432 'Object.create(null);$n');
1388 } 1433 }
1389 1434
1390 // Using a named function here produces easier to read stack traces in 1435 // Using a named function here produces easier to read stack traces in
1391 // Chrome/V8. 1436 // Chrome/V8.
1392 mainOutput.add('(function(${namer.currentIsolate})$_{\n'); 1437 mainOutput.add('(function(${namer.currentIsolate})$_{\n');
1438 emitSupportsDirectProtoAccess(mainOutput);
1393 if (compiler.hasIncrementalSupport) { 1439 if (compiler.hasIncrementalSupport) {
1394 mainOutput.addBuffer(jsAst.prettyPrint(js.statement( 1440 mainOutput.addBuffer(jsAst.prettyPrint(js.statement(
1395 """ 1441 """
1396 { 1442 {
1397 #helper = #helper || Object.create(null); 1443 #helper = #helper || Object.create(null);
1398 #helper.patch = function(a) { eval(a)}; 1444 #helper.patch = function(a) { eval(a)};
1399 #helper.schemaChange = #schemaChange; 1445 #helper.schemaChange = #schemaChange;
1400 #helper.addMethod = #addMethod; 1446 #helper.addMethod = #addMethod;
1401 #helper.extractStubs = function(array, name, isStatic, originalDescriptor) { 1447 #helper.extractStubs = function(array, name, isStatic, originalDescriptor) {
1402 var descriptor = Object.create(null); 1448 var descriptor = Object.create(null);
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1480 for (LibraryElement element in remainingLibraries) { 1526 for (LibraryElement element in remainingLibraries) {
1481 assert(element is LibraryElement || compiler.hasIncrementalSupport); 1527 assert(element is LibraryElement || compiler.hasIncrementalSupport);
1482 if (element is LibraryElement) { 1528 if (element is LibraryElement) {
1483 writeLibraryDescriptor(libraryBuffer, element); 1529 writeLibraryDescriptor(libraryBuffer, element);
1484 elementDescriptors.remove(element); 1530 elementDescriptors.remove(element);
1485 } 1531 }
1486 } 1532 }
1487 } 1533 }
1488 1534
1489 bool needsNativeSupport = program.needsNativeSupport; 1535 bool needsNativeSupport = program.needsNativeSupport;
1490 mainOutput 1536 mainOutput.addBuffer(
1491 ..addBuffer( 1537 jsAst.prettyPrint(
1492 jsAst.prettyPrint( 1538 getReflectionDataParser(this, backend, needsNativeSupport),
1493 getReflectionDataParser(this, backend, needsNativeSupport), 1539 compiler));
1494 compiler))
1495 ..add(n);
1496 1540
1497 // The argument to reflectionDataParser is assigned to a temporary 'dart' 1541 // The argument to reflectionDataParser is assigned to a temporary 'dart'
1498 // so that 'dart.' will appear as the prefix to dart methods in stack 1542 // so that 'dart.' will appear as the prefix to dart methods in stack
1499 // traces and profile entries. 1543 // traces and profile entries.
1500 mainOutput..add('var dart = [$n') 1544 mainOutput..add('var dart = [$n')
1501 ..addBuffer(libraryBuffer) 1545 ..addBuffer(libraryBuffer)
1502 ..add(']$N'); 1546 ..add(']$N');
1503 if (compiler.useContentSecurityPolicy) { 1547 if (compiler.useContentSecurityPolicy) {
1504 jsAst.Statement precompiledFunctionAst = 1548 jsAst.Statement precompiledFunctionAst =
1505 buildCspPrecompiledFunctionFor(mainOutputUnit); 1549 buildCspPrecompiledFunctionFor(mainOutputUnit);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1548 // The following code should not use the short-hand for the 1592 // The following code should not use the short-hand for the
1549 // initialStatics. 1593 // initialStatics.
1550 mainOutput.add('${namer.currentIsolate}$_=${_}null$N'); 1594 mainOutput.add('${namer.currentIsolate}$_=${_}null$N');
1551 1595
1552 emitFinishIsolateConstructorInvocation(mainOutput); 1596 emitFinishIsolateConstructorInvocation(mainOutput);
1553 mainOutput.add( 1597 mainOutput.add(
1554 '${namer.currentIsolate}$_=${_}new ${namer.isolateName}()$N'); 1598 '${namer.currentIsolate}$_=${_}new ${namer.isolateName}()$N');
1555 1599
1556 emitConvertToFastObjectFunction(mainOutput); 1600 emitConvertToFastObjectFunction(mainOutput);
1557 emitConvertToSlowObjectFunction(mainOutput); 1601 emitConvertToSlowObjectFunction(mainOutput);
1602 emitMarkerFun(mainOutput);
1558 1603
1559 for (String globalObject in Namer.reservedGlobalObjectNames) { 1604 for (String globalObject in Namer.reservedGlobalObjectNames) {
1560 mainOutput.add('$globalObject = convertToFastObject($globalObject)$N'); 1605 mainOutput.add('$globalObject = convertToFastObject($globalObject)$N');
1561 } 1606 }
1562 if (DEBUG_FAST_OBJECTS) { 1607 if (DEBUG_FAST_OBJECTS) {
1563 mainOutput.add(r''' 1608 mainOutput.add(r'''
1564 // The following only works on V8 when run with option 1609 // The following only works on V8 when run with option
1565 // "--allow-natives-syntax". We use'new Function' because the 1610 // "--allow-natives-syntax". We use'new Function' because the
1566 // miniparser does not understand V8 native syntax. 1611 // miniparser does not understand V8 native syntax.
1567 if (typeof print === "function") { 1612 if (typeof print === "function") {
(...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after
2075 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { 2120 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) {
2076 if (element.isInstanceMember) { 2121 if (element.isInstanceMember) {
2077 cachedClassBuilders.remove(element.enclosingClass); 2122 cachedClassBuilders.remove(element.enclosingClass);
2078 2123
2079 nativeEmitter.cachedBuilders.remove(element.enclosingClass); 2124 nativeEmitter.cachedBuilders.remove(element.enclosingClass);
2080 2125
2081 } 2126 }
2082 } 2127 }
2083 } 2128 }
2084 } 2129 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/namer.dart ('k') | pkg/compiler/lib/src/js_emitter/old_emitter/reflection_data_parser.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698