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