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

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: Ensure fast prototypes and avoid polymorphic access in constructor 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 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 328
329 for (var i = 0; i < fields.length; i++) { 329 for (var i = 0; i < fields.length; i++) {
330 if(i != 0) str += ", "; 330 if(i != 0) str += ", ";
331 331
332 var field = generateAccessor(fields[i], accessors, name); 332 var field = generateAccessor(fields[i], accessors, name);
333 if (#hasIsolateSupport) { fieldNames += "'" + field + "',"; } 333 if (#hasIsolateSupport) { fieldNames += "'" + field + "',"; }
334 var parameter = "p_" + field; 334 var parameter = "p_" + field;
335 str += parameter; 335 str += parameter;
336 body += ("this." + field + " = " + parameter + ";\n"); 336 body += ("this." + field + " = " + parameter + ";\n");
337 } 337 }
338 if (supportsDirectProtoAccess)
floitsch 2015/03/06 14:54:09 Sigurd put in an optimization that removes blocks
herhut 2015/03/09 14:28:34 WHOOHOO! Done.
339 body += "this." + #deferredAction + "();";
338 str += ") {\n" + body + "}\n"; 340 str += ") {\n" + body + "}\n";
339 str += name + ".builtin$cls=\"" + name + "\";\n"; 341 str += name + ".builtin$cls=\"" + name + "\";\n";
340 str += "$desc=$collectedClasses." + name + "[1];\n"; 342 str += "$desc=$collectedClasses." + name + "[1];\n";
341 str += name + ".prototype = $desc;\n"; 343 str += name + ".prototype = $desc;\n";
342 if (typeof defineClass.name != "string") { 344 if (typeof defineClass.name != "string") {
343 str += name + ".name=\"" + name + "\";\n"; 345 str += name + ".name=\"" + name + "\";\n";
344 } 346 }
345 if (#hasIsolateSupport) { 347 if (#hasIsolateSupport) {
346 str += name + "." + #fieldNamesProperty + "=[" + fieldNames 348 str += name + "." + #fieldNamesProperty + "=[" + fieldNames
347 + "];\n"; 349 + "];\n";
348 } 350 }
349 str += accessors.join(""); 351 str += accessors.join("");
350 352
351 return str; 353 return str;
352 }''', { 'hasIsolateSupport': hasIsolateSupport, 354 }''', { 'deferredAction': js.string(namer.deferredAction),
355 'hasIsolateSupport': hasIsolateSupport,
353 'fieldNamesProperty': js.string(fieldNamesProperty)}); 356 'fieldNamesProperty': js.string(fieldNamesProperty)});
354 357
355 // Declare a function called "generateAccessor". This is used in 358 // Declare a function called "generateAccessor". This is used in
356 // defineClassFunction. 359 // defineClassFunction.
357 List result = <jsAst.Node>[ 360 List result = <jsAst.Node>[
358 generateAccessorFunction, 361 generateAccessorFunction,
359 new jsAst.FunctionDeclaration( 362 new jsAst.FunctionDeclaration(
360 new jsAst.VariableDeclaration('defineClass'), defineClass) ]; 363 new jsAst.VariableDeclaration('defineClass'), defineClass) ];
361 364
362 if (compiler.hasIncrementalSupport) { 365 if (compiler.hasIncrementalSupport) {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
416 419
417 return result; 420 return result;
418 } 421 }
419 422
420 /** Needs defineClass to be defined. */ 423 /** Needs defineClass to be defined. */
421 jsAst.Expression buildInheritFrom() { 424 jsAst.Expression buildInheritFrom() {
422 jsAst.Expression result = js(r""" 425 jsAst.Expression result = js(r"""
423 // If the browser supports changing the prototype via __proto__, we make 426 // If the browser supports changing the prototype via __proto__, we make
424 // use of that feature. Otherwise, we copy the properties into a new 427 // use of that feature. Otherwise, we copy the properties into a new
425 // constructor. 428 // constructor.
426 (function () { 429 supportsDirectProtoAccess ?
427 var cls = function () {};
428 cls.prototype = {'p': {}};
429 var object = new cls();
430 return object.__proto__ &&
431 object.__proto__.p === cls.prototype.p;
432 })() ?
433 function(constructor, superConstructor) { 430 function(constructor, superConstructor) {
434 var prototype = constructor.prototype; 431 var prototype = constructor.prototype;
435 prototype.__proto__ = superConstructor.prototype; 432 prototype.__proto__ = superConstructor.prototype;
436 // Use a function for `true` here, as functions are stored in the 433 // Use a function for `true` here, as functions are stored in the
437 // hidden class and not as properties in the object. 434 // hidden class and not as properties in the object.
438 prototype.constructor = constructor; 435 prototype.constructor = constructor;
439 prototype[#operatorIsPrefix + constructor.name] = constructor; 436 prototype[#operatorIsPrefix + constructor.name] = constructor;
440 return convertToFastObject(prototype); 437 return convertToFastObject(prototype);
441 } : 438 } :
442 function() { 439 function() {
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 // class. The minifier together with noSuchMethod can put methods on 519 // class. The minifier together with noSuchMethod can put methods on
523 // the Object.prototype object, and they show through here, so we check 520 // the Object.prototype object, and they show through here, so we check
524 // that we have a string. 521 // that we have a string.
525 if (!superclass || typeof superclass != "string") { 522 if (!superclass || typeof superclass != "string") {
526 // Inlined special case of InheritFrom here for performance reasons. 523 // Inlined special case of InheritFrom here for performance reasons.
527 // Fix up the the Dart Object class' prototype. 524 // Fix up the the Dart Object class' prototype.
528 var constructor = allClasses[cls]; 525 var constructor = allClasses[cls];
529 var prototype = constructor.prototype; 526 var prototype = constructor.prototype;
530 prototype.constructor = constructor; 527 prototype.constructor = constructor;
531 prototype.#isObject = constructor; 528 prototype.#isObject = constructor;
529 prototype.#deferredAction = markerFun;
floitsch 2015/03/06 14:54:09 given that this function comes from a different fi
floitsch 2015/03/06 14:54:09 Explain what the marker-fun is for (either here or
herhut 2015/03/09 14:28:34 zarah@ is working on putting the two chunks of JS
herhut 2015/03/09 14:28:34 Done.
532 return; 530 return;
533 } 531 }
534 finishClass(superclass); 532 finishClass(superclass);
535 var superConstructor = allClasses[superclass]; 533 var superConstructor = allClasses[superclass];
536 534
537 if (!superConstructor) 535 if (!superConstructor)
538 superConstructor = existingIsolateProperties[superclass]; 536 superConstructor = existingIsolateProperties[superclass];
539 537
540 var constructor = allClasses[cls]; 538 var constructor = allClasses[cls];
541 var prototype = inheritFrom(constructor, superConstructor); 539 var prototype = inheritFrom(constructor, superConstructor);
542 540
543 if (#hasNativeClasses) 541 if (#hasNativeClasses)
544 if (Object.prototype.hasOwnProperty.call(prototype, $specProperty)) 542 if (Object.prototype.hasOwnProperty.call(prototype, $specProperty)) {
545 #nativeInfoHandler 543 #nativeInfoHandler;
544 // As native classes can come into existence without a constructor
545 // call, we have to ensure that the class has been fully
546 // initialized.
547 if (constructor.prototype.#deferredAction)
floitsch 2015/03/06 14:54:09 ditto (add curly braces).
herhut 2015/03/09 14:28:34 Done.
548 finishAddStubsHelper(constructor.prototype);
549 }
550 // Interceptors (or rather their prototypes) are also used without
551 // first instantiating them first.
floitsch 2015/03/06 14:54:09 This looks like we are only eagerly running the de
floitsch 2015/03/09 16:35:06 any thoughts on this one?
552 if (superclass === #interceptorClassName &&
553 constructor.prototype.#deferredAction) {
554 finishAddStubsHelper(constructor.prototype);
555 }
546 } 556 }
547 }''', {'finishedClassesAccess': finishedClassesAccess, 557 }''', {'deferredAction': namer.deferredAction,
558 'finishedClassesAccess': finishedClassesAccess,
548 'needsMixinSupport': needsMixinSupport, 559 'needsMixinSupport': needsMixinSupport,
549 'hasNativeClasses': hasNativeClasses, 560 'hasNativeClasses': hasNativeClasses,
550 'nativeInfoHandler': nativeInfoHandler, 561 'nativeInfoHandler': nativeInfoHandler,
562 'interceptorClassName':
563 js.string(namer.getNameOfClass(backend.jsInterceptorClass)),
551 'isObject' : namer.operatorIs(compiler.objectClass) }); 564 'isObject' : namer.operatorIs(compiler.objectClass) });
552 } 565 }
553 566
554 void emitFinishIsolateConstructorInvocation(CodeOutput output) { 567 void emitFinishIsolateConstructorInvocation(CodeOutput output) {
555 String isolate = namer.isolateName; 568 String isolate = namer.isolateName;
556 output.add("$isolate = $finishIsolateConstructorName($isolate)$N"); 569 output.add("$isolate = $finishIsolateConstructorName($isolate)$N");
557 } 570 }
558 571
559 /// In minified mode we want to keep the name for the most common core types. 572 /// In minified mode we want to keep the name for the most common core types.
560 bool _isNativeTypeNeedingReflectionName(Element element) { 573 bool _isNativeTypeNeedingReflectionName(Element element) {
(...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after
1134 // mode. 1147 // mode.
1135 properties.__MAGIC_SLOW_PROPERTY = 1; 1148 properties.__MAGIC_SLOW_PROPERTY = 1;
1136 delete properties.__MAGIC_SLOW_PROPERTY; 1149 delete properties.__MAGIC_SLOW_PROPERTY;
1137 return properties; 1150 return properties;
1138 }'''); 1151 }''');
1139 1152
1140 output.addBuffer(jsAst.prettyPrint(convertToSlowObject, compiler)); 1153 output.addBuffer(jsAst.prettyPrint(convertToSlowObject, compiler));
1141 output.add(N); 1154 output.add(N);
1142 } 1155 }
1143 1156
1157 void emitSupportsDirectProtoAccess(CodeOutput output) {
1158 jsAst.Statement supportsDirectProtoAccess = js.statement(r'''
floitsch 2015/03/06 14:54:09 Since this is used in a completely different part
herhut 2015/03/09 14:28:35 I would actually prefer to emit this as part of th
1159 var supportsDirectProtoAccess = (function () {
1160 var cls = function () {};
1161 cls.prototype = {'p': {}};
1162 var object = new cls();
1163 return object.__proto__ &&
1164 object.__proto__.p === cls.prototype.p;
1165 })();
1166 ''');
1167
1168 output.addBuffer(jsAst.prettyPrint(supportsDirectProtoAccess, compiler));
1169 output.add(N);
1170 }
1171
1144 void writeLibraryDescriptors(CodeOutput output, LibraryElement library) { 1172 void writeLibraryDescriptors(CodeOutput output, LibraryElement library) {
1145 var uri = ""; 1173 var uri = "";
1146 if (!compiler.enableMinification || backend.mustPreserveUris) { 1174 if (!compiler.enableMinification || backend.mustPreserveUris) {
1147 uri = library.canonicalUri; 1175 uri = library.canonicalUri;
1148 if (uri.scheme == 'file' && compiler.outputUri != null) { 1176 if (uri.scheme == 'file' && compiler.outputUri != null) {
1149 uri = relativize(compiler.outputUri, library.canonicalUri, false); 1177 uri = relativize(compiler.outputUri, library.canonicalUri, false);
1150 } 1178 }
1151 } 1179 }
1152 ClassBuilder descriptor = elementDescriptors[library]; 1180 ClassBuilder descriptor = elementDescriptors[library];
1153 if (descriptor == null) { 1181 if (descriptor == null) {
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
1363 /// The semicolon is important in minified mode, without it the 1391 /// The semicolon is important in minified mode, without it the
1364 /// following parenthesis looks like a call to the object literal. 1392 /// following parenthesis looks like a call to the object literal.
1365 mainOutput.add( 1393 mainOutput.add(
1366 'self.${deferredInitializers} = self.${deferredInitializers} || ' 1394 'self.${deferredInitializers} = self.${deferredInitializers} || '
1367 'Object.create(null);$n'); 1395 'Object.create(null);$n');
1368 } 1396 }
1369 1397
1370 // Using a named function here produces easier to read stack traces in 1398 // Using a named function here produces easier to read stack traces in
1371 // Chrome/V8. 1399 // Chrome/V8.
1372 mainOutput.add('(function(${namer.currentIsolate})$_{\n'); 1400 mainOutput.add('(function(${namer.currentIsolate})$_{\n');
1401 emitSupportsDirectProtoAccess(mainOutput);
1373 if (compiler.hasIncrementalSupport) { 1402 if (compiler.hasIncrementalSupport) {
1374 mainOutput.addBuffer(jsAst.prettyPrint(js.statement( 1403 mainOutput.addBuffer(jsAst.prettyPrint(js.statement(
1375 """ 1404 """
1376 { 1405 {
1377 #helper = #helper || Object.create(null); 1406 #helper = #helper || Object.create(null);
1378 #helper.patch = function(a) { eval(a)}; 1407 #helper.patch = function(a) { eval(a)};
1379 #helper.schemaChange = #schemaChange; 1408 #helper.schemaChange = #schemaChange;
1380 #helper.addMethod = #addMethod; 1409 #helper.addMethod = #addMethod;
1381 #helper.extractStubs = function(array, name, isStatic, originalDescriptor) { 1410 #helper.extractStubs = function(array, name, isStatic, originalDescriptor) {
1382 var descriptor = Object.create(null); 1411 var descriptor = Object.create(null);
(...skipping 651 matching lines...) Expand 10 before | Expand all | Expand 10 after
2034 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { 2063 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) {
2035 if (element.isInstanceMember) { 2064 if (element.isInstanceMember) {
2036 cachedClassBuilders.remove(element.enclosingClass); 2065 cachedClassBuilders.remove(element.enclosingClass);
2037 2066
2038 nativeEmitter.cachedBuilders.remove(element.enclosingClass); 2067 nativeEmitter.cachedBuilders.remove(element.enclosingClass);
2039 2068
2040 } 2069 }
2041 } 2070 }
2042 } 2071 }
2043 } 2072 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698