Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 /** | 5 /** |
| 6 * A function element that represents a closure call. The signature is copied | 6 * A function element that represents a closure call. The signature is copied |
| 7 * from the given element. | 7 * from the given element. |
| 8 */ | 8 */ |
| 9 class ClosureInvocationElement extends FunctionElement { | 9 class ClosureInvocationElement extends FunctionElement { |
| 10 ClosureInvocationElement(SourceString name, | 10 ClosureInvocationElement(SourceString name, |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 21 * The code for the containing (used) methods must exist in the [:universe:]. | 21 * The code for the containing (used) methods must exist in the [:universe:]. |
| 22 */ | 22 */ |
| 23 class CodeEmitterTask extends CompilerTask { | 23 class CodeEmitterTask extends CompilerTask { |
| 24 bool needsInheritFunction = false; | 24 bool needsInheritFunction = false; |
| 25 bool needsDefineClass = false; | 25 bool needsDefineClass = false; |
| 26 bool needsClosureClass = false; | 26 bool needsClosureClass = false; |
| 27 final Namer namer; | 27 final Namer namer; |
| 28 final NativeEmitter nativeEmitter; | 28 final NativeEmitter nativeEmitter; |
| 29 StringBuffer boundClosureBuffer; | 29 StringBuffer boundClosureBuffer; |
| 30 StringBuffer mainBuffer; | 30 StringBuffer mainBuffer; |
| 31 String isolatePrototype; | 31 /** Shorter access to [initialStaticValuesName]. Both here in the code, as |
| 32 well as in the generated code. */ | |
| 33 String initialStatics; | |
|
kasperl
2012/05/03 12:30:18
isolateProperties?
floitsch
2012/05/03 14:24:01
Done.
| |
| 32 | 34 |
| 33 CodeEmitterTask(Compiler compiler) | 35 CodeEmitterTask(Compiler compiler) |
| 34 : namer = compiler.namer, | 36 : namer = compiler.namer, |
| 35 nativeEmitter = new NativeEmitter(compiler), | 37 nativeEmitter = new NativeEmitter(compiler), |
| 36 boundClosureBuffer = new StringBuffer(), | 38 boundClosureBuffer = new StringBuffer(), |
| 37 mainBuffer = new StringBuffer(), | 39 mainBuffer = new StringBuffer(), |
| 38 super(compiler); | 40 super(compiler); |
| 39 | 41 |
| 40 String get name() => 'CodeEmitter'; | 42 String get name() => 'CodeEmitter'; |
| 41 | 43 |
| 42 String get defineClassName() => '${namer.ISOLATE}.\$defineClass'; | 44 String get defineClassName() => '${namer.ISOLATE}.\$defineClass'; |
|
kasperl
2012/05/03 12:30:18
I think I'd prefer to break before => in this enti
floitsch
2012/05/03 14:24:01
Done.
| |
| 43 String get finishClassesName() => '${namer.ISOLATE}.\$finishClasses'; | 45 String get finishClassesName() => '${namer.ISOLATE}.\$finishClasses'; |
| 46 String get finishIsolateConstructorName() | |
| 47 => '${namer.ISOLATE}.\$finishIsolateConstructor'; | |
| 48 String get pendingClassesName() => '${namer.ISOLATE}.\$pendingClasses'; | |
| 49 String get initialStaticValuesName() | |
| 50 => '${namer.ISOLATE}.${namer.INITIAL_STATICS}'; | |
| 44 | 51 |
| 45 String buildDefineClassFunction(String isolate) { | 52 String get defineClassFunction() { |
|
kasperl
2012/05/03 12:30:18
It feels a bit weird to me that these are getters.
floitsch
2012/05/03 14:24:01
If they weren't going through other getters (which
| |
| 46 // Example: | 53 // Example: |
| 47 // defineClass("A", "B", | 54 // defineClass("A", "B", |
| 48 // function(x) { /* The JavaScript constructor. */ | 55 // function(x) { /* The JavaScript constructor. */ |
| 49 // this.x = x; | 56 // this.x = x; |
| 50 // }, { /* The members inside an Object literal. */ | 57 // }, { /* The members inside an Object literal. */ |
| 51 // foo$1: function(y) { | 58 // foo$1: function(y) { |
| 52 // print(this.x + y); | 59 // print(this.x + y); |
| 53 // }, | 60 // }, |
| 54 // bar$2: function(t, v) { | 61 // bar$2: function(t, v) { |
| 55 // this.x = t - v; | 62 // this.x = t - v; |
| 56 // }, | 63 // }, |
| 57 // }); | 64 // }); |
| 58 return """ | 65 return """ |
| 59 function(cls, superclass, constructor, prototype) { | 66 function(cls, superclass, constructor, prototype) { |
| 60 $isolate.prototype[cls] = constructor; | 67 $initialStaticValuesName[cls] = constructor; |
| 61 constructor.prototype = prototype; | 68 constructor.prototype = prototype; |
| 62 if (superclass !== "") { | 69 if (superclass !== "") { |
| 63 $isolate.pendingClasses[cls] = superclass; | 70 $pendingClassesName[cls] = superclass; |
| 64 } | 71 } |
| 65 }"""; | 72 }"""; |
| 66 } | 73 } |
| 67 | 74 |
| 68 String buildFinishClassesFunction(String isolate) { | 75 String get finishClassesFunction() { |
| 69 // 'defineClass' does not require the classes to be constructed in order. | 76 // 'defineClass' does not require the classes to be constructed in order. |
| 70 // Classes are initially just stored in the 'pendingClasses' field. | 77 // Classes are initially just stored in the 'pendingClasses' field. |
| 71 // 'finishClasses' takes all pending classes and sets up the prototype. | 78 // 'finishClasses' takes all pending classes and sets up the prototype. |
| 72 // Once set up, the constructors prototype field satisfy: | 79 // Once set up, the constructors prototype field satisfy: |
| 73 // - it contains all (local) members. | 80 // - it contains all (local) members. |
| 74 // - its internal prototype (__proto__) points to the superclass' | 81 // - its internal prototype (__proto__) points to the superclass' |
| 75 // prototype field. | 82 // prototype field. |
| 76 // - the prototype's constructor field points to the JavaScript | 83 // - the prototype's constructor field points to the JavaScript |
| 77 // constructor. | 84 // constructor. |
| 78 // For engines where we have access to the '__proto__' we can manipulate | 85 // For engines where we have access to the '__proto__' we can manipulate |
| 79 // the object literal directly. For other engines we have to create a new | 86 // the object literal directly. For other engines we have to create a new |
| 80 // object and copy over the members. | 87 // object and copy over the members. |
| 81 return ''' | 88 return ''' |
| 82 function() { | 89 function() { |
| 83 var pendingClasses = $isolate.pendingClasses; | 90 var pendingClasses = $pendingClassesName; |
| 84 '''/* FinishClasses can be called multiple times. This means that we need to | 91 '''/* FinishClasses can be called multiple times. This means that we need to |
| 85 clear the pendingClasses property. */''' | 92 clear the pendingClasses property. */''' |
| 86 $isolate.pendingClasses = {}; | 93 $pendingClassesName = {}; |
| 87 var finishedClasses = {}; | 94 var finishedClasses = {}; |
| 88 function finishClass(cls) { | 95 function finishClass(cls) { |
| 89 if (finishedClasses[cls]) return; | 96 if (finishedClasses[cls]) return; |
| 90 finishedClasses[cls] = true; | 97 finishedClasses[cls] = true; |
| 91 var superclass = pendingClasses[cls]; | 98 var superclass = pendingClasses[cls]; |
| 92 '''/* The superclass is only false (empty string) for Dart's Object class. */''' | 99 '''/* The superclass is only false (empty string) for Dart's Object class. */''' |
| 93 if (!superclass) return; | 100 if (!superclass) return; |
| 94 finishClass(superclass); | 101 finishClass(superclass); |
| 95 var constructor = $isolate.prototype[cls]; | 102 var constructor = $initialStaticValuesName[cls]; |
| 96 var superConstructor = $isolate.prototype[superclass]; | 103 var superConstructor = $initialStaticValuesName[superclass]; |
| 97 var prototype = constructor.prototype; | 104 var prototype = constructor.prototype; |
| 98 if (prototype.__proto__) { | 105 if (prototype.__proto__) { |
| 99 '''/* On Firefox and Webkit browsers we can manipulate the __proto__ | 106 '''/* On Firefox and Webkit browsers we can manipulate the __proto__ |
| 100 directly. */''' | 107 directly. */''' |
| 101 prototype.__proto__ = superConstructor.prototype; | 108 prototype.__proto__ = superConstructor.prototype; |
| 102 prototype.constructor = constructor; | 109 prototype.constructor = constructor; |
| 103 } else { | 110 } else { |
| 104 '''/* On the remaining browsers we need to instantiate an object with the | 111 '''/* On the remaining browsers we need to instantiate an object with the |
| 105 correct (internal) prototype set up correctly, and then copy the | 112 correct (internal) prototype set up correctly, and then copy the |
| 106 members. */''' | 113 members. */''' |
| 107 function tmp() {}; | 114 function tmp() {}; |
| 108 tmp.prototype = superConstructor.prototype; | 115 tmp.prototype = superConstructor.prototype; |
| 109 var newPrototype = new tmp(); | 116 var newPrototype = new tmp(); |
| 110 constructor.prototype = newPrototype; | 117 constructor.prototype = newPrototype; |
| 111 newPrototype.constructor = constructor; | 118 newPrototype.constructor = constructor; |
| 112 '''/* Opera does not support 'getOwnPropertyNames'. Therefore we use | 119 '''/* Opera does not support 'getOwnPropertyNames'. Therefore we use |
| 113 hosOwnProperty instead. */''' | 120 hosOwnProperty instead. */''' |
| 114 var hasOwnProperty = Object.prototype.hasOwnProperty; | 121 var hasOwnProperty = Object.prototype.hasOwnProperty; |
| 115 for (var member in prototype) { | 122 for (var member in prototype) { |
| 116 if (hasOwnProperty.call(prototype, member)) { | 123 if (hasOwnProperty.call(prototype, member)) { |
| 117 newPrototype[member] = prototype[member]; | 124 newPrototype[member] = prototype[member]; |
| 118 } | 125 } |
| 119 } | 126 } |
| 120 } | 127 } |
| 121 } | 128 } |
| 122 for (var cls in pendingClasses) finishClass(cls); | 129 for (var cls in pendingClasses) finishClass(cls); |
| 123 }; | 130 }'''; |
| 124 '''; | 131 } |
| 132 | |
| 133 String get finishIsolateConstructorFunction() { | |
| 134 return """function(oldIsolate) { | |
| 135 var initialStatics = oldIsolate.${namer.INITIAL_STATICS}; | |
| 136 var isolatePrototype = oldIsolate.prototype; | |
| 137 var str = "{\\n"; | |
| 138 """/* We fetch the initial static values from the same location as before. */""" | |
|
kasperl
2012/05/03 12:30:18
Somehow this "embedded comment" make it harder to
floitsch
2012/05/03 14:24:01
Done.
| |
| 139 str += "var initialStatics = ${namer.ISOLATE}.${namer.INITIAL_STATICS};\\n"; | |
| 140 for (var staticName in initialStatics) { | |
| 141 if (Object.prototype.hasOwnProperty.call(initialStatics, staticName)) { | |
| 142 str += "this." + staticName + "= initialStatics." + staticName + ";\\n"; | |
| 143 } | |
| 144 } | |
| 145 str += "}\\n"; | |
| 146 var newIsolate = new Function(str); | |
| 147 newIsolate.prototype = isolatePrototype; | |
| 148 isolatePrototype.constructor = newIsolate; | |
| 149 newIsolate.${namer.INITIAL_STATICS} = initialStatics; | |
| 150 return newIsolate; | |
| 151 }"""; | |
| 125 } | 152 } |
| 126 | 153 |
| 127 void addDefineClassAndFinishClassFunctionsIfNecessary(StringBuffer buffer) { | 154 void addDefineClassAndFinishClassFunctionsIfNecessary(StringBuffer buffer) { |
| 128 String isolate = namer.ISOLATE; | 155 String isolate = namer.ISOLATE; |
| 129 buffer.add("$defineClassName = ${buildDefineClassFunction(isolate)};\n"); | 156 buffer.add("$defineClassName = $defineClassFunction;\n"); |
| 130 buffer.add("$isolate.pendingClasses = {};\n"); | 157 buffer.add("$pendingClassesName = {};\n"); |
| 131 buffer.add("$finishClassesName = ${buildFinishClassesFunction(isolate)};"); | 158 buffer.add("$finishClassesName = $finishClassesFunction;\n"); |
| 132 buffer.add("\n"); | 159 } |
| 160 | |
| 161 void emitFinishIsolateConstructor(StringBuffer buffer) { | |
| 162 String name = finishIsolateConstructorName; | |
| 163 String value = finishIsolateConstructorFunction; | |
| 164 buffer.add("$name = $value;\n"); | |
| 165 } | |
| 166 | |
| 167 void emitFinishIsolateConstructorInvocation(StringBuffer buffer) { | |
| 168 String isolate = namer.ISOLATE; | |
| 169 buffer.add("$isolate = $finishIsolateConstructorName($isolate);\n"); | |
| 133 } | 170 } |
| 134 | 171 |
| 135 void addParameterStub(FunctionElement member, | 172 void addParameterStub(FunctionElement member, |
| 136 Selector selector, | 173 Selector selector, |
| 137 void defineInstanceMember(String invocationName, | 174 void defineInstanceMember(String invocationName, |
| 138 String definition)) { | 175 String definition)) { |
| 139 FunctionParameters parameters = member.computeParameters(compiler); | 176 FunctionParameters parameters = member.computeParameters(compiler); |
| 140 int positionalArgumentCount = selector.positionalArgumentCount; | 177 int positionalArgumentCount = selector.positionalArgumentCount; |
| 141 if (positionalArgumentCount == parameters.parameterCount) { | 178 if (positionalArgumentCount == parameters.parameterCount) { |
| 142 assert(selector.namedArgumentCount == 0); | 179 assert(selector.namedArgumentCount == 0); |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 436 | 473 |
| 437 void emitFinishClassesInvocationIfNecessary(StringBuffer buffer) { | 474 void emitFinishClassesInvocationIfNecessary(StringBuffer buffer) { |
| 438 if (needsDefineClass) buffer.add("$finishClassesName();\n"); | 475 if (needsDefineClass) buffer.add("$finishClassesName();\n"); |
| 439 } | 476 } |
| 440 | 477 |
| 441 void emitStaticFunctionsWithNamer(StringBuffer buffer, | 478 void emitStaticFunctionsWithNamer(StringBuffer buffer, |
| 442 Map<Element, String> generatedCode, | 479 Map<Element, String> generatedCode, |
| 443 String functionNamer(Element element)) { | 480 String functionNamer(Element element)) { |
| 444 generatedCode.forEach((Element element, String codeBlock) { | 481 generatedCode.forEach((Element element, String codeBlock) { |
| 445 if (!element.isInstanceMember()) { | 482 if (!element.isInstanceMember()) { |
| 446 buffer.add(isolatePrototype); | 483 String functionName = functionNamer(element); |
| 447 buffer.add('.${functionNamer(element)} = '); | 484 buffer.add('$initialStatics.$functionName = $codeBlock;\n\n'); |
| 448 buffer.add(codeBlock); | |
| 449 buffer.add(';\n\n'); | |
| 450 } | 485 } |
| 451 }); | 486 }); |
| 452 } | 487 } |
| 453 | 488 |
| 454 void emitStaticFunctions(StringBuffer buffer) { | 489 void emitStaticFunctions(StringBuffer buffer) { |
| 455 emitStaticFunctionsWithNamer(buffer, | 490 emitStaticFunctionsWithNamer(buffer, |
| 456 compiler.universe.generatedCode, | 491 compiler.universe.generatedCode, |
| 457 namer.getName); | 492 namer.getName); |
| 458 emitStaticFunctionsWithNamer(buffer, | 493 emitStaticFunctionsWithNamer(buffer, |
| 459 compiler.universe.generatedBailoutCode, | 494 compiler.universe.generatedBailoutCode, |
| 460 namer.getBailoutName); | 495 namer.getBailoutName); |
| 461 } | 496 } |
| 462 | 497 |
| 463 void emitStaticFunctionGetters(StringBuffer buffer) { | 498 void emitStaticFunctionGetters(StringBuffer buffer) { |
| 464 Set<FunctionElement> functionsNeedingGetter = | 499 Set<FunctionElement> functionsNeedingGetter = |
| 465 compiler.universe.staticFunctionsNeedingGetter; | 500 compiler.universe.staticFunctionsNeedingGetter; |
| 466 for (FunctionElement element in functionsNeedingGetter) { | 501 for (FunctionElement element in functionsNeedingGetter) { |
| 467 // The static function does not have the correct name. Since | 502 // The static function does not have the correct name. Since |
| 468 // [addParameterStubs] use the name to create its stubs we simply | 503 // [addParameterStubs] use the name to create its stubs we simply |
| 469 // create a fake element with the correct name. | 504 // create a fake element with the correct name. |
| 470 // Note: the callElement will not have any enclosingElement. | 505 // Note: the callElement will not have any enclosingElement. |
| 471 FunctionElement callElement = | 506 FunctionElement callElement = |
| 472 new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, element); | 507 new ClosureInvocationElement(Namer.CLOSURE_INVOCATION_NAME, element); |
| 473 String staticName = namer.getName(element); | 508 String staticName = namer.getName(element); |
| 474 int parameterCount = element.parameterCount(compiler); | 509 int parameterCount = element.parameterCount(compiler); |
| 475 String invocationName = | 510 String invocationName = |
| 476 namer.instanceMethodName(element.getLibrary(), callElement.name, | 511 namer.instanceMethodName(element.getLibrary(), callElement.name, |
| 477 parameterCount); | 512 parameterCount); |
| 478 buffer.add(isolatePrototype); | 513 String fieldAccess = '$initialStatics.$staticName'; |
| 479 buffer.add(".$staticName.$invocationName = "); | 514 buffer.add("$fieldAccess.$invocationName = $fieldAccess;\n"); |
| 480 buffer.add(isolatePrototype); | |
| 481 buffer.add(".$staticName;\n"); | |
| 482 addParameterStubs(callElement, (String name, String value) { | 515 addParameterStubs(callElement, (String name, String value) { |
| 483 buffer.add('$isolatePrototype.$staticName.$name = $value;\n'); | 516 buffer.add('$fieldAccess.$name = $value;\n'); |
| 484 }); | 517 }); |
| 485 } | 518 } |
| 486 } | 519 } |
| 487 | 520 |
| 488 void emitDynamicFunctionGetter(FunctionElement member, | 521 void emitDynamicFunctionGetter(FunctionElement member, |
| 489 defineInstanceMember(String invocationName, | 522 defineInstanceMember(String invocationName, |
| 490 String definition)) { | 523 String definition)) { |
| 491 // For every method that has the same name as a property-get we create a | 524 // For every method that has the same name as a property-get we create a |
| 492 // getter that returns a bound closure. Say we have a class 'A' with method | 525 // getter that returns a bound closure. Say we have a class 'A' with method |
| 493 // 'foo' and somewhere in the code there is a dynamic property get of | 526 // 'foo' and somewhere in the code there is a dynamic property get of |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 579 } | 612 } |
| 580 String joined = Strings.join(arguments, ", "); | 613 String joined = Strings.join(arguments, ", "); |
| 581 defineInstanceMember( | 614 defineInstanceMember( |
| 582 invocationName, | 615 invocationName, |
| 583 "function($joined) { return $getter.$closureCallName($joined); }"); | 616 "function($joined) { return $getter.$closureCallName($joined); }"); |
| 584 } | 617 } |
| 585 } | 618 } |
| 586 } | 619 } |
| 587 | 620 |
| 588 void emitStaticNonFinalFieldInitializations(StringBuffer buffer) { | 621 void emitStaticNonFinalFieldInitializations(StringBuffer buffer) { |
| 589 // Adds initializations inside the Isolate constructor. | |
| 590 // Example: | |
| 591 // function Isolate() { | |
| 592 // this.staticNonFinal = Isolate.prototype.someVal; | |
| 593 // ... | |
| 594 // } | |
| 595 ConstantHandler handler = compiler.constantHandler; | 622 ConstantHandler handler = compiler.constantHandler; |
| 596 List<VariableElement> staticNonFinalFields = | 623 List<VariableElement> staticNonFinalFields = |
| 597 handler.getStaticNonFinalFieldsForEmission(); | 624 handler.getStaticNonFinalFieldsForEmission(); |
| 598 if (!staticNonFinalFields.isEmpty()) buffer.add('\n'); | |
| 599 for (Element element in staticNonFinalFields) { | 625 for (Element element in staticNonFinalFields) { |
| 600 buffer.add(' this.${namer.getName(element)} = '); | 626 buffer.add('$initialStatics.${namer.getName(element)} = '); |
| 601 compiler.withCurrentElement(element, () { | 627 compiler.withCurrentElement(element, () { |
| 602 handler.writeJsCodeForVariable(buffer, element); | 628 handler.writeJsCodeForVariable(buffer, element); |
| 603 }); | 629 }); |
| 604 buffer.add(';\n'); | 630 buffer.add(';\n'); |
| 605 } | 631 } |
| 606 } | 632 } |
| 607 | 633 |
| 608 void emitCompileTimeConstants(StringBuffer buffer) { | 634 void emitCompileTimeConstants(StringBuffer buffer) { |
| 609 ConstantHandler handler = compiler.constantHandler; | 635 ConstantHandler handler = compiler.constantHandler; |
| 610 List<Constant> constants = handler.getConstantsForEmission(); | 636 List<Constant> constants = handler.getConstantsForEmission(); |
| 611 bool addedMakeConstantList = false; | 637 bool addedMakeConstantList = false; |
| 612 for (Constant constant in constants) { | 638 for (Constant constant in constants) { |
| 613 String name = handler.getNameForConstant(constant); | 639 String name = handler.getNameForConstant(constant); |
| 614 // The name is null when the constant is already a JS constant. | 640 // The name is null when the constant is already a JS constant. |
| 615 // TODO(floitsch): every constant should be registered, so that we can | 641 // TODO(floitsch): every constant should be registered, so that we can |
| 616 // share the ones that take up too much space (like some strings). | 642 // share the ones that take up too much space (like some strings). |
| 617 if (name === null) continue; | 643 if (name === null) continue; |
| 618 if (!addedMakeConstantList && constant.isList()) { | 644 if (!addedMakeConstantList && constant.isList()) { |
| 619 addedMakeConstantList = true; | 645 addedMakeConstantList = true; |
| 620 emitMakeConstantList(buffer); | 646 emitMakeConstantList(buffer); |
| 621 } | 647 } |
| 622 buffer.add('$isolatePrototype.$name = '); | 648 buffer.add('$initialStatics.$name = '); |
| 623 handler.writeJsCode(buffer, constant); | 649 handler.writeJsCode(buffer, constant); |
| 624 buffer.add(';\n'); | 650 buffer.add(';\n'); |
| 625 } | 651 } |
| 626 } | 652 } |
| 627 | 653 |
| 628 void emitMakeConstantList(StringBuffer buffer) { | 654 void emitMakeConstantList(StringBuffer buffer) { |
| 629 buffer.add(isolatePrototype); | 655 buffer.add(namer.ISOLATE); |
| 630 buffer.add(@'''.makeConstantList = function(list) { | 656 buffer.add(@'''.makeConstantList = function(list) { |
| 631 list.immutable$list = true; | 657 list.immutable$list = true; |
| 632 list.fixed$length = true; | 658 list.fixed$length = true; |
| 633 return list; | 659 return list; |
| 634 }; | 660 }; |
| 635 '''); | 661 '''); |
| 636 } | 662 } |
| 637 | 663 |
| 638 void emitExtraAccessors(Element member, | 664 void emitExtraAccessors(Element member, |
| 639 void defineInstanceMember(String invocationName, | 665 void defineInstanceMember(String invocationName, |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 801 ${mainCall}; | 827 ${mainCall}; |
| 802 }); | 828 }); |
| 803 } else { | 829 } else { |
| 804 ${mainCall}; | 830 ${mainCall}; |
| 805 } | 831 } |
| 806 """); | 832 """); |
| 807 } | 833 } |
| 808 | 834 |
| 809 String assembleProgram() { | 835 String assembleProgram() { |
| 810 measure(() { | 836 measure(() { |
| 811 mainBuffer.add('function ${namer.ISOLATE}() {'); | 837 mainBuffer.add('function ${namer.ISOLATE}() {}\n'); |
| 812 emitStaticNonFinalFieldInitializations(mainBuffer); | |
| 813 mainBuffer.add('}\n'); | |
| 814 mainBuffer.add('init();\n\n'); | 838 mainBuffer.add('init();\n\n'); |
| 815 // Shorten the code by using [namer.CURRENT_ISOLATE] as temporary. | 839 // Shorten the code by using [namer.CURRENT_ISOLATE] as temporary. |
| 816 isolatePrototype = namer.CURRENT_ISOLATE; | 840 initialStatics = namer.CURRENT_ISOLATE; |
| 817 mainBuffer.add('var $isolatePrototype = ${namer.ISOLATE}.prototype;\n'); | 841 mainBuffer.add('var $initialStatics = $initialStaticValuesName;\n'); |
| 818 emitClasses(mainBuffer); | 842 emitClasses(mainBuffer); |
| 819 mainBuffer.add(boundClosureBuffer); | 843 mainBuffer.add(boundClosureBuffer); |
| 820 // Clear the buffer, so that we can reuse it for the native classes. | 844 // Clear the buffer, so that we can reuse it for the native classes. |
| 821 boundClosureBuffer.clear(); | 845 boundClosureBuffer.clear(); |
| 822 emitStaticFunctions(mainBuffer); | 846 emitStaticFunctions(mainBuffer); |
| 823 emitStaticFunctionGetters(mainBuffer); | 847 emitStaticFunctionGetters(mainBuffer); |
| 824 // We need to finish the classes before we construct compile time | 848 // We need to finish the classes before we construct compile time |
| 825 // constants. | 849 // constants. |
| 826 emitFinishClassesInvocationIfNecessary(mainBuffer); | 850 emitFinishClassesInvocationIfNecessary(mainBuffer); |
| 851 // Static field initializations require the classes to be set up. | |
| 852 emitStaticNonFinalFieldInitializations(mainBuffer); | |
| 827 emitCompileTimeConstants(mainBuffer); | 853 emitCompileTimeConstants(mainBuffer); |
| 828 | 854 |
| 829 isolatePrototype = '${namer.ISOLATE}.prototype;\n'; | 855 initialStatics = initialStaticValuesName; |
| 830 mainBuffer.add( | 856 // The following code should not use the short-hand for the |
| 831 'var ${namer.CURRENT_ISOLATE} = new ${namer.ISOLATE}();\n'); | 857 // initialStatics. |
| 858 mainBuffer.add('var ${namer.CURRENT_ISOLATE} = null;\n'); | |
| 832 nativeEmitter.emitDynamicDispatchMetadata(); | 859 nativeEmitter.emitDynamicDispatchMetadata(); |
| 833 nativeEmitter.assembleCode(mainBuffer); | 860 nativeEmitter.assembleCode(mainBuffer); |
| 834 mainBuffer.add(boundClosureBuffer); | 861 mainBuffer.add(boundClosureBuffer); |
| 835 emitFinishClassesInvocationIfNecessary(mainBuffer); | 862 emitFinishClassesInvocationIfNecessary(mainBuffer); |
| 863 | |
| 864 emitFinishIsolateConstructorInvocation(mainBuffer); | |
| 865 mainBuffer.add( | |
| 866 'var ${namer.CURRENT_ISOLATE} = new ${namer.ISOLATE}();\n'); | |
| 867 | |
| 836 emitMain(mainBuffer); | 868 emitMain(mainBuffer); |
| 837 mainBuffer.add('function init() {\n'); | 869 mainBuffer.add('function init() {\n'); |
| 870 mainBuffer.add(' $initialStatics = {};\n'); | |
| 838 addDefineClassAndFinishClassFunctionsIfNecessary(mainBuffer); | 871 addDefineClassAndFinishClassFunctionsIfNecessary(mainBuffer); |
| 872 emitFinishIsolateConstructor(mainBuffer); | |
| 839 mainBuffer.add('}\n'); | 873 mainBuffer.add('}\n'); |
| 840 compiler.assembledCode = mainBuffer.toString(); | 874 compiler.assembledCode = mainBuffer.toString(); |
| 841 }); | 875 }); |
| 842 return compiler.assembledCode; | 876 return compiler.assembledCode; |
| 843 } | 877 } |
| 844 } | 878 } |
| OLD | NEW |