| 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 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 } | 247 } |
| 245 str += "}\\n"; | 248 str += "}\\n"; |
| 246 var newIsolate = new Function(str); | 249 var newIsolate = new Function(str); |
| 247 newIsolate.prototype = isolatePrototype; | 250 newIsolate.prototype = isolatePrototype; |
| 248 isolatePrototype.constructor = newIsolate; | 251 isolatePrototype.constructor = newIsolate; |
| 249 newIsolate.${namer.ISOLATE_PROPERTIES} = isolateProperties; | 252 newIsolate.${namer.ISOLATE_PROPERTIES} = isolateProperties; |
| 250 return newIsolate; | 253 return newIsolate; |
| 251 }"""; | 254 }"""; |
| 252 } | 255 } |
| 253 | 256 |
| 257 String get lazyInitializerFunction() { |
| 258 String isolate = namer.CURRENT_ISOLATE; |
| 259 JavaScriptBackend backend = compiler.backend; |
| 260 String cyclicThrow = namer.isolateAccess(backend.cyclicThrowHelper); |
| 261 return """ |
| 262 function(prototype, staticName, fieldName, getterName, lazyValue) { |
| 263 var sentinelUndefined = {}; |
| 264 var sentinelInProgress = {}; |
| 265 prototype[fieldName] = sentinelUndefined; |
| 266 var getter = new Function("{ return $isolate." + fieldName + ";}"); |
| 267 prototype[getterName] = function() { |
| 268 var result = $isolate[fieldName]; |
| 269 try { |
| 270 if (result === sentinelUndefined) { |
| 271 $isolate[fieldName] = sentinelInProgress; |
| 272 try { |
| 273 result = $isolate[fieldName] = lazyValue(); |
| 274 } catch (e) { |
| 275 if ($isolate[fieldName] === sentinelInProgress) { |
| 276 $isolate[fieldName] = null; |
| 277 } |
| 278 throw e; |
| 279 } |
| 280 } else if (result === sentinelInProgress) { |
| 281 $cyclicThrow(staticName); |
| 282 } |
| 283 return result; |
| 284 } finally { |
| 285 $isolate[getterName] = getter; |
| 286 } |
| 287 }; |
| 288 }"""; |
| 289 } |
| 290 |
| 254 void addDefineClassAndFinishClassFunctionsIfNecessary(CodeBuffer buffer) { | 291 void addDefineClassAndFinishClassFunctionsIfNecessary(CodeBuffer buffer) { |
| 255 if (needsDefineClass) { | 292 if (needsDefineClass) { |
| 256 String isolate = namer.ISOLATE; | |
| 257 buffer.add("$defineClassName = $defineClassFunction;\n"); | 293 buffer.add("$defineClassName = $defineClassFunction;\n"); |
| 258 buffer.add(protoSupportCheck); | 294 buffer.add(protoSupportCheck); |
| 259 buffer.add("$pendingClassesName = {};\n"); | 295 buffer.add("$pendingClassesName = {};\n"); |
| 260 buffer.add("$finishClassesName = $finishClassesFunction;\n"); | 296 buffer.add("$finishClassesName = $finishClassesFunction;\n"); |
| 261 } | 297 } |
| 262 } | 298 } |
| 263 | 299 |
| 300 void addLazyInitializerFunctionIfNecessary(CodeBuffer buffer) { |
| 301 if (needsLazyInitializer) { |
| 302 buffer.add("$lazyInitializerName = $lazyInitializerFunction;\n"); |
| 303 } |
| 304 } |
| 305 |
| 264 void emitFinishIsolateConstructor(CodeBuffer buffer) { | 306 void emitFinishIsolateConstructor(CodeBuffer buffer) { |
| 265 String name = finishIsolateConstructorName; | 307 String name = finishIsolateConstructorName; |
| 266 String value = finishIsolateConstructorFunction; | 308 String value = finishIsolateConstructorFunction; |
| 267 buffer.add("$name = $value;\n"); | 309 buffer.add("$name = $value;\n"); |
| 268 } | 310 } |
| 269 | 311 |
| 270 void emitFinishIsolateConstructorInvocation(CodeBuffer buffer) { | 312 void emitFinishIsolateConstructorInvocation(CodeBuffer buffer) { |
| 271 String isolate = namer.ISOLATE; | 313 String isolate = namer.ISOLATE; |
| 272 buffer.add("$isolate = $finishIsolateConstructorName($isolate);\n"); | 314 buffer.add("$isolate = $finishIsolateConstructorName($isolate);\n"); |
| 273 } | 315 } |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 381 DefineMemberFunction defineInstanceMember) { | 423 DefineMemberFunction defineInstanceMember) { |
| 382 Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; | 424 Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; |
| 383 if (selectors == null) return; | 425 if (selectors == null) return; |
| 384 for (Selector selector in selectors) { | 426 for (Selector selector in selectors) { |
| 385 if (!selector.applies(member, compiler)) continue; | 427 if (!selector.applies(member, compiler)) continue; |
| 386 addParameterStub(member, selector, defineInstanceMember); | 428 addParameterStub(member, selector, defineInstanceMember); |
| 387 } | 429 } |
| 388 } | 430 } |
| 389 | 431 |
| 390 bool instanceFieldNeedsGetter(Element member) { | 432 bool instanceFieldNeedsGetter(Element member) { |
| 391 assert(member.kind === ElementKind.FIELD); | 433 assert(member.isField()); |
| 392 return compiler.codegenWorld.hasInvokedGetter(member, compiler); | 434 return compiler.codegenWorld.hasInvokedGetter(member, compiler); |
| 393 } | 435 } |
| 394 | 436 |
| 395 bool instanceFieldNeedsSetter(Element member) { | 437 bool instanceFieldNeedsSetter(Element member) { |
| 396 assert(member.kind === ElementKind.FIELD); | 438 assert(member.isField()); |
| 397 return (member.modifiers === null || !member.modifiers.isFinalOrConst()) | 439 return (member.modifiers === null || !member.modifiers.isFinalOrConst()) |
| 398 && compiler.codegenWorld.hasInvokedSetter(member, compiler); | 440 && compiler.codegenWorld.hasInvokedSetter(member, compiler); |
| 399 } | 441 } |
| 400 | 442 |
| 401 String compiledFieldName(Element member) { | 443 String compiledFieldName(Element member) { |
| 402 assert(member.kind === ElementKind.FIELD); | 444 assert(member.isField()); |
| 403 return member.isNative() | 445 return member.isNative() |
| 404 ? member.name.slowToString() | 446 ? member.name.slowToString() |
| 405 : namer.getName(member); | 447 : namer.getName(member); |
| 406 } | 448 } |
| 407 | 449 |
| 408 void addInstanceMember(Element member, | 450 void addInstanceMember(Element member, |
| 409 DefineMemberFunction defineInstanceMember) { | 451 DefineMemberFunction defineInstanceMember) { |
| 410 // TODO(floitsch): we don't need to deal with members of | 452 // TODO(floitsch): we don't need to deal with members of |
| 411 // uninstantiated classes, that have been overwritten by subclasses. | 453 // uninstantiated classes, that have been overwritten by subclasses. |
| 412 | 454 |
| 413 if (member.kind === ElementKind.FUNCTION | 455 if (member.isFunction() |
| 414 || member.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY | 456 || member.isGenerativeConstructorBody() |
| 415 || member.kind === ElementKind.GETTER | 457 || member.isGetter() |
| 416 || member.kind === ElementKind.SETTER) { | 458 || member.isSetter()) { |
| 417 if (member.modifiers !== null && member.modifiers.isAbstract()) return; | 459 if (member.modifiers !== null && member.modifiers.isAbstract()) return; |
| 418 CodeBuffer codeBuffer = compiler.codegenWorld.generatedCode[member]; | 460 CodeBuffer codeBuffer = compiler.codegenWorld.generatedCode[member]; |
| 419 if (codeBuffer == null) return; | 461 if (codeBuffer == null) return; |
| 420 defineInstanceMember(namer.getName(member), codeBuffer); | 462 defineInstanceMember(namer.getName(member), codeBuffer); |
| 421 codeBuffer = compiler.codegenWorld.generatedBailoutCode[member]; | 463 codeBuffer = compiler.codegenWorld.generatedBailoutCode[member]; |
| 422 if (codeBuffer !== null) { | 464 if (codeBuffer !== null) { |
| 423 defineInstanceMember(compiler.namer.getBailoutName(member), codeBuffer); | 465 defineInstanceMember(compiler.namer.getBailoutName(member), codeBuffer); |
| 424 } | 466 } |
| 425 FunctionElement function = member; | 467 FunctionElement function = member; |
| 426 FunctionSignature parameters = function.computeSignature(compiler); | 468 FunctionSignature parameters = function.computeSignature(compiler); |
| 427 if (!parameters.optionalParameters.isEmpty()) { | 469 if (!parameters.optionalParameters.isEmpty()) { |
| 428 addParameterStubs(member, defineInstanceMember); | 470 addParameterStubs(member, defineInstanceMember); |
| 429 } | 471 } |
| 430 } else if (member.kind !== ElementKind.FIELD) { | 472 } else if (!member.isField()) { |
| 431 compiler.internalError('unexpected kind: "${member.kind}"', | 473 compiler.internalError('unexpected kind: "${member.kind}"', |
| 432 element: member); | 474 element: member); |
| 433 } | 475 } |
| 434 emitExtraAccessors(member, defineInstanceMember); | 476 emitExtraAccessors(member, defineInstanceMember); |
| 435 } | 477 } |
| 436 | 478 |
| 437 String generateCheckedSetter(Element member, String fieldName) { | 479 String generateCheckedSetter(Element member, String fieldName) { |
| 438 Type type = member.computeType(compiler); | 480 Type type = member.computeType(compiler); |
| 439 if (type.element.isTypeVariable() | 481 if (type.element.isTypeVariable() |
| 440 || type.element == compiler.dynamicClass | 482 || type.element == compiler.dynamicClass |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 678 } | 720 } |
| 679 | 721 |
| 680 void emitFinishClassesInvocationIfNecessary(CodeBuffer buffer) { | 722 void emitFinishClassesInvocationIfNecessary(CodeBuffer buffer) { |
| 681 if (needsDefineClass) { | 723 if (needsDefineClass) { |
| 682 buffer.add("$finishClassesName($classesCollector);\n"); | 724 buffer.add("$finishClassesName($classesCollector);\n"); |
| 683 // Reset the map. | 725 // Reset the map. |
| 684 buffer.add("$classesCollector = {};\n"); | 726 buffer.add("$classesCollector = {};\n"); |
| 685 } | 727 } |
| 686 } | 728 } |
| 687 | 729 |
| 730 void emitStaticFunctionWithNamer(CodeBuffer buffer, |
| 731 Element element, |
| 732 CodeBuffer functionBuffer, |
| 733 String functionNamer(Element element)) { |
| 734 String functionName = functionNamer(element); |
| 735 buffer.add('$isolateProperties.$functionName = '); |
| 736 addMappings(functionBuffer, buffer.length); |
| 737 buffer.add(functionBuffer); |
| 738 buffer.add(';\n\n'); |
| 739 } |
| 688 void emitStaticFunctionsWithNamer(CodeBuffer buffer, | 740 void emitStaticFunctionsWithNamer(CodeBuffer buffer, |
| 689 Map<Element, CodeBuffer> generatedCode, | 741 Map<Element, CodeBuffer> generatedCode, |
| 690 String functionNamer(Element element)) { | 742 String functionNamer(Element element)) { |
| 691 generatedCode.forEach((Element element, CodeBuffer functionBuffer) { | 743 generatedCode.forEach((Element element, CodeBuffer functionBuffer) { |
| 692 if (!element.isInstanceMember()) { | 744 if (!element.isInstanceMember() && !element.isField()) { |
| 693 String functionName = functionNamer(element); | 745 emitStaticFunctionWithNamer( |
| 694 buffer.add('$isolateProperties.$functionName = '); | 746 buffer, element, functionBuffer,functionNamer); |
| 695 addMappings(functionBuffer, buffer.length); | |
| 696 buffer.add(functionBuffer); | |
| 697 buffer.add(';\n\n'); | |
| 698 } | 747 } |
| 699 }); | 748 }); |
| 700 } | 749 } |
| 701 | 750 |
| 702 void emitStaticFunctions(CodeBuffer buffer) { | 751 void emitStaticFunctions(CodeBuffer buffer) { |
| 703 emitStaticFunctionsWithNamer(buffer, | 752 emitStaticFunctionsWithNamer(buffer, |
| 704 compiler.codegenWorld.generatedCode, | 753 compiler.codegenWorld.generatedCode, |
| 705 namer.getName); | 754 namer.getName); |
| 706 emitStaticFunctionsWithNamer(buffer, | 755 emitStaticFunctionsWithNamer(buffer, |
| 707 compiler.codegenWorld.generatedBailoutCode, | 756 compiler.codegenWorld.generatedBailoutCode, |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 819 CodeBuffer getterBuffer = new CodeBuffer(); | 868 CodeBuffer getterBuffer = new CodeBuffer(); |
| 820 getterBuffer.add( | 869 getterBuffer.add( |
| 821 "function() { return new $closureClass(this, '$targetName'); }"); | 870 "function() { return new $closureClass(this, '$targetName'); }"); |
| 822 defineInstanceMember(getterName, getterBuffer); | 871 defineInstanceMember(getterName, getterBuffer); |
| 823 } | 872 } |
| 824 | 873 |
| 825 void emitCallStubForGetter(Element member, | 874 void emitCallStubForGetter(Element member, |
| 826 Set<Selector> selectors, | 875 Set<Selector> selectors, |
| 827 DefineMemberFunction defineInstanceMember) { | 876 DefineMemberFunction defineInstanceMember) { |
| 828 String getter; | 877 String getter; |
| 829 if (member.kind == ElementKind.GETTER) { | 878 if (member.isGetter()) { |
| 830 getter = "this.${namer.getterName(member.getLibrary(), member.name)}()"; | 879 getter = "this.${namer.getterName(member.getLibrary(), member.name)}()"; |
| 831 } else { | 880 } else { |
| 832 String name = namer.instanceFieldName(member.getLibrary(), member.name); | 881 String name = namer.instanceFieldName(member.getLibrary(), member.name); |
| 833 getter = "this.$name"; | 882 getter = "this.$name"; |
| 834 } | 883 } |
| 835 for (Selector selector in selectors) { | 884 for (Selector selector in selectors) { |
| 836 if (selector.applies(member, compiler)) { | 885 if (selector.applies(member, compiler)) { |
| 837 String invocationName = | 886 String invocationName = |
| 838 namer.instanceMethodInvocationName(member.getLibrary(), member.name, | 887 namer.instanceMethodInvocationName(member.getLibrary(), member.name, |
| 839 selector); | 888 selector); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 860 handler.getStaticNonFinalFieldsForEmission(); | 909 handler.getStaticNonFinalFieldsForEmission(); |
| 861 for (Element element in staticNonFinalFields) { | 910 for (Element element in staticNonFinalFields) { |
| 862 buffer.add('$isolateProperties.${namer.getName(element)} = '); | 911 buffer.add('$isolateProperties.${namer.getName(element)} = '); |
| 863 compiler.withCurrentElement(element, () { | 912 compiler.withCurrentElement(element, () { |
| 864 handler.writeJsCodeForVariable(buffer, element); | 913 handler.writeJsCodeForVariable(buffer, element); |
| 865 }); | 914 }); |
| 866 buffer.add(';\n'); | 915 buffer.add(';\n'); |
| 867 } | 916 } |
| 868 } | 917 } |
| 869 | 918 |
| 919 void emitLazilyInitializedStaticFields(CodeBuffer buffer) { |
| 920 ConstantHandler handler = compiler.constantHandler; |
| 921 List<VariableElement> lazyFields = |
| 922 handler.getLazilyInitializedFieldsForEmission(); |
| 923 if (!lazyFields.isEmpty()) { |
| 924 needsLazyInitializer = true; |
| 925 for (VariableElement element in lazyFields) { |
| 926 assert(compiler.codegenWorld.generatedBailoutCode[element] === null); |
| 927 StringBuffer code = compiler.codegenWorld.generatedCode[element]; |
| 928 assert(code != null); |
| 929 // The code only computes the initial value. We build the lazy-check |
| 930 // here: |
| 931 // lazyInitializer(prototype, 'name', fieldName, getterName, initial); |
| 932 // The name is used for error reporting. The 'initial' must be a |
| 933 // closure that constructs the initial value. |
| 934 buffer.add("$lazyInitializerName("); |
| 935 buffer.add(isolateProperties); |
| 936 buffer.add(", '"); |
| 937 buffer.add(element.name.slowToString()); |
| 938 buffer.add("', '"); |
| 939 buffer.add(namer.getName(element)); |
| 940 buffer.add("', '"); |
| 941 buffer.add(namer.getLazyInitializerName(element)); |
| 942 buffer.add("', "); |
| 943 addMappings(code, buffer.length); |
| 944 buffer.add(code); |
| 945 buffer.add(");\n"); |
| 946 } |
| 947 } |
| 948 } |
| 949 |
| 870 void emitCompileTimeConstants(CodeBuffer buffer) { | 950 void emitCompileTimeConstants(CodeBuffer buffer) { |
| 871 ConstantHandler handler = compiler.constantHandler; | 951 ConstantHandler handler = compiler.constantHandler; |
| 872 List<Constant> constants = handler.getConstantsForEmission(); | 952 List<Constant> constants = handler.getConstantsForEmission(); |
| 873 bool addedMakeConstantList = false; | 953 bool addedMakeConstantList = false; |
| 874 for (Constant constant in constants) { | 954 for (Constant constant in constants) { |
| 875 String name = handler.getNameForConstant(constant); | 955 String name = handler.getNameForConstant(constant); |
| 876 // The name is null when the constant is already a JS constant. | 956 // The name is null when the constant is already a JS constant. |
| 877 // TODO(floitsch): every constant should be registered, so that we can | 957 // TODO(floitsch): every constant should be registered, so that we can |
| 878 // share the ones that take up too much space (like some strings). | 958 // share the ones that take up too much space (like some strings). |
| 879 if (name === null) continue; | 959 if (name === null) continue; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 892 buffer.add(@'''.makeConstantList = function(list) { | 972 buffer.add(@'''.makeConstantList = function(list) { |
| 893 list.immutable$list = true; | 973 list.immutable$list = true; |
| 894 list.fixed$length = true; | 974 list.fixed$length = true; |
| 895 return list; | 975 return list; |
| 896 }; | 976 }; |
| 897 '''); | 977 '''); |
| 898 } | 978 } |
| 899 | 979 |
| 900 void emitExtraAccessors(Element member, | 980 void emitExtraAccessors(Element member, |
| 901 DefineMemberFunction defineInstanceMember) { | 981 DefineMemberFunction defineInstanceMember) { |
| 902 if (member.kind == ElementKind.GETTER || member.kind == ElementKind.FIELD) { | 982 if (member.isGetter() || member.isField()) { |
| 903 Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; | 983 Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; |
| 904 if (selectors !== null && !selectors.isEmpty()) { | 984 if (selectors !== null && !selectors.isEmpty()) { |
| 905 emitCallStubForGetter(member, selectors, defineInstanceMember); | 985 emitCallStubForGetter(member, selectors, defineInstanceMember); |
| 906 } | 986 } |
| 907 } else if (member.kind == ElementKind.FUNCTION) { | 987 } else if (member.isFunction()) { |
| 908 if (compiler.codegenWorld.hasInvokedGetter(member, compiler)) { | 988 if (compiler.codegenWorld.hasInvokedGetter(member, compiler)) { |
| 909 emitDynamicFunctionGetter(member, defineInstanceMember); | 989 emitDynamicFunctionGetter(member, defineInstanceMember); |
| 910 } | 990 } |
| 911 } | 991 } |
| 912 } | 992 } |
| 913 | 993 |
| 914 void emitNoSuchMethodHandlers(DefineMemberFunction defineInstanceMember) { | 994 void emitNoSuchMethodHandlers(DefineMemberFunction defineInstanceMember) { |
| 915 // Do not generate no such method handlers if there is no class. | 995 // Do not generate no such method handlers if there is no class. |
| 916 if (compiler.codegenWorld.instantiatedClasses.isEmpty()) return; | 996 if (compiler.codegenWorld.instantiatedClasses.isEmpty()) return; |
| 917 | 997 |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1147 boundClosureBuffer.clear(); | 1227 boundClosureBuffer.clear(); |
| 1148 emitStaticFunctions(mainBuffer); | 1228 emitStaticFunctions(mainBuffer); |
| 1149 emitStaticFunctionGetters(mainBuffer); | 1229 emitStaticFunctionGetters(mainBuffer); |
| 1150 // We need to finish the classes before we construct compile time | 1230 // We need to finish the classes before we construct compile time |
| 1151 // constants. | 1231 // constants. |
| 1152 emitFinishClassesInvocationIfNecessary(mainBuffer); | 1232 emitFinishClassesInvocationIfNecessary(mainBuffer); |
| 1153 emitCompileTimeConstants(mainBuffer); | 1233 emitCompileTimeConstants(mainBuffer); |
| 1154 // Static field initializations require the classes and compile-time | 1234 // Static field initializations require the classes and compile-time |
| 1155 // constants to be set up. | 1235 // constants to be set up. |
| 1156 emitStaticNonFinalFieldInitializations(mainBuffer); | 1236 emitStaticNonFinalFieldInitializations(mainBuffer); |
| 1237 emitLazilyInitializedStaticFields(mainBuffer); |
| 1157 | 1238 |
| 1158 isolateProperties = isolatePropertiesName; | 1239 isolateProperties = isolatePropertiesName; |
| 1159 // The following code should not use the short-hand for the | 1240 // The following code should not use the short-hand for the |
| 1160 // initialStatics. | 1241 // initialStatics. |
| 1161 mainBuffer.add('var ${namer.CURRENT_ISOLATE} = null;\n'); | 1242 mainBuffer.add('var ${namer.CURRENT_ISOLATE} = null;\n'); |
| 1162 mainBuffer.add(boundClosureBuffer); | 1243 mainBuffer.add(boundClosureBuffer); |
| 1163 emitFinishClassesInvocationIfNecessary(mainBuffer); | 1244 emitFinishClassesInvocationIfNecessary(mainBuffer); |
| 1164 // After this assignment we will produce invalid JavaScript code if we use | 1245 // After this assignment we will produce invalid JavaScript code if we use |
| 1165 // the classesCollector variable. | 1246 // the classesCollector variable. |
| 1166 classesCollector = 'classesCollector should not be used from now on'; | 1247 classesCollector = 'classesCollector should not be used from now on'; |
| 1167 | 1248 |
| 1168 emitFinishIsolateConstructorInvocation(mainBuffer); | 1249 emitFinishIsolateConstructorInvocation(mainBuffer); |
| 1169 mainBuffer.add( | 1250 mainBuffer.add( |
| 1170 'var ${namer.CURRENT_ISOLATE} = new ${namer.ISOLATE}();\n'); | 1251 'var ${namer.CURRENT_ISOLATE} = new ${namer.ISOLATE}();\n'); |
| 1171 | 1252 |
| 1172 nativeEmitter.assembleCode(mainBuffer); | 1253 nativeEmitter.assembleCode(mainBuffer); |
| 1173 emitMain(mainBuffer); | 1254 emitMain(mainBuffer); |
| 1174 mainBuffer.add('function init() {\n'); | 1255 mainBuffer.add('function init() {\n'); |
| 1175 mainBuffer.add('$isolateProperties = {};\n'); | 1256 mainBuffer.add('$isolateProperties = {};\n'); |
| 1176 addDefineClassAndFinishClassFunctionsIfNecessary(mainBuffer); | 1257 addDefineClassAndFinishClassFunctionsIfNecessary(mainBuffer); |
| 1258 addLazyInitializerFunctionIfNecessary(mainBuffer); |
| 1177 emitFinishIsolateConstructor(mainBuffer); | 1259 emitFinishIsolateConstructor(mainBuffer); |
| 1178 mainBuffer.add('}\n'); | 1260 mainBuffer.add('}\n'); |
| 1179 compiler.assembledCode = mainBuffer.toString(); | 1261 compiler.assembledCode = mainBuffer.toString(); |
| 1180 | 1262 |
| 1181 if (generateSourceMap) { | 1263 if (generateSourceMap) { |
| 1182 SourceFile compiledFile = new SourceFile(null, compiler.assembledCode); | 1264 SourceFile compiledFile = new SourceFile(null, compiler.assembledCode); |
| 1183 String sourceMap = sourceMapBuilder.build(compiledFile); | 1265 String sourceMap = sourceMapBuilder.build(compiledFile); |
| 1184 // TODO(podivilov): We should find a better way to return source maps to | 1266 // TODO(podivilov): We should find a better way to return source maps to |
| 1185 // compiler. Using diagnostic handler for that purpose is a temporary | 1267 // compiler. Using diagnostic handler for that purpose is a temporary |
| 1186 // hack. | 1268 // hack. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1199 sourceName = token.slowToString(); | 1281 sourceName = token.slowToString(); |
| 1200 } | 1282 } |
| 1201 int totalOffset = bufferOffset + offset; | 1283 int totalOffset = bufferOffset + offset; |
| 1202 sourceMapBuilder.addMapping( | 1284 sourceMapBuilder.addMapping( |
| 1203 sourceFile, token.charOffset, sourceName, totalOffset); | 1285 sourceFile, token.charOffset, sourceName, totalOffset); |
| 1204 }); | 1286 }); |
| 1205 } | 1287 } |
| 1206 } | 1288 } |
| 1207 | 1289 |
| 1208 typedef void DefineMemberFunction(String invocationName, CodeBuffer definition); | 1290 typedef void DefineMemberFunction(String invocationName, CodeBuffer definition); |
| OLD | NEW |