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