blob: cd17e561b68b418bc7a1889bf38d4ad1a23ae3db [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 '../common.dart';
import '../common/backend_api.dart' show Backend;
import '../constants/values.dart' show ConstantValue;
import '../elements/resolution_types.dart'
show ResolutionDartType, ResolutionInterfaceType;
import '../elements/elements.dart'
show
AstElement,
ClassElement,
Element,
FunctionElement,
LocalFunctionElement,
ResolvedAst;
import '../enqueue.dart' show Enqueuer;
import '../universe/use.dart' show DynamicUse, StaticUse, TypeUse;
import '../universe/world_impact.dart'
show WorldImpact, WorldImpactBuilderImpl, WorldImpactVisitor;
import '../util/util.dart' show Pair, Setlet;
import 'work.dart' show WorkItem;
class CodegenImpact extends WorldImpact {
const CodegenImpact();
Iterable<ConstantValue> get compileTimeConstants => const <ConstantValue>[];
Iterable<Pair<ResolutionDartType, ResolutionDartType>>
get typeVariableBoundsSubtypeChecks {
return const <Pair<ResolutionDartType, ResolutionDartType>>[];
}
Iterable<String> get constSymbols => const <String>[];
Iterable<Set<ClassElement>> get specializedGetInterceptors {
return const <Set<ClassElement>>[];
}
bool get usesInterceptor => false;
Iterable<ClassElement> get typeConstants => const <ClassElement>[];
Iterable<Element> get asyncMarkers => const <FunctionElement>[];
}
class _CodegenImpact extends WorldImpactBuilderImpl implements CodegenImpact {
Setlet<ConstantValue> _compileTimeConstants;
Setlet<Pair<ResolutionDartType, ResolutionDartType>>
_typeVariableBoundsSubtypeChecks;
Setlet<String> _constSymbols;
List<Set<ClassElement>> _specializedGetInterceptors;
bool _usesInterceptor = false;
Setlet<ClassElement> _typeConstants;
Setlet<FunctionElement> _asyncMarkers;
_CodegenImpact();
void apply(WorldImpactVisitor visitor) {
staticUses.forEach(visitor.visitStaticUse);
dynamicUses.forEach(visitor.visitDynamicUse);
typeUses.forEach(visitor.visitTypeUse);
}
void registerCompileTimeConstant(ConstantValue constant) {
if (_compileTimeConstants == null) {
_compileTimeConstants = new Setlet<ConstantValue>();
}
_compileTimeConstants.add(constant);
}
Iterable<ConstantValue> get compileTimeConstants {
return _compileTimeConstants != null
? _compileTimeConstants
: const <ConstantValue>[];
}
void registerTypeVariableBoundsSubtypeCheck(
ResolutionDartType subtype, ResolutionDartType supertype) {
if (_typeVariableBoundsSubtypeChecks == null) {
_typeVariableBoundsSubtypeChecks =
new Setlet<Pair<ResolutionDartType, ResolutionDartType>>();
}
_typeVariableBoundsSubtypeChecks.add(
new Pair<ResolutionDartType, ResolutionDartType>(subtype, supertype));
}
Iterable<Pair<ResolutionDartType, ResolutionDartType>>
get typeVariableBoundsSubtypeChecks {
return _typeVariableBoundsSubtypeChecks != null
? _typeVariableBoundsSubtypeChecks
: const <Pair<ResolutionDartType, ResolutionDartType>>[];
}
void registerConstSymbol(String name) {
if (_constSymbols == null) {
_constSymbols = new Setlet<String>();
}
_constSymbols.add(name);
}
Iterable<String> get constSymbols {
return _constSymbols != null ? _constSymbols : const <String>[];
}
void registerSpecializedGetInterceptor(Set<ClassElement> classes) {
if (_specializedGetInterceptors == null) {
_specializedGetInterceptors = <Set<ClassElement>>[];
}
_specializedGetInterceptors.add(classes);
}
Iterable<Set<ClassElement>> get specializedGetInterceptors {
return _specializedGetInterceptors != null
? _specializedGetInterceptors
: const <Set<ClassElement>>[];
}
void registerUseInterceptor() {
_usesInterceptor = true;
}
bool get usesInterceptor => _usesInterceptor;
void registerTypeConstant(ClassElement element) {
if (_typeConstants == null) {
_typeConstants = new Setlet<ClassElement>();
}
_typeConstants.add(element);
}
Iterable<ClassElement> get typeConstants {
return _typeConstants != null ? _typeConstants : const <ClassElement>[];
}
void registerAsyncMarker(FunctionElement element) {
if (_asyncMarkers == null) {
_asyncMarkers = new Setlet<FunctionElement>();
}
_asyncMarkers.add(element);
}
Iterable<Element> get asyncMarkers {
return _asyncMarkers != null ? _asyncMarkers : const <FunctionElement>[];
}
}
// TODO(johnniwinther): Split this class into interface and implementation.
// TODO(johnniwinther): Move this implementation to the JS backend.
class CodegenRegistry {
final Element currentElement;
final _CodegenImpact worldImpact;
CodegenRegistry(AstElement currentElement)
: this.currentElement = currentElement,
this.worldImpact = new _CodegenImpact();
bool get isForResolution => false;
String toString() => 'CodegenRegistry for $currentElement';
/// Add the uses in [impact] to the impact of this registry.
void addImpact(WorldImpact impact) {
worldImpact.addImpact(impact);
}
@deprecated
void registerInstantiatedClass(ClassElement element) {
registerInstantiation(element.rawType);
}
void registerStaticUse(StaticUse staticUse) {
worldImpact.registerStaticUse(staticUse);
}
void registerDynamicUse(DynamicUse dynamicUse) {
worldImpact.registerDynamicUse(dynamicUse);
}
void registerTypeUse(TypeUse typeUse) {
worldImpact.registerTypeUse(typeUse);
}
void registerCompileTimeConstant(ConstantValue constant) {
worldImpact.registerCompileTimeConstant(constant);
}
void registerTypeVariableBoundsSubtypeCheck(
ResolutionDartType subtype, ResolutionDartType supertype) {
worldImpact.registerTypeVariableBoundsSubtypeCheck(subtype, supertype);
}
void registerInstantiatedClosure(LocalFunctionElement element) {
worldImpact.registerStaticUse(new StaticUse.closure(element));
}
void registerConstSymbol(String name) {
worldImpact.registerConstSymbol(name);
}
void registerSpecializedGetInterceptor(Set<ClassElement> classes) {
worldImpact.registerSpecializedGetInterceptor(classes);
}
void registerUseInterceptor() {
worldImpact.registerUseInterceptor();
}
void registerTypeConstant(ClassElement element) {
worldImpact.registerTypeConstant(element);
}
void registerInstantiation(ResolutionInterfaceType type) {
registerTypeUse(new TypeUse.instantiation(type));
}
void registerAsyncMarker(FunctionElement element) {
worldImpact.registerAsyncMarker(element);
}
}
/// [WorkItem] used exclusively by the [CodegenEnqueuer].
class CodegenWorkItem extends WorkItem {
CodegenRegistry registry;
final ResolvedAst resolvedAst;
final Backend backend;
factory CodegenWorkItem(Backend backend, AstElement element) {
// 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, element.hasResolvedAst,
message: "$element has no resolved ast."));
ResolvedAst resolvedAst = element.resolvedAst;
return new CodegenWorkItem.internal(resolvedAst, backend);
}
CodegenWorkItem.internal(ResolvedAst resolvedAst, this.backend)
: this.resolvedAst = resolvedAst,
super(resolvedAst.element);
WorldImpact run() {
registry = new CodegenRegistry(element);
return backend.codegen(this);
}
String toString() => 'CodegenWorkItem(${resolvedAst.element})';
}