| // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| library dart2js.common.codegen; |
| |
| import '../compiler.dart' show |
| Compiler; |
| import '../constants/values.dart' show |
| ConstantValue; |
| import '../dart_types.dart' show |
| DartType, |
| InterfaceType; |
| import '../diagnostics/invariant.dart' show |
| invariant; |
| import '../elements/elements.dart' show |
| AstElement, |
| ClassElement, |
| Element, |
| FunctionElement, |
| LocalFunctionElement; |
| import '../enqueue.dart' show |
| CodegenEnqueuer, |
| WorldImpact; |
| import '../js_backend/js_backend.dart' show |
| JavaScriptBackend; |
| import '../resolution/tree_elements.dart' show |
| TreeElements; |
| import '../universe/selector.dart' show |
| Selector; |
| import '../universe/universe.dart' show |
| UniverseSelector; |
| import '../util/util.dart' show |
| Setlet; |
| import 'registry.dart' show |
| Registry; |
| import 'work.dart' show |
| ItemCompilationContext, |
| WorkItem; |
| |
| // TODO(johnniwinther): Split this class into interface and implementation. |
| // TODO(johnniwinther): Move this implementation to the JS backend. |
| class CodegenRegistry extends Registry { |
| final Compiler compiler; |
| final TreeElements treeElements; |
| |
| CodegenRegistry(this.compiler, this.treeElements); |
| |
| bool get isForResolution => false; |
| |
| Element get currentElement => treeElements.analyzedElement; |
| |
| String toString() => 'CodegenRegistry for $currentElement'; |
| |
| // TODO(johnniwinther): Remove this getter when [Registry] creates a |
| // dependency node. |
| Setlet<Element> get otherDependencies => treeElements.otherDependencies; |
| |
| CodegenEnqueuer get world => compiler.enqueuer.codegen; |
| JavaScriptBackend get backend => compiler.backend; |
| |
| void registerAssert(bool hasMessage) { |
| // Codegen does not register asserts. They have been lowered to calls. |
| assert(false); |
| } |
| |
| void registerDependency(Element element) { |
| treeElements.registerDependency(element); |
| } |
| |
| void registerInlining(Element inlinedElement, Element context) { |
| if (compiler.dumpInfo) { |
| compiler.dumpInfoTask.registerInlined(inlinedElement, context); |
| } |
| } |
| |
| void registerInstantiatedClass(ClassElement element) { |
| backend.registerInstantiatedType(element.rawType, world, this); |
| } |
| |
| void registerInstantiatedType(InterfaceType type) { |
| backend.registerInstantiatedType(type, world, this); |
| } |
| |
| void registerStaticUse(Element element) { |
| world.registerStaticUse(element); |
| } |
| |
| void registerDynamicInvocation(UniverseSelector selector) { |
| world.registerDynamicInvocation(selector); |
| compiler.dumpInfoTask.elementUsesSelector(currentElement, selector); |
| } |
| |
| void registerDynamicSetter(UniverseSelector selector) { |
| world.registerDynamicSetter(selector); |
| compiler.dumpInfoTask.elementUsesSelector(currentElement, selector); |
| } |
| |
| void registerDynamicGetter(UniverseSelector selector) { |
| world.registerDynamicGetter(selector); |
| compiler.dumpInfoTask.elementUsesSelector(currentElement, selector); |
| } |
| |
| void registerGetterForSuperMethod(Element element) { |
| world.registerGetterForSuperMethod(element); |
| } |
| |
| void registerFieldGetter(Element element) { |
| world.registerFieldGetter(element); |
| } |
| |
| void registerFieldSetter(Element element) { |
| world.registerFieldSetter(element); |
| } |
| |
| void registerIsCheck(DartType type) { |
| world.registerIsCheck(type); |
| backend.registerIsCheckForCodegen(type, world, this); |
| } |
| |
| void registerCompileTimeConstant(ConstantValue constant) { |
| backend.registerCompileTimeConstant(constant, this); |
| } |
| |
| void registerTypeVariableBoundsSubtypeCheck(DartType subtype, |
| DartType supertype) { |
| backend.registerTypeVariableBoundsSubtypeCheck(subtype, supertype); |
| } |
| |
| void registerInstantiatedClosure(LocalFunctionElement element) { |
| backend.registerInstantiatedClosure(element, this); |
| } |
| |
| void registerGetOfStaticFunction(FunctionElement element) { |
| world.registerGetOfStaticFunction(element); |
| } |
| |
| void registerSelectorUse(Selector selector) { |
| world.registerSelectorUse(new UniverseSelector(selector, null)); |
| } |
| |
| void registerConstSymbol(String name) { |
| backend.registerConstSymbol(name, this); |
| } |
| |
| void registerSpecializedGetInterceptor(Set<ClassElement> classes) { |
| backend.registerSpecializedGetInterceptor(classes); |
| } |
| |
| void registerUseInterceptor() { |
| backend.registerUseInterceptor(world); |
| } |
| |
| void registerTypeConstant(ClassElement element) { |
| backend.customElementsAnalysis.registerTypeConstant(element, world); |
| backend.lookupMapAnalysis.registerTypeConstant(element); |
| } |
| |
| void registerStaticInvocation(Element element) { |
| world.registerStaticUse(element); |
| } |
| |
| void registerSuperInvocation(Element element) { |
| world.registerStaticUse(element); |
| } |
| |
| void registerDirectInvocation(Element element) { |
| world.registerStaticUse(element); |
| } |
| |
| void registerInstantiation(InterfaceType type) { |
| backend.registerInstantiatedType(type, world, this); |
| } |
| |
| void registerAsyncMarker(FunctionElement element) { |
| backend.registerAsyncMarker(element, world, this); |
| } |
| |
| } |
| |
| /// [WorkItem] used exclusively by the [CodegenEnqueuer]. |
| class CodegenWorkItem extends WorkItem { |
| CodegenRegistry registry; |
| |
| factory CodegenWorkItem( |
| Compiler compiler, |
| AstElement element, |
| ItemCompilationContext compilationContext) { |
| // If this assertion fails, the resolution callbacks of the backend may be |
| // missing call of form registry.registerXXX. Alternatively, the code |
| // generation could spuriously be adding dependencies on things we know we |
| // don't need. |
| assert(invariant(element, |
| compiler.enqueuer.resolution.hasBeenResolved(element), |
| message: "$element has not been resolved.")); |
| assert(invariant(element, element.resolvedAst.elements != null, |
| message: 'Resolution tree is null for $element in codegen work item')); |
| return new CodegenWorkItem.internal(element, compilationContext); |
| } |
| |
| CodegenWorkItem.internal( |
| AstElement element, |
| ItemCompilationContext compilationContext) |
| : super(element, compilationContext); |
| |
| TreeElements get resolutionTree => element.resolvedAst.elements; |
| |
| WorldImpact run(Compiler compiler, CodegenEnqueuer world) { |
| if (world.isProcessed(element)) return const WorldImpact(); |
| |
| registry = new CodegenRegistry(compiler, resolutionTree); |
| return compiler.codegen(this, world); |
| } |
| } |