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