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

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: Use JS_NAME and fix deferred loading. 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),
floitsch 2015/03/11 13:59:33 potentially create the string here? (although mayb
herhut 2015/03/13 12:28:52 I would prefer to leave the fact that it is a call
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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
459 instanceFromClassIdAssignment, 463 instanceFromClassIdAssignment,
460 initializeEmptyInstanceAssignment]); 464 initializeEmptyInstanceAssignment]);
461 } 465 }
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"""
473 // If the browser supports changing the prototype via __proto__, we make
474 // use of that feature. Otherwise, we copy the properties into a new
475 // constructor.
476 supportsDirectProtoAccess ?
477 function(constructor, superConstructor) {
478 var prototype = constructor.prototype;
479 prototype.__proto__ = superConstructor.prototype;
480 // Use a function for `true` here, as functions are stored in the
481 // hidden class and not as properties in the object.
482 prototype.constructor = constructor;
483 prototype[#operatorIsPrefix + constructor.name] = constructor;
484 return convertToFastObject(prototype);
485 } :
469 function() { 486 function() {
470 function tmp() {} 487 function tmp() {}
471 return function (constructor, superConstructor) { 488 return function (constructor, superConstructor) {
472 tmp.prototype = superConstructor.prototype; 489 tmp.prototype = superConstructor.prototype;
473 var object = new tmp(); 490 var object = new tmp();
474 object.x = 0; delete object.x; // Make object slow. 491 convertToSlowObject(object);
475 var properties = constructor.prototype; 492 var properties = constructor.prototype;
476 var members = Object.keys(properties); 493 var members = Object.keys(properties);
477 for (var i = 0; i < members.length; i++) { 494 for (var i = 0; i < members.length; i++) {
478 var member = members[i]; 495 var member = members[i];
479 object[member] = properties[member]; 496 object[member] = properties[member];
480 } 497 }
481 // Use a function for `true` here, as functions are stored in the 498 // Use a function for `true` here, as functions are stored in the
482 // hidden class and not as properties in the object. 499 // hidden class and not as properties in the object.
483 object[#operatorIsPrefix + constructor.name] = constructor; 500 object[#operatorIsPrefix + constructor.name] = constructor;
484 object.constructor = constructor; 501 object.constructor = constructor;
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
549 // class. The minifier together with noSuchMethod can put methods on 566 // class. The minifier together with noSuchMethod can put methods on
550 // 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
551 // that we have a string. 568 // that we have a string.
552 if (!superclass || typeof superclass != "string") { 569 if (!superclass || typeof superclass != "string") {
553 // Inlined special case of InheritFrom here for performance reasons. 570 // Inlined special case of InheritFrom here for performance reasons.
554 // Fix up the the Dart Object class' prototype. 571 // Fix up the the Dart Object class' prototype.
555 var constructor = allClasses[cls]; 572 var constructor = allClasses[cls];
556 var prototype = constructor.prototype; 573 var prototype = constructor.prototype;
557 prototype.constructor = constructor; 574 prototype.constructor = constructor;
558 prototype.#isObject = constructor; 575 prototype.#isObject = constructor;
576 prototype.#deferredAction = #markerFun;
559 return; 577 return;
560 } 578 }
561 finishClass(superclass); 579 finishClass(superclass);
562 var superConstructor = allClasses[superclass]; 580 var superConstructor = allClasses[superclass];
563 581
564 if (!superConstructor) 582 if (!superConstructor) {
565 superConstructor = existingIsolateProperties[superclass]; 583 superConstructor = existingIsolateProperties[superclass];
584 }
566 585
567 var constructor = allClasses[cls]; 586 var constructor = allClasses[cls];
568 var prototype = inheritFrom(constructor, superConstructor); 587 var prototype = inheritFrom(constructor, superConstructor);
569 588
570 if (#needsNativeSupport) 589 if (#needsNativeSupport) {
571 if (Object.prototype.hasOwnProperty.call(prototype, $specProperty)) 590 if (Object.prototype.hasOwnProperty.call(prototype, $specProperty)) {
572 #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 }
573 } 605 }
574 }''', {'finishedClassesAccess': finishedClassesAccess, 606 }''', {'deferredAction': namer.deferredAction,
607 'finishedClassesAccess': finishedClassesAccess,
608 'markerFun': markerFun,
575 'needsMixinSupport': needsMixinSupport, 609 'needsMixinSupport': needsMixinSupport,
576 'needsNativeSupport': needsNativeSupport, 610 'needsNativeSupport': needsNativeSupport,
577 'nativeInfoHandler': nativeInfoHandler, 611 'nativeInfoHandler': nativeInfoHandler,
612 'isInterceptorClass': namer.operatorIs(backend.jsInterceptorClass),
578 'isObject' : namer.operatorIs(compiler.objectClass) }); 613 'isObject' : namer.operatorIs(compiler.objectClass) });
579 } 614 }
580 615
581 void emitFinishIsolateConstructorInvocation(CodeOutput output) { 616 void emitFinishIsolateConstructorInvocation(CodeOutput output) {
582 String isolate = namer.isolateName; 617 String isolate = namer.isolateName;
583 output.add("$isolate = $finishIsolateConstructorName($isolate)$N"); 618 output.add("$isolate = $finishIsolateConstructorName($isolate)$N");
584 } 619 }
585 620
586 /// 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.
587 bool _isNativeTypeNeedingReflectionName(Element element) { 622 bool _isNativeTypeNeedingReflectionName(Element element) {
(...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after
1091 'hasIncrementalSupport': compiler.hasIncrementalSupport, 1126 'hasIncrementalSupport': compiler.hasIncrementalSupport,
1092 'lazyInitializerProperty': lazyInitializerProperty,}); 1127 'lazyInitializerProperty': lazyInitializerProperty,});
1093 1128
1094 output.addBuffer( 1129 output.addBuffer(
1095 jsAst.prettyPrint(decl, compiler, monitor: compiler.dumpInfoTask)); 1130 jsAst.prettyPrint(decl, compiler, monitor: compiler.dumpInfoTask));
1096 if (compiler.enableMinification) { 1131 if (compiler.enableMinification) {
1097 output.add('\n'); 1132 output.add('\n');
1098 } 1133 }
1099 } 1134 }
1100 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
1101 void emitConvertToFastObjectFunction(CodeOutput output) { 1150 void emitConvertToFastObjectFunction(CodeOutput output) {
1102 List<jsAst.Statement> debugCode = <jsAst.Statement>[]; 1151 List<jsAst.Statement> debugCode = <jsAst.Statement>[];
1103 if (DEBUG_FAST_OBJECTS) { 1152 if (DEBUG_FAST_OBJECTS) {
1104 debugCode.add(js.statement(r''' 1153 debugCode.add(js.statement(r'''
1105 // The following only works on V8 when run with option 1154 // The following only works on V8 when run with option
1106 // "--allow-natives-syntax". We use'new Function' because the 1155 // "--allow-natives-syntax". We use'new Function' because the
1107 // miniparser does not understand V8 native syntax. 1156 // miniparser does not understand V8 native syntax.
1108 if (typeof print === "function") { 1157 if (typeof print === "function") {
1109 var HasFastProperties = 1158 var HasFastProperties =
1110 new Function("a", "return %HasFastProperties(a)"); 1159 new Function("a", "return %HasFastProperties(a)");
(...skipping 11 matching lines...) Expand all
1122 MyClass.prototype = properties; 1171 MyClass.prototype = properties;
1123 new MyClass(); 1172 new MyClass();
1124 #; 1173 #;
1125 return properties; 1174 return properties;
1126 }''', [debugCode]); 1175 }''', [debugCode]);
1127 1176
1128 output.addBuffer(jsAst.prettyPrint(convertToFastObject, compiler)); 1177 output.addBuffer(jsAst.prettyPrint(convertToFastObject, compiler));
1129 output.add(N); 1178 output.add(N);
1130 } 1179 }
1131 1180
1181 void emitConvertToSlowObjectFunction(CodeOutput output) {
1182 jsAst.Statement convertToSlowObject = js.statement(r'''
1183 function convertToSlowObject(properties) {
1184 // Add and remove a property to make the object transition into hashmap
1185 // mode.
1186 properties.__MAGIC_SLOW_PROPERTY = 1;
1187 delete properties.__MAGIC_SLOW_PROPERTY;
1188 return properties;
1189 }''');
1190
1191 output.addBuffer(jsAst.prettyPrint(convertToSlowObject, compiler));
1192 output.add(N);
1193 }
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
1132 void writeLibraryDescriptors(CodeOutput output, LibraryElement library) { 1210 void writeLibraryDescriptors(CodeOutput output, LibraryElement library) {
1133 var uri = ""; 1211 var uri = "";
1134 if (!compiler.enableMinification || backend.mustPreserveUris) { 1212 if (!compiler.enableMinification || backend.mustPreserveUris) {
1135 uri = library.canonicalUri; 1213 uri = library.canonicalUri;
1136 if (uri.scheme == 'file' && compiler.outputUri != null) { 1214 if (uri.scheme == 'file' && compiler.outputUri != null) {
1137 uri = relativize(compiler.outputUri, library.canonicalUri, false); 1215 uri = relativize(compiler.outputUri, library.canonicalUri, false);
1138 } 1216 }
1139 } 1217 }
1140 ClassBuilder descriptor = elementDescriptors[library]; 1218 ClassBuilder descriptor = elementDescriptors[library];
1141 if (descriptor == null) { 1219 if (descriptor == null) {
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
1350 /// The semicolon is important in minified mode, without it the 1428 /// The semicolon is important in minified mode, without it the
1351 /// following parenthesis looks like a call to the object literal. 1429 /// following parenthesis looks like a call to the object literal.
1352 mainOutput.add( 1430 mainOutput.add(
1353 'self.${deferredInitializers} = self.${deferredInitializers} || ' 1431 'self.${deferredInitializers} = self.${deferredInitializers} || '
1354 'Object.create(null);$n'); 1432 'Object.create(null);$n');
1355 } 1433 }
1356 1434
1357 // 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
1358 // Chrome/V8. 1436 // Chrome/V8.
1359 mainOutput.add('(function(${namer.currentIsolate})$_{\n'); 1437 mainOutput.add('(function(${namer.currentIsolate})$_{\n');
1438 emitSupportsDirectProtoAccess(mainOutput);
1360 if (compiler.hasIncrementalSupport) { 1439 if (compiler.hasIncrementalSupport) {
1361 mainOutput.addBuffer(jsAst.prettyPrint(js.statement( 1440 mainOutput.addBuffer(jsAst.prettyPrint(js.statement(
1362 """ 1441 """
1363 { 1442 {
1364 #helper = #helper || Object.create(null); 1443 #helper = #helper || Object.create(null);
1365 #helper.patch = function(a) { eval(a)}; 1444 #helper.patch = function(a) { eval(a)};
1366 #helper.schemaChange = #schemaChange; 1445 #helper.schemaChange = #schemaChange;
1367 #helper.addMethod = #addMethod; 1446 #helper.addMethod = #addMethod;
1368 #helper.extractStubs = function(array, name, isStatic, originalDescriptor) { 1447 #helper.extractStubs = function(array, name, isStatic, originalDescriptor) {
1369 var descriptor = Object.create(null); 1448 var descriptor = Object.create(null);
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1430 1509
1431 checkEverythingEmitted(elementDescriptors.keys); 1510 checkEverythingEmitted(elementDescriptors.keys);
1432 1511
1433 CodeBuffer libraryBuffer = new CodeBuffer(); 1512 CodeBuffer libraryBuffer = new CodeBuffer();
1434 for (LibraryElement library in Elements.sortedByPosition(libraries)) { 1513 for (LibraryElement library in Elements.sortedByPosition(libraries)) {
1435 writeLibraryDescriptors(libraryBuffer, library); 1514 writeLibraryDescriptors(libraryBuffer, library);
1436 elementDescriptors.remove(library); 1515 elementDescriptors.remove(library);
1437 } 1516 }
1438 1517
1439 bool needsNativeSupport = program.needsNativeSupport; 1518 bool needsNativeSupport = program.needsNativeSupport;
1440 mainOutput 1519 mainOutput.addBuffer(
1441 ..addBuffer( 1520 jsAst.prettyPrint(
1442 jsAst.prettyPrint( 1521 getReflectionDataParser(this, backend, needsNativeSupport),
1443 getReflectionDataParser(this, backend, needsNativeSupport), 1522 compiler));
1444 compiler))
1445 ..add(n);
1446 1523
1447 // The argument to reflectionDataParser is assigned to a temporary 'dart' 1524 // The argument to reflectionDataParser is assigned to a temporary 'dart'
1448 // so that 'dart.' will appear as the prefix to dart methods in stack 1525 // so that 'dart.' will appear as the prefix to dart methods in stack
1449 // traces and profile entries. 1526 // traces and profile entries.
1450 mainOutput..add('var dart = [$n') 1527 mainOutput..add('var dart = [$n')
1451 ..addBuffer(libraryBuffer) 1528 ..addBuffer(libraryBuffer)
1452 ..add(']$N'); 1529 ..add(']$N');
1453 if (compiler.useContentSecurityPolicy) { 1530 if (compiler.useContentSecurityPolicy) {
1454 jsAst.Statement precompiledFunctionAst = 1531 jsAst.Statement precompiledFunctionAst =
1455 buildCspPrecompiledFunctionFor(mainOutputUnit); 1532 buildCspPrecompiledFunctionFor(mainOutputUnit);
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1496 isolateProperties = isolatePropertiesName; 1573 isolateProperties = isolatePropertiesName;
1497 // The following code should not use the short-hand for the 1574 // The following code should not use the short-hand for the
1498 // initialStatics. 1575 // initialStatics.
1499 mainOutput.add('${namer.currentIsolate}$_=${_}null$N'); 1576 mainOutput.add('${namer.currentIsolate}$_=${_}null$N');
1500 1577
1501 emitFinishIsolateConstructorInvocation(mainOutput); 1578 emitFinishIsolateConstructorInvocation(mainOutput);
1502 mainOutput.add( 1579 mainOutput.add(
1503 '${namer.currentIsolate}$_=${_}new ${namer.isolateName}()$N'); 1580 '${namer.currentIsolate}$_=${_}new ${namer.isolateName}()$N');
1504 1581
1505 emitConvertToFastObjectFunction(mainOutput); 1582 emitConvertToFastObjectFunction(mainOutput);
1583 emitConvertToSlowObjectFunction(mainOutput);
1584 emitMarkerFun(mainOutput);
1585
1506 for (String globalObject in Namer.reservedGlobalObjectNames) { 1586 for (String globalObject in Namer.reservedGlobalObjectNames) {
1507 mainOutput.add('$globalObject = convertToFastObject($globalObject)$N'); 1587 mainOutput.add('$globalObject = convertToFastObject($globalObject)$N');
1508 } 1588 }
1509 if (DEBUG_FAST_OBJECTS) { 1589 if (DEBUG_FAST_OBJECTS) {
1510 mainOutput.add(r''' 1590 mainOutput.add(r'''
1511 // The following only works on V8 when run with option 1591 // The following only works on V8 when run with option
1512 // "--allow-natives-syntax". We use'new Function' because the 1592 // "--allow-natives-syntax". We use'new Function' because the
1513 // miniparser does not understand V8 native syntax. 1593 // miniparser does not understand V8 native syntax.
1514 if (typeof print === "function") { 1594 if (typeof print === "function") {
1515 var HasFastProperties = 1595 var HasFastProperties =
(...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after
2021 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { 2101 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) {
2022 if (element.isInstanceMember) { 2102 if (element.isInstanceMember) {
2023 cachedClassBuilders.remove(element.enclosingClass); 2103 cachedClassBuilders.remove(element.enclosingClass);
2024 2104
2025 nativeEmitter.cachedBuilders.remove(element.enclosingClass); 2105 nativeEmitter.cachedBuilders.remove(element.enclosingClass);
2026 2106
2027 } 2107 }
2028 } 2108 }
2029 } 2109 }
2030 } 2110 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698