blob: 90dba81a60a36c13749ea139a811677cca40f1d9 [file] [log] [blame]
// Copyright (c) 2015, 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.js_helpers.impact;
import '../common/names.dart' show
Identifiers;
import '../compiler.dart' show
Compiler;
import '../dart_types.dart' show
InterfaceType;
import '../elements/elements.dart' show
ClassElement,
Element;
import 'backend_helpers.dart';
import 'constant_system_javascript.dart';
import 'js_backend.dart';
/// A set of JavaScript backend dependencies.
class BackendImpact {
final List<Element> staticUses;
final List<InterfaceType> instantiatedTypes;
final List<ClassElement> instantiatedClasses;
final List<BackendImpact> otherImpacts;
BackendImpact({this.staticUses: const <Element>[],
this.instantiatedTypes: const <InterfaceType>[],
this.instantiatedClasses: const <ClassElement>[],
this.otherImpacts: const <BackendImpact>[]});
}
/// The JavaScript backend dependencies for various features.
class BackendImpacts {
final Compiler compiler;
BackendImpacts(this.compiler);
JavaScriptBackend get backend => compiler.backend;
BackendHelpers get helpers => backend.helpers;
BackendImpact get getRuntimeTypeArgument => new BackendImpact(
staticUses: [
helpers.getRuntimeTypeArgument,
helpers.getTypeArgumentByIndex,
helpers.copyTypeArguments]);
BackendImpact get computeSignature => new BackendImpact(
staticUses: [
helpers.setRuntimeTypeInfo,
helpers.getRuntimeTypeInfo,
helpers.computeSignature,
helpers.getRuntimeTypeArguments],
instantiatedClasses: [
compiler.listClass]);
BackendImpact get asyncBody => new BackendImpact(
staticUses: [
helpers.asyncHelper,
helpers.syncCompleterConstructor,
helpers.streamIteratorConstructor,
helpers.wrapBody]);
BackendImpact get syncStarBody => new BackendImpact(
staticUses: [
helpers.syncStarIterableConstructor,
helpers.endOfIteration,
helpers.yieldStar,
helpers.syncStarUncaughtError],
instantiatedClasses: [
helpers.syncStarIterable]);
BackendImpact get asyncStarBody => new BackendImpact(
staticUses: [
helpers.asyncStarHelper,
helpers.streamOfController,
helpers.yieldSingle,
helpers.yieldStar,
helpers.asyncStarControllerConstructor,
helpers.streamIteratorConstructor,
helpers.wrapBody],
instantiatedClasses: [
helpers.asyncStarController]);
BackendImpact get typeVariableBoundCheck => new BackendImpact(
staticUses: [
helpers.throwTypeError,
helpers.assertIsSubtype]);
BackendImpact get abstractClassInstantiation => new BackendImpact(
staticUses: [
helpers.throwAbstractClassInstantiationError],
otherImpacts: [
needsString('Needed to encode the message.')]);
BackendImpact get fallThroughError => new BackendImpact(
staticUses: [
helpers.fallThroughError]);
BackendImpact get asCheck => new BackendImpact(
staticUses: [
helpers.throwRuntimeError]);
BackendImpact get throwNoSuchMethod => new BackendImpact(
staticUses: [
helpers.throwNoSuchMethod],
otherImpacts: [
// Also register the types of the arguments passed to this method.
needsList(
'Needed to encode the arguments for throw NoSuchMethodError.'),
needsString(
'Needed to encode the name for throw NoSuchMethodError.')]);
BackendImpact get throwRuntimeError => new BackendImpact(
staticUses: [
helpers.throwRuntimeError],
// Also register the types of the arguments passed to this method.
instantiatedClasses: [
helpers.compiler.stringClass]);
BackendImpact get superNoSuchMethod => new BackendImpact(
staticUses: [
helpers.createInvocationMirror,
helpers.compiler.objectClass.lookupLocalMember(
Identifiers.noSuchMethod_)],
otherImpacts: [
needsInt(
'Needed to encode the invocation kind of super.noSuchMethod.'),
needsList(
'Needed to encode the arguments of super.noSuchMethod.'),
needsString(
'Needed to encode the name of super.noSuchMethod.')]);
BackendImpact get constantMapLiteral {
ClassElement find(String name) {
return helpers.find(backend.jsHelperLibrary, name);
}
return new BackendImpact(
instantiatedClasses: [
find(JavaScriptMapConstant.DART_CLASS),
find(JavaScriptMapConstant.DART_PROTO_CLASS),
find(JavaScriptMapConstant.DART_STRING_CLASS),
find(JavaScriptMapConstant.DART_GENERAL_CLASS)]);
}
BackendImpact get symbolConstructor => new BackendImpact(
staticUses: [
helpers.compiler.symbolValidatedConstructor]);
BackendImpact get incDecOperation =>
needsInt('Needed for the `+ 1` or `- 1` operation of ++/--.');
/// Helper for registering that `int` is needed.
BackendImpact needsInt(String reason) {
// TODO(johnniwinther): Register [reason] for use in dump-info.
return new BackendImpact(
instantiatedClasses: [helpers.compiler.intClass]);
}
/// Helper for registering that `List` is needed.
BackendImpact needsList(String reason) {
// TODO(johnniwinther): Register [reason] for use in dump-info.
return new BackendImpact(
instantiatedClasses: [helpers.compiler.listClass]);
}
/// Helper for registering that `String` is needed.
BackendImpact needsString(String reason) {
// TODO(johnniwinther): Register [reason] for use in dump-info.
return new BackendImpact(
instantiatedClasses: [
helpers.compiler.stringClass]);
}
BackendImpact get assertWithoutMessage => new BackendImpact(
staticUses: [
helpers.assertHelper]);
BackendImpact get assertWithMessage => new BackendImpact(
staticUses: [
helpers.assertTest,
helpers.assertThrow]);
BackendImpact get asyncForIn => new BackendImpact(
staticUses: [
helpers.streamIteratorConstructor]);
BackendImpact get stringInterpolation => new BackendImpact(
staticUses: [
helpers.stringInterpolationHelper]);
BackendImpact get catchStatement => new BackendImpact(
staticUses: [
helpers.exceptionUnwrapper],
instantiatedClasses: [
backend.jsPlainJavaScriptObjectClass,
backend.jsUnknownJavaScriptObjectClass]);
BackendImpact get throwExpression => new BackendImpact(
// We don't know ahead of time whether we will need the throw in a
// statement context or an expression context, so we register both
// here, even though we may not need the throwExpression helper.
staticUses: [
helpers.wrapExceptionHelper,
helpers.throwExpressionHelper]);
BackendImpact get lazyField => new BackendImpact(
staticUses: [
helpers.cyclicThrowHelper]);
BackendImpact get typeLiteral => new BackendImpact(
instantiatedClasses: [
backend.typeImplementation],
staticUses: [
helpers.createRuntimeType]);
BackendImpact get stackTraceInCatch => new BackendImpact(
staticUses: [
helpers.traceFromException]);
BackendImpact get syncForIn => new BackendImpact(
// The SSA builder recognizes certain for-in loops and can generate calls
// to throwConcurrentModificationError.
staticUses: [
helpers.checkConcurrentModificationError]);
BackendImpact get typeVariableExpression => new BackendImpact(
staticUses: [
helpers.setRuntimeTypeInfo,
helpers.getRuntimeTypeInfo,
helpers.runtimeTypeToString,
helpers.createRuntimeType],
instantiatedClasses: [
helpers.compiler.listClass],
otherImpacts: [
getRuntimeTypeArgument,
needsInt('Needed for accessing a type variable literal on this.')]);
BackendImpact get typeCheck => new BackendImpact(
instantiatedClasses: [
helpers.compiler.boolClass]);
BackendImpact get checkedModeTypeCheck => new BackendImpact(
staticUses: [
helpers.throwRuntimeError]);
BackendImpact get malformedTypeCheck => new BackendImpact(
staticUses: [
helpers.throwTypeError]);
BackendImpact get genericTypeCheck => new BackendImpact(
staticUses: [
helpers.checkSubtype,
// TODO(johnniwinther): Investigate why this is needed.
helpers.setRuntimeTypeInfo,
helpers.getRuntimeTypeInfo],
instantiatedClasses: [
helpers.compiler.listClass],
otherImpacts: [
getRuntimeTypeArgument]);
BackendImpact get genericCheckedModeTypeCheck => new BackendImpact(
staticUses: [
helpers.assertSubtype]);
BackendImpact get typeVariableTypeCheck => new BackendImpact(
staticUses: [
helpers.checkSubtypeOfRuntimeType]);
BackendImpact get typeVariableCheckedModeTypeCheck => new BackendImpact(
staticUses: [
helpers.assertSubtypeOfRuntimeType]);
BackendImpact get functionTypeCheck => new BackendImpact(
staticUses: [
helpers.functionTypeTestMetaHelper]);
BackendImpact get nativeTypeCheck => new BackendImpact(
staticUses: [
// We will neeed to add the "$is" and "$as" properties on the
// JavaScript object prototype, so we make sure
// [:defineProperty:] is compiled.
helpers.defineProperty]);
}