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, |
| 11 FunctionElement other) | 11 FunctionElement other) |
| 12 : super.from(name, other, other.enclosingElement); | 12 : super.from(name, other, other.enclosingElement); |
| 13 | 13 |
| 14 isInstanceMember() => true; | 14 isInstanceMember() => true; |
| 15 } | 15 } |
| 16 | 16 |
| 17 /** | 17 /** |
| 18 * Generates the code for all used classes in the program. Static fields (even | 18 * Generates the code for all used classes in the program. Static fields (even |
| 19 * in classes) are ignored, since they can be treated as non-class elements. | 19 * in classes) are ignored, since they can be treated as non-class elements. |
| 20 * | 20 * |
| 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 bool needsLazyInitializer = false; | |
| 27 final Namer namer; | 28 final Namer namer; |
| 28 NativeEmitter nativeEmitter; | 29 NativeEmitter nativeEmitter; |
| 29 CodeBuffer boundClosureBuffer; | 30 CodeBuffer boundClosureBuffer; |
| 30 CodeBuffer mainBuffer; | 31 CodeBuffer mainBuffer; |
| 31 /** Shorter access to [isolatePropertiesName]. Both here in the code, as | 32 /** Shorter access to [isolatePropertiesName]. Both here in the code, as |
| 32 well as in the generated code. */ | 33 well as in the generated code. */ |
| 33 String isolateProperties; | 34 String isolateProperties; |
| 34 String classesCollector; | 35 String classesCollector; |
| 35 final Map<int, String> boundClosureCache; | 36 final Map<int, String> boundClosureCache; |
| 36 | 37 |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 55 String get finishClassesName() | 56 String get finishClassesName() |
| 56 => '${namer.ISOLATE}.\$finishClasses'; | 57 => '${namer.ISOLATE}.\$finishClasses'; |
| 57 String get finishIsolateConstructorName() | 58 String get finishIsolateConstructorName() |
| 58 => '${namer.ISOLATE}.\$finishIsolateConstructor'; | 59 => '${namer.ISOLATE}.\$finishIsolateConstructor'; |
| 59 String get pendingClassesName() | 60 String get pendingClassesName() |
| 60 => '${namer.ISOLATE}.\$pendingClasses'; | 61 => '${namer.ISOLATE}.\$pendingClasses'; |
| 61 String get isolatePropertiesName() | 62 String get isolatePropertiesName() |
| 62 => '${namer.ISOLATE}.${namer.ISOLATE_PROPERTIES}'; | 63 => '${namer.ISOLATE}.${namer.ISOLATE_PROPERTIES}'; |
| 63 String get supportsProtoName() | 64 String get supportsProtoName() |
| 64 => 'supportsProto'; | 65 => 'supportsProto'; |
| 66 String get lazyInitializerName() | |
| 67 => '${namer.ISOLATE}.\$lazy'; | |
| 65 | 68 |
| 66 final String GETTER_SUFFIX = "?"; | 69 final String GETTER_SUFFIX = "?"; |
| 67 final String SETTER_SUFFIX = "!"; | 70 final String SETTER_SUFFIX = "!"; |
| 68 final String GETTER_SETTER_SUFFIX = "="; | 71 final String GETTER_SETTER_SUFFIX = "="; |
| 69 | 72 |
| 70 String get generateGetterSetterFunction() { | 73 String get generateGetterSetterFunction() { |
| 71 return """ | 74 return """ |
| 72 function(field, prototype) { | 75 function(field, prototype) { |
| 73 var len = field.length; | 76 var len = field.length; |
| 74 var lastChar = field[len - 1]; | 77 var lastChar = field[len - 1]; |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 242 } | 245 } |
| 243 str += "}\\n"; | 246 str += "}\\n"; |
| 244 var newIsolate = new Function(str); | 247 var newIsolate = new Function(str); |
| 245 newIsolate.prototype = isolatePrototype; | 248 newIsolate.prototype = isolatePrototype; |
| 246 isolatePrototype.constructor = newIsolate; | 249 isolatePrototype.constructor = newIsolate; |
| 247 newIsolate.${namer.ISOLATE_PROPERTIES} = isolateProperties; | 250 newIsolate.${namer.ISOLATE_PROPERTIES} = isolateProperties; |
| 248 return newIsolate; | 251 return newIsolate; |
| 249 }"""; | 252 }"""; |
| 250 } | 253 } |
| 251 | 254 |
| 255 String get lazyInitializerFunction() { | |
| 256 String isolate = namer.CURRENT_ISOLATE; | |
| 257 return """ | |
| 258 function(prototype, fieldName, getterName, lazyValue) { | |
| 259 var sentinel = {}; | |
| 260 prototype[fieldName] = sentinel; | |
| 261 var getter = new Function("{ return $isolate." + fieldName + ";}"); | |
| 262 prototype[getterName] = function() { | |
| 263 var result = $isolate[fieldName]; | |
| 264 try { | |
| 265 if (result === sentinel) { | |
|
kasperl
2012/08/17 09:30:04
I guess this doesn't catch cyclic initialization.
floitsch
2012/09/04 17:32:21
Done.
| |
| 266 try { | |
| 267 result = $isolate[fieldName] = lazyValue(); | |
| 268 } catch (e) { | |
| 269 if ($isolate[fieldName] === sentinel) { | |
| 270 $isolate[fieldName] = null; | |
| 271 } | |
| 272 throw e; | |
| 273 } | |
| 274 } | |
| 275 return result; | |
| 276 } finally { | |
| 277 $isolate[getterName] = getter; | |
| 278 } | |
| 279 }; | |
| 280 }"""; | |
| 281 } | |
| 282 | |
| 252 void addDefineClassAndFinishClassFunctionsIfNecessary(CodeBuffer buffer) { | 283 void addDefineClassAndFinishClassFunctionsIfNecessary(CodeBuffer buffer) { |
| 253 if (needsDefineClass) { | 284 if (needsDefineClass) { |
| 254 String isolate = namer.ISOLATE; | |
| 255 buffer.add("$defineClassName = $defineClassFunction;\n"); | 285 buffer.add("$defineClassName = $defineClassFunction;\n"); |
| 256 buffer.add(protoSupportCheck); | 286 buffer.add(protoSupportCheck); |
| 257 buffer.add("$pendingClassesName = {};\n"); | 287 buffer.add("$pendingClassesName = {};\n"); |
| 258 buffer.add("$finishClassesName = $finishClassesFunction;\n"); | 288 buffer.add("$finishClassesName = $finishClassesFunction;\n"); |
| 259 } | 289 } |
| 260 } | 290 } |
| 261 | 291 |
| 292 void addLazyInitializerFunctionIfNecessary(CodeBuffer buffer) { | |
| 293 if (needsLazyInitializer) { | |
| 294 buffer.add("$lazyInitializerName = $lazyInitializerFunction;\n"); | |
| 295 } | |
| 296 } | |
| 297 | |
| 262 void emitFinishIsolateConstructor(CodeBuffer buffer) { | 298 void emitFinishIsolateConstructor(CodeBuffer buffer) { |
| 263 String name = finishIsolateConstructorName; | 299 String name = finishIsolateConstructorName; |
| 264 String value = finishIsolateConstructorFunction; | 300 String value = finishIsolateConstructorFunction; |
| 265 buffer.add("$name = $value;\n"); | 301 buffer.add("$name = $value;\n"); |
| 266 } | 302 } |
| 267 | 303 |
| 268 void emitFinishIsolateConstructorInvocation(CodeBuffer buffer) { | 304 void emitFinishIsolateConstructorInvocation(CodeBuffer buffer) { |
| 269 String isolate = namer.ISOLATE; | 305 String isolate = namer.ISOLATE; |
| 270 buffer.add("$isolate = $finishIsolateConstructorName($isolate);\n"); | 306 buffer.add("$isolate = $finishIsolateConstructorName($isolate);\n"); |
| 271 } | 307 } |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 379 DefineMemberFunction defineInstanceMember) { | 415 DefineMemberFunction defineInstanceMember) { |
| 380 Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; | 416 Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; |
| 381 if (selectors == null) return; | 417 if (selectors == null) return; |
| 382 for (Selector selector in selectors) { | 418 for (Selector selector in selectors) { |
| 383 if (!selector.applies(member, compiler)) continue; | 419 if (!selector.applies(member, compiler)) continue; |
| 384 addParameterStub(member, selector, defineInstanceMember); | 420 addParameterStub(member, selector, defineInstanceMember); |
| 385 } | 421 } |
| 386 } | 422 } |
| 387 | 423 |
| 388 bool instanceFieldNeedsGetter(Element member) { | 424 bool instanceFieldNeedsGetter(Element member) { |
| 389 assert(member.kind === ElementKind.FIELD); | 425 assert(member.isField()); |
| 390 return compiler.codegenWorld.hasInvokedGetter(member, compiler); | 426 return compiler.codegenWorld.hasInvokedGetter(member, compiler); |
| 391 } | 427 } |
| 392 | 428 |
| 393 bool instanceFieldNeedsSetter(Element member) { | 429 bool instanceFieldNeedsSetter(Element member) { |
| 394 assert(member.kind === ElementKind.FIELD); | 430 assert(member.isField()); |
| 395 return (member.modifiers === null || !member.modifiers.isFinal()) | 431 return (member.modifiers === null || !member.modifiers.isFinal()) |
| 396 && compiler.codegenWorld.hasInvokedSetter(member, compiler); | 432 && compiler.codegenWorld.hasInvokedSetter(member, compiler); |
| 397 } | 433 } |
| 398 | 434 |
| 399 String compiledFieldName(Element member) { | 435 String compiledFieldName(Element member) { |
| 400 assert(member.kind === ElementKind.FIELD); | 436 assert(member.isField()); |
| 401 return member.isNative() | 437 return member.isNative() |
| 402 ? member.name.slowToString() | 438 ? member.name.slowToString() |
| 403 : namer.getName(member); | 439 : namer.getName(member); |
| 404 } | 440 } |
| 405 | 441 |
| 406 void addInstanceMember(Element member, | 442 void addInstanceMember(Element member, |
| 407 DefineMemberFunction defineInstanceMember) { | 443 DefineMemberFunction defineInstanceMember) { |
| 408 // TODO(floitsch): we don't need to deal with members of | 444 // TODO(floitsch): we don't need to deal with members of |
| 409 // uninstantiated classes, that have been overwritten by subclasses. | 445 // uninstantiated classes, that have been overwritten by subclasses. |
| 410 | 446 |
| 411 if (member.kind === ElementKind.FUNCTION | 447 if (member.isFunction() |
| 412 || member.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY | 448 || member.isGenerativeConstructorBody() |
| 413 || member.kind === ElementKind.GETTER | 449 || member.isGetter() |
| 414 || member.kind === ElementKind.SETTER) { | 450 || member.isSetter()) { |
| 415 if (member.modifiers !== null && member.modifiers.isAbstract()) return; | 451 if (member.modifiers !== null && member.modifiers.isAbstract()) return; |
| 416 CodeBuffer codeBuffer = compiler.codegenWorld.generatedCode[member]; | 452 CodeBuffer codeBuffer = compiler.codegenWorld.generatedCode[member]; |
| 417 if (codeBuffer == null) return; | 453 if (codeBuffer == null) return; |
| 418 defineInstanceMember(namer.getName(member), codeBuffer); | 454 defineInstanceMember(namer.getName(member), codeBuffer); |
| 419 codeBuffer = compiler.codegenWorld.generatedBailoutCode[member]; | 455 codeBuffer = compiler.codegenWorld.generatedBailoutCode[member]; |
| 420 if (codeBuffer !== null) { | 456 if (codeBuffer !== null) { |
| 421 defineInstanceMember(compiler.namer.getBailoutName(member), codeBuffer); | 457 defineInstanceMember(compiler.namer.getBailoutName(member), codeBuffer); |
| 422 } | 458 } |
| 423 FunctionElement function = member; | 459 FunctionElement function = member; |
| 424 FunctionSignature parameters = function.computeSignature(compiler); | 460 FunctionSignature parameters = function.computeSignature(compiler); |
| 425 if (!parameters.optionalParameters.isEmpty()) { | 461 if (!parameters.optionalParameters.isEmpty()) { |
| 426 addParameterStubs(member, defineInstanceMember); | 462 addParameterStubs(member, defineInstanceMember); |
| 427 } | 463 } |
| 428 } else if (member.kind !== ElementKind.FIELD) { | 464 } else if (!member.isField()) { |
| 429 compiler.internalError('unexpected kind: "${member.kind}"', | 465 compiler.internalError('unexpected kind: "${member.kind}"', |
| 430 element: member); | 466 element: member); |
| 431 } | 467 } |
| 432 emitExtraAccessors(member, defineInstanceMember); | 468 emitExtraAccessors(member, defineInstanceMember); |
| 433 } | 469 } |
| 434 | 470 |
| 435 Set<Element> emitClassFields(ClassElement classElement, CodeBuffer buffer) { | 471 Set<Element> emitClassFields(ClassElement classElement, CodeBuffer buffer) { |
| 436 // If the class is never instantiated we still need to set it up for | 472 // If the class is never instantiated we still need to set it up for |
| 437 // inheritance purposes, but we can simplify its JavaScript constructor. | 473 // inheritance purposes, but we can simplify its JavaScript constructor. |
| 438 bool isInstantiated = | 474 bool isInstantiated = |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 646 } | 682 } |
| 647 | 683 |
| 648 void emitFinishClassesInvocationIfNecessary(CodeBuffer buffer) { | 684 void emitFinishClassesInvocationIfNecessary(CodeBuffer buffer) { |
| 649 if (needsDefineClass) { | 685 if (needsDefineClass) { |
| 650 buffer.add("$finishClassesName($classesCollector);\n"); | 686 buffer.add("$finishClassesName($classesCollector);\n"); |
| 651 // Reset the map. | 687 // Reset the map. |
| 652 buffer.add("$classesCollector = {};\n"); | 688 buffer.add("$classesCollector = {};\n"); |
| 653 } | 689 } |
| 654 } | 690 } |
| 655 | 691 |
| 692 void emitStaticFunctionWithNamer(CodeBuffer buffer, | |
| 693 Element element, | |
| 694 CodeBuffer functionBuffer, | |
| 695 String functionNamer(Element element)) { | |
| 696 String functionName = functionNamer(element); | |
| 697 buffer.add('$isolateProperties.$functionName = '); | |
| 698 addMappings(functionBuffer, buffer.length); | |
| 699 buffer.add(functionBuffer); | |
| 700 buffer.add(';\n\n'); | |
| 701 } | |
| 656 void emitStaticFunctionsWithNamer(CodeBuffer buffer, | 702 void emitStaticFunctionsWithNamer(CodeBuffer buffer, |
| 657 Map<Element, CodeBuffer> generatedCode, | 703 Map<Element, CodeBuffer> generatedCode, |
| 658 String functionNamer(Element element)) { | 704 String functionNamer(Element element)) { |
| 659 generatedCode.forEach((Element element, CodeBuffer functionBuffer) { | 705 generatedCode.forEach((Element element, CodeBuffer functionBuffer) { |
| 660 if (!element.isInstanceMember()) { | 706 if (!element.isInstanceMember() && !element.isField()) { |
| 661 String functionName = functionNamer(element); | 707 emitStaticFunctionWithNamer( |
| 662 buffer.add('$isolateProperties.$functionName = '); | 708 buffer, element, functionBuffer,functionNamer); |
| 663 addMappings(functionBuffer, buffer.length); | |
| 664 buffer.add(functionBuffer); | |
| 665 buffer.add(';\n\n'); | |
| 666 } | 709 } |
| 667 }); | 710 }); |
| 668 } | 711 } |
| 669 | 712 |
| 670 void emitStaticFunctions(CodeBuffer buffer) { | 713 void emitStaticFunctions(CodeBuffer buffer) { |
| 671 emitStaticFunctionsWithNamer(buffer, | 714 emitStaticFunctionsWithNamer(buffer, |
| 672 compiler.codegenWorld.generatedCode, | 715 compiler.codegenWorld.generatedCode, |
| 673 namer.getName); | 716 namer.getName); |
| 674 emitStaticFunctionsWithNamer(buffer, | 717 emitStaticFunctionsWithNamer(buffer, |
| 675 compiler.codegenWorld.generatedBailoutCode, | 718 compiler.codegenWorld.generatedBailoutCode, |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 787 CodeBuffer getterBuffer = new CodeBuffer(); | 830 CodeBuffer getterBuffer = new CodeBuffer(); |
| 788 getterBuffer.add( | 831 getterBuffer.add( |
| 789 "function() { return new $closureClass(this, '$targetName'); }"); | 832 "function() { return new $closureClass(this, '$targetName'); }"); |
| 790 defineInstanceMember(getterName, getterBuffer); | 833 defineInstanceMember(getterName, getterBuffer); |
| 791 } | 834 } |
| 792 | 835 |
| 793 void emitCallStubForGetter(Element member, | 836 void emitCallStubForGetter(Element member, |
| 794 Set<Selector> selectors, | 837 Set<Selector> selectors, |
| 795 DefineMemberFunction defineInstanceMember) { | 838 DefineMemberFunction defineInstanceMember) { |
| 796 String getter; | 839 String getter; |
| 797 if (member.kind == ElementKind.GETTER) { | 840 if (member.isGetter()) { |
| 798 getter = "this.${namer.getterName(member.getLibrary(), member.name)}()"; | 841 getter = "this.${namer.getterName(member.getLibrary(), member.name)}()"; |
| 799 } else { | 842 } else { |
| 800 String name = namer.instanceFieldName(member.getLibrary(), member.name); | 843 String name = namer.instanceFieldName(member.getLibrary(), member.name); |
| 801 getter = "this.$name"; | 844 getter = "this.$name"; |
| 802 } | 845 } |
| 803 for (Selector selector in selectors) { | 846 for (Selector selector in selectors) { |
| 804 if (selector.applies(member, compiler)) { | 847 if (selector.applies(member, compiler)) { |
| 805 String invocationName = | 848 String invocationName = |
| 806 namer.instanceMethodInvocationName(member.getLibrary(), member.name, | 849 namer.instanceMethodInvocationName(member.getLibrary(), member.name, |
| 807 selector); | 850 selector); |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 828 handler.getStaticNonFinalFieldsForEmission(); | 871 handler.getStaticNonFinalFieldsForEmission(); |
| 829 for (Element element in staticNonFinalFields) { | 872 for (Element element in staticNonFinalFields) { |
| 830 buffer.add('$isolateProperties.${namer.getName(element)} = '); | 873 buffer.add('$isolateProperties.${namer.getName(element)} = '); |
| 831 compiler.withCurrentElement(element, () { | 874 compiler.withCurrentElement(element, () { |
| 832 handler.writeJsCodeForVariable(buffer, element); | 875 handler.writeJsCodeForVariable(buffer, element); |
| 833 }); | 876 }); |
| 834 buffer.add(';\n'); | 877 buffer.add(';\n'); |
| 835 } | 878 } |
| 836 } | 879 } |
| 837 | 880 |
| 881 void emitLazilyInitializedStaticFields(CodeBuffer buffer) { | |
| 882 ConstantHandler handler = compiler.constantHandler; | |
| 883 List<VariableElement> lazyFields = | |
| 884 handler.getLazilyInitializedFieldsForEmission(); | |
| 885 if (!lazyFields.isEmpty()) { | |
| 886 needsLazyInitializer = true; | |
| 887 for (VariableElement element in lazyFields) { | |
| 888 StringBuffer code = compiler.codegenWorld.generatedCode[element]; | |
| 889 assert(code != null); | |
| 890 // The code only computes the initial value. We build the lazy-check | |
| 891 // here: | |
| 892 // lazyInitializer(prototype, fieldName, getterName, initialValue); | |
| 893 buffer.add("$lazyInitializerName("); | |
| 894 buffer.add(isolateProperties); | |
| 895 buffer.add(", '"); | |
| 896 buffer.add(namer.getName(element)); | |
| 897 buffer.add("', '"); | |
| 898 buffer.add(namer.getLazyInitializerName(element)); | |
| 899 buffer.add("', "); | |
| 900 addMappings(code, buffer.length); | |
| 901 buffer.add(code); | |
| 902 buffer.add(");\n"); | |
| 903 | |
| 904 CodeBuffer bailoutCode = | |
| 905 compiler.codegenWorld.generatedBailoutCode[element]; | |
| 906 if (bailoutCode != null) { | |
| 907 Function functionNamer = namer.getLazyInitializerBailoutName; | |
| 908 emitStaticFunctionWithNamer( | |
| 909 buffer, element, bailoutCode, functionNamer); | |
| 910 } | |
| 911 } | |
| 912 } | |
| 913 } | |
| 914 | |
| 838 void emitCompileTimeConstants(CodeBuffer buffer) { | 915 void emitCompileTimeConstants(CodeBuffer buffer) { |
| 839 ConstantHandler handler = compiler.constantHandler; | 916 ConstantHandler handler = compiler.constantHandler; |
| 840 List<Constant> constants = handler.getConstantsForEmission(); | 917 List<Constant> constants = handler.getConstantsForEmission(); |
| 841 bool addedMakeConstantList = false; | 918 bool addedMakeConstantList = false; |
| 842 for (Constant constant in constants) { | 919 for (Constant constant in constants) { |
| 843 String name = handler.getNameForConstant(constant); | 920 String name = handler.getNameForConstant(constant); |
| 844 // The name is null when the constant is already a JS constant. | 921 // The name is null when the constant is already a JS constant. |
| 845 // TODO(floitsch): every constant should be registered, so that we can | 922 // TODO(floitsch): every constant should be registered, so that we can |
| 846 // share the ones that take up too much space (like some strings). | 923 // share the ones that take up too much space (like some strings). |
| 847 if (name === null) continue; | 924 if (name === null) continue; |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 860 buffer.add(@'''.makeConstantList = function(list) { | 937 buffer.add(@'''.makeConstantList = function(list) { |
| 861 list.immutable$list = true; | 938 list.immutable$list = true; |
| 862 list.fixed$length = true; | 939 list.fixed$length = true; |
| 863 return list; | 940 return list; |
| 864 }; | 941 }; |
| 865 '''); | 942 '''); |
| 866 } | 943 } |
| 867 | 944 |
| 868 void emitExtraAccessors(Element member, | 945 void emitExtraAccessors(Element member, |
| 869 DefineMemberFunction defineInstanceMember) { | 946 DefineMemberFunction defineInstanceMember) { |
| 870 if (member.kind == ElementKind.GETTER || member.kind == ElementKind.FIELD) { | 947 if (member.isGetter() || member.isField()) { |
| 871 Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; | 948 Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; |
| 872 if (selectors !== null && !selectors.isEmpty()) { | 949 if (selectors !== null && !selectors.isEmpty()) { |
| 873 emitCallStubForGetter(member, selectors, defineInstanceMember); | 950 emitCallStubForGetter(member, selectors, defineInstanceMember); |
| 874 } | 951 } |
| 875 } else if (member.kind == ElementKind.FUNCTION) { | 952 } else if (member.isFunction()) { |
| 876 if (compiler.codegenWorld.hasInvokedGetter(member, compiler)) { | 953 if (compiler.codegenWorld.hasInvokedGetter(member, compiler)) { |
| 877 emitDynamicFunctionGetter(member, defineInstanceMember); | 954 emitDynamicFunctionGetter(member, defineInstanceMember); |
| 878 } | 955 } |
| 879 } | 956 } |
| 880 } | 957 } |
| 881 | 958 |
| 882 void emitNoSuchMethodHandlers(DefineMemberFunction defineInstanceMember) { | 959 void emitNoSuchMethodHandlers(DefineMemberFunction defineInstanceMember) { |
| 883 // Do not generate no such method handlers if there is no class. | 960 // Do not generate no such method handlers if there is no class. |
| 884 if (compiler.codegenWorld.instantiatedClasses.isEmpty()) return; | 961 if (compiler.codegenWorld.instantiatedClasses.isEmpty()) return; |
| 885 | 962 |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1123 boundClosureBuffer.clear(); | 1200 boundClosureBuffer.clear(); |
| 1124 emitStaticFunctions(mainBuffer); | 1201 emitStaticFunctions(mainBuffer); |
| 1125 emitStaticFunctionGetters(mainBuffer); | 1202 emitStaticFunctionGetters(mainBuffer); |
| 1126 // We need to finish the classes before we construct compile time | 1203 // We need to finish the classes before we construct compile time |
| 1127 // constants. | 1204 // constants. |
| 1128 emitFinishClassesInvocationIfNecessary(mainBuffer); | 1205 emitFinishClassesInvocationIfNecessary(mainBuffer); |
| 1129 emitCompileTimeConstants(mainBuffer); | 1206 emitCompileTimeConstants(mainBuffer); |
| 1130 // Static field initializations require the classes and compile-time | 1207 // Static field initializations require the classes and compile-time |
| 1131 // constants to be set up. | 1208 // constants to be set up. |
| 1132 emitStaticNonFinalFieldInitializations(mainBuffer); | 1209 emitStaticNonFinalFieldInitializations(mainBuffer); |
| 1210 emitLazilyInitializedStaticFields(mainBuffer); | |
| 1133 | 1211 |
| 1134 isolateProperties = isolatePropertiesName; | 1212 isolateProperties = isolatePropertiesName; |
| 1135 // The following code should not use the short-hand for the | 1213 // The following code should not use the short-hand for the |
| 1136 // initialStatics. | 1214 // initialStatics. |
| 1137 mainBuffer.add('var ${namer.CURRENT_ISOLATE} = null;\n'); | 1215 mainBuffer.add('var ${namer.CURRENT_ISOLATE} = null;\n'); |
| 1138 mainBuffer.add(boundClosureBuffer); | 1216 mainBuffer.add(boundClosureBuffer); |
| 1139 emitFinishClassesInvocationIfNecessary(mainBuffer); | 1217 emitFinishClassesInvocationIfNecessary(mainBuffer); |
| 1140 // After this assignment we will produce invalid JavaScript code if we use | 1218 // After this assignment we will produce invalid JavaScript code if we use |
| 1141 // the classesCollector variable. | 1219 // the classesCollector variable. |
| 1142 classesCollector = 'classesCollector should not be used from now on'; | 1220 classesCollector = 'classesCollector should not be used from now on'; |
| 1143 | 1221 |
| 1144 emitFinishIsolateConstructorInvocation(mainBuffer); | 1222 emitFinishIsolateConstructorInvocation(mainBuffer); |
| 1145 mainBuffer.add( | 1223 mainBuffer.add( |
| 1146 'var ${namer.CURRENT_ISOLATE} = new ${namer.ISOLATE}();\n'); | 1224 'var ${namer.CURRENT_ISOLATE} = new ${namer.ISOLATE}();\n'); |
| 1147 | 1225 |
| 1148 nativeEmitter.assembleCode(mainBuffer); | 1226 nativeEmitter.assembleCode(mainBuffer); |
| 1149 emitMain(mainBuffer); | 1227 emitMain(mainBuffer); |
| 1150 mainBuffer.add('function init() {\n'); | 1228 mainBuffer.add('function init() {\n'); |
| 1151 mainBuffer.add('$isolateProperties = {};\n'); | 1229 mainBuffer.add('$isolateProperties = {};\n'); |
| 1152 addDefineClassAndFinishClassFunctionsIfNecessary(mainBuffer); | 1230 addDefineClassAndFinishClassFunctionsIfNecessary(mainBuffer); |
| 1231 addLazyInitializerFunctionIfNecessary(mainBuffer); | |
| 1153 emitFinishIsolateConstructor(mainBuffer); | 1232 emitFinishIsolateConstructor(mainBuffer); |
| 1154 mainBuffer.add('}\n'); | 1233 mainBuffer.add('}\n'); |
| 1155 compiler.assembledCode = mainBuffer.toString(); | 1234 compiler.assembledCode = mainBuffer.toString(); |
| 1156 | 1235 |
| 1157 if (generateSourceMap) { | 1236 if (generateSourceMap) { |
| 1158 SourceFile compiledFile = new SourceFile(null, compiler.assembledCode); | 1237 SourceFile compiledFile = new SourceFile(null, compiler.assembledCode); |
| 1159 String sourceMap = sourceMapBuilder.build(compiledFile); | 1238 String sourceMap = sourceMapBuilder.build(compiledFile); |
| 1160 // TODO(podivilov): We should find a better way to return source maps to | 1239 // TODO(podivilov): We should find a better way to return source maps to |
| 1161 // compiler. Using diagnostic handler for that purpose is a temporary | 1240 // compiler. Using diagnostic handler for that purpose is a temporary |
| 1162 // hack. | 1241 // hack. |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1175 sourceName = token.slowToString(); | 1254 sourceName = token.slowToString(); |
| 1176 } | 1255 } |
| 1177 int totalOffset = bufferOffset + offset; | 1256 int totalOffset = bufferOffset + offset; |
| 1178 sourceMapBuilder.addMapping( | 1257 sourceMapBuilder.addMapping( |
| 1179 sourceFile, token.charOffset, sourceName, totalOffset); | 1258 sourceFile, token.charOffset, sourceName, totalOffset); |
| 1180 }); | 1259 }); |
| 1181 } | 1260 } |
| 1182 } | 1261 } |
| 1183 | 1262 |
| 1184 typedef void DefineMemberFunction(String invocationName, CodeBuffer definition); | 1263 typedef void DefineMemberFunction(String invocationName, CodeBuffer definition); |
| OLD | NEW |