| 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 2609 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2620 } | 2620 } |
| 2621 } | 2621 } |
| 2622 | 2622 |
| 2623 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer) { | 2623 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer) { |
| 2624 ConstantHandler handler = compiler.constantHandler; | 2624 ConstantHandler handler = compiler.constantHandler; |
| 2625 Iterable<VariableElement> staticNonFinalFields = | 2625 Iterable<VariableElement> staticNonFinalFields = |
| 2626 handler.getStaticNonFinalFieldsForEmission(); | 2626 handler.getStaticNonFinalFieldsForEmission(); |
| 2627 for (Element element in Elements.sortedByPosition(staticNonFinalFields)) { | 2627 for (Element element in Elements.sortedByPosition(staticNonFinalFields)) { |
| 2628 // [:interceptedNames:] is handled in [emitInterceptedNames]. | 2628 // [:interceptedNames:] is handled in [emitInterceptedNames]. |
| 2629 if (element == backend.interceptedNames) continue; | 2629 if (element == backend.interceptedNames) continue; |
| 2630 // `mapTypeToInterceptor` is handled in [emitMapTypeToInterceptor]. |
| 2631 if (element == backend.mapTypeToInterceptor) continue; |
| 2630 compiler.withCurrentElement(element, () { | 2632 compiler.withCurrentElement(element, () { |
| 2631 Constant initialValue = handler.getInitialValueFor(element); | 2633 Constant initialValue = handler.getInitialValueFor(element); |
| 2632 jsAst.Expression init = | 2634 jsAst.Expression init = |
| 2633 js('$isolateProperties.${namer.getName(element)} = #', | 2635 js('$isolateProperties.${namer.getName(element)} = #', |
| 2634 constantEmitter.referenceInInitializationContext(initialValue)); | 2636 constantEmitter.referenceInInitializationContext(initialValue)); |
| 2635 buffer.write(jsAst.prettyPrint(init, compiler)); | 2637 buffer.write(jsAst.prettyPrint(init, compiler)); |
| 2636 buffer.write('$N'); | 2638 buffer.write('$N'); |
| 2637 }); | 2639 }); |
| 2638 } | 2640 } |
| 2639 } | 2641 } |
| (...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3033 cls == backend.jsFixedArrayClass || | 3035 cls == backend.jsFixedArrayClass || |
| 3034 cls == backend.jsExtendableArrayClass) hasArray = true; | 3036 cls == backend.jsExtendableArrayClass) hasArray = true; |
| 3035 else if (cls == backend.jsBoolClass) hasBool = true; | 3037 else if (cls == backend.jsBoolClass) hasBool = true; |
| 3036 else if (cls == backend.jsDoubleClass) hasDouble = true; | 3038 else if (cls == backend.jsDoubleClass) hasDouble = true; |
| 3037 else if (cls == backend.jsIntClass) hasInt = true; | 3039 else if (cls == backend.jsIntClass) hasInt = true; |
| 3038 else if (cls == backend.jsNullClass) hasNull = true; | 3040 else if (cls == backend.jsNullClass) hasNull = true; |
| 3039 else if (cls == backend.jsNumberClass) hasNumber = true; | 3041 else if (cls == backend.jsNumberClass) hasNumber = true; |
| 3040 else if (cls == backend.jsStringClass) hasString = true; | 3042 else if (cls == backend.jsStringClass) hasString = true; |
| 3041 else { | 3043 else { |
| 3042 // TODO(sra): The set of classes includes classes mixed-in to | 3044 // TODO(sra): The set of classes includes classes mixed-in to |
| 3043 // interceptor classes. | 3045 // interceptor classes and user extensions of native classes. |
| 3044 // assert(cls == compiler.objectClass || cls.isNative()); | 3046 if (Elements.isNativeOrExtendsNative(cls)) hasNative = true; |
| 3045 if (cls.isNative()) hasNative = true; | |
| 3046 } | 3047 } |
| 3047 } | 3048 } |
| 3048 if (hasDouble) { | 3049 if (hasDouble) { |
| 3049 hasNumber = true; | 3050 hasNumber = true; |
| 3050 } | 3051 } |
| 3051 if (hasInt) hasNumber = true; | 3052 if (hasInt) hasNumber = true; |
| 3052 | 3053 |
| 3053 if (classes == backend.interceptedClasses) { | 3054 if (classes == backend.interceptedClasses) { |
| 3054 // I.e. this is the general interceptor. | 3055 // I.e. this is the general interceptor. |
| 3055 hasNative = compiler.enqueuer.codegen.nativeEnqueuer | 3056 hasNative = compiler.enqueuer.codegen.nativeEnqueuer |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3209 rtiNeededClasses.removeAll(neededClasses); | 3210 rtiNeededClasses.removeAll(neededClasses); |
| 3210 // rtiNeededClasses now contains only the "empty shells". | 3211 // rtiNeededClasses now contains only the "empty shells". |
| 3211 neededClasses.addAll(rtiNeededClasses); | 3212 neededClasses.addAll(rtiNeededClasses); |
| 3212 | 3213 |
| 3213 // 5. Finally, sort the classes. | 3214 // 5. Finally, sort the classes. |
| 3214 List<ClassElement> sortedClasses = Elements.sortedByPosition(neededClasses); | 3215 List<ClassElement> sortedClasses = Elements.sortedByPosition(neededClasses); |
| 3215 | 3216 |
| 3216 for (ClassElement element in sortedClasses) { | 3217 for (ClassElement element in sortedClasses) { |
| 3217 if (rtiNeededClasses.contains(element)) { | 3218 if (rtiNeededClasses.contains(element)) { |
| 3218 regularClasses.add(element); | 3219 regularClasses.add(element); |
| 3219 } else if (element.isNative()) { | 3220 } else if (Elements.isNativeOrExtendsNative(element)) { |
| 3220 // For now, native classes cannot be deferred. | 3221 // For now, native classes and related classes cannot be deferred. |
| 3221 nativeClasses.add(element); | 3222 nativeClasses.add(element); |
| 3223 if (!element.isNative()) { |
| 3224 assert(!isDeferred(element)); |
| 3225 regularClasses.add(element); |
| 3226 } |
| 3222 } else if (isDeferred(element)) { | 3227 } else if (isDeferred(element)) { |
| 3223 deferredClasses.add(element); | 3228 deferredClasses.add(element); |
| 3224 } else { | 3229 } else { |
| 3225 regularClasses.add(element); | 3230 regularClasses.add(element); |
| 3226 } | 3231 } |
| 3227 } | 3232 } |
| 3228 } | 3233 } |
| 3229 | 3234 |
| 3230 Set<ClassElement> computeRtiNeededClasses() { | 3235 Set<ClassElement> computeRtiNeededClasses() { |
| 3231 void addClassWithSuperclasses(ClassElement cls) { | 3236 void addClassWithSuperclasses(ClassElement cls) { |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3475 }).toList(); | 3480 }).toList(); |
| 3476 jsAst.ArrayInitializer array = | 3481 jsAst.ArrayInitializer array = |
| 3477 new jsAst.ArrayInitializer(invocationNames.length, elements); | 3482 new jsAst.ArrayInitializer(invocationNames.length, elements); |
| 3478 | 3483 |
| 3479 jsAst.Expression assignment = js('$isolateProperties.$name = #', array); | 3484 jsAst.Expression assignment = js('$isolateProperties.$name = #', array); |
| 3480 | 3485 |
| 3481 buffer.write(jsAst.prettyPrint(assignment, compiler)); | 3486 buffer.write(jsAst.prettyPrint(assignment, compiler)); |
| 3482 buffer.write(N); | 3487 buffer.write(N); |
| 3483 } | 3488 } |
| 3484 | 3489 |
| 3490 /** |
| 3491 * Emit initializer for [mapTypeToInterceptor] data structure used by |
| 3492 * [findInterceptorForType]. |
| 3493 */ |
| 3494 void emitMapTypeToInterceptor(CodeBuffer buffer) { |
| 3495 // TODO(sra): Perhaps inject a constant instead? |
| 3496 // TODO(sra): Filter by subclasses of native types. |
| 3497 List<jsAst.Expression> elements = <jsAst.Expression>[]; |
| 3498 ConstantHandler handler = compiler.constantHandler; |
| 3499 List<Constant> constants = handler.getConstantsForEmission(); |
| 3500 for (Constant constant in constants) { |
| 3501 if (constant is TypeConstant) { |
| 3502 TypeConstant typeConstant = constant; |
| 3503 Element element = typeConstant.representedType.element; |
| 3504 if (element is ClassElement) { |
| 3505 ClassElement classElement = element; |
| 3506 elements.add(backend.emitter.constantReference(constant)); |
| 3507 elements.add(js(namer.isolateAccess(classElement))); |
| 3508 } |
| 3509 } |
| 3510 } |
| 3511 |
| 3512 jsAst.ArrayInitializer array = new jsAst.ArrayInitializer.from(elements); |
| 3513 String name = backend.namer.getName(backend.mapTypeToInterceptor); |
| 3514 jsAst.Expression assignment = js('$isolateProperties.$name = #', array); |
| 3515 |
| 3516 buffer.write(jsAst.prettyPrint(assignment, compiler)); |
| 3517 buffer.write(N); |
| 3518 } |
| 3519 |
| 3485 void emitInitFunction(CodeBuffer buffer) { | 3520 void emitInitFunction(CodeBuffer buffer) { |
| 3486 jsAst.Fun fun = js.fun([], [ | 3521 jsAst.Fun fun = js.fun([], [ |
| 3487 js('$isolateProperties = {}'), | 3522 js('$isolateProperties = {}'), |
| 3488 ] | 3523 ] |
| 3489 ..addAll(buildDefineClassAndFinishClassFunctionsIfNecessary()) | 3524 ..addAll(buildDefineClassAndFinishClassFunctionsIfNecessary()) |
| 3490 ..addAll(buildLazyInitializerFunctionIfNecessary()) | 3525 ..addAll(buildLazyInitializerFunctionIfNecessary()) |
| 3491 ..addAll(buildFinishIsolateConstructor()) | 3526 ..addAll(buildFinishIsolateConstructor()) |
| 3492 ); | 3527 ); |
| 3493 jsAst.FunctionDeclaration decl = new jsAst.FunctionDeclaration( | 3528 jsAst.FunctionDeclaration decl = new jsAst.FunctionDeclaration( |
| 3494 new jsAst.VariableDeclaration('init'), fun); | 3529 new jsAst.VariableDeclaration('init'), fun); |
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3807 emitGetInterceptorMethods(mainBuffer); | 3842 emitGetInterceptorMethods(mainBuffer); |
| 3808 // Constants in checked mode call into RTI code to set type information | 3843 // Constants in checked mode call into RTI code to set type information |
| 3809 // which may need getInterceptor methods, so we have to make sure that | 3844 // which may need getInterceptor methods, so we have to make sure that |
| 3810 // [emitGetInterceptorMethods] has been called. | 3845 // [emitGetInterceptorMethods] has been called. |
| 3811 emitCompileTimeConstants(mainBuffer); | 3846 emitCompileTimeConstants(mainBuffer); |
| 3812 // Static field initializations require the classes and compile-time | 3847 // Static field initializations require the classes and compile-time |
| 3813 // constants to be set up. | 3848 // constants to be set up. |
| 3814 emitStaticNonFinalFieldInitializations(mainBuffer); | 3849 emitStaticNonFinalFieldInitializations(mainBuffer); |
| 3815 emitOneShotInterceptors(mainBuffer); | 3850 emitOneShotInterceptors(mainBuffer); |
| 3816 emitInterceptedNames(mainBuffer); | 3851 emitInterceptedNames(mainBuffer); |
| 3852 emitMapTypeToInterceptor(mainBuffer); |
| 3817 emitLazilyInitializedStaticFields(mainBuffer); | 3853 emitLazilyInitializedStaticFields(mainBuffer); |
| 3818 | 3854 |
| 3819 mainBuffer.add(nativeBuffer); | 3855 mainBuffer.add(nativeBuffer); |
| 3820 | 3856 |
| 3821 emitMetadata(mainBuffer); | 3857 emitMetadata(mainBuffer); |
| 3822 | 3858 |
| 3823 isolateProperties = isolatePropertiesName; | 3859 isolateProperties = isolatePropertiesName; |
| 3824 // The following code should not use the short-hand for the | 3860 // The following code should not use the short-hand for the |
| 3825 // initialStatics. | 3861 // initialStatics. |
| 3826 mainBuffer.add('${namer.CURRENT_ISOLATE}$_=${_}null$N'); | 3862 mainBuffer.add('${namer.CURRENT_ISOLATE}$_=${_}null$N'); |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4064 | 4100 |
| 4065 const String HOOKS_API_USAGE = """ | 4101 const String HOOKS_API_USAGE = """ |
| 4066 // The code supports the following hooks: | 4102 // The code supports the following hooks: |
| 4067 // dartPrint(message) - if this function is defined it is called | 4103 // dartPrint(message) - if this function is defined it is called |
| 4068 // instead of the Dart [print] method. | 4104 // instead of the Dart [print] method. |
| 4069 // dartMainRunner(main) - if this function is defined, the Dart [main] | 4105 // dartMainRunner(main) - if this function is defined, the Dart [main] |
| 4070 // method will not be invoked directly. | 4106 // method will not be invoked directly. |
| 4071 // Instead, a closure that will invoke [main] is | 4107 // Instead, a closure that will invoke [main] is |
| 4072 // passed to [dartMainRunner]. | 4108 // passed to [dartMainRunner]. |
| 4073 """; | 4109 """; |
| OLD | NEW |