| 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 needsDefineClass = false; | 24 bool needsClassSupport = 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'; | |
| 158 String get finishIsolateConstructorName | 150 String get finishIsolateConstructorName |
| 159 => '${namer.isolateName}.\$finishIsolateConstructor'; | 151 => '${namer.isolateName}.\$finishIsolateConstructor'; |
| 160 String get isolatePropertiesName | 152 String get isolatePropertiesName |
| 161 => '${namer.isolateName}.${namer.isolatePropertiesName}'; | 153 => '${namer.isolateName}.${namer.isolatePropertiesName}'; |
| 162 String get lazyInitializerProperty | 154 String get lazyInitializerProperty |
| 163 => r'$lazy'; | 155 => r'$lazy'; |
| 164 String get lazyInitializerName | 156 String get lazyInitializerName |
| 165 => '${namer.isolateName}.${lazyInitializerProperty}'; | 157 => '${namer.isolateName}.${lazyInitializerProperty}'; |
| 166 String get initName => 'init'; | 158 String get initName => 'init'; |
| 167 String get makeConstListProperty | 159 String get makeConstListProperty |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 214 } | 206 } |
| 215 | 207 |
| 216 jsAst.PropertyAccess classAccess(Element element) { | 208 jsAst.PropertyAccess classAccess(Element element) { |
| 217 return globalPropertyAccess(element); | 209 return globalPropertyAccess(element); |
| 218 } | 210 } |
| 219 | 211 |
| 220 jsAst.PropertyAccess typedefAccess(Element element) { | 212 jsAst.PropertyAccess typedefAccess(Element element) { |
| 221 return globalPropertyAccess(element); | 213 return globalPropertyAccess(element); |
| 222 } | 214 } |
| 223 | 215 |
| 216 List<jsAst.Statement> buildTrivialNsmHandlers(){ |
| 217 return nsmEmitter.buildTrivialNsmHandlers(); |
| 218 } |
| 219 |
| 224 jsAst.FunctionDeclaration get generateAccessorFunction { | 220 jsAst.FunctionDeclaration get generateAccessorFunction { |
| 225 const RANGE1_SIZE = RANGE1_LAST - RANGE1_FIRST + 1; | 221 const RANGE1_SIZE = RANGE1_LAST - RANGE1_FIRST + 1; |
| 226 const RANGE2_SIZE = RANGE2_LAST - RANGE2_FIRST + 1; | 222 const RANGE2_SIZE = RANGE2_LAST - RANGE2_FIRST + 1; |
| 227 const RANGE1_ADJUST = - (FIRST_FIELD_CODE - RANGE1_FIRST); | 223 const RANGE1_ADJUST = - (FIRST_FIELD_CODE - RANGE1_FIRST); |
| 228 const RANGE2_ADJUST = - (FIRST_FIELD_CODE + RANGE1_SIZE - RANGE2_FIRST); | 224 const RANGE2_ADJUST = - (FIRST_FIELD_CODE + RANGE1_SIZE - RANGE2_FIRST); |
| 229 const RANGE3_ADJUST = | 225 const RANGE3_ADJUST = |
| 230 - (FIRST_FIELD_CODE + RANGE1_SIZE + RANGE2_SIZE - RANGE3_FIRST); | 226 - (FIRST_FIELD_CODE + RANGE1_SIZE + RANGE2_SIZE - RANGE3_FIRST); |
| 231 | 227 |
| 232 String receiverParamName = compiler.enableMinification ? "r" : "receiver"; | 228 String receiverParamName = compiler.enableMinification ? "r" : "receiver"; |
| 233 String valueParamName = compiler.enableMinification ? "v" : "value"; | 229 String valueParamName = compiler.enableMinification ? "v" : "value"; |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 } | 335 } |
| 340 if (#hasIsolateSupport) { | 336 if (#hasIsolateSupport) { |
| 341 str += name + ".$fieldNamesProperty=[" + fieldNames + "];\\n"; | 337 str += name + ".$fieldNamesProperty=[" + fieldNames + "];\\n"; |
| 342 } | 338 } |
| 343 str += accessors.join(""); | 339 str += accessors.join(""); |
| 344 | 340 |
| 345 return str; | 341 return str; |
| 346 }''', { 'hasIsolateSupport': hasIsolateSupport }); | 342 }''', { 'hasIsolateSupport': hasIsolateSupport }); |
| 347 | 343 |
| 348 // Declare a function called "generateAccessor". This is used in | 344 // Declare a function called "generateAccessor". This is used in |
| 349 // defineClassFunction (it's a local declaration in init()). | 345 // defineClassFunction. |
| 350 List result = <jsAst.Node>[ | 346 List result = <jsAst.Node>[ |
| 351 generateAccessorFunction, | 347 generateAccessorFunction, |
| 352 js('$generateAccessorHolder = generateAccessor'), | |
| 353 new jsAst.FunctionDeclaration( | 348 new jsAst.FunctionDeclaration( |
| 354 new jsAst.VariableDeclaration('defineClass'), defineClass) ]; | 349 new jsAst.VariableDeclaration('defineClass'), defineClass) ]; |
| 355 | 350 |
| 356 if (compiler.hasIncrementalSupport) { | 351 if (compiler.hasIncrementalSupport) { |
| 357 result.add( | 352 result.add( |
| 358 js(r'#.defineClass = defineClass', [namer.accessIncrementalHelper])); | 353 js(r'#.defineClass = defineClass', [namer.accessIncrementalHelper])); |
| 359 } | 354 } |
| 360 | 355 |
| 361 if (hasIsolateSupport) { | 356 if (hasIsolateSupport) { |
| 362 jsAst.Expression classIdExtractorAccess = | 357 jsAst.Expression classIdExtractorAccess = |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 436 }; | 431 }; |
| 437 }() | 432 }() |
| 438 '''); | 433 '''); |
| 439 if (compiler.hasIncrementalSupport) { | 434 if (compiler.hasIncrementalSupport) { |
| 440 result = js( | 435 result = js( |
| 441 r'#.inheritFrom = #', [namer.accessIncrementalHelper, result]); | 436 r'#.inheritFrom = #', [namer.accessIncrementalHelper, result]); |
| 442 } | 437 } |
| 443 return js(r'var inheritFrom = #', [result]); | 438 return js(r'var inheritFrom = #', [result]); |
| 444 } | 439 } |
| 445 | 440 |
| 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 | |
| 596 jsAst.Statement buildFinishClass() { | 441 jsAst.Statement buildFinishClass() { |
| 597 String specProperty = '"${namer.nativeSpecProperty}"'; // "%" | 442 String specProperty = '"${namer.nativeSpecProperty}"'; // "%" |
| 598 | 443 |
| 599 jsAst.Expression finishedClassesAccess = | 444 jsAst.Expression finishedClassesAccess = |
| 600 generateEmbeddedGlobalAccess(embeddedNames.FINISHED_CLASSES); | 445 generateEmbeddedGlobalAccess(embeddedNames.FINISHED_CLASSES); |
| 601 jsAst.Expression interceptorsByTagAccess = | 446 jsAst.Expression interceptorsByTagAccess = |
| 602 generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG); | 447 generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG); |
| 603 jsAst.Expression leafTagsAccess = | 448 jsAst.Expression leafTagsAccess = |
| 604 generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS); | 449 generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS); |
| 605 | 450 |
| 606 return js.statement(''' | 451 return js.statement(''' |
| 607 { | 452 { |
| 608 var finishedClasses = #finishedClassesAccess; | 453 var finishedClasses = #finishedClassesAccess; |
| 609 | 454 |
| 610 function finishClass(cls) { | 455 function finishClass(cls) { |
| 611 | 456 |
| 612 if (finishedClasses[cls]) return; | 457 if (finishedClasses[cls]) return; |
| 613 finishedClasses[cls] = true; | 458 finishedClasses[cls] = true; |
| 614 | 459 |
| 615 var superclass = pendingClasses[cls]; | 460 var superclass = processedClasses.pending[cls]; |
| 616 | 461 |
| 617 if (#needsMixinSupport) { | 462 if (#needsMixinSupport) { |
| 618 if (superclass && superclass.indexOf("+") > 0) { | 463 if (superclass && superclass.indexOf("+") > 0) { |
| 619 var s = superclass.split("+"); | 464 var s = superclass.split("+"); |
| 620 superclass = s[0]; | 465 superclass = s[0]; |
| 621 var mixinClass = s[1]; | 466 var mixinClass = s[1]; |
| 622 finishClass(mixinClass); | 467 finishClass(mixinClass); |
| 623 var mixin = allClasses[mixinClass]; | 468 var mixin = allClasses[mixinClass]; |
| 624 // TODO(21896): this test shouldn't be necessary. Without it | 469 // TODO(21896): this test shouldn't be necessary. Without it |
| 625 // we have a crash in language/mixin_only_for_rti and | 470 // we have a crash in language/mixin_only_for_rti and |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 704 } | 549 } |
| 705 } | 550 } |
| 706 }''', {'finishedClassesAccess': finishedClassesAccess, | 551 }''', {'finishedClassesAccess': finishedClassesAccess, |
| 707 'needsMixinSupport': needsMixinSupport, | 552 'needsMixinSupport': needsMixinSupport, |
| 708 'hasNativeClasses': nativeClasses.isNotEmpty, | 553 'hasNativeClasses': nativeClasses.isNotEmpty, |
| 709 'interceptorsByTagAccess': interceptorsByTagAccess, | 554 'interceptorsByTagAccess': interceptorsByTagAccess, |
| 710 'leafTagsAccess': leafTagsAccess, | 555 'leafTagsAccess': leafTagsAccess, |
| 711 'allowNativesSubclassing': true}); | 556 'allowNativesSubclassing': true}); |
| 712 } | 557 } |
| 713 | 558 |
| 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 | |
| 840 void emitFinishIsolateConstructorInvocation(CodeBuffer buffer) { | 559 void emitFinishIsolateConstructorInvocation(CodeBuffer buffer) { |
| 841 String isolate = namer.isolateName; | 560 String isolate = namer.isolateName; |
| 842 buffer.write("$isolate = $finishIsolateConstructorName($isolate)$N"); | 561 buffer.write("$isolate = $finishIsolateConstructorName($isolate)$N"); |
| 843 } | 562 } |
| 844 | 563 |
| 845 /// In minified mode we want to keep the name for the most common core types. | 564 /// In minified mode we want to keep the name for the most common core types. |
| 846 bool _isNativeTypeNeedingReflectionName(Element element) { | 565 bool _isNativeTypeNeedingReflectionName(Element element) { |
| 847 if (!element.isClass) return false; | 566 if (!element.isClass) return false; |
| 848 return (element == compiler.intClass || | 567 return (element == compiler.intClass || |
| 849 element == compiler.doubleClass || | 568 element == compiler.doubleClass || |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1004 invariant(classElement, builder.functionType == null); | 723 invariant(classElement, builder.functionType == null); |
| 1005 invariant(classElement, builder.fieldMetadata == null); | 724 invariant(classElement, builder.fieldMetadata == null); |
| 1006 properties.properties.addAll(builder.properties); | 725 properties.properties.addAll(builder.properties); |
| 1007 } else { | 726 } else { |
| 1008 classEmitter.generateClass( | 727 classEmitter.generateClass( |
| 1009 classElement, properties, additionalProperties[classElement]); | 728 classElement, properties, additionalProperties[classElement]); |
| 1010 } | 729 } |
| 1011 }); | 730 }); |
| 1012 } | 731 } |
| 1013 | 732 |
| 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 | |
| 1025 void emitStaticFunctions(List<Element> staticFunctions) { | 733 void emitStaticFunctions(List<Element> staticFunctions) { |
| 1026 for (Element element in staticFunctions) { | 734 for (Element element in staticFunctions) { |
| 1027 ClassBuilder builder = new ClassBuilder(element, namer); | 735 ClassBuilder builder = new ClassBuilder(element, namer); |
| 1028 containerBuilder.addMember(element, builder); | 736 containerBuilder.addMember(element, builder); |
| 1029 getElementDescriptor(element).properties.addAll(builder.properties); | 737 getElementDescriptor(element).properties.addAll(builder.properties); |
| 1030 } | 738 } |
| 1031 } | 739 } |
| 1032 | 740 |
| 1033 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer, | 741 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer, |
| 1034 OutputUnit outputUnit) { | 742 OutputUnit outputUnit) { |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1330 'mainCallClosure': mainCallClosure}); | 1038 'mainCallClosure': mainCallClosure}); |
| 1331 | 1039 |
| 1332 buffer.write(';'); | 1040 buffer.write(';'); |
| 1333 buffer.write(jsAst.prettyPrint(invokeMain, | 1041 buffer.write(jsAst.prettyPrint(invokeMain, |
| 1334 compiler, monitor: compiler.dumpInfoTask)); | 1042 compiler, monitor: compiler.dumpInfoTask)); |
| 1335 buffer.write(N); | 1043 buffer.write(N); |
| 1336 addComment('END invoke [main].', buffer); | 1044 addComment('END invoke [main].', buffer); |
| 1337 } | 1045 } |
| 1338 | 1046 |
| 1339 void emitInitFunction(CodeBuffer buffer) { | 1047 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 |
| 1340 jsAst.FunctionDeclaration decl = js.statement(''' | 1062 jsAst.FunctionDeclaration decl = js.statement(''' |
| 1341 function init() { | 1063 function init() { |
| 1342 $isolateProperties = Object.create(null); | 1064 $isolateProperties = Object.create(null); |
| 1343 #; #; #; | 1065 (function(){ |
| 1344 }''', [ | 1066 #allClasses = Object.create(null); |
| 1345 buildDefineClassAndFinishClassFunctionsIfNecessary(), | 1067 #interceptorsByTag = Object.create(null); |
| 1346 buildLazyInitializerFunctionIfNecessary(), | 1068 #leafTags = Object.create(null); |
| 1347 buildFinishIsolateConstructor()]); | 1069 #finishedClasses = Object.create(null); |
| 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,}); |
| 1348 | 1170 |
| 1349 buffer.write(jsAst.prettyPrint(decl, | 1171 buffer.write(jsAst.prettyPrint(decl, |
| 1350 compiler, monitor: compiler.dumpInfoTask).getText()); | 1172 compiler, monitor: compiler.dumpInfoTask).getText()); |
| 1351 if (compiler.enableMinification) buffer.write('\n'); | 1173 if (compiler.enableMinification) buffer.write('\n'); |
| 1352 } | 1174 } |
| 1353 | 1175 |
| 1354 void emitConvertToFastObjectFunction() { | 1176 void emitConvertToFastObjectFunction() { |
| 1355 List<jsAst.Statement> debugCode = <jsAst.Statement>[]; | 1177 List<jsAst.Statement> debugCode = <jsAst.Statement>[]; |
| 1356 if (DEBUG_FAST_OBJECTS) { | 1178 if (DEBUG_FAST_OBJECTS) { |
| 1357 debugCode.add(js.statement(r''' | 1179 debugCode.add(js.statement(r''' |
| (...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1659 mainBuffer | 1481 mainBuffer |
| 1660 .write('${globalsHolder}.${namer.isolateName}$_=$_' | 1482 .write('${globalsHolder}.${namer.isolateName}$_=$_' |
| 1661 '${namer.isolateName}$N' | 1483 '${namer.isolateName}$N' |
| 1662 '${globalsHolder}.$initName$_=${_}$initName$N'); | 1484 '${globalsHolder}.$initName$_=${_}$initName$N'); |
| 1663 } | 1485 } |
| 1664 mainBuffer.write('init()$N$n'); | 1486 mainBuffer.write('init()$N$n'); |
| 1665 mainBuffer.write('$isolateProperties$_=$_$isolatePropertiesName$N'); | 1487 mainBuffer.write('$isolateProperties$_=$_$isolatePropertiesName$N'); |
| 1666 | 1488 |
| 1667 emitStaticFunctions(task.outputStaticLists[mainOutputUnit]); | 1489 emitStaticFunctions(task.outputStaticLists[mainOutputUnit]); |
| 1668 | 1490 |
| 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 | |
| 1680 List<ClassElement> classes = task.outputClassLists[mainOutputUnit]; | 1491 List<ClassElement> classes = task.outputClassLists[mainOutputUnit]; |
| 1681 if (classes != null) { | 1492 if (classes != null) { |
| 1682 for (ClassElement element in classes) { | 1493 for (ClassElement element in classes) { |
| 1683 generateClass(element, getElementDescriptor(element)); | 1494 generateClass(element, getElementDescriptor(element)); |
| 1684 } | 1495 } |
| 1685 } | 1496 } |
| 1686 | 1497 |
| 1687 if (compiler.enableMinification) { | 1498 if (compiler.enableMinification) { |
| 1688 mainBuffer.write(';'); | 1499 mainBuffer.write(';'); |
| 1689 } | 1500 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1701 CodeBuffer libraryBuffer = new CodeBuffer(); | 1512 CodeBuffer libraryBuffer = new CodeBuffer(); |
| 1702 for (LibraryElement library in Elements.sortedByPosition(libraries)) { | 1513 for (LibraryElement library in Elements.sortedByPosition(libraries)) { |
| 1703 writeLibraryDescriptors(libraryBuffer, library); | 1514 writeLibraryDescriptors(libraryBuffer, library); |
| 1704 elementDescriptors.remove(library); | 1515 elementDescriptors.remove(library); |
| 1705 } | 1516 } |
| 1706 | 1517 |
| 1707 mainBuffer | 1518 mainBuffer |
| 1708 ..write('(') | 1519 ..write('(') |
| 1709 ..write( | 1520 ..write( |
| 1710 jsAst.prettyPrint( | 1521 jsAst.prettyPrint( |
| 1711 getReflectionDataParser(classesCollector, backend), | 1522 getReflectionDataParser(this, backend), |
| 1712 compiler)) | 1523 compiler)) |
| 1713 ..write(')') | 1524 ..write(')') |
| 1714 ..write('([$n') | 1525 ..write('([$n') |
| 1715 ..write(libraryBuffer) | 1526 ..write(libraryBuffer) |
| 1716 ..write('])$N'); | 1527 ..write('])$N'); |
| 1717 | |
| 1718 emitFinishClassesInvocationIfNecessary(mainBuffer); | |
| 1719 } | 1528 } |
| 1720 | 1529 |
| 1721 interceptorEmitter.emitGetInterceptorMethods(mainBuffer); | 1530 interceptorEmitter.emitGetInterceptorMethods(mainBuffer); |
| 1722 interceptorEmitter.emitOneShotInterceptors(mainBuffer); | 1531 interceptorEmitter.emitOneShotInterceptors(mainBuffer); |
| 1723 | 1532 |
| 1724 if (task.outputContainsConstantList) { | 1533 if (task.outputContainsConstantList) { |
| 1725 emitMakeConstantList(mainBuffer); | 1534 emitMakeConstantList(mainBuffer); |
| 1726 } | 1535 } |
| 1727 | 1536 |
| 1728 // Constants in checked mode call into RTI code to set type information | 1537 // 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... |
| 2001 nativeEmitter.finishGenerateNativeClasses(); | 1810 nativeEmitter.finishGenerateNativeClasses(); |
| 2002 nativeEmitter.assembleCode(nativeBuffer); | 1811 nativeEmitter.assembleCode(nativeBuffer); |
| 2003 | 1812 |
| 2004 return nativeBuffer; | 1813 return nativeBuffer; |
| 2005 } | 1814 } |
| 2006 | 1815 |
| 2007 void emitProgram(Program program) { | 1816 void emitProgram(Program program) { |
| 2008 // Shorten the code by using [namer.currentIsolate] as temporary. | 1817 // Shorten the code by using [namer.currentIsolate] as temporary. |
| 2009 isolateProperties = namer.currentIsolate; | 1818 isolateProperties = namer.currentIsolate; |
| 2010 | 1819 |
| 2011 classesCollector = r"$$"; | |
| 2012 | |
| 2013 // Emit deferred units first, so we have their hashes. | 1820 // Emit deferred units first, so we have their hashes. |
| 2014 // Map from OutputUnit to a hash of its content. The hash uniquely | 1821 // Map from OutputUnit to a hash of its content. The hash uniquely |
| 2015 // identifies the code of the output-unit. It does not include | 1822 // identifies the code of the output-unit. It does not include |
| 2016 // boilerplate JS code, like the sourcemap directives or the hash | 1823 // boilerplate JS code, like the sourcemap directives or the hash |
| 2017 // itself. | 1824 // itself. |
| 2018 Map<OutputUnit, String> deferredLoadHashes = emitDeferredOutputUnits(); | 1825 Map<OutputUnit, String> deferredLoadHashes = emitDeferredOutputUnits(); |
| 2019 CodeBuffer nativeBuffer = buildNativesBuffer(); | 1826 CodeBuffer nativeBuffer = buildNativesBuffer(); |
| 2020 emitMainOutputUnit(deferredLoadHashes, nativeBuffer); | 1827 emitMainOutputUnit(deferredLoadHashes, nativeBuffer); |
| 2021 | 1828 |
| 2022 if (backend.requiresPreamble && | 1829 if (backend.requiresPreamble && |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2150 outputBuffer | 1957 outputBuffer |
| 2151 ..write('var init$_=$_${globalsHolder}.init$N') | 1958 ..write('var init$_=$_${globalsHolder}.init$N') |
| 2152 ..write('var ${namer.isolateName}$_=$_' | 1959 ..write('var ${namer.isolateName}$_=$_' |
| 2153 '${globalsHolder}.${namer.isolateName}$N'); | 1960 '${globalsHolder}.${namer.isolateName}$N'); |
| 2154 if (libraryDescriptorBuffer != null) { | 1961 if (libraryDescriptorBuffer != null) { |
| 2155 // TODO(ahe): This defines a lot of properties on the | 1962 // TODO(ahe): This defines a lot of properties on the |
| 2156 // Isolate.prototype object. We know this will turn it into a | 1963 // Isolate.prototype object. We know this will turn it into a |
| 2157 // slow object in V8, so instead we should do something similar | 1964 // slow object in V8, so instead we should do something similar |
| 2158 // to Isolate.$finishIsolateConstructor. | 1965 // to Isolate.$finishIsolateConstructor. |
| 2159 outputBuffer | 1966 outputBuffer |
| 2160 ..write('var ${namer.currentIsolate}$_=$_$isolatePropertiesName$N') | 1967 ..write('var ${namer.currentIsolate}$_=$_$isolatePropertiesName;$n') |
| 2161 // The classesCollector object ($$). | |
| 2162 ..write('$classesCollector$_=${_}Object.create(null);$n') | |
| 2163 ..write('(') | 1968 ..write('(') |
| 2164 ..write( | 1969 ..write( |
| 2165 jsAst.prettyPrint( | 1970 jsAst.prettyPrint( |
| 2166 getReflectionDataParser(classesCollector, backend), | 1971 getReflectionDataParser(this, backend), |
| 2167 compiler, monitor: compiler.dumpInfoTask)) | 1972 compiler, monitor: compiler.dumpInfoTask)) |
| 2168 ..write(')') | 1973 ..write(')') |
| 2169 ..write('([$n') | 1974 ..write('([$n') |
| 2170 ..addBuffer(libraryDescriptorBuffer) | 1975 ..addBuffer(libraryDescriptorBuffer) |
| 2171 ..write('])$N'); | 1976 ..write('])$N'); |
| 2172 | 1977 |
| 2173 if (outputClassLists.containsKey(outputUnit)) { | |
| 2174 outputBuffer.write( | |
| 2175 '$finishClassesName($classesCollector,$_${namer.currentIsolate},' | |
| 2176 '$_$isolatePropertiesName)$N'); | |
| 2177 } | |
| 2178 | |
| 2179 } | 1978 } |
| 2180 | 1979 |
| 2181 // Set the currentIsolate variable to the current isolate (which is | 1980 // Set the currentIsolate variable to the current isolate (which is |
| 2182 // provided as second argument). | 1981 // provided as second argument). |
| 2183 // We need to do this, because we use the same variable for setting up | 1982 // We need to do this, because we use the same variable for setting up |
| 2184 // the isolate-properties and for storing the current isolate. During | 1983 // the isolate-properties and for storing the current isolate. During |
| 2185 // the setup (the code above this lines) we must set the variable to | 1984 // the setup (the code above this lines) we must set the variable to |
| 2186 // the isolate-properties. | 1985 // the isolate-properties. |
| 2187 // After we have done the setup (finishing with `finishClasses`) it must | 1986 // After we have done the setup it must point to the current Isolate. |
| 2188 // point to the current Isolate. Otherwise all methods/functions | 1987 // Otherwise all methods/functions accessing isolate variables will |
| 2189 // accessing isolate variables will access the wrong object. | 1988 // access the wrong object. |
| 2190 outputBuffer.write("${namer.currentIsolate}$_=${_}arguments[1]$N"); | 1989 outputBuffer.write("${namer.currentIsolate}$_=${_}arguments[1]$N"); |
| 2191 | 1990 |
| 2192 emitCompileTimeConstants(outputBuffer, outputUnit); | 1991 emitCompileTimeConstants(outputBuffer, outputUnit); |
| 2193 emitStaticNonFinalFieldInitializations(outputBuffer, outputUnit); | 1992 emitStaticNonFinalFieldInitializations(outputBuffer, outputUnit); |
| 2194 outputBuffer.write('}$N'); | 1993 outputBuffer.write('}$N'); |
| 2195 | 1994 |
| 2196 if (compiler.useContentSecurityPolicy) { | 1995 if (compiler.useContentSecurityPolicy) { |
| 2197 jsAst.FunctionDeclaration precompiledFunctionAst = | 1996 jsAst.FunctionDeclaration precompiledFunctionAst = |
| 2198 buildCspPrecompiledFunctionFor(outputUnit); | 1997 buildCspPrecompiledFunctionFor(outputUnit); |
| 2199 | 1998 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2276 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { | 2075 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { |
| 2277 if (element.isInstanceMember) { | 2076 if (element.isInstanceMember) { |
| 2278 cachedClassBuilders.remove(element.enclosingClass); | 2077 cachedClassBuilders.remove(element.enclosingClass); |
| 2279 | 2078 |
| 2280 nativeEmitter.cachedBuilders.remove(element.enclosingClass); | 2079 nativeEmitter.cachedBuilders.remove(element.enclosingClass); |
| 2281 | 2080 |
| 2282 } | 2081 } |
| 2283 } | 2082 } |
| 2284 } | 2083 } |
| 2285 } | 2084 } |
| OLD | NEW |