Chromium Code Reviews| Index: lib/compiler/implementation/native_handler.dart |
| diff --git a/lib/compiler/implementation/native_handler.dart b/lib/compiler/implementation/native_handler.dart |
| index 0ba42aea08f475ea08ac938302867d44a04d2ed6..b9f5ae22ae2280a0aa128c098b39de1a11072313 100644 |
| --- a/lib/compiler/implementation/native_handler.dart |
| +++ b/lib/compiler/implementation/native_handler.dart |
| @@ -13,66 +13,162 @@ import 'ssa/ssa.dart'; |
| import 'tree/tree.dart'; |
| import 'util/util.dart'; |
| -void processNativeClasses(Enqueuer world, |
| - CodeEmitterTask emitter, |
| - Collection<LibraryElement> libraries) { |
| - for (LibraryElement library in libraries) { |
| - processNativeClassesInLibrary(world, emitter, library); |
| - } |
| + |
| +// This could be an abstract class but we use it as a stub for the dart_backend. |
| +class NativeEnqueuer { |
| + void processNativeClasses(Collection<LibraryElement> libraries) {} |
| + |
| + |
| + void registerElement(Element element) {} |
| + |
| + // Method is a member of a native class. |
| + void registerMethod(Element method) {} |
| + |
| + // Field is a member of a native class. |
| + void registerFieldLoad(FieldElement field) {} |
| + void registerFieldStore(FieldElement field) {} |
| + |
| + // JS-form code can be an instantiation point for types. |
| + // |
| + // JS('_DOMWindowImpl', 'window'); |
| + // |
| + // TODO(sra): Who calls this? |
| + // TODO(sra): How do we parse the type? |
| + void registerJS(code) {} |
| } |
| -void addSubtypes(ClassElement cls, |
| - NativeEmitter emitter) { |
| - for (DartType type in cls.allSupertypes) { |
| - List<Element> subtypes = emitter.subtypes.putIfAbsent( |
| - type.element, |
| - () => <ClassElement>[]); |
| - subtypes.add(cls); |
| + |
| +class NativeEnqueuerBase implements NativeEnqueuer { |
| + |
| + final Set<ClassElement> nativeClasses = new Set<ClassElement>(); |
| + final Set<ClassElement> registeredClasses = new Set<ClassElement>(); |
| + final Set<ClassElement> unusedClasses = new Set<ClassElement>(); |
| + |
| + final Enqueuer world; |
| + final Compiler compiler; |
| + |
| + // constructed by backend. |
| + NativeEnqueuerBase(this.world, this.compiler); |
| + |
| + void processNativeClasses(Collection<LibraryElement> libraries) { |
| + libraries.forEach(processNativeClassesInLibrary); |
| + |
| + // TODO(sra): Register classes that liveness analysis misses, e.g. DOM |
| + // exception classes. Could to it at the first class. |
| + |
| + //nativeClasses.forEach(registerClass); |
|
sra1
2012/10/27 01:00:48
Uncomment to go back to registering everything.
|
| } |
| - List<Element> directSubtypes = emitter.directSubtypes.putIfAbsent( |
| - cls.superclass, |
| - () => <ClassElement>[]); |
| - directSubtypes.add(cls); |
| -} |
| + void processNativeClassesInLibrary(LibraryElement library) { |
| + // Use implementation to ensure the inclusion of injected members. |
| + library.implementation.forEachLocalMember((Element element) { |
| + if (element.kind == ElementKind.CLASS) { |
| + ClassElement classElement = element; |
| + if (classElement.isNative()) { |
| + nativeClasses.add(classElement); |
| + unusedClasses.add(classElement); |
| + } |
| + } |
| + }); |
| + } |
| + |
| + /// Action to process |
| + registerClass(ClassElement classElement) { |
| + assert(!registerClass.contains(classElement)); |
| + if (registeredClasses.isEmpty) { |
| + onFirstNativeClass(); |
| + } |
| + registeredClasses.add(classElement); |
| + unusedClasses.remove(classElement); |
| + world.registerInstantiatedClass(classElement); |
| + // Also parse the node to know all its methods because |
| + // otherwise it will only be parsed if there is a call to |
| + // one of its constructors. |
| + classElement.parseNode(compiler); |
| + // Resolve to setup the inheritance. |
| + classElement.ensureResolved(compiler); |
| + } |
| + |
| + registerElement(Element element) { |
| + print('registerElement $element'); |
| + if (element.isFunction) return registerMethod(element); |
| + } |
| -void processNativeClassesInLibrary(Enqueuer world, |
| - CodeEmitterTask emitter, |
| - LibraryElement library) { |
| - bool hasNativeClass = false; |
| - final compiler = emitter.compiler; |
| - // Use implementation to ensure the inclusion of injected members. |
| - library.implementation.forEachLocalMember((Element element) { |
| - if (element.kind == ElementKind.CLASS) { |
| - ClassElement classElement = element; |
| - if (classElement.isNative()) { |
| - hasNativeClass = true; |
| - world.registerInstantiatedClass(classElement); |
| - // Also parse the node to know all its methods because |
| - // otherwise it will only be parsed if there is a call to |
| - // one of its constructor. |
| - classElement.parseNode(compiler); |
| - // Resolve to setup the inheritance. |
| - classElement.ensureResolved(compiler); |
| - // Add the information that this class is a subtype of |
| - // its supertypes. The code emitter and the ssa builder use that |
| - // information. |
| - addSubtypes(classElement, emitter.nativeEmitter); |
| + registerMethod(Element method) { |
| + captureType(method.computeType(compiler)); |
| + } |
| + |
| + registerFieldLoad(FieldElement field) { |
| + captureType(field.computeType(compiler)); |
| + } |
| + |
| + registerFieldStore(FieldElement field) { |
| + escapeType(field.computeType(compiler)); |
| + } |
| + |
| + escapeType(DartType type) { |
| + } |
| + |
| + captureType(DartType type) { |
| + if (type is FunctionType) { |
| + captureType(type.returnType); |
| + } else { |
| + if (type.element.kind == Element.CLASS) { |
| + ClassElement classElement = type.element; |
| + // All native classes that are, implement, or extend classElement. |
| + if (classElement.isNative && unusedClasses.contains(classElement)) { |
| + registerClass(classElement); |
| + } |
| } |
| } |
| - }); |
| - if (hasNativeClass) { |
| - world.registerStaticUse(compiler.findHelper( |
| - const SourceString('dynamicFunction'))); |
| - world.registerStaticUse(compiler.findHelper( |
| - const SourceString('dynamicSetMetadata'))); |
| - world.registerStaticUse(compiler.findHelper( |
| - const SourceString('defineProperty'))); |
| - world.registerStaticUse(compiler.findHelper( |
| - const SourceString('toStringForNativeObject'))); |
| - world.registerStaticUse(compiler.findHelper( |
| - const SourceString('hashCodeForNativeObject'))); |
| } |
| + |
| + onFirstNativeClass() { |
| + staticUse(name) => world.registerStaticUse(compiler.findHelper(name)); |
| + |
| + staticUse(const SourceString('dynamicFunction')); |
| + staticUse(const SourceString('dynamicSetMetadata')); |
| + staticUse(const SourceString('defineProperty')); |
| + staticUse(const SourceString('toStringForNativeObject')); |
| + staticUse(const SourceString('hashCodeForNativeObject')); |
| + } |
| +} |
| + |
| +class NativeResolutionEnqueuer extends NativeEnqueuerBase { |
| + |
| + NativeResolutionEnqueuer(Enqueuer world, Compiler compiler) |
| + : super(world, compiler); |
| +} |
| + |
| +class NativeCodegenEnqueuer extends NativeEnqueuerBase { |
| + |
| + final CodeEmitterTask emitter; |
| + |
| + NativeCodegenEnqueuer(Enqueuer world, Compiler compiler, this.emitter) |
| + : super(world, compiler); |
| + |
| + registerClass(ClassElement classElement) { |
| + super.registerClass(classElement); |
| + // Add the information that this class is a subtype of |
| + // its supertypes. The code emitter and the ssa builder use that |
|
sra1
2012/10/27 01:00:48
Nicolas: How and when does the ssa builder use thi
ngeoffray
2012/10/29 14:10:47
That's in handleSsaNative in this file: method isO
|
| + // information. |
| + addSubtypes(classElement, emitter.nativeEmitter); |
| + } |
| + |
| + void addSubtypes(ClassElement cls, NativeEmitter emitter) { |
| + for (DartType type in cls.allSupertypes) { |
| + List<Element> subtypes = emitter.subtypes.putIfAbsent( |
| + type.element, |
| + () => <ClassElement>[]); |
| + subtypes.add(cls); |
| + } |
| + |
| + List<Element> directSubtypes = emitter.directSubtypes.putIfAbsent( |
| + cls.superclass, |
| + () => <ClassElement>[]); |
| + directSubtypes.add(cls); |
| + } |
| + |
| } |
| void maybeEnableNative(Compiler compiler, |