| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |