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 part of js_backend; | 5 part of js_backend; |
6 | 6 |
7 /** | 7 /** |
8 * A function element that represents a closure call. The signature is copied | 8 * A function element that represents a closure call. The signature is copied |
9 * from the given element. | 9 * from the given element. |
10 */ | 10 */ |
(...skipping 2613 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2624 } | 2624 } |
2625 } | 2625 } |
2626 | 2626 |
2627 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer) { | 2627 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer) { |
2628 ConstantHandler handler = compiler.constantHandler; | 2628 ConstantHandler handler = compiler.constantHandler; |
2629 Iterable<VariableElement> staticNonFinalFields = | 2629 Iterable<VariableElement> staticNonFinalFields = |
2630 handler.getStaticNonFinalFieldsForEmission(); | 2630 handler.getStaticNonFinalFieldsForEmission(); |
2631 for (Element element in Elements.sortedByPosition(staticNonFinalFields)) { | 2631 for (Element element in Elements.sortedByPosition(staticNonFinalFields)) { |
2632 // [:interceptedNames:] is handled in [emitInterceptedNames]. | 2632 // [:interceptedNames:] is handled in [emitInterceptedNames]. |
2633 if (element == backend.interceptedNames) continue; | 2633 if (element == backend.interceptedNames) continue; |
| 2634 // `mapTypeToInterceptor` is handled in [emitMapTypeToInterceptor]. |
| 2635 if (element == backend.mapTypeToInterceptor) continue; |
2634 compiler.withCurrentElement(element, () { | 2636 compiler.withCurrentElement(element, () { |
2635 Constant initialValue = handler.getInitialValueFor(element); | 2637 Constant initialValue = handler.getInitialValueFor(element); |
2636 jsAst.Expression init = | 2638 jsAst.Expression init = |
2637 js('$isolateProperties.${namer.getName(element)} = #', | 2639 js('$isolateProperties.${namer.getName(element)} = #', |
2638 constantEmitter.referenceInInitializationContext(initialValue)); | 2640 constantEmitter.referenceInInitializationContext(initialValue)); |
2639 buffer.write(jsAst.prettyPrint(init, compiler)); | 2641 buffer.write(jsAst.prettyPrint(init, compiler)); |
2640 buffer.write('$N'); | 2642 buffer.write('$N'); |
2641 }); | 2643 }); |
2642 } | 2644 } |
2643 } | 2645 } |
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3049 } | 3051 } |
3050 | 3052 |
3051 bool hasArray = false; | 3053 bool hasArray = false; |
3052 bool hasBool = false; | 3054 bool hasBool = false; |
3053 bool hasDouble = false; | 3055 bool hasDouble = false; |
3054 bool hasInt = false; | 3056 bool hasInt = false; |
3055 bool hasNull = false; | 3057 bool hasNull = false; |
3056 bool hasNumber = false; | 3058 bool hasNumber = false; |
3057 bool hasString = false; | 3059 bool hasString = false; |
3058 bool hasNative = false; | 3060 bool hasNative = false; |
| 3061 bool anyNativeClasses = compiler.enqueuer.codegen.nativeEnqueuer |
| 3062 .hasInstantiatedNativeClasses(); |
| 3063 |
3059 for (ClassElement cls in classes) { | 3064 for (ClassElement cls in classes) { |
3060 if (cls == backend.jsArrayClass || | 3065 if (cls == backend.jsArrayClass || |
3061 cls == backend.jsMutableArrayClass || | 3066 cls == backend.jsMutableArrayClass || |
3062 cls == backend.jsFixedArrayClass || | 3067 cls == backend.jsFixedArrayClass || |
3063 cls == backend.jsExtendableArrayClass) hasArray = true; | 3068 cls == backend.jsExtendableArrayClass) hasArray = true; |
3064 else if (cls == backend.jsBoolClass) hasBool = true; | 3069 else if (cls == backend.jsBoolClass) hasBool = true; |
3065 else if (cls == backend.jsDoubleClass) hasDouble = true; | 3070 else if (cls == backend.jsDoubleClass) hasDouble = true; |
3066 else if (cls == backend.jsIntClass) hasInt = true; | 3071 else if (cls == backend.jsIntClass) hasInt = true; |
3067 else if (cls == backend.jsNullClass) hasNull = true; | 3072 else if (cls == backend.jsNullClass) hasNull = true; |
3068 else if (cls == backend.jsNumberClass) hasNumber = true; | 3073 else if (cls == backend.jsNumberClass) hasNumber = true; |
3069 else if (cls == backend.jsStringClass) hasString = true; | 3074 else if (cls == backend.jsStringClass) hasString = true; |
3070 else { | 3075 else { |
3071 // TODO(sra): The set of classes includes classes mixed-in to | 3076 // The set of classes includes classes mixed-in to interceptor classes |
3072 // interceptor classes. | 3077 // and user extensions of native classes. |
3073 // assert(cls == compiler.objectClass || cls.isNative()); | 3078 // |
3074 if (cls.isNative()) hasNative = true; | 3079 // The set of classes also includes the 'primitive' interceptor |
| 3080 // PlainJavaScriptObject even when it has not been resolved, since it is |
| 3081 // only resolved through the reference in getNativeInterceptor when |
| 3082 // getNativeInterceptor is marked as used. Guard against probing |
| 3083 // unresolved PlainJavaScriptObject by testing for anyNativeClasses. |
| 3084 |
| 3085 if (anyNativeClasses) { |
| 3086 if (Elements.isNativeOrExtendsNative(cls)) hasNative = true; |
| 3087 } |
3075 } | 3088 } |
3076 } | 3089 } |
3077 if (hasDouble) { | 3090 if (hasDouble) { |
3078 hasNumber = true; | 3091 hasNumber = true; |
3079 } | 3092 } |
3080 if (hasInt) hasNumber = true; | 3093 if (hasInt) hasNumber = true; |
3081 | 3094 |
3082 if (classes == backend.interceptedClasses) { | 3095 if (classes == backend.interceptedClasses) { |
3083 // I.e. this is the general interceptor. | 3096 // I.e. this is the general interceptor. |
3084 hasNative = compiler.enqueuer.codegen.nativeEnqueuer | 3097 hasNative = anyNativeClasses; |
3085 .hasInstantiatedNativeClasses(); | |
3086 } | 3098 } |
3087 | 3099 |
3088 jsAst.Block block = new jsAst.Block.empty(); | 3100 jsAst.Block block = new jsAst.Block.empty(); |
3089 | 3101 |
3090 if (hasNumber) { | 3102 if (hasNumber) { |
3091 jsAst.Statement whenNumber; | 3103 jsAst.Statement whenNumber; |
3092 | 3104 |
3093 /// Note: there are two number classes in play: Dart's [num], | 3105 /// Note: there are two number classes in play: Dart's [num], |
3094 /// and JavaScript's Number (typeof receiver == 'number'). This | 3106 /// and JavaScript's Number (typeof receiver == 'number'). This |
3095 /// is the fallback used when we have determined that receiver | 3107 /// is the fallback used when we have determined that receiver |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3238 rtiNeededClasses.removeAll(neededClasses); | 3250 rtiNeededClasses.removeAll(neededClasses); |
3239 // rtiNeededClasses now contains only the "empty shells". | 3251 // rtiNeededClasses now contains only the "empty shells". |
3240 neededClasses.addAll(rtiNeededClasses); | 3252 neededClasses.addAll(rtiNeededClasses); |
3241 | 3253 |
3242 // 5. Finally, sort the classes. | 3254 // 5. Finally, sort the classes. |
3243 List<ClassElement> sortedClasses = Elements.sortedByPosition(neededClasses); | 3255 List<ClassElement> sortedClasses = Elements.sortedByPosition(neededClasses); |
3244 | 3256 |
3245 for (ClassElement element in sortedClasses) { | 3257 for (ClassElement element in sortedClasses) { |
3246 if (rtiNeededClasses.contains(element)) { | 3258 if (rtiNeededClasses.contains(element)) { |
3247 regularClasses.add(element); | 3259 regularClasses.add(element); |
3248 } else if (element.isNative()) { | 3260 } else if (Elements.isNativeOrExtendsNative(element)) { |
3249 // For now, native classes cannot be deferred. | 3261 // For now, native classes and related classes cannot be deferred. |
3250 nativeClasses.add(element); | 3262 nativeClasses.add(element); |
| 3263 if (!element.isNative()) { |
| 3264 assert(invariant(element, !isDeferred(element))); |
| 3265 regularClasses.add(element); |
| 3266 } |
3251 } else if (isDeferred(element)) { | 3267 } else if (isDeferred(element)) { |
3252 deferredClasses.add(element); | 3268 deferredClasses.add(element); |
3253 } else { | 3269 } else { |
3254 regularClasses.add(element); | 3270 regularClasses.add(element); |
3255 } | 3271 } |
3256 } | 3272 } |
3257 } | 3273 } |
3258 | 3274 |
3259 Set<ClassElement> computeRtiNeededClasses() { | 3275 Set<ClassElement> computeRtiNeededClasses() { |
3260 void addClassWithSuperclasses(ClassElement cls) { | 3276 void addClassWithSuperclasses(ClassElement cls) { |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3504 }).toList(); | 3520 }).toList(); |
3505 jsAst.ArrayInitializer array = | 3521 jsAst.ArrayInitializer array = |
3506 new jsAst.ArrayInitializer(invocationNames.length, elements); | 3522 new jsAst.ArrayInitializer(invocationNames.length, elements); |
3507 | 3523 |
3508 jsAst.Expression assignment = js('$isolateProperties.$name = #', array); | 3524 jsAst.Expression assignment = js('$isolateProperties.$name = #', array); |
3509 | 3525 |
3510 buffer.write(jsAst.prettyPrint(assignment, compiler)); | 3526 buffer.write(jsAst.prettyPrint(assignment, compiler)); |
3511 buffer.write(N); | 3527 buffer.write(N); |
3512 } | 3528 } |
3513 | 3529 |
| 3530 /** |
| 3531 * Emit initializer for [mapTypeToInterceptor] data structure used by |
| 3532 * [findInterceptorForType]. See declaration of [mapTypeToInterceptor] in |
| 3533 * `interceptors.dart`. |
| 3534 */ |
| 3535 void emitMapTypeToInterceptor(CodeBuffer buffer) { |
| 3536 // TODO(sra): Perhaps inject a constant instead? |
| 3537 // TODO(sra): Filter by subclasses of native types. |
| 3538 List<jsAst.Expression> elements = <jsAst.Expression>[]; |
| 3539 ConstantHandler handler = compiler.constantHandler; |
| 3540 List<Constant> constants = handler.getConstantsForEmission(); |
| 3541 for (Constant constant in constants) { |
| 3542 if (constant is TypeConstant) { |
| 3543 TypeConstant typeConstant = constant; |
| 3544 Element element = typeConstant.representedType.element; |
| 3545 if (element is ClassElement) { |
| 3546 ClassElement classElement = element; |
| 3547 elements.add(backend.emitter.constantReference(constant)); |
| 3548 elements.add(js(namer.isolateAccess(classElement))); |
| 3549 } |
| 3550 } |
| 3551 } |
| 3552 |
| 3553 jsAst.ArrayInitializer array = new jsAst.ArrayInitializer.from(elements); |
| 3554 String name = backend.namer.getName(backend.mapTypeToInterceptor); |
| 3555 jsAst.Expression assignment = js('$isolateProperties.$name = #', array); |
| 3556 |
| 3557 buffer.write(jsAst.prettyPrint(assignment, compiler)); |
| 3558 buffer.write(N); |
| 3559 } |
| 3560 |
3514 void emitInitFunction(CodeBuffer buffer) { | 3561 void emitInitFunction(CodeBuffer buffer) { |
3515 jsAst.Fun fun = js.fun([], [ | 3562 jsAst.Fun fun = js.fun([], [ |
3516 js('$isolateProperties = {}'), | 3563 js('$isolateProperties = {}'), |
3517 ] | 3564 ] |
3518 ..addAll(buildDefineClassAndFinishClassFunctionsIfNecessary()) | 3565 ..addAll(buildDefineClassAndFinishClassFunctionsIfNecessary()) |
3519 ..addAll(buildLazyInitializerFunctionIfNecessary()) | 3566 ..addAll(buildLazyInitializerFunctionIfNecessary()) |
3520 ..addAll(buildFinishIsolateConstructor()) | 3567 ..addAll(buildFinishIsolateConstructor()) |
3521 ); | 3568 ); |
3522 jsAst.FunctionDeclaration decl = new jsAst.FunctionDeclaration( | 3569 jsAst.FunctionDeclaration decl = new jsAst.FunctionDeclaration( |
3523 new jsAst.VariableDeclaration('init'), fun); | 3570 new jsAst.VariableDeclaration('init'), fun); |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3836 emitGetInterceptorMethods(mainBuffer); | 3883 emitGetInterceptorMethods(mainBuffer); |
3837 // Constants in checked mode call into RTI code to set type information | 3884 // Constants in checked mode call into RTI code to set type information |
3838 // which may need getInterceptor methods, so we have to make sure that | 3885 // which may need getInterceptor methods, so we have to make sure that |
3839 // [emitGetInterceptorMethods] has been called. | 3886 // [emitGetInterceptorMethods] has been called. |
3840 emitCompileTimeConstants(mainBuffer); | 3887 emitCompileTimeConstants(mainBuffer); |
3841 // Static field initializations require the classes and compile-time | 3888 // Static field initializations require the classes and compile-time |
3842 // constants to be set up. | 3889 // constants to be set up. |
3843 emitStaticNonFinalFieldInitializations(mainBuffer); | 3890 emitStaticNonFinalFieldInitializations(mainBuffer); |
3844 emitOneShotInterceptors(mainBuffer); | 3891 emitOneShotInterceptors(mainBuffer); |
3845 emitInterceptedNames(mainBuffer); | 3892 emitInterceptedNames(mainBuffer); |
| 3893 emitMapTypeToInterceptor(mainBuffer); |
3846 emitLazilyInitializedStaticFields(mainBuffer); | 3894 emitLazilyInitializedStaticFields(mainBuffer); |
3847 | 3895 |
3848 mainBuffer.add(nativeBuffer); | 3896 mainBuffer.add(nativeBuffer); |
3849 | 3897 |
3850 emitMetadata(mainBuffer); | 3898 emitMetadata(mainBuffer); |
3851 | 3899 |
3852 isolateProperties = isolatePropertiesName; | 3900 isolateProperties = isolatePropertiesName; |
3853 // The following code should not use the short-hand for the | 3901 // The following code should not use the short-hand for the |
3854 // initialStatics. | 3902 // initialStatics. |
3855 mainBuffer.add('${namer.CURRENT_ISOLATE}$_=${_}null$N'); | 3903 mainBuffer.add('${namer.CURRENT_ISOLATE}$_=${_}null$N'); |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4093 | 4141 |
4094 const String HOOKS_API_USAGE = """ | 4142 const String HOOKS_API_USAGE = """ |
4095 // The code supports the following hooks: | 4143 // The code supports the following hooks: |
4096 // dartPrint(message) - if this function is defined it is called | 4144 // dartPrint(message) - if this function is defined it is called |
4097 // instead of the Dart [print] method. | 4145 // instead of the Dart [print] method. |
4098 // dartMainRunner(main) - if this function is defined, the Dart [main] | 4146 // dartMainRunner(main) - if this function is defined, the Dart [main] |
4099 // method will not be invoked directly. | 4147 // method will not be invoked directly. |
4100 // Instead, a closure that will invoke [main] is | 4148 // Instead, a closure that will invoke [main] is |
4101 // passed to [dartMainRunner]. | 4149 // passed to [dartMainRunner]. |
4102 """; | 4150 """; |
OLD | NEW |