| 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 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 380 // constructor. | 380 // constructor. |
| 381 // For engines where we have access to the '__proto__' we can manipulate | 381 // For engines where we have access to the '__proto__' we can manipulate |
| 382 // the object literal directly. For other engines we have to create a new | 382 // the object literal directly. For other engines we have to create a new |
| 383 // object and copy over the members. | 383 // object and copy over the members. |
| 384 | 384 |
| 385 String reflectableField = namer.reflectableField; | 385 String reflectableField = namer.reflectableField; |
| 386 jsAst.Expression allClassesAccess = | 386 jsAst.Expression allClassesAccess = |
| 387 generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES); | 387 generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES); |
| 388 jsAst.Expression metadataAccess = | 388 jsAst.Expression metadataAccess = |
| 389 generateEmbeddedGlobalAccess(embeddedNames.METADATA); | 389 generateEmbeddedGlobalAccess(embeddedNames.METADATA); |
| 390 jsAst.Expression finishedClassesAccess = | |
| 391 generateEmbeddedGlobalAccess(embeddedNames.FINISHED_CLASSES); | |
| 392 | 390 |
| 393 return js(''' | 391 return js(''' |
| 394 function(collectedClasses, isolateProperties, existingIsolateProperties) { | 392 function(collectedClasses, isolateProperties, existingIsolateProperties) { |
| 395 var pendingClasses = Object.create(null); | 393 var pendingClasses = Object.create(null); |
| 396 var allClasses = #; // embedded allClasses; | 394 var allClasses = #allClasses; |
| 397 var constructors; | 395 var constructors; |
| 398 | 396 |
| 399 if (#) // DEBUG_FAST_OBJECTS | 397 if (#debugFastObjects) |
| 400 print("Number of classes: " + | 398 print("Number of classes: " + |
| 401 Object.getOwnPropertyNames(\$\$).length); | 399 Object.getOwnPropertyNames(\$\$).length); |
| 402 | 400 |
| 403 var hasOwnProperty = Object.prototype.hasOwnProperty; | 401 var hasOwnProperty = Object.prototype.hasOwnProperty; |
| 404 | 402 |
| 405 if (typeof dart_precompiled == "function") { | 403 if (typeof dart_precompiled == "function") { |
| 406 constructors = dart_precompiled(collectedClasses); | 404 constructors = dart_precompiled(collectedClasses); |
| 407 } else { | 405 } else { |
| 408 var combinedConstructorFunction = | 406 var combinedConstructorFunction = |
| 409 "function \$reflectable(fn){fn.$reflectableField=1;return fn};\\n"+ | 407 "function \$reflectable(fn){fn.$reflectableField=1;return fn};\\n"+ |
| 410 "var \$desc;\\n"; | 408 "var \$desc;\\n"; |
| 411 var constructorsList = []; | 409 var constructorsList = []; |
| 412 } | 410 } |
| 413 | 411 |
| 414 for (var cls in collectedClasses) { | 412 for (var cls in collectedClasses) { |
| 415 var desc = collectedClasses[cls]; | 413 var desc = collectedClasses[cls]; |
| 416 if (desc instanceof Array) desc = desc[1]; | 414 if (desc instanceof Array) desc = desc[1]; |
| 417 | 415 |
| 418 /* The 'fields' are either a constructor function or a | 416 /* The 'fields' are either a constructor function or a |
| 419 * string encoding fields, constructor and superclass. Gets the | 417 * string encoding fields, constructor and superclass. Gets the |
| 420 * superclass and fields in the format | 418 * superclass and fields in the format |
| 421 * '[name/]Super;field1,field2' | 419 * '[name/]Super;field1,field2' |
| 422 * from the CLASS_DESCRIPTOR_PROPERTY property on the descriptor. | 420 * from the CLASS_DESCRIPTOR_PROPERTY property on the descriptor. |
| 423 * The 'name/' is optional and contains the name that should be used | 421 * The 'name/' is optional and contains the name that should be used |
| 424 * when printing the runtime type string. It is used, for example, | 422 * when printing the runtime type string. It is used, for example, |
| 425 * to print the runtime type JSInt as 'int'. | 423 * to print the runtime type JSInt as 'int'. |
| 426 */ | 424 */ |
| 427 var classData = desc["${namer.classDescriptorProperty}"], | 425 var classData = desc["${namer.classDescriptorProperty}"], |
| 428 supr, name = cls, fields = classData; | 426 supr, name = cls, fields = classData; |
| 429 if (#) // backend.hasRetainedMetadata | 427 if (#hasRetainedMetadata) |
| 430 if (typeof classData == "object" && | 428 if (typeof classData == "object" && |
| 431 classData instanceof Array) { | 429 classData instanceof Array) { |
| 432 classData = fields = classData[0]; | 430 classData = fields = classData[0]; |
| 433 } | 431 } |
| 434 if (typeof classData == "string") { | 432 if (typeof classData == "string") { |
| 435 var split = classData.split("/"); | 433 var split = classData.split("/"); |
| 436 if (split.length == 2) { | 434 if (split.length == 2) { |
| 437 name = split[0]; | 435 name = split[0]; |
| 438 fields = split[1]; | 436 fields = split[1]; |
| 439 } | 437 } |
| 440 } | 438 } |
| 441 | 439 |
| 442 var s = fields.split(";"); | 440 var s = fields.split(";"); |
| 443 fields = s[1] == "" ? [] : s[1].split(","); | 441 fields = s[1] == "" ? [] : s[1].split(","); |
| 444 supr = s[0]; | 442 supr = s[0]; |
| 445 split = supr.split(":"); | 443 split = supr.split(":"); |
| 446 if (split.length == 2) { | 444 if (split.length == 2) { |
| 447 supr = split[0]; | 445 supr = split[0]; |
| 448 var functionSignature = split[1]; | 446 var functionSignature = split[1]; |
| 449 if (functionSignature) | 447 if (functionSignature) |
| 450 desc.\$signature = (function(s) { | 448 desc.\$signature = (function(s) { |
| 451 return function(){ return #[s]; }; // embedded metadata. | 449 return function(){ return #metadata[s]; }; |
| 452 })(functionSignature); | 450 })(functionSignature); |
| 453 } | 451 } |
| 454 | 452 |
| 455 if (#) // needsMixinSupport | 453 if (#needsMixinSupport) |
| 456 if (supr && supr.indexOf("+") > 0) { | 454 if (supr && supr.indexOf("+") > 0) { |
| 457 s = supr.split("+"); | 455 s = supr.split("+"); |
| 458 supr = s[0]; | 456 supr = s[0]; |
| 459 var mixin = collectedClasses[s[1]]; | 457 var mixin = collectedClasses[s[1]]; |
| 460 if (mixin instanceof Array) mixin = mixin[1]; | 458 if (mixin instanceof Array) mixin = mixin[1]; |
| 461 for (var d in mixin) { | 459 for (var d in mixin) { |
| 462 if (hasOwnProperty.call(mixin, d) && | 460 if (hasOwnProperty.call(mixin, d) && |
| 463 !hasOwnProperty.call(desc, d)) | 461 !hasOwnProperty.call(desc, d)) |
| 464 desc[d] = mixin[d]; | 462 desc[d] = mixin[d]; |
| 465 } | 463 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 483 | 481 |
| 484 for (var i = 0; i < constructors.length; i++) { | 482 for (var i = 0; i < constructors.length; i++) { |
| 485 var constructor = constructors[i]; | 483 var constructor = constructors[i]; |
| 486 var cls = constructor.name; | 484 var cls = constructor.name; |
| 487 var desc = collectedClasses[cls]; | 485 var desc = collectedClasses[cls]; |
| 488 var globalObject = isolateProperties; | 486 var globalObject = isolateProperties; |
| 489 if (desc instanceof Array) { | 487 if (desc instanceof Array) { |
| 490 globalObject = desc[0] || isolateProperties; | 488 globalObject = desc[0] || isolateProperties; |
| 491 desc = desc[1]; | 489 desc = desc[1]; |
| 492 } | 490 } |
| 493 if (#) //backend.isTreeShakingDisabled, | 491 if (#isTreeShakingDisabled) |
| 494 constructor["${namer.metadataField}"] = desc; | 492 constructor["${namer.metadataField}"] = desc; |
| 495 allClasses[cls] = constructor; | 493 allClasses[cls] = constructor; |
| 496 globalObject[cls] = constructor; | 494 globalObject[cls] = constructor; |
| 497 } | 495 } |
| 498 | 496 |
| 499 constructors = null; | 497 constructors = null; |
| 500 | 498 |
| 501 var finishedClasses = #; // embedded finishedClasses | 499 #finishClassFunction; |
| 502 | 500 |
| 503 #; // buildFinishClass(), | 501 #trivialNsmHandlers; |
| 504 | |
| 505 #; // buildTrivialNsmHandlers() | |
| 506 | 502 |
| 507 for (var cls in pendingClasses) finishClass(cls); | 503 for (var cls in pendingClasses) finishClass(cls); |
| 508 }''', [ | 504 }''', { 'allClasses': allClassesAccess, |
| 509 allClassesAccess, | 505 'debugFastObjects': DEBUG_FAST_OBJECTS, |
| 510 DEBUG_FAST_OBJECTS, | 506 'hasRetainedMetadata': backend.hasRetainedMetadata, |
| 511 backend.hasRetainedMetadata, | 507 'metadata': metadataAccess, |
| 512 metadataAccess, | 508 'needsMixinSupport': needsMixinSupport, |
| 513 needsMixinSupport, | 509 'isTreeShakingDisabled': backend.isTreeShakingDisabled, |
| 514 backend.isTreeShakingDisabled, | 510 'finishClassFunction': buildFinishClass(), |
| 515 finishedClassesAccess, | 511 'trivialNsmHandlers': nsmEmitter.buildTrivialNsmHandlers()}); |
| 516 buildFinishClass(), | |
| 517 nsmEmitter.buildTrivialNsmHandlers()]); | |
| 518 } | 512 } |
| 519 | 513 |
| 520 jsAst.Node optional(bool condition, jsAst.Node node) { | 514 jsAst.Node optional(bool condition, jsAst.Node node) { |
| 521 return condition ? node : new jsAst.EmptyStatement(); | 515 return condition ? node : new jsAst.EmptyStatement(); |
| 522 } | 516 } |
| 523 | 517 |
| 524 jsAst.FunctionDeclaration buildFinishClass() { | 518 jsAst.Statement buildFinishClass() { |
| 525 String specProperty = '"${namer.nativeSpecProperty}"'; // "%" | 519 String specProperty = '"${namer.nativeSpecProperty}"'; // "%" |
| 526 | 520 |
| 521 jsAst.Expression finishedClassesAccess = |
| 522 generateEmbeddedGlobalAccess(embeddedNames.FINISHED_CLASSES); |
| 527 jsAst.Expression interceptorsByTagAccess = | 523 jsAst.Expression interceptorsByTagAccess = |
| 528 generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG); | 524 generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG); |
| 529 jsAst.Expression leafTagsAccess = | 525 jsAst.Expression leafTagsAccess = |
| 530 generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS); | 526 generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS); |
| 531 | 527 |
| 532 return js.statement(''' | 528 return js.statement(''' |
| 529 { |
| 530 var finishedClasses = #; // finishedClassesAccess. |
| 531 |
| 533 function finishClass(cls) { | 532 function finishClass(cls) { |
| 534 | 533 |
| 535 if (finishedClasses[cls]) return; | 534 if (finishedClasses[cls]) return; |
| 536 finishedClasses[cls] = true; | 535 finishedClasses[cls] = true; |
| 537 | 536 |
| 538 var superclass = pendingClasses[cls]; | 537 var superclass = pendingClasses[cls]; |
| 539 var constructor = allClasses[cls]; | 538 var constructor = allClasses[cls]; |
| 540 | 539 |
| 541 // Process aliased members due to super calls. We have to do this early | 540 // Process aliased members due to super calls. We have to do this early |
| 542 // to ensure that we also hit the object class. | 541 // to ensure that we also hit the object class. |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 597 } | 596 } |
| 598 } | 597 } |
| 599 for (i = 0; i < tags.length; i++) { | 598 for (i = 0; i < tags.length; i++) { |
| 600 #[tags[i]] = constructor; // embedded interceptorsByTag. | 599 #[tags[i]] = constructor; // embedded interceptorsByTag. |
| 601 #[tags[i]] = false; // embedded leafTags. | 600 #[tags[i]] = false; // embedded leafTags. |
| 602 } | 601 } |
| 603 } | 602 } |
| 604 } | 603 } |
| 605 } | 604 } |
| 606 } | 605 } |
| 607 }''', [!nativeClasses.isEmpty, | 606 } |
| 608 interceptorsByTagAccess, | 607 }''', [finishedClassesAccess, |
| 609 leafTagsAccess, | 608 !nativeClasses.isEmpty, |
| 610 true, | 609 interceptorsByTagAccess, |
| 611 interceptorsByTagAccess, | 610 leafTagsAccess, |
| 612 leafTagsAccess]); | 611 true, |
| 612 interceptorsByTagAccess, |
| 613 leafTagsAccess]); |
| 613 } | 614 } |
| 614 | 615 |
| 615 jsAst.Fun get finishIsolateConstructorFunction { | 616 jsAst.Fun get finishIsolateConstructorFunction { |
| 616 // We replace the old Isolate function with a new one that initializes | 617 // We replace the old Isolate function with a new one that initializes |
| 617 // all its fields with the initial (and often final) value of all globals. | 618 // all its fields with the initial (and often final) value of all globals. |
| 618 // | 619 // |
| 619 // We also copy over old values like the prototype, and the | 620 // We also copy over old values like the prototype, and the |
| 620 // isolateProperties themselves. | 621 // isolateProperties themselves. |
| 621 return js(''' | 622 return js(''' |
| 622 function (oldIsolate) { | 623 function (oldIsolate) { |
| (...skipping 1409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2032 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { | 2033 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { |
| 2033 if (element.isInstanceMember) { | 2034 if (element.isInstanceMember) { |
| 2034 cachedClassBuilders.remove(element.enclosingClass); | 2035 cachedClassBuilders.remove(element.enclosingClass); |
| 2035 | 2036 |
| 2036 nativeEmitter.cachedBuilders.remove(element.enclosingClass); | 2037 nativeEmitter.cachedBuilders.remove(element.enclosingClass); |
| 2037 | 2038 |
| 2038 } | 2039 } |
| 2039 } | 2040 } |
| 2040 } | 2041 } |
| 2041 } | 2042 } |
| OLD | NEW |