blob: 5b3f57243b6465ee6a16ebeeed4199ad884c2bc2 [file] [log] [blame]
// Copyright (c) 2014, 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 code_generator_dependencies;
import '../backend_helpers.dart' show
BackendHelpers;
import '../js_backend.dart';
import '../../common.dart';
import '../../common/codegen.dart' show
CodegenRegistry;
import '../../compiler.dart' show
Compiler;
import '../../constants/values.dart';
import '../../dart_types.dart' show
DartType,
TypeVariableType,
InterfaceType;
import '../../enqueue.dart' show
CodegenEnqueuer;
import '../../elements/elements.dart';
import '../../js_emitter/js_emitter.dart';
import '../../js/js.dart' as js;
import '../../native/native.dart' show NativeBehavior;
import '../../universe/selector.dart' show
Selector;
import '../../world.dart' show
ClassWorld;
import '../../types/types.dart';
/// Encapsulates the dependencies of the function-compiler to the compiler,
/// backend and emitter.
// TODO(sigurdm): Should be refactored when we have a better feeling for the
// interface.
class Glue {
final Compiler _compiler;
CodegenEnqueuer get _enqueuer => _compiler.enqueuer.codegen;
FunctionElement get getInterceptorMethod => _helpers.getInterceptorMethod;
JavaScriptBackend get _backend => _compiler.backend;
BackendHelpers get _helpers => _backend.helpers;
CodeEmitterTask get _emitter => _backend.emitter;
Namer get _namer => _backend.namer;
Glue(this._compiler);
ClassWorld get classWorld => _compiler.world;
DiagnosticReporter get reporter => _compiler.reporter;
js.Expression constantReference(ConstantValue value) {
return _emitter.constantReference(value);
}
reportInternalError(String message) {
reporter.internalError(CURRENT_ELEMENT_SPANNABLE, message);
}
bool isUsedAsMixin(ClassElement classElement) {
return classWorld.isUsedAsMixin(classElement);
}
js.Expression staticFunctionAccess(FunctionElement element) {
return _backend.emitter.staticFunctionAccess(element);
}
js.Expression isolateStaticClosureAccess(FunctionElement element) {
return _backend.emitter.isolateStaticClosureAccess(element);
}
js.Expression staticFieldAccess(FieldElement element) {
return _backend.emitter.staticFieldAccess(element);
}
js.Expression isolateLazyInitializerAccess(FieldElement element) {
return _backend.emitter.isolateLazyInitializerAccess(element);
}
bool isLazilyInitialized(FieldElement element) {
return _backend.constants.lazyStatics.contains(element);
}
String safeVariableName(String name) {
return _namer.safeVariableName(name);
}
ClassElement get listClass => _compiler.coreClasses.listClass;
ConstructorElement get mapLiteralConstructor {
return _helpers.mapLiteralConstructor;
}
ConstructorElement get mapLiteralConstructorEmpty {
return _helpers.mapLiteralConstructorEmpty;
}
FunctionElement get identicalFunction => _compiler.identicalFunction;
js.Name invocationName(Selector selector) {
return _namer.invocationName(selector);
}
FunctionElement get createInvocationMirrorMethod {
return _helpers.createInvocationMirror;
}
bool isInterceptedSelector(Selector selector) {
return _backend.isInterceptedSelector(selector);
}
bool isInterceptedMethod(Element element) {
return _backend.isInterceptedMethod(element);
}
bool isInterceptorClass(ClassElement element) {
return element.isSubclassOf(_helpers.jsInterceptorClass);
}
Set<ClassElement> getInterceptedClassesOn(Selector selector) {
return _backend.getInterceptedClassesOn(selector.name);
}
Set<ClassElement> get interceptedClasses {
return _backend.interceptedClasses;
}
void registerSpecializedGetInterceptor(Set<ClassElement> classes) {
_backend.registerSpecializedGetInterceptor(classes);
}
js.Expression constructorAccess(ClassElement element) {
return _backend.emitter.constructorAccess(element);
}
js.Name instanceFieldPropertyName(Element field) {
return _namer.instanceFieldPropertyName(field);
}
js.Name instanceMethodName(FunctionElement element) {
return _namer.instanceMethodName(element);
}
js.Expression prototypeAccess(ClassElement e,
{bool hasBeenInstantiated: false}) {
return _emitter.prototypeAccess(e,
hasBeenInstantiated: hasBeenInstantiated);
}
js.Name getInterceptorName(Set<ClassElement> interceptedClasses) {
return _backend.namer.nameForGetInterceptor(interceptedClasses);
}
js.Expression getInterceptorLibrary() {
return new js.VariableUse(
_backend.namer.globalObjectFor(_helpers.interceptorsLibrary));
}
FunctionElement getWrapExceptionHelper() {
return _helpers.wrapExceptionHelper;
}
FunctionElement getExceptionUnwrapper() {
return _helpers.exceptionUnwrapper;
}
FunctionElement getTraceFromException() {
return _helpers.traceFromException;
}
FunctionElement getCreateRuntimeType() {
return _helpers.createRuntimeType;
}
FunctionElement getRuntimeTypeToString() {
return _helpers.runtimeTypeToString;
}
FunctionElement getRuntimeTypeArgument() {
return _helpers.getRuntimeTypeArgument;
}
FunctionElement getTypeArgumentByIndex() {
return _helpers.getTypeArgumentByIndex;
}
FunctionElement getAddRuntimeTypeInformation() {
return _helpers.setRuntimeTypeInfo;
}
/// checkSubtype(value, $isT, typeArgs, $asT)
FunctionElement getCheckSubtype() {
return _helpers.checkSubtype;
}
/// subtypeCast(value, $isT, typeArgs, $asT)
FunctionElement getSubtypeCast() {
return _helpers.subtypeCast;
}
/// checkSubtypeOfRuntime(value, runtimeType)
FunctionElement getCheckSubtypeOfRuntimeType() {
return _helpers.checkSubtypeOfRuntimeType;
}
/// subtypeOfRuntimeTypeCast(value, runtimeType)
FunctionElement getSubtypeOfRuntimeTypeCast() {
return _helpers.subtypeOfRuntimeTypeCast;
}
js.Expression getRuntimeTypeName(ClassElement cls) {
return js.quoteName(_namer.runtimeTypeName(cls));
}
int getTypeVariableIndex(TypeVariableType variable) {
return variable.element.index;
}
bool needsSubstitutionForTypeVariableAccess(ClassElement cls) {
ClassWorld classWorld = _compiler.world;
if (classWorld.isUsedAsMixin(cls)) return true;
return _compiler.world.anyStrictSubclassOf(cls, (ClassElement subclass) {
return !_backend.rti.isTrivialSubstitution(subclass, cls);
});
}
js.Expression generateTypeRepresentation(DartType dartType,
List<js.Expression> arguments,
CodegenRegistry registry) {
int variableIndex = 0;
js.Expression representation = _backend.rtiEncoder.getTypeRepresentation(
dartType,
(_) => arguments[variableIndex++]);
assert(variableIndex == arguments.length);
// Representation contains JavaScript Arrays.
registry.registerInstantiatedClass(_helpers.jsArrayClass);
return representation;
}
js.Name getTypeTestTag(DartType type) {
return _backend.namer.operatorIsType(type);
}
js.Name getTypeSubstitutionTag(ClassElement element) {
return _backend.namer.substitutionName(element);
}
bool operatorEqHandlesNullArgument(FunctionElement element) {
return _backend.operatorEqHandlesNullArgument(element);
}
bool hasStrictSubtype(ClassElement element) {
return _compiler.world.hasAnyStrictSubtype(element);
}
ClassElement get jsFixedArrayClass => _helpers.jsFixedArrayClass;
ClassElement get jsExtendableArrayClass => _helpers.jsExtendableArrayClass;
ClassElement get jsUnmodifiableArrayClass =>
_helpers.jsUnmodifiableArrayClass;
ClassElement get jsMutableArrayClass => _helpers.jsMutableArrayClass;
bool isStringClass(ClassElement classElement) =>
classElement == _helpers.jsStringClass ||
classElement == _compiler.coreClasses.stringClass;
bool isBoolClass(ClassElement classElement) =>
classElement == _helpers.jsBoolClass ||
classElement == _compiler.coreClasses.boolClass;
// TODO(sra,johnniwinther): Should this be part of CodegenRegistry?
void registerNativeBehavior(NativeBehavior nativeBehavior, node) {
if (nativeBehavior == null) return;
_enqueuer.nativeEnqueuer.registerNativeBehavior(nativeBehavior, node);
}
ConstantValue getDefaultParameterValue(ParameterElement elem) {
return _backend.constants.getConstantValueForVariable(elem);
}
TypeMask extendMaskIfReachesAll(Selector selector, TypeMask mask) {
return _compiler.world.extendMaskIfReachesAll(selector, mask);
}
FunctionElement get closureFromTearOff => _backend.helpers.closureFromTearOff;
js.Name registerOneShotInterceptor(Selector selector) {
return _backend.registerOneShotInterceptor(selector);
}
bool mayGenerateInstanceofCheck(DartType type) {
return _backend.mayGenerateInstanceofCheck(type);
}
bool methodUsesReceiverArgument(FunctionElement function) {
assert(isInterceptedMethod(function));
ClassElement class_ = function.enclosingClass.declaration;
return isInterceptorClass(class_) || isUsedAsMixin(class_);
}
}