blob: e5554c9642a240c97dbab70ed9df1897a77c1395 [file] [log] [blame]
// 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.hasBeenProcessed(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);
}
}