Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of dart2js.js_emitter; | 5 part of dart2js.js_emitter; |
| 6 | 6 |
| 7 | 7 |
| 8 class OldEmitter implements Emitter { | 8 class OldEmitter implements Emitter { |
| 9 final Compiler compiler; | 9 final Compiler compiler; |
| 10 final CodeEmitterTask task; | 10 final CodeEmitterTask task; |
| 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 hasClasses = false; |
|
floitsch
2014/12/29 18:00:22
I prefer to stay consistent: needsClassSupport ?
zarah
2014/12/30 14:02:43
Done.
| |
| 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 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 337 if (typeof defineClass.name != "string") { | 333 if (typeof defineClass.name != "string") { |
| 338 str += name + ".name=\\"" + name + "\\";\\n"; | 334 str += name + ".name=\\"" + name + "\\";\\n"; |
| 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 | |
|
floitsch
2014/12/29 18:00:21
nit. I would keep this new line.
zarah
2014/12/30 14:02:43
Done.
| |
| 348 // Declare a function called "generateAccessor". This is used in | 343 // Declare a function called "generateAccessor". This is used in |
| 349 // defineClassFunction (it's a local declaration in init()). | 344 // defineClassFunction. |
| 350 List result = <jsAst.Node>[ | 345 List result = <jsAst.Node>[ |
| 351 generateAccessorFunction, | 346 generateAccessorFunction, |
| 352 js('$generateAccessorHolder = generateAccessor'), | |
| 353 new jsAst.FunctionDeclaration( | 347 new jsAst.FunctionDeclaration( |
| 354 new jsAst.VariableDeclaration('defineClass'), defineClass) ]; | 348 new jsAst.VariableDeclaration('defineClass'), defineClass) ]; |
| 355 | 349 |
| 356 if (compiler.hasIncrementalSupport) { | 350 if (compiler.hasIncrementalSupport) { |
| 357 result.add( | 351 result.add( |
| 358 js(r'#.defineClass = defineClass', [namer.accessIncrementalHelper])); | 352 js(r'#.defineClass = defineClass', [namer.accessIncrementalHelper])); |
| 359 } | 353 } |
| 360 | 354 |
| 361 if (hasIsolateSupport) { | 355 if (hasIsolateSupport) { |
| 362 jsAst.Expression classIdExtractorAccess = | 356 jsAst.Expression classIdExtractorAccess = |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 436 }; | 430 }; |
| 437 }() | 431 }() |
| 438 '''); | 432 '''); |
| 439 if (compiler.hasIncrementalSupport) { | 433 if (compiler.hasIncrementalSupport) { |
| 440 result = js( | 434 result = js( |
| 441 r'#.inheritFrom = #', [namer.accessIncrementalHelper, result]); | 435 r'#.inheritFrom = #', [namer.accessIncrementalHelper, result]); |
| 442 } | 436 } |
| 443 return js(r'var inheritFrom = #', [result]); | 437 return js(r'var inheritFrom = #', [result]); |
| 444 } | 438 } |
| 445 | 439 |
| 446 /// Code that needs to be run before first invocation of | 440 /// Code that needs to be run before processing reflection data, |
| 447 /// [finishClassesFunction], but should only be run once. | 441 /// but should only be run once. |
|
floitsch
2014/12/29 18:00:21
specify that the "once" refers to deferred librari
zarah
2014/12/30 14:02:43
Done.
| |
| 448 jsAst.Expression get initFinishClasses { | 442 jsAst.Expression get initProcessStatics { |
|
floitsch
2014/12/29 18:00:21
was already a bad name: "initX" looks/sounds like
zarah
2014/12/30 14:02:43
Done.
| |
| 449 jsAst.Expression allClassesAccess = | 443 jsAst.Expression allClassesAccess = |
| 450 generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES); | 444 generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES); |
| 451 jsAst.Expression interceptorsByTagAccess = | 445 jsAst.Expression interceptorsByTagAccess = |
| 452 generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG); | 446 generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG); |
| 453 jsAst.Expression leafTagsAccess = | 447 jsAst.Expression leafTagsAccess = |
| 454 generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS); | 448 generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS); |
| 455 jsAst.Expression finishedClassesAccess = | 449 jsAst.Expression finishedClassesAccess = |
| 456 generateEmbeddedGlobalAccess(embeddedNames.FINISHED_CLASSES); | 450 generateEmbeddedGlobalAccess(embeddedNames.FINISHED_CLASSES); |
| 457 | 451 |
| 458 return js(''' | 452 return js(''' |
| 459 (function(){ | 453 (function(){ |
|
floitsch
2014/12/29 18:00:22
I don't see any reason why there should be the ano
zarah
2014/12/30 14:02:43
Acknowledged.
| |
| 460 # = Object.create(null); // embedded allClasses. | 454 # = Object.create(null); // embedded allClasses. |
| 461 # = Object.create(null); // embedded interceptorsByTag. | 455 # = Object.create(null); // embedded interceptorsByTag. |
| 462 # = Object.create(null); // embedded leafTags. | 456 # = Object.create(null); // embedded leafTags. |
| 463 # = Object.create(null); // embedded finishedClasses | 457 # = Object.create(null); // embedded finishedClasses |
| 464 })() | 458 })() |
| 465 ''', [allClassesAccess, | 459 ''', [allClassesAccess, |
| 466 interceptorsByTagAccess, | 460 interceptorsByTagAccess, |
| 467 leafTagsAccess, | 461 leafTagsAccess, |
| 468 finishedClassesAccess]); | 462 finishedClassesAccess]); |
| 469 } | 463 } |
| 470 | 464 |
| 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.Node optional(bool condition, jsAst.Node node) { | 465 jsAst.Node optional(bool condition, jsAst.Node node) { |
| 597 return condition ? node : new jsAst.EmptyStatement(); | 466 return condition ? node : new jsAst.EmptyStatement(); |
| 598 } | 467 } |
| 599 | 468 |
| 600 jsAst.Statement buildFinishClass() { | 469 jsAst.Statement buildFinishClass() { |
| 601 String specProperty = '"${namer.nativeSpecProperty}"'; // "%" | 470 String specProperty = '"${namer.nativeSpecProperty}"'; // "%" |
| 602 | 471 |
| 603 jsAst.Expression finishedClassesAccess = | 472 jsAst.Expression finishedClassesAccess = |
| 604 generateEmbeddedGlobalAccess(embeddedNames.FINISHED_CLASSES); | 473 generateEmbeddedGlobalAccess(embeddedNames.FINISHED_CLASSES); |
| 605 jsAst.Expression interceptorsByTagAccess = | 474 jsAst.Expression interceptorsByTagAccess = |
| 606 generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG); | 475 generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG); |
| 607 jsAst.Expression leafTagsAccess = | 476 jsAst.Expression leafTagsAccess = |
| 608 generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS); | 477 generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS); |
| 609 | 478 |
| 610 return js.statement(''' | 479 return js.statement(''' |
| 611 { | 480 { |
| 612 var finishedClasses = #finishedClassesAccess; | 481 var finishedClasses = #finishedClassesAccess; |
| 613 | 482 |
| 614 function finishClass(cls) { | 483 function finishClass(cls) { |
| 615 | 484 |
| 616 if (finishedClasses[cls]) return; | 485 if (finishedClasses[cls]) return; |
| 617 finishedClasses[cls] = true; | 486 finishedClasses[cls] = true; |
| 618 | 487 |
| 619 var superclass = pendingClasses[cls]; | 488 var superclass = processedClasses.pending[cls]; |
| 620 | 489 |
| 621 if (#needsMixinSupport) { | 490 if (#needsMixinSupport) { |
| 622 if (superclass && superclass.indexOf("+") > 0) { | 491 if (superclass && superclass.indexOf("+") > 0) { |
| 623 var s = superclass.split("+"); | 492 var s = superclass.split("+"); |
| 624 superclass = s[0]; | 493 superclass = s[0]; |
| 625 var mixinClass = s[1]; | 494 var mixinClass = s[1]; |
| 626 finishClass(mixinClass); | 495 finishClass(mixinClass); |
| 627 var mixin = allClasses[mixinClass]; | 496 var mixin = allClasses[mixinClass]; |
| 628 // TODO(21896): this test shouldn't be necessary. Without it | 497 // TODO(21896): this test shouldn't be necessary. Without it |
| 629 // we have a crash in language/mixin_only_for_rti and | 498 // we have a crash in language/mixin_only_for_rti and |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 750 | 619 |
| 751 // Now, after being a fast map we can set the lazies again. | 620 // Now, after being a fast map we can set the lazies again. |
| 752 for (var lazyInit in lazies) { | 621 for (var lazyInit in lazies) { |
| 753 var lazyInitName = lazies[lazyInit]; | 622 var lazyInitName = lazies[lazyInit]; |
| 754 this[lazyInitName] = isolateProperties[lazyInitName]; | 623 this[lazyInitName] = isolateProperties[lazyInitName]; |
| 755 } | 624 } |
| 756 } | 625 } |
| 757 Isolate.prototype = oldIsolate.prototype; | 626 Isolate.prototype = oldIsolate.prototype; |
| 758 Isolate.prototype.constructor = Isolate; | 627 Isolate.prototype.constructor = Isolate; |
| 759 Isolate.#isolatePropertiesName = isolateProperties; | 628 Isolate.#isolatePropertiesName = isolateProperties; |
| 760 if (#needsDefineClass) | |
| 761 Isolate.#finishClassesProperty = oldIsolate.#finishClassesProperty; | |
| 762 if (#outputContainsConstantList) | 629 if (#outputContainsConstantList) |
| 763 Isolate.#makeConstListProperty = oldIsolate.#makeConstListProperty; | 630 Isolate.#makeConstListProperty = oldIsolate.#makeConstListProperty; |
| 764 if (#hasIncrementalSupport) | 631 if (#hasIncrementalSupport) |
| 765 Isolate.#lazyInitializerProperty = | 632 Isolate.#lazyInitializerProperty = |
| 766 oldIsolate.#lazyInitializerProperty; | 633 oldIsolate.#lazyInitializerProperty; |
| 767 return Isolate; | 634 return Isolate; |
| 768 } | 635 } |
| 769 """, | 636 """, |
| 770 { 'isolatePropertiesName': namer.isolatePropertiesName, | 637 { 'isolatePropertiesName': namer.isolatePropertiesName, |
| 771 'needsDefineClass': needsDefineClass, | |
| 772 'finishClassesProperty': finishClassesProperty, | |
| 773 'outputContainsConstantList': task.outputContainsConstantList, | 638 'outputContainsConstantList': task.outputContainsConstantList, |
| 774 'makeConstListProperty': makeConstListProperty, | 639 'makeConstListProperty': makeConstListProperty, |
| 775 'hasIncrementalSupport': compiler.hasIncrementalSupport, | 640 'hasIncrementalSupport': compiler.hasIncrementalSupport, |
| 776 'lazyInitializerProperty': lazyInitializerProperty, | 641 'lazyInitializerProperty': lazyInitializerProperty, |
| 777 }); | 642 }); |
| 778 } | 643 } |
| 779 | 644 |
| 780 jsAst.Fun get lazyInitializerFunction { | 645 jsAst.Fun get lazyInitializerFunction { |
| 781 String isolate = namer.currentIsolate; | 646 String isolate = namer.currentIsolate; |
| 782 jsAst.Expression cyclicThrow = | 647 jsAst.Expression cyclicThrow = |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 816 } finally { | 681 } finally { |
| 817 $isolate[getterName] = function() { return this[fieldName]; }; | 682 $isolate[getterName] = function() { return this[fieldName]; }; |
| 818 } | 683 } |
| 819 } | 684 } |
| 820 } | 685 } |
| 821 ''', [laziesAccess, laziesAccess, | 686 ''', [laziesAccess, laziesAccess, |
| 822 laziesAccess, | 687 laziesAccess, |
| 823 cyclicThrow]); | 688 cyclicThrow]); |
| 824 } | 689 } |
| 825 | 690 |
| 826 List buildDefineClassAndFinishClassFunctionsIfNecessary() { | |
| 827 if (!needsDefineClass) return []; | |
| 828 return defineClassFunction | |
| 829 ..add(buildInheritFrom()) | |
| 830 ..add(js('$finishClassesName = #', finishClassesFunction)) | |
| 831 ..add(initFinishClasses); | |
| 832 } | |
| 833 | |
| 834 List buildLazyInitializerFunctionIfNecessary() { | 691 List buildLazyInitializerFunctionIfNecessary() { |
| 835 if (!needsLazyInitializer) return []; | 692 if (!needsLazyInitializer) return []; |
| 836 | 693 |
| 837 return [js('# = #', [js(lazyInitializerName), lazyInitializerFunction])]; | 694 return [js('# = #', [js(lazyInitializerName), lazyInitializerFunction])]; |
| 838 } | 695 } |
| 839 | 696 |
| 840 List buildFinishIsolateConstructor() { | 697 List buildFinishIsolateConstructor() { |
| 841 return [ | 698 return [ |
| 842 js('$finishIsolateConstructorName = #', finishIsolateConstructorFunction) | 699 js('$finishIsolateConstructorName = #', finishIsolateConstructorFunction) |
| 843 ]; | 700 ]; |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1010 invariant(classElement, builder.functionType == null); | 867 invariant(classElement, builder.functionType == null); |
| 1011 invariant(classElement, builder.fieldMetadata == null); | 868 invariant(classElement, builder.fieldMetadata == null); |
| 1012 properties.properties.addAll(builder.properties); | 869 properties.properties.addAll(builder.properties); |
| 1013 } else { | 870 } else { |
| 1014 classEmitter.generateClass( | 871 classEmitter.generateClass( |
| 1015 classElement, properties, additionalProperties[classElement]); | 872 classElement, properties, additionalProperties[classElement]); |
| 1016 } | 873 } |
| 1017 }); | 874 }); |
| 1018 } | 875 } |
| 1019 | 876 |
| 1020 void emitFinishClassesInvocationIfNecessary(CodeBuffer buffer) { | |
| 1021 if (needsDefineClass) { | |
| 1022 buffer.write('$finishClassesName($classesCollector,' | |
| 1023 '$_$isolateProperties,' | |
| 1024 '${_}null)$N'); | |
| 1025 | |
| 1026 // Reset the map. | |
| 1027 buffer.write("$classesCollector$_=${_}null$N$n"); | |
| 1028 } | |
| 1029 } | |
| 1030 | |
| 1031 void emitStaticFunctions(List<Element> staticFunctions) { | 877 void emitStaticFunctions(List<Element> staticFunctions) { |
| 1032 for (Element element in staticFunctions) { | 878 for (Element element in staticFunctions) { |
| 1033 ClassBuilder builder = new ClassBuilder(element, namer); | 879 ClassBuilder builder = new ClassBuilder(element, namer); |
| 1034 containerBuilder.addMember(element, builder); | 880 containerBuilder.addMember(element, builder); |
| 1035 getElementDescriptor(element).properties.addAll(builder.properties); | 881 getElementDescriptor(element).properties.addAll(builder.properties); |
| 1036 } | 882 } |
| 1037 } | 883 } |
| 1038 | 884 |
| 1039 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer, | 885 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer, |
| 1040 OutputUnit outputUnit) { | 886 OutputUnit outputUnit) { |
| (...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1343 buffer.write(N); | 1189 buffer.write(N); |
| 1344 addComment('END invoke [main].', buffer); | 1190 addComment('END invoke [main].', buffer); |
| 1345 } | 1191 } |
| 1346 | 1192 |
| 1347 void emitInitFunction(CodeBuffer buffer) { | 1193 void emitInitFunction(CodeBuffer buffer) { |
| 1348 jsAst.FunctionDeclaration decl = js.statement(''' | 1194 jsAst.FunctionDeclaration decl = js.statement(''' |
| 1349 function init() { | 1195 function init() { |
| 1350 $isolateProperties = Object.create(null); | 1196 $isolateProperties = Object.create(null); |
| 1351 #; #; #; | 1197 #; #; #; |
| 1352 }''', [ | 1198 }''', [ |
| 1353 buildDefineClassAndFinishClassFunctionsIfNecessary(), | 1199 initProcessStatics, |
| 1354 buildLazyInitializerFunctionIfNecessary(), | 1200 buildLazyInitializerFunctionIfNecessary(), |
|
floitsch
2014/12/29 18:00:21
just inline all three functions.
Use "if (#) ..."
zarah
2014/12/30 14:02:43
Done.
| |
| 1355 buildFinishIsolateConstructor()]); | 1201 buildFinishIsolateConstructor()]); |
| 1356 | 1202 |
| 1357 buffer.write(jsAst.prettyPrint(decl, | 1203 buffer.write(jsAst.prettyPrint(decl, |
| 1358 compiler, monitor: compiler.dumpInfoTask).getText()); | 1204 compiler, monitor: compiler.dumpInfoTask).getText()); |
| 1359 if (compiler.enableMinification) buffer.write('\n'); | 1205 if (compiler.enableMinification) buffer.write('\n'); |
| 1360 } | 1206 } |
| 1361 | 1207 |
| 1362 void emitConvertToFastObjectFunction() { | 1208 void emitConvertToFastObjectFunction() { |
| 1363 List<jsAst.Statement> debugCode = <jsAst.Statement>[]; | 1209 List<jsAst.Statement> debugCode = <jsAst.Statement>[]; |
| 1364 if (DEBUG_FAST_OBJECTS) { | 1210 if (DEBUG_FAST_OBJECTS) { |
| (...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1667 mainBuffer | 1513 mainBuffer |
| 1668 .write('${globalsHolder}.${namer.isolateName}$_=$_' | 1514 .write('${globalsHolder}.${namer.isolateName}$_=$_' |
| 1669 '${namer.isolateName}$N' | 1515 '${namer.isolateName}$N' |
| 1670 '${globalsHolder}.$initName$_=${_}$initName$N'); | 1516 '${globalsHolder}.$initName$_=${_}$initName$N'); |
| 1671 } | 1517 } |
| 1672 mainBuffer.add('init()$N$n'); | 1518 mainBuffer.add('init()$N$n'); |
| 1673 mainBuffer.add('$isolateProperties$_=$_$isolatePropertiesName$N'); | 1519 mainBuffer.add('$isolateProperties$_=$_$isolatePropertiesName$N'); |
| 1674 | 1520 |
| 1675 emitStaticFunctions(task.outputStaticLists[mainOutputUnit]); | 1521 emitStaticFunctions(task.outputStaticLists[mainOutputUnit]); |
| 1676 | 1522 |
| 1677 // Only output the classesCollector if we actually have any classes. | |
| 1678 if (needsDefineClass || | |
| 1679 !(nativeClasses.isEmpty && | |
| 1680 compiler.codegenWorld.staticFunctionsNeedingGetter.isEmpty && | |
| 1681 outputClassLists.values.every((classList) => classList.isEmpty) && | |
| 1682 typedefsNeededForReflection.isEmpty)) { | |
| 1683 // Shorten the code by using "$$" as temporary. | |
| 1684 classesCollector = r"$$"; | |
| 1685 mainBuffer.add('var $classesCollector$_=${_}Object.create(null)$N$n'); | |
| 1686 } | |
| 1687 | |
| 1688 if (!nativeClasses.isEmpty) { | 1523 if (!nativeClasses.isEmpty) { |
| 1689 addComment('Native classes', mainBuffer); | 1524 addComment('Native classes', mainBuffer); |
| 1690 } | 1525 } |
| 1691 | 1526 |
| 1692 List<ClassElement> classes = task.outputClassLists[mainOutputUnit]; | 1527 List<ClassElement> classes = task.outputClassLists[mainOutputUnit]; |
| 1693 if (classes != null) { | 1528 if (classes != null) { |
| 1694 for (ClassElement element in classes) { | 1529 for (ClassElement element in classes) { |
| 1695 generateClass(element, getElementDescriptor(element)); | 1530 generateClass(element, getElementDescriptor(element)); |
| 1696 } | 1531 } |
| 1697 } | 1532 } |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 1713 CodeBuffer libraryBuffer = new CodeBuffer(); | 1548 CodeBuffer libraryBuffer = new CodeBuffer(); |
| 1714 for (LibraryElement library in Elements.sortedByPosition(libraries)) { | 1549 for (LibraryElement library in Elements.sortedByPosition(libraries)) { |
| 1715 writeLibraryDescriptors(libraryBuffer, library); | 1550 writeLibraryDescriptors(libraryBuffer, library); |
| 1716 elementDescriptors.remove(library); | 1551 elementDescriptors.remove(library); |
| 1717 } | 1552 } |
| 1718 | 1553 |
| 1719 mainBuffer | 1554 mainBuffer |
| 1720 ..write('(') | 1555 ..write('(') |
| 1721 ..write( | 1556 ..write( |
| 1722 jsAst.prettyPrint( | 1557 jsAst.prettyPrint( |
| 1723 getReflectionDataParser(classesCollector, backend), | 1558 getReflectionDataParser(this, backend), |
| 1724 compiler)) | 1559 compiler)) |
| 1725 ..write(')') | 1560 ..write(')') |
| 1726 ..write('([$n') | 1561 ..write('([$n') |
| 1727 ..add(libraryBuffer) | 1562 ..add(libraryBuffer) |
| 1728 ..write('])$N'); | 1563 ..write('])$N'); |
| 1729 | |
| 1730 emitFinishClassesInvocationIfNecessary(mainBuffer); | |
| 1731 } | 1564 } |
| 1732 | 1565 |
| 1733 interceptorEmitter.emitGetInterceptorMethods(mainBuffer); | 1566 interceptorEmitter.emitGetInterceptorMethods(mainBuffer); |
| 1734 interceptorEmitter.emitOneShotInterceptors(mainBuffer); | 1567 interceptorEmitter.emitOneShotInterceptors(mainBuffer); |
| 1735 | 1568 |
| 1736 if (task.outputContainsConstantList) { | 1569 if (task.outputContainsConstantList) { |
| 1737 emitMakeConstantList(mainBuffer); | 1570 emitMakeConstantList(mainBuffer); |
| 1738 } | 1571 } |
| 1739 | 1572 |
| 1740 // Constants in checked mode call into RTI code to set type information | 1573 // 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... | |
| 2013 nativeEmitter.finishGenerateNativeClasses(); | 1846 nativeEmitter.finishGenerateNativeClasses(); |
| 2014 nativeEmitter.assembleCode(nativeBuffer); | 1847 nativeEmitter.assembleCode(nativeBuffer); |
| 2015 | 1848 |
| 2016 return nativeBuffer; | 1849 return nativeBuffer; |
| 2017 } | 1850 } |
| 2018 | 1851 |
| 2019 void emitProgram(Program program) { | 1852 void emitProgram(Program program) { |
| 2020 // Shorten the code by using [namer.currentIsolate] as temporary. | 1853 // Shorten the code by using [namer.currentIsolate] as temporary. |
| 2021 isolateProperties = namer.currentIsolate; | 1854 isolateProperties = namer.currentIsolate; |
| 2022 | 1855 |
| 2023 classesCollector = r"$$"; | |
| 2024 | |
| 2025 // Emit deferred units first, so we have their hashes. | 1856 // Emit deferred units first, so we have their hashes. |
| 2026 // Map from OutputUnit to a hash of its content. The hash uniquely | 1857 // Map from OutputUnit to a hash of its content. The hash uniquely |
| 2027 // identifies the code of the output-unit. It does not include | 1858 // identifies the code of the output-unit. It does not include |
| 2028 // boilerplate JS code, like the sourcemap directives or the hash | 1859 // boilerplate JS code, like the sourcemap directives or the hash |
| 2029 // itself. | 1860 // itself. |
| 2030 Map<OutputUnit, String> deferredLoadHashes = emitDeferredOutputUnits(); | 1861 Map<OutputUnit, String> deferredLoadHashes = emitDeferredOutputUnits(); |
| 2031 CodeBuffer nativeBuffer = buildNativesBuffer(); | 1862 CodeBuffer nativeBuffer = buildNativesBuffer(); |
| 2032 emitMainOutputUnit(deferredLoadHashes, nativeBuffer); | 1863 emitMainOutputUnit(deferredLoadHashes, nativeBuffer); |
| 2033 | 1864 |
| 2034 if (backend.requiresPreamble && | 1865 if (backend.requiresPreamble && |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2163 ..write('var init$_=$_${globalsHolder}.init$N') | 1994 ..write('var init$_=$_${globalsHolder}.init$N') |
| 2164 ..write('var ${namer.isolateName}$_=$_' | 1995 ..write('var ${namer.isolateName}$_=$_' |
| 2165 '${globalsHolder}.${namer.isolateName}$N'); | 1996 '${globalsHolder}.${namer.isolateName}$N'); |
| 2166 if (libraryDescriptorBuffer != null) { | 1997 if (libraryDescriptorBuffer != null) { |
| 2167 // TODO(ahe): This defines a lot of properties on the | 1998 // TODO(ahe): This defines a lot of properties on the |
| 2168 // Isolate.prototype object. We know this will turn it into a | 1999 // Isolate.prototype object. We know this will turn it into a |
| 2169 // slow object in V8, so instead we should do something similar | 2000 // slow object in V8, so instead we should do something similar |
| 2170 // to Isolate.$finishIsolateConstructor. | 2001 // to Isolate.$finishIsolateConstructor. |
| 2171 outputBuffer | 2002 outputBuffer |
| 2172 ..write('var ${namer.currentIsolate}$_=$_$isolatePropertiesName$N') | 2003 ..write('var ${namer.currentIsolate}$_=$_$isolatePropertiesName$N') |
| 2173 // The classesCollector object ($$). | |
| 2174 ..write('$classesCollector$_=${_}Object.create(null);$n') | |
| 2175 ..write('(') | 2004 ..write('(') |
| 2176 ..write( | 2005 ..write( |
| 2177 jsAst.prettyPrint( | 2006 jsAst.prettyPrint( |
| 2178 getReflectionDataParser(classesCollector, backend), | 2007 getReflectionDataParser(this, backend), |
| 2179 compiler, monitor: compiler.dumpInfoTask)) | 2008 compiler, monitor: compiler.dumpInfoTask)) |
| 2180 ..write(')') | 2009 ..write(')') |
| 2181 ..write('([$n') | 2010 ..write('([$n') |
| 2182 ..addBuffer(libraryDescriptorBuffer) | 2011 ..addBuffer(libraryDescriptorBuffer) |
| 2183 ..write('])$N'); | 2012 ..write('])$N'); |
| 2184 | 2013 |
| 2185 if (outputClassLists.containsKey(outputUnit)) { | |
| 2186 outputBuffer.write( | |
| 2187 '$finishClassesName($classesCollector,$_${namer.currentIsolate},' | |
| 2188 '$_$isolatePropertiesName)$N'); | |
| 2189 } | |
| 2190 | |
| 2191 } | 2014 } |
| 2192 | 2015 |
| 2193 // Set the currentIsolate variable to the current isolate (which is | 2016 // Set the currentIsolate variable to the current isolate (which is |
| 2194 // provided as second argument). | 2017 // provided as second argument). |
| 2195 // We need to do this, because we use the same variable for setting up | 2018 // We need to do this, because we use the same variable for setting up |
| 2196 // the isolate-properties and for storing the current isolate. During | 2019 // the isolate-properties and for storing the current isolate. During |
| 2197 // the setup (the code above this lines) we must set the variable to | 2020 // the setup (the code above this lines) we must set the variable to |
| 2198 // the isolate-properties. | 2021 // the isolate-properties. |
| 2199 // After we have done the setup (finishing with `finishClasses`) it must | 2022 // After we have done the setup it must point to the current Isolate. |
| 2200 // point to the current Isolate. Otherwise all methods/functions | 2023 // Otherwise all methods/functions accessing isolate variables will |
| 2201 // accessing isolate variables will access the wrong object. | 2024 // access the wrong object. |
| 2202 outputBuffer.write("${namer.currentIsolate}$_=${_}arguments[1]$N"); | 2025 outputBuffer.write("${namer.currentIsolate}$_=${_}arguments[1]$N"); |
| 2203 | 2026 |
| 2204 emitCompileTimeConstants(outputBuffer, outputUnit); | 2027 emitCompileTimeConstants(outputBuffer, outputUnit); |
| 2205 emitStaticNonFinalFieldInitializations(outputBuffer, outputUnit); | 2028 emitStaticNonFinalFieldInitializations(outputBuffer, outputUnit); |
| 2206 outputBuffer.write('}$N'); | 2029 outputBuffer.write('}$N'); |
| 2207 | 2030 |
| 2208 if (compiler.useContentSecurityPolicy) { | 2031 if (compiler.useContentSecurityPolicy) { |
| 2209 jsAst.FunctionDeclaration precompiledFunctionAst = | 2032 jsAst.FunctionDeclaration precompiledFunctionAst = |
| 2210 buildCspPrecompiledFunctionFor(outputUnit); | 2033 buildCspPrecompiledFunctionFor(outputUnit); |
| 2211 | 2034 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2288 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { | 2111 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { |
| 2289 if (element.isInstanceMember) { | 2112 if (element.isInstanceMember) { |
| 2290 cachedClassBuilders.remove(element.enclosingClass); | 2113 cachedClassBuilders.remove(element.enclosingClass); |
| 2291 | 2114 |
| 2292 nativeEmitter.cachedBuilders.remove(element.enclosingClass); | 2115 nativeEmitter.cachedBuilders.remove(element.enclosingClass); |
| 2293 | 2116 |
| 2294 } | 2117 } |
| 2295 } | 2118 } |
| 2296 } | 2119 } |
| 2297 } | 2120 } |
| OLD | NEW |