Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(51)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart

Issue 15026006: Support for extending native classes (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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 """;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698