| 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; |
| 11 | 11 |
| 12 final ContainerBuilder containerBuilder = new ContainerBuilder(); | 12 final ContainerBuilder containerBuilder = new ContainerBuilder(); |
| 13 final ClassEmitter classEmitter = new ClassEmitter(); | 13 final ClassEmitter classEmitter = new ClassEmitter(); |
| 14 final NsmEmitter nsmEmitter = new NsmEmitter(); | 14 final NsmEmitter nsmEmitter = new NsmEmitter(); |
| 15 final TypeTestEmitter typeTestEmitter = new TypeTestEmitter(); | 15 final TypeTestEmitter typeTestEmitter = new TypeTestEmitter(); |
| 16 final InterceptorEmitter interceptorEmitter = new InterceptorEmitter(); | 16 final InterceptorEmitter interceptorEmitter = new InterceptorEmitter(); |
| 17 final MetadataEmitter metadataEmitter = new MetadataEmitter(); | 17 final MetadataEmitter metadataEmitter = new MetadataEmitter(); |
| 18 | 18 |
| 19 final Set<ConstantValue> cachedEmittedConstants; | 19 final Set<ConstantValue> cachedEmittedConstants; |
| 20 final CodeBuffer cachedEmittedConstantsBuffer = new CodeBuffer(); | 20 final CodeBuffer cachedEmittedConstantsBuffer = new CodeBuffer(); |
| 21 final Map<Element, ClassBuilder> cachedClassBuilders; | 21 final Map<Element, ClassBuilder> cachedClassBuilders; |
| 22 final Set<Element> cachedElements; | 22 final Set<Element> cachedElements; |
| 23 | 23 |
| 24 bool needsClassSupport = false; | 24 bool needsDefineClass = false; |
| 25 bool needsMixinSupport = false; | 25 bool needsMixinSupport = false; |
| 26 bool needsLazyInitializer = false; | 26 bool needsLazyInitializer = false; |
| 27 final Namer namer; | 27 final Namer namer; |
| 28 ConstantEmitter constantEmitter; | 28 ConstantEmitter constantEmitter; |
| 29 NativeEmitter get nativeEmitter => task.nativeEmitter; | 29 NativeEmitter get nativeEmitter => task.nativeEmitter; |
| 30 TypeTestRegistry get typeTestRegistry => task.typeTestRegistry; | 30 TypeTestRegistry get typeTestRegistry => task.typeTestRegistry; |
| 31 | 31 |
| 32 // The full code that is written to each hunk part-file. | 32 // The full code that is written to each hunk part-file. |
| 33 Map<OutputUnit, CodeBuffer> outputBuffers = new Map<OutputUnit, CodeBuffer>(); | 33 Map<OutputUnit, CodeBuffer> outputBuffers = new Map<OutputUnit, CodeBuffer>(); |
| 34 final CodeBuffer deferredConstants = new CodeBuffer(); | 34 final CodeBuffer deferredConstants = new CodeBuffer(); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 jsAst.Expression constantReference(ConstantValue value) { | 140 jsAst.Expression constantReference(ConstantValue value) { |
| 141 return constantEmitter.reference(value); | 141 return constantEmitter.reference(value); |
| 142 } | 142 } |
| 143 | 143 |
| 144 jsAst.Expression constantInitializerExpression(ConstantValue value) { | 144 jsAst.Expression constantInitializerExpression(ConstantValue value) { |
| 145 return constantEmitter.initializationExpression(value); | 145 return constantEmitter.initializationExpression(value); |
| 146 } | 146 } |
| 147 | 147 |
| 148 String get name => 'CodeEmitter'; | 148 String get name => 'CodeEmitter'; |
| 149 | 149 |
| 150 String get currentGenerateAccessorName |
| 151 => '${namer.currentIsolate}.\$generateAccessor'; |
| 152 String get generateAccessorHolder |
| 153 => '$isolatePropertiesName.\$generateAccessor'; |
| 154 String get finishClassesProperty |
| 155 => r'$finishClasses'; |
| 156 String get finishClassesName |
| 157 => '${namer.isolateName}.$finishClassesProperty'; |
| 150 String get finishIsolateConstructorName | 158 String get finishIsolateConstructorName |
| 151 => '${namer.isolateName}.\$finishIsolateConstructor'; | 159 => '${namer.isolateName}.\$finishIsolateConstructor'; |
| 152 String get isolatePropertiesName | 160 String get isolatePropertiesName |
| 153 => '${namer.isolateName}.${namer.isolatePropertiesName}'; | 161 => '${namer.isolateName}.${namer.isolatePropertiesName}'; |
| 154 String get lazyInitializerProperty | 162 String get lazyInitializerProperty |
| 155 => r'$lazy'; | 163 => r'$lazy'; |
| 156 String get lazyInitializerName | 164 String get lazyInitializerName |
| 157 => '${namer.isolateName}.${lazyInitializerProperty}'; | 165 => '${namer.isolateName}.${lazyInitializerProperty}'; |
| 158 String get initName => 'init'; | 166 String get initName => 'init'; |
| 159 String get makeConstListProperty | 167 String get makeConstListProperty |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 } | 214 } |
| 207 | 215 |
| 208 jsAst.PropertyAccess classAccess(Element element) { | 216 jsAst.PropertyAccess classAccess(Element element) { |
| 209 return globalPropertyAccess(element); | 217 return globalPropertyAccess(element); |
| 210 } | 218 } |
| 211 | 219 |
| 212 jsAst.PropertyAccess typedefAccess(Element element) { | 220 jsAst.PropertyAccess typedefAccess(Element element) { |
| 213 return globalPropertyAccess(element); | 221 return globalPropertyAccess(element); |
| 214 } | 222 } |
| 215 | 223 |
| 216 List<jsAst.Statement> buildTrivialNsmHandlers(){ | |
| 217 return nsmEmitter.buildTrivialNsmHandlers(); | |
| 218 } | |
| 219 | |
| 220 jsAst.FunctionDeclaration get generateAccessorFunction { | 224 jsAst.FunctionDeclaration get generateAccessorFunction { |
| 221 const RANGE1_SIZE = RANGE1_LAST - RANGE1_FIRST + 1; | 225 const RANGE1_SIZE = RANGE1_LAST - RANGE1_FIRST + 1; |
| 222 const RANGE2_SIZE = RANGE2_LAST - RANGE2_FIRST + 1; | 226 const RANGE2_SIZE = RANGE2_LAST - RANGE2_FIRST + 1; |
| 223 const RANGE1_ADJUST = - (FIRST_FIELD_CODE - RANGE1_FIRST); | 227 const RANGE1_ADJUST = - (FIRST_FIELD_CODE - RANGE1_FIRST); |
| 224 const RANGE2_ADJUST = - (FIRST_FIELD_CODE + RANGE1_SIZE - RANGE2_FIRST); | 228 const RANGE2_ADJUST = - (FIRST_FIELD_CODE + RANGE1_SIZE - RANGE2_FIRST); |
| 225 const RANGE3_ADJUST = | 229 const RANGE3_ADJUST = |
| 226 - (FIRST_FIELD_CODE + RANGE1_SIZE + RANGE2_SIZE - RANGE3_FIRST); | 230 - (FIRST_FIELD_CODE + RANGE1_SIZE + RANGE2_SIZE - RANGE3_FIRST); |
| 227 | 231 |
| 228 String receiverParamName = compiler.enableMinification ? "r" : "receiver"; | 232 String receiverParamName = compiler.enableMinification ? "r" : "receiver"; |
| 229 String valueParamName = compiler.enableMinification ? "v" : "value"; | 233 String valueParamName = compiler.enableMinification ? "v" : "value"; |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 335 } | 339 } |
| 336 if (#hasIsolateSupport) { | 340 if (#hasIsolateSupport) { |
| 337 str += name + ".$fieldNamesProperty=[" + fieldNames + "];\\n"; | 341 str += name + ".$fieldNamesProperty=[" + fieldNames + "];\\n"; |
| 338 } | 342 } |
| 339 str += accessors.join(""); | 343 str += accessors.join(""); |
| 340 | 344 |
| 341 return str; | 345 return str; |
| 342 }''', { 'hasIsolateSupport': hasIsolateSupport }); | 346 }''', { 'hasIsolateSupport': hasIsolateSupport }); |
| 343 | 347 |
| 344 // Declare a function called "generateAccessor". This is used in | 348 // Declare a function called "generateAccessor". This is used in |
| 345 // defineClassFunction. | 349 // defineClassFunction (it's a local declaration in init()). |
| 346 List result = <jsAst.Node>[ | 350 List result = <jsAst.Node>[ |
| 347 generateAccessorFunction, | 351 generateAccessorFunction, |
| 352 js('$generateAccessorHolder = generateAccessor'), |
| 348 new jsAst.FunctionDeclaration( | 353 new jsAst.FunctionDeclaration( |
| 349 new jsAst.VariableDeclaration('defineClass'), defineClass) ]; | 354 new jsAst.VariableDeclaration('defineClass'), defineClass) ]; |
| 350 | 355 |
| 351 if (compiler.hasIncrementalSupport) { | 356 if (compiler.hasIncrementalSupport) { |
| 352 result.add( | 357 result.add( |
| 353 js(r'#.defineClass = defineClass', [namer.accessIncrementalHelper])); | 358 js(r'#.defineClass = defineClass', [namer.accessIncrementalHelper])); |
| 354 } | 359 } |
| 355 | 360 |
| 356 if (hasIsolateSupport) { | 361 if (hasIsolateSupport) { |
| 357 jsAst.Expression classIdExtractorAccess = | 362 jsAst.Expression classIdExtractorAccess = |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 }; | 436 }; |
| 432 }() | 437 }() |
| 433 '''); | 438 '''); |
| 434 if (compiler.hasIncrementalSupport) { | 439 if (compiler.hasIncrementalSupport) { |
| 435 result = js( | 440 result = js( |
| 436 r'#.inheritFrom = #', [namer.accessIncrementalHelper, result]); | 441 r'#.inheritFrom = #', [namer.accessIncrementalHelper, result]); |
| 437 } | 442 } |
| 438 return js(r'var inheritFrom = #', [result]); | 443 return js(r'var inheritFrom = #', [result]); |
| 439 } | 444 } |
| 440 | 445 |
| 446 /// Code that needs to be run before first invocation of |
| 447 /// [finishClassesFunction], but should only be run once. |
| 448 jsAst.Expression get initFinishClasses { |
| 449 jsAst.Expression allClassesAccess = |
| 450 generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES); |
| 451 jsAst.Expression interceptorsByTagAccess = |
| 452 generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG); |
| 453 jsAst.Expression leafTagsAccess = |
| 454 generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS); |
| 455 jsAst.Expression finishedClassesAccess = |
| 456 generateEmbeddedGlobalAccess(embeddedNames.FINISHED_CLASSES); |
| 457 |
| 458 return js(''' |
| 459 (function(){ |
| 460 #allClasses = Object.create(null); |
| 461 #interceptorsByTag = Object.create(null); |
| 462 #leafTags = Object.create(null); |
| 463 #finishedClasses = Object.create(null); |
| 464 })() |
| 465 ''', {'allClasses': allClassesAccess, |
| 466 'interceptorsByTag': interceptorsByTagAccess, |
| 467 'leafTags': leafTagsAccess, |
| 468 'finishedClasses': finishedClassesAccess}); |
| 469 } |
| 470 |
| 471 jsAst.Fun get finishClassesFunction { |
| 472 // Class descriptions are collected in a JS object. |
| 473 // 'finishClasses' takes all collected descriptions and sets up |
| 474 // the prototype. |
| 475 // Once set up, the constructors prototype field satisfy: |
| 476 // - it contains all (local) members. |
| 477 // - its internal prototype (__proto__) points to the superclass' |
| 478 // prototype field. |
| 479 // - the prototype's constructor field points to the JavaScript |
| 480 // constructor. |
| 481 // For engines where we have access to the '__proto__' we can manipulate |
| 482 // the object literal directly. For other engines we have to create a new |
| 483 // object and copy over the members. |
| 484 |
| 485 String reflectableField = namer.reflectableField; |
| 486 jsAst.Expression allClassesAccess = |
| 487 generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES); |
| 488 jsAst.Expression metadataAccess = |
| 489 generateEmbeddedGlobalAccess(embeddedNames.METADATA); |
| 490 String signaturePropertyName = namer.operatorSignature; |
| 491 |
| 492 return js(''' |
| 493 function(collectedClasses, isolateProperties, existingIsolateProperties) { |
| 494 var pendingClasses = Object.create(null); |
| 495 var allClasses = #allClasses; |
| 496 var constructors; |
| 497 |
| 498 if (#debugFastObjects) |
| 499 print("Number of classes: " + |
| 500 Object.getOwnPropertyNames(\$\$).length); |
| 501 |
| 502 var hasOwnProperty = Object.prototype.hasOwnProperty; |
| 503 |
| 504 if (#inCspMode) { |
| 505 constructors = dart_precompiled(collectedClasses); |
| 506 } |
| 507 |
| 508 if (#notInCspMode) { |
| 509 var combinedConstructorFunction = |
| 510 "function \$reflectable(fn){fn.$reflectableField=1;return fn};\\n"+ |
| 511 "var \$desc;\\n"; |
| 512 var constructorsList = []; |
| 513 } |
| 514 |
| 515 for (var cls in collectedClasses) { |
| 516 var desc = collectedClasses[cls]; |
| 517 if (desc instanceof Array) desc = desc[1]; |
| 518 |
| 519 /* The 'fields' are either a constructor function or a |
| 520 * string encoding fields, constructor and superclass. Gets the |
| 521 * superclass and fields in the format |
| 522 * 'Super;field1,field2' |
| 523 * from the CLASS_DESCRIPTOR_PROPERTY property on the descriptor. |
| 524 */ |
| 525 var classData = desc["${namer.classDescriptorProperty}"], |
| 526 supr, fields = classData; |
| 527 if (#hasRetainedMetadata) |
| 528 if (typeof classData == "object" && |
| 529 classData instanceof Array) { |
| 530 classData = fields = classData[0]; |
| 531 } |
| 532 // ${ClassBuilder.fieldEncodingDescription}. |
| 533 var s = fields.split(";"); |
| 534 fields = s[1] == "" ? [] : s[1].split(","); |
| 535 supr = s[0]; |
| 536 // ${ClassBuilder.functionTypeEncodingDescription}. |
| 537 split = supr.split(":"); |
| 538 if (split.length == 2) { |
| 539 supr = split[0]; |
| 540 var functionSignature = split[1]; |
| 541 if (functionSignature) |
| 542 desc.$signaturePropertyName = (function(s) { |
| 543 return function(){ return #metadata[s]; }; |
| 544 })(functionSignature); |
| 545 } |
| 546 |
| 547 if (#notInCspMode) { |
| 548 combinedConstructorFunction += defineClass(cls, fields); |
| 549 constructorsList.push(cls); |
| 550 } |
| 551 if (supr) pendingClasses[cls] = supr; |
| 552 } |
| 553 |
| 554 if (#notInCspMode) { |
| 555 combinedConstructorFunction += |
| 556 "return [\\n " + constructorsList.join(",\\n ") + "\\n]"; |
| 557 var constructors = |
| 558 new Function("\$collectedClasses", combinedConstructorFunction) |
| 559 (collectedClasses); |
| 560 combinedConstructorFunction = null; |
| 561 } |
| 562 |
| 563 for (var i = 0; i < constructors.length; i++) { |
| 564 var constructor = constructors[i]; |
| 565 var cls = constructor.name; |
| 566 var desc = collectedClasses[cls]; |
| 567 var globalObject = isolateProperties; |
| 568 if (desc instanceof Array) { |
| 569 globalObject = desc[0] || isolateProperties; |
| 570 desc = desc[1]; |
| 571 } |
| 572 if (#isTreeShakingDisabled) |
| 573 constructor["${namer.metadataField}"] = desc; |
| 574 allClasses[cls] = constructor; |
| 575 globalObject[cls] = constructor; |
| 576 } |
| 577 |
| 578 constructors = null; |
| 579 |
| 580 #finishClassFunction; |
| 581 |
| 582 #trivialNsmHandlers; |
| 583 |
| 584 for (var cls in pendingClasses) finishClass(cls); |
| 585 }''', { 'allClasses': allClassesAccess, |
| 586 'debugFastObjects': DEBUG_FAST_OBJECTS, |
| 587 'hasRetainedMetadata': backend.hasRetainedMetadata, |
| 588 'metadata': metadataAccess, |
| 589 'isTreeShakingDisabled': backend.isTreeShakingDisabled, |
| 590 'finishClassFunction': buildFinishClass(), |
| 591 'trivialNsmHandlers': nsmEmitter.buildTrivialNsmHandlers(), |
| 592 'inCspMode': compiler.useContentSecurityPolicy, |
| 593 'notInCspMode': !compiler.useContentSecurityPolicy}); |
| 594 } |
| 595 |
| 441 jsAst.Statement buildFinishClass() { | 596 jsAst.Statement buildFinishClass() { |
| 442 String specProperty = '"${namer.nativeSpecProperty}"'; // "%" | 597 String specProperty = '"${namer.nativeSpecProperty}"'; // "%" |
| 443 | 598 |
| 444 jsAst.Expression finishedClassesAccess = | 599 jsAst.Expression finishedClassesAccess = |
| 445 generateEmbeddedGlobalAccess(embeddedNames.FINISHED_CLASSES); | 600 generateEmbeddedGlobalAccess(embeddedNames.FINISHED_CLASSES); |
| 446 jsAst.Expression interceptorsByTagAccess = | 601 jsAst.Expression interceptorsByTagAccess = |
| 447 generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG); | 602 generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG); |
| 448 jsAst.Expression leafTagsAccess = | 603 jsAst.Expression leafTagsAccess = |
| 449 generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS); | 604 generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS); |
| 450 | 605 |
| 451 return js.statement(''' | 606 return js.statement(''' |
| 452 { | 607 { |
| 453 var finishedClasses = #finishedClassesAccess; | 608 var finishedClasses = #finishedClassesAccess; |
| 454 | 609 |
| 455 function finishClass(cls) { | 610 function finishClass(cls) { |
| 456 | 611 |
| 457 if (finishedClasses[cls]) return; | 612 if (finishedClasses[cls]) return; |
| 458 finishedClasses[cls] = true; | 613 finishedClasses[cls] = true; |
| 459 | 614 |
| 460 var superclass = processedClasses.pending[cls]; | 615 var superclass = pendingClasses[cls]; |
| 461 | 616 |
| 462 if (#needsMixinSupport) { | 617 if (#needsMixinSupport) { |
| 463 if (superclass && superclass.indexOf("+") > 0) { | 618 if (superclass && superclass.indexOf("+") > 0) { |
| 464 var s = superclass.split("+"); | 619 var s = superclass.split("+"); |
| 465 superclass = s[0]; | 620 superclass = s[0]; |
| 466 var mixinClass = s[1]; | 621 var mixinClass = s[1]; |
| 467 finishClass(mixinClass); | 622 finishClass(mixinClass); |
| 468 var mixin = allClasses[mixinClass]; | 623 var mixin = allClasses[mixinClass]; |
| 469 // TODO(21896): this test shouldn't be necessary. Without it | 624 // TODO(21896): this test shouldn't be necessary. Without it |
| 470 // we have a crash in language/mixin_only_for_rti and | 625 // we have a crash in language/mixin_only_for_rti and |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 549 } | 704 } |
| 550 } | 705 } |
| 551 }''', {'finishedClassesAccess': finishedClassesAccess, | 706 }''', {'finishedClassesAccess': finishedClassesAccess, |
| 552 'needsMixinSupport': needsMixinSupport, | 707 'needsMixinSupport': needsMixinSupport, |
| 553 'hasNativeClasses': nativeClasses.isNotEmpty, | 708 'hasNativeClasses': nativeClasses.isNotEmpty, |
| 554 'interceptorsByTagAccess': interceptorsByTagAccess, | 709 'interceptorsByTagAccess': interceptorsByTagAccess, |
| 555 'leafTagsAccess': leafTagsAccess, | 710 'leafTagsAccess': leafTagsAccess, |
| 556 'allowNativesSubclassing': true}); | 711 'allowNativesSubclassing': true}); |
| 557 } | 712 } |
| 558 | 713 |
| 714 jsAst.Fun get finishIsolateConstructorFunction { |
| 715 // We replace the old Isolate function with a new one that initializes |
| 716 // all its fields with the initial (and often final) value of all globals. |
| 717 // |
| 718 // We also copy over old values like the prototype, and the |
| 719 // isolateProperties themselves. |
| 720 return js( |
| 721 """ |
| 722 function (oldIsolate) { |
| 723 var isolateProperties = oldIsolate.#isolatePropertiesName; |
| 724 function Isolate() { |
| 725 var hasOwnProperty = Object.prototype.hasOwnProperty; |
| 726 for (var staticName in isolateProperties) |
| 727 if (hasOwnProperty.call(isolateProperties, staticName)) |
| 728 this[staticName] = isolateProperties[staticName]; |
| 729 |
| 730 // Reset lazy initializers to null. |
| 731 // When forcing the object to fast mode (below) v8 will consider |
| 732 // functions as part the object's map. Since we will change them |
| 733 // (after the first call to the getter), we would have a map |
| 734 // transition. |
| 735 var lazies = init.lazies; |
| 736 for (var lazyInit in lazies) { |
| 737 this[lazies[lazyInit]] = null; |
| 738 } |
| 739 |
| 740 // Use the newly created object as prototype. In Chrome, |
| 741 // this creates a hidden class for the object and makes |
| 742 // sure it is fast to access. |
| 743 function ForceEfficientMap() {} |
| 744 ForceEfficientMap.prototype = this; |
| 745 new ForceEfficientMap(); |
| 746 |
| 747 // Now, after being a fast map we can set the lazies again. |
| 748 for (var lazyInit in lazies) { |
| 749 var lazyInitName = lazies[lazyInit]; |
| 750 this[lazyInitName] = isolateProperties[lazyInitName]; |
| 751 } |
| 752 } |
| 753 Isolate.prototype = oldIsolate.prototype; |
| 754 Isolate.prototype.constructor = Isolate; |
| 755 Isolate.#isolatePropertiesName = isolateProperties; |
| 756 if (#needsDefineClass) |
| 757 Isolate.#finishClassesProperty = oldIsolate.#finishClassesProperty; |
| 758 if (#outputContainsConstantList) |
| 759 Isolate.#makeConstListProperty = oldIsolate.#makeConstListProperty; |
| 760 if (#hasIncrementalSupport) |
| 761 Isolate.#lazyInitializerProperty = |
| 762 oldIsolate.#lazyInitializerProperty; |
| 763 return Isolate; |
| 764 } |
| 765 """, |
| 766 { 'isolatePropertiesName': namer.isolatePropertiesName, |
| 767 'needsDefineClass': needsDefineClass, |
| 768 'finishClassesProperty': finishClassesProperty, |
| 769 'outputContainsConstantList': task.outputContainsConstantList, |
| 770 'makeConstListProperty': makeConstListProperty, |
| 771 'hasIncrementalSupport': compiler.hasIncrementalSupport, |
| 772 'lazyInitializerProperty': lazyInitializerProperty, |
| 773 }); |
| 774 } |
| 775 |
| 776 jsAst.Fun get lazyInitializerFunction { |
| 777 String isolate = namer.currentIsolate; |
| 778 jsAst.Expression cyclicThrow = |
| 779 staticFunctionAccess(backend.getCyclicThrowHelper()); |
| 780 jsAst.Expression laziesAccess = |
| 781 generateEmbeddedGlobalAccess(embeddedNames.LAZIES); |
| 782 |
| 783 return js(''' |
| 784 function (prototype, staticName, fieldName, getterName, lazyValue) { |
| 785 if (!#lazies) #lazies = Object.create(null); |
| 786 #lazies[fieldName] = getterName; |
| 787 |
| 788 var sentinelUndefined = {}; |
| 789 var sentinelInProgress = {}; |
| 790 prototype[fieldName] = sentinelUndefined; |
| 791 |
| 792 prototype[getterName] = function () { |
| 793 var result = $isolate[fieldName]; |
| 794 try { |
| 795 if (result === sentinelUndefined) { |
| 796 $isolate[fieldName] = sentinelInProgress; |
| 797 |
| 798 try { |
| 799 result = $isolate[fieldName] = lazyValue(); |
| 800 } finally { |
| 801 // Use try-finally, not try-catch/throw as it destroys the |
| 802 // stack trace. |
| 803 if (result === sentinelUndefined) |
| 804 $isolate[fieldName] = null; |
| 805 } |
| 806 } else { |
| 807 if (result === sentinelInProgress) |
| 808 #cyclicThrow(staticName); |
| 809 } |
| 810 |
| 811 return result; |
| 812 } finally { |
| 813 $isolate[getterName] = function() { return this[fieldName]; }; |
| 814 } |
| 815 } |
| 816 } |
| 817 ''', {'lazies': laziesAccess, 'cyclicThrow': cyclicThrow}); |
| 818 } |
| 819 |
| 820 List buildDefineClassAndFinishClassFunctionsIfNecessary() { |
| 821 if (!needsDefineClass) return []; |
| 822 return defineClassFunction |
| 823 ..add(buildInheritFrom()) |
| 824 ..add(js('$finishClassesName = #', finishClassesFunction)) |
| 825 ..add(initFinishClasses); |
| 826 } |
| 827 |
| 828 List buildLazyInitializerFunctionIfNecessary() { |
| 829 if (!needsLazyInitializer) return []; |
| 830 |
| 831 return [js('# = #', [js(lazyInitializerName), lazyInitializerFunction])]; |
| 832 } |
| 833 |
| 834 List buildFinishIsolateConstructor() { |
| 835 return [ |
| 836 js('$finishIsolateConstructorName = #', finishIsolateConstructorFunction) |
| 837 ]; |
| 838 } |
| 839 |
| 559 void emitFinishIsolateConstructorInvocation(CodeBuffer buffer) { | 840 void emitFinishIsolateConstructorInvocation(CodeBuffer buffer) { |
| 560 String isolate = namer.isolateName; | 841 String isolate = namer.isolateName; |
| 561 buffer.write("$isolate = $finishIsolateConstructorName($isolate)$N"); | 842 buffer.write("$isolate = $finishIsolateConstructorName($isolate)$N"); |
| 562 } | 843 } |
| 563 | 844 |
| 564 /// In minified mode we want to keep the name for the most common core types. | 845 /// In minified mode we want to keep the name for the most common core types. |
| 565 bool _isNativeTypeNeedingReflectionName(Element element) { | 846 bool _isNativeTypeNeedingReflectionName(Element element) { |
| 566 if (!element.isClass) return false; | 847 if (!element.isClass) return false; |
| 567 return (element == compiler.intClass || | 848 return (element == compiler.intClass || |
| 568 element == compiler.doubleClass || | 849 element == compiler.doubleClass || |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 723 invariant(classElement, builder.functionType == null); | 1004 invariant(classElement, builder.functionType == null); |
| 724 invariant(classElement, builder.fieldMetadata == null); | 1005 invariant(classElement, builder.fieldMetadata == null); |
| 725 properties.properties.addAll(builder.properties); | 1006 properties.properties.addAll(builder.properties); |
| 726 } else { | 1007 } else { |
| 727 classEmitter.generateClass( | 1008 classEmitter.generateClass( |
| 728 classElement, properties, additionalProperties[classElement]); | 1009 classElement, properties, additionalProperties[classElement]); |
| 729 } | 1010 } |
| 730 }); | 1011 }); |
| 731 } | 1012 } |
| 732 | 1013 |
| 1014 void emitFinishClassesInvocationIfNecessary(CodeBuffer buffer) { |
| 1015 if (needsDefineClass) { |
| 1016 buffer.write('$finishClassesName($classesCollector,' |
| 1017 '$_$isolateProperties,' |
| 1018 '${_}null)$N'); |
| 1019 |
| 1020 // Reset the map. |
| 1021 buffer.write("$classesCollector$_=${_}null$N$n"); |
| 1022 } |
| 1023 } |
| 1024 |
| 733 void emitStaticFunctions(List<Element> staticFunctions) { | 1025 void emitStaticFunctions(List<Element> staticFunctions) { |
| 734 for (Element element in staticFunctions) { | 1026 for (Element element in staticFunctions) { |
| 735 ClassBuilder builder = new ClassBuilder(element, namer); | 1027 ClassBuilder builder = new ClassBuilder(element, namer); |
| 736 containerBuilder.addMember(element, builder); | 1028 containerBuilder.addMember(element, builder); |
| 737 getElementDescriptor(element).properties.addAll(builder.properties); | 1029 getElementDescriptor(element).properties.addAll(builder.properties); |
| 738 } | 1030 } |
| 739 } | 1031 } |
| 740 | 1032 |
| 741 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer, | 1033 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer, |
| 742 OutputUnit outputUnit) { | 1034 OutputUnit outputUnit) { |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1038 'mainCallClosure': mainCallClosure}); | 1330 'mainCallClosure': mainCallClosure}); |
| 1039 | 1331 |
| 1040 buffer.write(';'); | 1332 buffer.write(';'); |
| 1041 buffer.write(jsAst.prettyPrint(invokeMain, | 1333 buffer.write(jsAst.prettyPrint(invokeMain, |
| 1042 compiler, monitor: compiler.dumpInfoTask)); | 1334 compiler, monitor: compiler.dumpInfoTask)); |
| 1043 buffer.write(N); | 1335 buffer.write(N); |
| 1044 addComment('END invoke [main].', buffer); | 1336 addComment('END invoke [main].', buffer); |
| 1045 } | 1337 } |
| 1046 | 1338 |
| 1047 void emitInitFunction(CodeBuffer buffer) { | 1339 void emitInitFunction(CodeBuffer buffer) { |
| 1048 String isolate = namer.currentIsolate; | |
| 1049 jsAst.Expression allClassesAccess = | |
| 1050 generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES); | |
| 1051 jsAst.Expression interceptorsByTagAccess = | |
| 1052 generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG); | |
| 1053 jsAst.Expression leafTagsAccess = | |
| 1054 generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS); | |
| 1055 jsAst.Expression finishedClassesAccess = | |
| 1056 generateEmbeddedGlobalAccess(embeddedNames.FINISHED_CLASSES); | |
| 1057 jsAst.Expression cyclicThrow = | |
| 1058 staticFunctionAccess(backend.getCyclicThrowHelper()); | |
| 1059 jsAst.Expression laziesAccess = | |
| 1060 generateEmbeddedGlobalAccess(embeddedNames.LAZIES); | |
| 1061 | |
| 1062 jsAst.FunctionDeclaration decl = js.statement(''' | 1340 jsAst.FunctionDeclaration decl = js.statement(''' |
| 1063 function init() { | 1341 function init() { |
| 1064 $isolateProperties = Object.create(null); | 1342 $isolateProperties = Object.create(null); |
| 1065 (function(){ | 1343 #; #; #; |
| 1066 #allClasses = Object.create(null); | 1344 }''', [ |
| 1067 #interceptorsByTag = Object.create(null); | 1345 buildDefineClassAndFinishClassFunctionsIfNecessary(), |
| 1068 #leafTags = Object.create(null); | 1346 buildLazyInitializerFunctionIfNecessary(), |
| 1069 #finishedClasses = Object.create(null); | 1347 buildFinishIsolateConstructor()]); |
| 1070 })(); | |
| 1071 | |
| 1072 if (#needsLazyInitializer) { | |
| 1073 $lazyInitializerName = function (prototype, staticName, fieldName, | |
| 1074 getterName, lazyValue) { | |
| 1075 if (!#lazies) #lazies = Object.create(null); | |
| 1076 #lazies[fieldName] = getterName; | |
| 1077 | |
| 1078 var sentinelUndefined = {}; | |
| 1079 var sentinelInProgress = {}; | |
| 1080 prototype[fieldName] = sentinelUndefined; | |
| 1081 | |
| 1082 prototype[getterName] = function () { | |
| 1083 var result = $isolate[fieldName]; | |
| 1084 try { | |
| 1085 if (result === sentinelUndefined) { | |
| 1086 $isolate[fieldName] = sentinelInProgress; | |
| 1087 | |
| 1088 try { | |
| 1089 result = $isolate[fieldName] = lazyValue(); | |
| 1090 } finally { | |
| 1091 // Use try-finally, not try-catch/throw as it destroys the | |
| 1092 // stack trace. | |
| 1093 if (result === sentinelUndefined) | |
| 1094 $isolate[fieldName] = null; | |
| 1095 } | |
| 1096 } else { | |
| 1097 if (result === sentinelInProgress) | |
| 1098 #cyclicThrow(staticName); | |
| 1099 } | |
| 1100 | |
| 1101 return result; | |
| 1102 } finally { | |
| 1103 $isolate[getterName] = function() { return this[fieldName]; }; | |
| 1104 } | |
| 1105 } | |
| 1106 } | |
| 1107 } | |
| 1108 | |
| 1109 // We replace the old Isolate function with a new one that initializes | |
| 1110 // all its fields with the initial (and often final) value of all | |
| 1111 // globals. | |
| 1112 // | |
| 1113 // We also copy over old values like the prototype, and the | |
| 1114 // isolateProperties themselves. | |
| 1115 $finishIsolateConstructorName = function (oldIsolate) { | |
| 1116 var isolateProperties = oldIsolate.#isolatePropertiesName; | |
| 1117 function Isolate() { | |
| 1118 var hasOwnProperty = Object.prototype.hasOwnProperty; | |
| 1119 for (var staticName in isolateProperties) | |
| 1120 if (hasOwnProperty.call(isolateProperties, staticName)) | |
| 1121 this[staticName] = isolateProperties[staticName]; | |
| 1122 | |
| 1123 // Reset lazy initializers to null. | |
| 1124 // When forcing the object to fast mode (below) v8 will consider | |
| 1125 // functions as part the object's map. Since we will change them | |
| 1126 // (after the first call to the getter), we would have a map | |
| 1127 // transition. | |
| 1128 var lazies = init.lazies; | |
| 1129 for (var lazyInit in lazies) { | |
| 1130 this[lazies[lazyInit]] = null; | |
| 1131 } | |
| 1132 | |
| 1133 // Use the newly created object as prototype. In Chrome, | |
| 1134 // this creates a hidden class for the object and makes | |
| 1135 // sure it is fast to access. | |
| 1136 function ForceEfficientMap() {} | |
| 1137 ForceEfficientMap.prototype = this; | |
| 1138 new ForceEfficientMap(); | |
| 1139 | |
| 1140 // Now, after being a fast map we can set the lazies again. | |
| 1141 for (var lazyInit in lazies) { | |
| 1142 var lazyInitName = lazies[lazyInit]; | |
| 1143 this[lazyInitName] = isolateProperties[lazyInitName]; | |
| 1144 } | |
| 1145 } | |
| 1146 Isolate.prototype = oldIsolate.prototype; | |
| 1147 Isolate.prototype.constructor = Isolate; | |
| 1148 Isolate.#isolatePropertiesName = isolateProperties; | |
| 1149 if (#outputContainsConstantList) { | |
| 1150 Isolate.#makeConstListProperty = oldIsolate.#makeConstListProperty; | |
| 1151 } | |
| 1152 if (#hasIncrementalSupport) { | |
| 1153 Isolate.#lazyInitializerProperty = | |
| 1154 oldIsolate.#lazyInitializerProperty; | |
| 1155 } | |
| 1156 return Isolate; | |
| 1157 } | |
| 1158 | |
| 1159 }''', {'allClasses': allClassesAccess, | |
| 1160 'interceptorsByTag': interceptorsByTagAccess, | |
| 1161 'leafTags': leafTagsAccess, | |
| 1162 'finishedClasses': finishedClassesAccess, | |
| 1163 'needsLazyInitializer': needsLazyInitializer, | |
| 1164 'lazies': laziesAccess, 'cyclicThrow': cyclicThrow, | |
| 1165 'isolatePropertiesName': namer.isolatePropertiesName, | |
| 1166 'outputContainsConstantList': task.outputContainsConstantList, | |
| 1167 'makeConstListProperty': makeConstListProperty, | |
| 1168 'hasIncrementalSupport': compiler.hasIncrementalSupport, | |
| 1169 'lazyInitializerProperty': lazyInitializerProperty,}); | |
| 1170 | 1348 |
| 1171 buffer.write(jsAst.prettyPrint(decl, | 1349 buffer.write(jsAst.prettyPrint(decl, |
| 1172 compiler, monitor: compiler.dumpInfoTask).getText()); | 1350 compiler, monitor: compiler.dumpInfoTask).getText()); |
| 1173 if (compiler.enableMinification) buffer.write('\n'); | 1351 if (compiler.enableMinification) buffer.write('\n'); |
| 1174 } | 1352 } |
| 1175 | 1353 |
| 1176 void emitConvertToFastObjectFunction() { | 1354 void emitConvertToFastObjectFunction() { |
| 1177 List<jsAst.Statement> debugCode = <jsAst.Statement>[]; | 1355 List<jsAst.Statement> debugCode = <jsAst.Statement>[]; |
| 1178 if (DEBUG_FAST_OBJECTS) { | 1356 if (DEBUG_FAST_OBJECTS) { |
| 1179 debugCode.add(js.statement(r''' | 1357 debugCode.add(js.statement(r''' |
| (...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1481 mainBuffer | 1659 mainBuffer |
| 1482 .write('${globalsHolder}.${namer.isolateName}$_=$_' | 1660 .write('${globalsHolder}.${namer.isolateName}$_=$_' |
| 1483 '${namer.isolateName}$N' | 1661 '${namer.isolateName}$N' |
| 1484 '${globalsHolder}.$initName$_=${_}$initName$N'); | 1662 '${globalsHolder}.$initName$_=${_}$initName$N'); |
| 1485 } | 1663 } |
| 1486 mainBuffer.write('init()$N$n'); | 1664 mainBuffer.write('init()$N$n'); |
| 1487 mainBuffer.write('$isolateProperties$_=$_$isolatePropertiesName$N'); | 1665 mainBuffer.write('$isolateProperties$_=$_$isolatePropertiesName$N'); |
| 1488 | 1666 |
| 1489 emitStaticFunctions(task.outputStaticLists[mainOutputUnit]); | 1667 emitStaticFunctions(task.outputStaticLists[mainOutputUnit]); |
| 1490 | 1668 |
| 1669 // Only output the classesCollector if we actually have any classes. |
| 1670 if (needsDefineClass || |
| 1671 !(nativeClasses.isEmpty && |
| 1672 compiler.codegenWorld.staticFunctionsNeedingGetter.isEmpty && |
| 1673 outputClassLists.values.every((classList) => classList.isEmpty) && |
| 1674 typedefsNeededForReflection.isEmpty)) { |
| 1675 // Shorten the code by using "$$" as temporary. |
| 1676 classesCollector = r"$$"; |
| 1677 mainBuffer.write('var $classesCollector$_=${_}Object.create(null)$N$n'); |
| 1678 } |
| 1679 |
| 1491 List<ClassElement> classes = task.outputClassLists[mainOutputUnit]; | 1680 List<ClassElement> classes = task.outputClassLists[mainOutputUnit]; |
| 1492 if (classes != null) { | 1681 if (classes != null) { |
| 1493 for (ClassElement element in classes) { | 1682 for (ClassElement element in classes) { |
| 1494 generateClass(element, getElementDescriptor(element)); | 1683 generateClass(element, getElementDescriptor(element)); |
| 1495 } | 1684 } |
| 1496 } | 1685 } |
| 1497 | 1686 |
| 1498 if (compiler.enableMinification) { | 1687 if (compiler.enableMinification) { |
| 1499 mainBuffer.write(';'); | 1688 mainBuffer.write(';'); |
| 1500 } | 1689 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1512 CodeBuffer libraryBuffer = new CodeBuffer(); | 1701 CodeBuffer libraryBuffer = new CodeBuffer(); |
| 1513 for (LibraryElement library in Elements.sortedByPosition(libraries)) { | 1702 for (LibraryElement library in Elements.sortedByPosition(libraries)) { |
| 1514 writeLibraryDescriptors(libraryBuffer, library); | 1703 writeLibraryDescriptors(libraryBuffer, library); |
| 1515 elementDescriptors.remove(library); | 1704 elementDescriptors.remove(library); |
| 1516 } | 1705 } |
| 1517 | 1706 |
| 1518 mainBuffer | 1707 mainBuffer |
| 1519 ..write('(') | 1708 ..write('(') |
| 1520 ..write( | 1709 ..write( |
| 1521 jsAst.prettyPrint( | 1710 jsAst.prettyPrint( |
| 1522 getReflectionDataParser(this, backend), | 1711 getReflectionDataParser(classesCollector, backend), |
| 1523 compiler)) | 1712 compiler)) |
| 1524 ..write(')') | 1713 ..write(')') |
| 1525 ..write('([$n') | 1714 ..write('([$n') |
| 1526 ..write(libraryBuffer) | 1715 ..write(libraryBuffer) |
| 1527 ..write('])$N'); | 1716 ..write('])$N'); |
| 1717 |
| 1718 emitFinishClassesInvocationIfNecessary(mainBuffer); |
| 1528 } | 1719 } |
| 1529 | 1720 |
| 1530 interceptorEmitter.emitGetInterceptorMethods(mainBuffer); | 1721 interceptorEmitter.emitGetInterceptorMethods(mainBuffer); |
| 1531 interceptorEmitter.emitOneShotInterceptors(mainBuffer); | 1722 interceptorEmitter.emitOneShotInterceptors(mainBuffer); |
| 1532 | 1723 |
| 1533 if (task.outputContainsConstantList) { | 1724 if (task.outputContainsConstantList) { |
| 1534 emitMakeConstantList(mainBuffer); | 1725 emitMakeConstantList(mainBuffer); |
| 1535 } | 1726 } |
| 1536 | 1727 |
| 1537 // Constants in checked mode call into RTI code to set type information | 1728 // Constants in checked mode call into RTI code to set type information |
| (...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1810 nativeEmitter.finishGenerateNativeClasses(); | 2001 nativeEmitter.finishGenerateNativeClasses(); |
| 1811 nativeEmitter.assembleCode(nativeBuffer); | 2002 nativeEmitter.assembleCode(nativeBuffer); |
| 1812 | 2003 |
| 1813 return nativeBuffer; | 2004 return nativeBuffer; |
| 1814 } | 2005 } |
| 1815 | 2006 |
| 1816 void emitProgram(Program program) { | 2007 void emitProgram(Program program) { |
| 1817 // Shorten the code by using [namer.currentIsolate] as temporary. | 2008 // Shorten the code by using [namer.currentIsolate] as temporary. |
| 1818 isolateProperties = namer.currentIsolate; | 2009 isolateProperties = namer.currentIsolate; |
| 1819 | 2010 |
| 2011 classesCollector = r"$$"; |
| 2012 |
| 1820 // Emit deferred units first, so we have their hashes. | 2013 // Emit deferred units first, so we have their hashes. |
| 1821 // Map from OutputUnit to a hash of its content. The hash uniquely | 2014 // Map from OutputUnit to a hash of its content. The hash uniquely |
| 1822 // identifies the code of the output-unit. It does not include | 2015 // identifies the code of the output-unit. It does not include |
| 1823 // boilerplate JS code, like the sourcemap directives or the hash | 2016 // boilerplate JS code, like the sourcemap directives or the hash |
| 1824 // itself. | 2017 // itself. |
| 1825 Map<OutputUnit, String> deferredLoadHashes = emitDeferredOutputUnits(); | 2018 Map<OutputUnit, String> deferredLoadHashes = emitDeferredOutputUnits(); |
| 1826 CodeBuffer nativeBuffer = buildNativesBuffer(); | 2019 CodeBuffer nativeBuffer = buildNativesBuffer(); |
| 1827 emitMainOutputUnit(deferredLoadHashes, nativeBuffer); | 2020 emitMainOutputUnit(deferredLoadHashes, nativeBuffer); |
| 1828 | 2021 |
| 1829 if (backend.requiresPreamble && | 2022 if (backend.requiresPreamble && |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1958 ..write('var init$_=$_${globalsHolder}.init$N') | 2151 ..write('var init$_=$_${globalsHolder}.init$N') |
| 1959 ..write('var ${namer.isolateName}$_=$_' | 2152 ..write('var ${namer.isolateName}$_=$_' |
| 1960 '${globalsHolder}.${namer.isolateName}$N'); | 2153 '${globalsHolder}.${namer.isolateName}$N'); |
| 1961 if (libraryDescriptorBuffer != null) { | 2154 if (libraryDescriptorBuffer != null) { |
| 1962 // TODO(ahe): This defines a lot of properties on the | 2155 // TODO(ahe): This defines a lot of properties on the |
| 1963 // Isolate.prototype object. We know this will turn it into a | 2156 // Isolate.prototype object. We know this will turn it into a |
| 1964 // slow object in V8, so instead we should do something similar | 2157 // slow object in V8, so instead we should do something similar |
| 1965 // to Isolate.$finishIsolateConstructor. | 2158 // to Isolate.$finishIsolateConstructor. |
| 1966 outputBuffer | 2159 outputBuffer |
| 1967 ..write('var ${namer.currentIsolate}$_=$_$isolatePropertiesName$N') | 2160 ..write('var ${namer.currentIsolate}$_=$_$isolatePropertiesName$N') |
| 2161 // The classesCollector object ($$). |
| 2162 ..write('$classesCollector$_=${_}Object.create(null);$n') |
| 1968 ..write('(') | 2163 ..write('(') |
| 1969 ..write( | 2164 ..write( |
| 1970 jsAst.prettyPrint( | 2165 jsAst.prettyPrint( |
| 1971 getReflectionDataParser(this, backend), | 2166 getReflectionDataParser(classesCollector, backend), |
| 1972 compiler, monitor: compiler.dumpInfoTask)) | 2167 compiler, monitor: compiler.dumpInfoTask)) |
| 1973 ..write(')') | 2168 ..write(')') |
| 1974 ..write('([$n') | 2169 ..write('([$n') |
| 1975 ..addBuffer(libraryDescriptorBuffer) | 2170 ..addBuffer(libraryDescriptorBuffer) |
| 1976 ..write('])$N'); | 2171 ..write('])$N'); |
| 1977 | 2172 |
| 2173 if (outputClassLists.containsKey(outputUnit)) { |
| 2174 outputBuffer.write( |
| 2175 '$finishClassesName($classesCollector,$_${namer.currentIsolate},' |
| 2176 '$_$isolatePropertiesName)$N'); |
| 2177 } |
| 2178 |
| 1978 } | 2179 } |
| 1979 | 2180 |
| 1980 // Set the currentIsolate variable to the current isolate (which is | 2181 // Set the currentIsolate variable to the current isolate (which is |
| 1981 // provided as second argument). | 2182 // provided as second argument). |
| 1982 // We need to do this, because we use the same variable for setting up | 2183 // We need to do this, because we use the same variable for setting up |
| 1983 // the isolate-properties and for storing the current isolate. During | 2184 // the isolate-properties and for storing the current isolate. During |
| 1984 // the setup (the code above this lines) we must set the variable to | 2185 // the setup (the code above this lines) we must set the variable to |
| 1985 // the isolate-properties. | 2186 // the isolate-properties. |
| 1986 // After we have done the setup it must point to the current Isolate. | 2187 // After we have done the setup (finishing with `finishClasses`) it must |
| 1987 // Otherwise all methods/functions accessing isolate variables will | 2188 // point to the current Isolate. Otherwise all methods/functions |
| 1988 // access the wrong object. | 2189 // accessing isolate variables will access the wrong object. |
| 1989 outputBuffer.write("${namer.currentIsolate}$_=${_}arguments[1]$N"); | 2190 outputBuffer.write("${namer.currentIsolate}$_=${_}arguments[1]$N"); |
| 1990 | 2191 |
| 1991 emitCompileTimeConstants(outputBuffer, outputUnit); | 2192 emitCompileTimeConstants(outputBuffer, outputUnit); |
| 1992 emitStaticNonFinalFieldInitializations(outputBuffer, outputUnit); | 2193 emitStaticNonFinalFieldInitializations(outputBuffer, outputUnit); |
| 1993 outputBuffer.write('}$N'); | 2194 outputBuffer.write('}$N'); |
| 1994 | 2195 |
| 1995 if (compiler.useContentSecurityPolicy) { | 2196 if (compiler.useContentSecurityPolicy) { |
| 1996 jsAst.FunctionDeclaration precompiledFunctionAst = | 2197 jsAst.FunctionDeclaration precompiledFunctionAst = |
| 1997 buildCspPrecompiledFunctionFor(outputUnit); | 2198 buildCspPrecompiledFunctionFor(outputUnit); |
| 1998 | 2199 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2075 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { | 2276 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { |
| 2076 if (element.isInstanceMember) { | 2277 if (element.isInstanceMember) { |
| 2077 cachedClassBuilders.remove(element.enclosingClass); | 2278 cachedClassBuilders.remove(element.enclosingClass); |
| 2078 | 2279 |
| 2079 nativeEmitter.cachedBuilders.remove(element.enclosingClass); | 2280 nativeEmitter.cachedBuilders.remove(element.enclosingClass); |
| 2080 | 2281 |
| 2081 } | 2282 } |
| 2082 } | 2283 } |
| 2083 } | 2284 } |
| 2084 } | 2285 } |
| OLD | NEW |