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

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

Issue 957343002: Make use of __proto__ when available. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Comments 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
« no previous file with comments | « no previous file | pkg/compiler/lib/src/js_emitter/old_emitter/reflection_data_parser.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
324 324
325 var str = "function " + name + "("; 325 var str = "function " + name + "(";
326 var body = ""; 326 var body = "";
327 if (#hasIsolateSupport) { var fieldNames = ""; } 327 if (#hasIsolateSupport) { var fieldNames = ""; }
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 = "parameter_" + 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 str += ") {\n" + body + "}\n"; 338 str += ") {\n" + body + "}\n";
339 str += name + ".builtin$cls=\"" + name + "\";\n"; 339 str += name + ".builtin$cls=\"" + name + "\";\n";
340 str += "$desc=$collectedClasses." + name + ";\n"; 340 str += "$desc=$collectedClasses." + name + "[1];\n";
341 str += "if($desc instanceof Array) $desc = \$desc[1];\n";
342 str += name + ".prototype = $desc;\n"; 341 str += name + ".prototype = $desc;\n";
343 if (typeof defineClass.name != "string") { 342 if (typeof defineClass.name != "string") {
344 str += name + ".name=\"" + name + "\";\n"; 343 str += name + ".name=\"" + name + "\";\n";
345 } 344 }
346 if (#hasIsolateSupport) { 345 if (#hasIsolateSupport) {
347 str += name + "." + #fieldNamesProperty + "=[" + fieldNames 346 str += name + "." + #fieldNamesProperty + "=[" + fieldNames
348 + "];\n"; 347 + "];\n";
349 } 348 }
350 str += accessors.join(""); 349 str += accessors.join("");
351 350
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
413 classFieldsExtractorAssignment, 412 classFieldsExtractorAssignment,
414 instanceFromClassIdAssignment, 413 instanceFromClassIdAssignment,
415 initializeEmptyInstanceAssignment]); 414 initializeEmptyInstanceAssignment]);
416 } 415 }
417 416
418 return result; 417 return result;
419 } 418 }
420 419
421 /** Needs defineClass to be defined. */ 420 /** Needs defineClass to be defined. */
422 jsAst.Expression buildInheritFrom() { 421 jsAst.Expression buildInheritFrom() {
423 jsAst.Expression result = js(r''' 422 jsAst.Expression result = js(r"""
423 // If the browser supports changing the prototype via __proto__, we make
424 // use of that feature. Otherwise, we copy the properties into a new
425 // constructor.
426 (function () {
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) {
434 var prototype = constructor.prototype;
435 prototype.__proto__ = superConstructor.prototype;
436 // Use a function for `true` here, as functions are stored in the
437 // hidden class and not as properties in the object.
438 prototype.constructor = constructor;
439 prototype[#operatorIsPrefix + constructor.name] = constructor;
440 return convertToFastObject(prototype);
441 } :
424 function() { 442 function() {
425 function tmp() {} 443 function tmp() {}
426 var hasOwnProperty = Object.prototype.hasOwnProperty;
427 return function (constructor, superConstructor) { 444 return function (constructor, superConstructor) {
428 if (superConstructor == null) {
429 // Fix up the the Dart Object class' prototype.
430 var prototype = constructor.prototype;
431 prototype.constructor = constructor;
432 prototype.#isObject = constructor;
433 return prototype;
434 }
435 tmp.prototype = superConstructor.prototype; 445 tmp.prototype = superConstructor.prototype;
436 var object = new tmp(); 446 var object = new tmp();
447 convertToSlowObject(object);
437 var properties = constructor.prototype; 448 var properties = constructor.prototype;
438 for (var member in properties) { 449 var members = Object.keys(properties);
439 if (hasOwnProperty.call(properties, member)) { 450 for (var i = 0; i < members.length; i++) {
440 object[member] = properties[member]; 451 var member = members[i];
441 } 452 object[member] = properties[member];
442 } 453 }
443 // Use a function for `true` here, as functions are stored in the 454 // Use a function for `true` here, as functions are stored in the
444 // hidden class and not as properties in the object. 455 // hidden class and not as properties in the object.
445 object[#operatorIsPrefix + constructor.name] = constructor; 456 object[#operatorIsPrefix + constructor.name] = constructor;
446 object.constructor = constructor; 457 object.constructor = constructor;
447 constructor.prototype = object; 458 constructor.prototype = object;
448 return object; 459 return object;
449 }; 460 };
450 }() 461 }()
451 ''', { 'operatorIsPrefix' : js.string(namer.operatorIsPrefix), 462 """, { 'operatorIsPrefix' : js.string(namer.operatorIsPrefix)});
452 'isObject' : namer.operatorIs(compiler.objectClass) });
453 if (compiler.hasIncrementalSupport) { 463 if (compiler.hasIncrementalSupport) {
454 result = js( 464 result = js(
455 r'#.inheritFrom = #', [namer.accessIncrementalHelper, result]); 465 r'#.inheritFrom = #', [namer.accessIncrementalHelper, result]);
456 } 466 }
457 return js(r'var inheritFrom = #', [result]); 467 return js(r'var inheritFrom = #', [result]);
458 } 468 }
459 469
460 jsAst.Statement buildFinishClass(bool hasNativeClasses) { 470 jsAst.Statement buildFinishClass(bool hasNativeClasses) {
461 String specProperty = '"${namer.nativeSpecProperty}"'; // "%" 471 String specProperty = '"${namer.nativeSpecProperty}"'; // "%"
462 472
(...skipping 28 matching lines...) Expand all
491 501
492 if (#needsMixinSupport) { 502 if (#needsMixinSupport) {
493 if (superclass && superclass.indexOf("+") > 0) { 503 if (superclass && superclass.indexOf("+") > 0) {
494 var s = superclass.split("+"); 504 var s = superclass.split("+");
495 superclass = s[0]; 505 superclass = s[0];
496 var mixinClass = s[1]; 506 var mixinClass = s[1];
497 finishClass(mixinClass); 507 finishClass(mixinClass);
498 var mixin = allClasses[mixinClass]; 508 var mixin = allClasses[mixinClass];
499 var mixinPrototype = mixin.prototype; 509 var mixinPrototype = mixin.prototype;
500 var clsPrototype = allClasses[cls].prototype; 510 var clsPrototype = allClasses[cls].prototype;
501 for (var d in mixinPrototype) { 511
502 if (hasOwnProperty.call(mixinPrototype, d) && 512 var properties = Object.keys(mixinPrototype);
503 !hasOwnProperty.call(clsPrototype, d)) 513 for (var i = 0; i < properties.length; i++) {
514 var d = properties[i];
515 if (!hasOwnProperty.call(clsPrototype, d))
504 clsPrototype[d] = mixinPrototype[d]; 516 clsPrototype[d] = mixinPrototype[d];
505 } 517 }
506 } 518 }
507 } 519 }
508 520
509 // The superclass is only false (empty string) for the Dart Object 521 // The superclass is only false (empty string) for the Dart Object
510 // class. The minifier together with noSuchMethod can put methods on 522 // class. The minifier together with noSuchMethod can put methods on
511 // the Object.prototype object, and they show through here, so we check 523 // the Object.prototype object, and they show through here, so we check
512 // that we have a string. 524 // that we have a string.
513 if (!superclass || typeof superclass != "string") { 525 if (!superclass || typeof superclass != "string") {
514 inheritFrom(allClasses[cls], null); 526 // Inlined special case of InheritFrom here for performance reasons.
527 // Fix up the the Dart Object class' prototype.
528 var constructor = allClasses[cls];
529 var prototype = constructor.prototype;
530 prototype.constructor = constructor;
531 prototype.#isObject = constructor;
515 return; 532 return;
516 } 533 }
517 finishClass(superclass); 534 finishClass(superclass);
518 var superConstructor = allClasses[superclass]; 535 var superConstructor = allClasses[superclass];
519 536
520 if (!superConstructor) 537 if (!superConstructor)
521 superConstructor = existingIsolateProperties[superclass]; 538 superConstructor = existingIsolateProperties[superclass];
522 539
523 var constructor = allClasses[cls]; 540 var constructor = allClasses[cls];
524 var prototype = inheritFrom(constructor, superConstructor); 541 var prototype = inheritFrom(constructor, superConstructor);
525 542
526 if (#hasNativeClasses) 543 if (#hasNativeClasses)
527 if (Object.prototype.hasOwnProperty.call(prototype, $specProperty)) 544 if (Object.prototype.hasOwnProperty.call(prototype, $specProperty))
528 #nativeInfoHandler 545 #nativeInfoHandler
529 } 546 }
530 }''', {'finishedClassesAccess': finishedClassesAccess, 547 }''', {'finishedClassesAccess': finishedClassesAccess,
531 'needsMixinSupport': needsMixinSupport, 548 'needsMixinSupport': needsMixinSupport,
532 'hasNativeClasses': hasNativeClasses, 549 'hasNativeClasses': hasNativeClasses,
533 'nativeInfoHandler': nativeInfoHandler}); 550 'nativeInfoHandler': nativeInfoHandler,
551 'isObject' : namer.operatorIs(compiler.objectClass) });
534 } 552 }
535 553
536 void emitFinishIsolateConstructorInvocation(CodeOutput output) { 554 void emitFinishIsolateConstructorInvocation(CodeOutput output) {
537 String isolate = namer.isolateName; 555 String isolate = namer.isolateName;
538 output.add("$isolate = $finishIsolateConstructorName($isolate)$N"); 556 output.add("$isolate = $finishIsolateConstructorName($isolate)$N");
539 } 557 }
540 558
541 /// In minified mode we want to keep the name for the most common core types. 559 /// In minified mode we want to keep the name for the most common core types.
542 bool _isNativeTypeNeedingReflectionName(Element element) { 560 bool _isNativeTypeNeedingReflectionName(Element element) {
543 if (!element.isClass) return false; 561 if (!element.isClass) return false;
(...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after
1007 1025
1008 // We replace the old Isolate function with a new one that initializes 1026 // We replace the old Isolate function with a new one that initializes
1009 // all its fields with the initial (and often final) value of all 1027 // all its fields with the initial (and often final) value of all
1010 // globals. 1028 // globals.
1011 // 1029 //
1012 // We also copy over old values like the prototype, and the 1030 // We also copy over old values like the prototype, and the
1013 // isolateProperties themselves. 1031 // isolateProperties themselves.
1014 $finishIsolateConstructorName = function (oldIsolate) { 1032 $finishIsolateConstructorName = function (oldIsolate) {
1015 var isolateProperties = oldIsolate.#isolatePropertiesName; 1033 var isolateProperties = oldIsolate.#isolatePropertiesName;
1016 function Isolate() { 1034 function Isolate() {
1017 var hasOwnProperty = Object.prototype.hasOwnProperty; 1035
1018 for (var staticName in isolateProperties) 1036 var staticNames = Object.keys(isolateProperties);
1019 if (hasOwnProperty.call(isolateProperties, staticName)) 1037 for (var i = 0; i < staticNames.length; i++) {
1020 this[staticName] = isolateProperties[staticName]; 1038 var staticName = staticNames[i];
1039 this[staticName] = isolateProperties[staticName];
1040 }
1021 1041
1022 // Reset lazy initializers to null. 1042 // Reset lazy initializers to null.
1023 // When forcing the object to fast mode (below) v8 will consider 1043 // When forcing the object to fast mode (below) v8 will consider
1024 // functions as part the object's map. Since we will change them 1044 // functions as part the object's map. Since we will change them
1025 // (after the first call to the getter), we would have a map 1045 // (after the first call to the getter), we would have a map
1026 // transition. 1046 // transition.
1027 var lazies = init.lazies; 1047 var lazies = init.lazies;
1028 for (var lazyInit in lazies) { 1048 var lazyInitializers = lazies ? Object.keys(lazies) : [];
1029 this[lazies[lazyInit]] = null; 1049 for (var i = 0; i < lazyInitializers.length; i++) {
1050 this[lazies[lazyInitializers[i]]] = null;
1030 } 1051 }
1031 1052
1032 // Use the newly created object as prototype. In Chrome, 1053 // Use the newly created object as prototype. In Chrome,
1033 // this creates a hidden class for the object and makes 1054 // this creates a hidden class for the object and makes
1034 // sure it is fast to access. 1055 // sure it is fast to access.
1035 function ForceEfficientMap() {} 1056 function ForceEfficientMap() {}
1036 ForceEfficientMap.prototype = this; 1057 ForceEfficientMap.prototype = this;
1037 new ForceEfficientMap(); 1058 new ForceEfficientMap();
1038 1059
1039 // Now, after being a fast map we can set the lazies again. 1060 // Now, after being a fast map we can set the lazies again.
1040 for (var lazyInit in lazies) { 1061 for (var i = 0; i < lazyInitializers.length; i++) {
1041 var lazyInitName = lazies[lazyInit]; 1062 var lazyInitName = lazies[lazyInitializers[i]];
1042 this[lazyInitName] = isolateProperties[lazyInitName]; 1063 this[lazyInitName] = isolateProperties[lazyInitName];
1043 } 1064 }
1044 } 1065 }
1045 Isolate.prototype = oldIsolate.prototype; 1066 Isolate.prototype = oldIsolate.prototype;
1046 Isolate.prototype.constructor = Isolate; 1067 Isolate.prototype.constructor = Isolate;
1047 Isolate.#isolatePropertiesName = isolateProperties; 1068 Isolate.#isolatePropertiesName = isolateProperties;
1048 if (#outputContainsConstantList) { 1069 if (#outputContainsConstantList) {
1049 Isolate.#makeConstListProperty = oldIsolate.#makeConstListProperty; 1070 Isolate.#makeConstListProperty = oldIsolate.#makeConstListProperty;
1050 } 1071 }
1051 if (#hasIncrementalSupport) { 1072 if (#hasIncrementalSupport) {
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1099 MyClass.prototype = properties; 1120 MyClass.prototype = properties;
1100 new MyClass(); 1121 new MyClass();
1101 #; 1122 #;
1102 return properties; 1123 return properties;
1103 }''', [debugCode]); 1124 }''', [debugCode]);
1104 1125
1105 output.addBuffer(jsAst.prettyPrint(convertToFastObject, compiler)); 1126 output.addBuffer(jsAst.prettyPrint(convertToFastObject, compiler));
1106 output.add(N); 1127 output.add(N);
1107 } 1128 }
1108 1129
1130 void emitConvertToSlowObjectFunction(CodeOutput output) {
1131 jsAst.Statement convertToSlowObject = js.statement(r'''
1132 function convertToSlowObject(properties) {
1133 // Add and remove a property to make the object transition into hashmap
1134 // mode.
1135 properties.__MAGIC_SLOW_PROPERTY = 1;
1136 delete properties.__MAGIC_SLOW_PROPERTY;
1137 return properties;
1138 }''');
1139
1140 output.addBuffer(jsAst.prettyPrint(convertToSlowObject, compiler));
1141 output.add(N);
1142 }
1143
1109 void writeLibraryDescriptors(CodeOutput output, LibraryElement library) { 1144 void writeLibraryDescriptors(CodeOutput output, LibraryElement library) {
1110 var uri = ""; 1145 var uri = "";
1111 if (!compiler.enableMinification || backend.mustPreserveUris) { 1146 if (!compiler.enableMinification || backend.mustPreserveUris) {
1112 uri = library.canonicalUri; 1147 uri = library.canonicalUri;
1113 if (uri.scheme == 'file' && compiler.outputUri != null) { 1148 if (uri.scheme == 'file' && compiler.outputUri != null) {
1114 uri = relativize(compiler.outputUri, library.canonicalUri, false); 1149 uri = relativize(compiler.outputUri, library.canonicalUri, false);
1115 } 1150 }
1116 } 1151 }
1117 ClassBuilder descriptor = elementDescriptors[library]; 1152 ClassBuilder descriptor = elementDescriptors[library];
1118 if (descriptor == null) { 1153 if (descriptor == null) {
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after
1463 isolateProperties = isolatePropertiesName; 1498 isolateProperties = isolatePropertiesName;
1464 // The following code should not use the short-hand for the 1499 // The following code should not use the short-hand for the
1465 // initialStatics. 1500 // initialStatics.
1466 mainOutput.add('${namer.currentIsolate}$_=${_}null$N'); 1501 mainOutput.add('${namer.currentIsolate}$_=${_}null$N');
1467 1502
1468 emitFinishIsolateConstructorInvocation(mainOutput); 1503 emitFinishIsolateConstructorInvocation(mainOutput);
1469 mainOutput.add( 1504 mainOutput.add(
1470 '${namer.currentIsolate}$_=${_}new ${namer.isolateName}()$N'); 1505 '${namer.currentIsolate}$_=${_}new ${namer.isolateName}()$N');
1471 1506
1472 emitConvertToFastObjectFunction(mainOutput); 1507 emitConvertToFastObjectFunction(mainOutput);
1508 emitConvertToSlowObjectFunction(mainOutput);
1509
1473 for (String globalObject in Namer.reservedGlobalObjectNames) { 1510 for (String globalObject in Namer.reservedGlobalObjectNames) {
1474 mainOutput.add('$globalObject = convertToFastObject($globalObject)$N'); 1511 mainOutput.add('$globalObject = convertToFastObject($globalObject)$N');
1475 } 1512 }
1476 if (DEBUG_FAST_OBJECTS) { 1513 if (DEBUG_FAST_OBJECTS) {
1477 mainOutput.add(r''' 1514 mainOutput.add(r'''
1478 // The following only works on V8 when run with option 1515 // The following only works on V8 when run with option
1479 // "--allow-natives-syntax". We use'new Function' because the 1516 // "--allow-natives-syntax". We use'new Function' because the
1480 // miniparser does not understand V8 native syntax. 1517 // miniparser does not understand V8 native syntax.
1481 if (typeof print === "function") { 1518 if (typeof print === "function") {
1482 var HasFastProperties = 1519 var HasFastProperties =
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after
1997 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { 2034 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) {
1998 if (element.isInstanceMember) { 2035 if (element.isInstanceMember) {
1999 cachedClassBuilders.remove(element.enclosingClass); 2036 cachedClassBuilders.remove(element.enclosingClass);
2000 2037
2001 nativeEmitter.cachedBuilders.remove(element.enclosingClass); 2038 nativeEmitter.cachedBuilders.remove(element.enclosingClass);
2002 2039
2003 } 2040 }
2004 } 2041 }
2005 } 2042 }
2006 } 2043 }
OLDNEW
« no previous file with comments | « no previous file | 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