Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(599)

Unified Diff: pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart

Issue 2246623002: Delete CPS IR (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart ('k') | pkg/compiler/lib/src/cps_ir/cps_ir_integrity.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
deleted file mode 100644
index 974830150676466dc472ce64dca98ca3613b8693..0000000000000000000000000000000000000000
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
+++ /dev/null
@@ -1,4038 +0,0 @@
-// Copyright (c) 2013, 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.ir_builder_task;
-
-import 'package:js_runtime/shared/embedded_names.dart'
- show JsBuiltin, JsGetName;
-
-import '../closure.dart' as closure;
-import '../common.dart';
-import '../common/names.dart' show Identifiers, Names, Selectors;
-import '../common/tasks.dart' show CompilerTask;
-import '../compiler.dart' show Compiler;
-import '../constants/expressions.dart';
-import '../constants/values.dart' show ConstantValue;
-import '../constants/values.dart';
-import '../dart_types.dart';
-import '../elements/elements.dart';
-import '../elements/modelx.dart' show ConstructorBodyElementX;
-import '../io/source_information.dart';
-import '../js/js.dart' as js show js, Template, Expression, Name;
-import '../js_backend/backend_helpers.dart' show BackendHelpers;
-import '../js_backend/js_backend.dart'
- show JavaScriptBackend, SyntheticConstantKind;
-import '../native/native.dart' show NativeBehavior, HasCapturedPlaceholders;
-import '../resolution/operators.dart' as op;
-import '../resolution/semantic_visitor.dart';
-import '../resolution/tree_elements.dart' show TreeElements;
-import '../ssa/types.dart' show TypeMaskFactory;
-import '../tree/tree.dart' as ast;
-import '../types/types.dart' show TypeMask;
-import '../universe/call_structure.dart' show CallStructure;
-import '../universe/selector.dart' show Selector;
-import '../util/util.dart';
-import 'cps_ir_builder.dart';
-import 'cps_ir_nodes.dart' as ir;
-import 'type_mask_system.dart' show TypeMaskSystem;
-// TODO(karlklose): remove.
-
-typedef void IrBuilderCallback(Element element, ir.FunctionDefinition irNode);
-
-class ExplicitReceiverParameter implements Local {
- final ExecutableElement executableContext;
-
- ExplicitReceiverParameter(this.executableContext);
-
- String get name => 'receiver';
- String toString() => 'ExplicitReceiverParameter($executableContext)';
-}
-
-/// This task provides the interface to build IR nodes from [ast.Node]s, which
-/// is used from the [CpsFunctionCompiler] to generate code.
-///
-/// This class is mainly there to correctly measure how long building the IR
-/// takes.
-class IrBuilderTask extends CompilerTask {
- final SourceInformationStrategy sourceInformationStrategy;
- final Compiler compiler;
-
- String bailoutMessage = null;
-
- /// If not null, this function will be called with for each
- /// [ir.FunctionDefinition] node that has been built.
- IrBuilderCallback builderCallback;
-
- IrBuilderTask(Compiler compiler, this.sourceInformationStrategy,
- [this.builderCallback])
- : compiler = compiler,
- super(compiler.measurer);
-
- String get name => 'CPS builder';
-
- ir.FunctionDefinition buildNode(
- AstElement element, TypeMaskSystem typeMaskSystem) {
- return measure(() {
- bailoutMessage = null;
-
- ResolvedAst resolvedAst = element.resolvedAst;
- element = element.implementation;
- return compiler.reporter.withCurrentElement(element, () {
- SourceInformationBuilder sourceInformationBuilder =
- sourceInformationStrategy.createBuilderForContext(resolvedAst);
-
- IrBuilderVisitor builder = new IrBuilderVisitor(
- resolvedAst, compiler, sourceInformationBuilder, typeMaskSystem);
- ir.FunctionDefinition irNode = builder.buildExecutable(element);
- if (irNode == null) {
- bailoutMessage = builder.bailoutMessage;
- } else if (builderCallback != null) {
- builderCallback(element, irNode);
- }
- return irNode;
- });
- });
- }
-}
-
-/// Translates the frontend AST of a method to its CPS IR.
-///
-/// The visitor has an [IrBuilder] which contains an IR fragment to build upon
-/// and the current reaching definition of local variables.
-///
-/// Visiting a statement or expression extends the IR builder's fragment.
-/// For expressions, the primitive holding the resulting value is returned.
-/// For statements, `null` is returned.
-// TODO(johnniwinther): Implement [SemanticDeclVisitor].
-class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
- with
- IrBuilderMixin<ast.Node>,
- SemanticSendResolvedMixin<ir.Primitive, dynamic>,
- ErrorBulkMixin<ir.Primitive, dynamic>,
- BaseImplementationOfStaticsMixin<ir.Primitive, dynamic>,
- BaseImplementationOfLocalsMixin<ir.Primitive, dynamic>,
- BaseImplementationOfDynamicsMixin<ir.Primitive, dynamic>,
- BaseImplementationOfConstantsMixin<ir.Primitive, dynamic>,
- BaseImplementationOfNewMixin<ir.Primitive, dynamic>,
- BaseImplementationOfCompoundsMixin<ir.Primitive, dynamic>,
- BaseImplementationOfSetIfNullsMixin<ir.Primitive, dynamic>,
- BaseImplementationOfIndexCompoundsMixin<ir.Primitive, dynamic>,
- BaseImplementationOfSuperIndexSetIfNullMixin<ir.Primitive, dynamic>
- implements SemanticSendVisitor<ir.Primitive, dynamic> {
- final ResolvedAst resolvedAst;
- final Compiler compiler;
- final SourceInformationBuilder sourceInformationBuilder;
- final TypeMaskSystem typeMaskSystem;
-
- /// A map from try statements in the source to analysis information about
- /// them.
- ///
- /// The analysis information includes the set of variables that must be
- /// copied into [ir.MutableVariable]s on entry to the try and copied out on
- /// exit.
- Map<ast.Node, TryStatementInfo> tryStatements = null;
-
- // In SSA terms, join-point continuation parameters are the phis and the
- // continuation invocation arguments are the corresponding phi inputs. To
- // support name introduction and renaming for source level variables, we use
- // nested (delimited) visitors for constructing subparts of the IR that will
- // need renaming. Each source variable is assigned an index.
- //
- // Each nested visitor maintains a list of free variable uses in the body.
- // These are implemented as a list of parameters, each with their own use
- // list of references. When the delimited subexpression is plugged into the
- // surrounding context, the free occurrences can be captured or become free
- // occurrences in the next outer delimited subexpression.
- //
- // Each nested visitor maintains a list that maps indexes of variables
- // assigned in the delimited subexpression to their reaching definition ---
- // that is, the definition in effect at the hole in 'current'. These are
- // used to determine if a join-point continuation needs to be passed
- // arguments, and what the arguments are.
-
- /// Construct a top-level visitor.
- IrBuilderVisitor(this.resolvedAst, this.compiler,
- this.sourceInformationBuilder, this.typeMaskSystem);
-
- TreeElements get elements => resolvedAst.elements;
-
- JavaScriptBackend get backend => compiler.backend;
- BackendHelpers get helpers => backend.helpers;
- DiagnosticReporter get reporter => compiler.reporter;
-
- String bailoutMessage = null;
-
- ir.Primitive visit(ast.Node node) => node.accept(this);
-
- @override
- ir.Primitive apply(ast.Node node, _) => node.accept(this);
-
- SemanticSendVisitor get sendVisitor => this;
-
- /// Result of closure conversion for the current body of code.
- ///
- /// Will be initialized upon entering the body of a function.
- /// It is computed by the [ClosureTranslator].
- closure.ClosureClassMap closureClassMap;
-
- /// If [node] has declarations for variables that should be boxed,
- /// returns a [ClosureScope] naming a box to create, and enumerating the
- /// variables that should be stored in the box.
- ///
- /// Also see [ClosureScope].
- ClosureScope getClosureScopeForNode(ast.Node node) {
- // We translate a ClosureScope from closure.dart into IR builder's variant
- // because the IR builder should not depend on the synthetic elements
- // created in closure.dart.
- return new ClosureScope(closureClassMap.capturingScopes[node]);
- }
-
- /// Returns the [ClosureScope] for any function, possibly different from the
- /// one currently being built.
- ClosureScope getClosureScopeForFunction(FunctionElement function) {
- closure.ClosureClassMap map = compiler.closureToClassMapper
- .computeClosureToClassMapping(function.resolvedAst);
- return new ClosureScope(map.capturingScopes[function.node]);
- }
-
- /// If the current function is a nested function with free variables (or a
- /// captured reference to `this`), returns a [ClosureEnvironment]
- /// indicating how to access these.
- ClosureEnvironment getClosureEnvironment() {
- return new ClosureEnvironment(closureClassMap);
- }
-
- IrBuilder getBuilderFor(Element element) {
- return new IrBuilder(
- new GlobalProgramInformation(compiler), backend.constants, element);
- }
-
- /// Builds the [ir.FunctionDefinition] for an executable element. In case the
- /// function uses features that cannot be expressed in the IR, this element
- /// returns `null`.
- ir.FunctionDefinition buildExecutable(ExecutableElement element) {
- return nullIfGiveup(() {
- ir.FunctionDefinition root;
- switch (element.kind) {
- case ElementKind.GENERATIVE_CONSTRUCTOR:
- root = buildConstructor(element);
- break;
-
- case ElementKind.GENERATIVE_CONSTRUCTOR_BODY:
- root = buildConstructorBody(element);
- break;
-
- case ElementKind.FACTORY_CONSTRUCTOR:
- case ElementKind.FUNCTION:
- case ElementKind.GETTER:
- case ElementKind.SETTER:
- root = buildFunction(element);
- break;
-
- case ElementKind.FIELD:
- if (Elements.isStaticOrTopLevel(element)) {
- root = buildStaticFieldInitializer(element);
- } else {
- // Instance field initializers are inlined in the constructor,
- // so we shouldn't need to build anything here.
- // TODO(asgerf): But what should we return?
- return null;
- }
- break;
-
- default:
- reporter.internalError(element, "Unexpected element type $element");
- }
- return root;
- });
- }
-
- /// Loads the type variables for all super classes of [superClass] into the
- /// IR builder's environment with their corresponding values.
- ///
- /// The type variables for [currentClass] must already be in the IR builder's
- /// environment.
- ///
- /// Type variables are stored as [TypeVariableLocal] in the environment.
- ///
- /// This ensures that access to type variables mentioned inside the
- /// constructors and initializers will happen through the local environment
- /// instead of using 'this'.
- void loadTypeVariablesForSuperClasses(ClassElement currentClass) {
- if (currentClass.isObject) return;
- loadTypeVariablesForType(currentClass.supertype);
- if (currentClass is MixinApplicationElement) {
- loadTypeVariablesForType(currentClass.mixinType);
- }
- }
-
- /// Loads all type variables for [type] and all of its super classes into
- /// the environment. All type variables mentioned in [type] must already
- /// be in the environment.
- void loadTypeVariablesForType(InterfaceType type) {
- ClassElement clazz = type.element;
- assert(clazz.typeVariables.length == type.typeArguments.length);
- for (int i = 0; i < clazz.typeVariables.length; ++i) {
- irBuilder.declareTypeVariable(
- clazz.typeVariables[i], type.typeArguments[i]);
- }
- loadTypeVariablesForSuperClasses(clazz);
- }
-
- /// Returns the constructor body associated with the given constructor or
- /// creates a new constructor body, if none can be found.
- ///
- /// Returns `null` if the constructor does not have a body.
- ConstructorBodyElement getConstructorBody(FunctionElement constructor) {
- // TODO(asgerf): This is largely inherited from the SSA builder.
- // The ConstructorBodyElement has an invalid function signature, but we
- // cannot add a BoxLocal as parameter, because BoxLocal is not an element.
- // Instead of forging ParameterElements to forge a FunctionSignature, we
- // need a way to create backend methods without creating more fake elements.
- assert(constructor.isGenerativeConstructor);
- assert(constructor.isImplementation);
- if (constructor.isSynthesized) return null;
- ResolvedAst resolvedAst = constructor.resolvedAst;
- ast.FunctionExpression node = constructor.node;
- // If we know the body doesn't have any code, we don't generate it.
- if (!node.hasBody) return null;
- if (node.hasEmptyBody) return null;
- ClassElement classElement = constructor.enclosingClass;
- ConstructorBodyElement bodyElement;
- classElement.forEachBackendMember((Element backendMember) {
- if (backendMember.isGenerativeConstructorBody) {
- ConstructorBodyElement body = backendMember;
- if (body.constructor == constructor) {
- bodyElement = backendMember;
- }
- }
- });
- if (bodyElement == null) {
- bodyElement = new ConstructorBodyElementX(resolvedAst, constructor);
- classElement.addBackendMember(bodyElement);
-
- if (constructor.isPatch) {
- // Create origin body element for patched constructors.
- ConstructorBodyElementX patch = bodyElement;
- ConstructorBodyElementX origin =
- new ConstructorBodyElementX(resolvedAst, constructor.origin);
- origin.applyPatch(patch);
- classElement.origin.addBackendMember(bodyElement.origin);
- }
- }
- assert(bodyElement.isGenerativeConstructorBody);
- return bodyElement;
- }
-
- /// The list of parameters to send from the generative constructor
- /// to the generative constructor body.
- ///
- /// Boxed parameters are not in the list, instead, a [BoxLocal] is passed
- /// containing the boxed parameters.
- ///
- /// For example, given the following constructor,
- ///
- /// Foo(x, y) : field = (() => ++x) { print(x + y) }
- ///
- /// the argument `x` would be replaced by a [BoxLocal]:
- ///
- /// Foo_body(box0, y) { print(box0.x + y) }
- ///
- List<Local> getConstructorBodyParameters(ConstructorBodyElement body) {
- List<Local> parameters = <Local>[];
- ClosureScope scope = getClosureScopeForFunction(body.constructor);
- if (scope != null) {
- parameters.add(scope.box);
- }
- body.functionSignature.orderedForEachParameter((ParameterElement param) {
- if (scope != null && scope.capturedVariables.containsKey(param)) {
- // Do not pass this parameter; the box will carry its value.
- } else {
- parameters.add(param);
- }
- });
- return parameters;
- }
-
- /// Builds the IR for a given constructor.
- ///
- /// 1. Computes the type held in all own or "inherited" type variables.
- /// 2. Evaluates all own or inherited field initializers.
- /// 3. Creates the object and assigns its fields and runtime type.
- /// 4. Calls constructor body and super constructor bodies.
- /// 5. Returns the created object.
- ir.FunctionDefinition buildConstructor(ConstructorElement constructor) {
- // TODO(asgerf): Optimization: If constructor is redirecting, then just
- // evaluate arguments and call the target constructor.
- constructor = constructor.implementation;
- ClassElement classElement = constructor.enclosingClass.implementation;
-
- IrBuilder builder = getBuilderFor(constructor);
-
- final bool requiresTypeInformation =
- builder.program.requiresRuntimeTypesFor(classElement);
-
- return withBuilder(builder, () {
- // Setup parameters and create a box if anything is captured.
- List<Local> parameters = <Local>[];
- if (constructor.isGenerativeConstructor &&
- backend.isNativeOrExtendsNative(classElement)) {
- parameters.add(new ExplicitReceiverParameter(constructor));
- }
- constructor.functionSignature
- .orderedForEachParameter((ParameterElement p) => parameters.add(p));
-
- int firstTypeArgumentParameterIndex;
-
- // If instances of the class may need runtime type information, we add a
- // synthetic parameter for each type parameter.
- if (requiresTypeInformation) {
- firstTypeArgumentParameterIndex = parameters.length;
- classElement.typeVariables.forEach((TypeVariableType variable) {
- parameters.add(new closure.TypeVariableLocal(variable, constructor));
- });
- } else {
- classElement.typeVariables.forEach((TypeVariableType variable) {
- irBuilder.declareTypeVariable(variable, const DynamicType());
- });
- }
-
- // Create IR parameters and setup the environment.
- List<ir.Parameter> irParameters = builder.buildFunctionHeader(parameters,
- closureScope: getClosureScopeForFunction(constructor));
-
- // Create a list of the values of all type argument parameters, if any.
- ir.Primitive typeInformation;
- if (requiresTypeInformation) {
- typeInformation = new ir.TypeExpression(
- ir.TypeExpressionKind.INSTANCE,
- classElement.thisType,
- irParameters.sublist(firstTypeArgumentParameterIndex));
- irBuilder.add(new ir.LetPrim(typeInformation));
- } else {
- typeInformation = null;
- }
-
- // -- Load values for type variables declared on super classes --
- // Field initializers for super classes can reference these, so they
- // must be available before evaluating field initializers.
- // This could be interleaved with field initialization, but we choose do
- // get it out of the way here to avoid complications with mixins.
- loadTypeVariablesForSuperClasses(classElement);
-
- /// Maps each field from this class or a superclass to its initial value.
- Map<FieldElement, ir.Primitive> fieldValues =
- <FieldElement, ir.Primitive>{};
-
- // -- Evaluate field initializers ---
- // Evaluate field initializers in constructor and super constructors.
- List<ConstructorElement> constructorList = <ConstructorElement>[];
- evaluateConstructorFieldInitializers(
- constructor, constructorList, fieldValues);
-
- // All parameters in all constructors are now bound in the environment.
- // BoxLocals for captured parameters are also in the environment.
- // The initial value of all fields are now bound in [fieldValues].
-
- // --- Create the object ---
- // Get the initial field values in the canonical order.
- List<ir.Primitive> instanceArguments = <ir.Primitive>[];
- List<FieldElement> fields = <FieldElement>[];
- classElement.forEachInstanceField((ClassElement c, FieldElement field) {
- ir.Primitive value = fieldValues[field];
- if (value != null) {
- fields.add(field);
- instanceArguments.add(value);
- } else {
- assert(backend.isNativeOrExtendsNative(c));
- // Native fields are initialized elsewhere.
- }
- }, includeSuperAndInjectedMembers: true);
-
- ir.Primitive instance;
- if (constructor.isGenerativeConstructor &&
- backend.isNativeOrExtendsNative(classElement)) {
- instance = irParameters.first;
- instance.type =
- new TypeMask.exact(classElement, typeMaskSystem.classWorld);
- irBuilder.addPrimitive(new ir.ReceiverCheck.nullCheck(
- instance, Selectors.toString_, null));
- for (int i = 0; i < fields.length; i++) {
- irBuilder.addPrimitive(
- new ir.SetField(instance, fields[i], instanceArguments[i]));
- }
- } else {
- instance = new ir.CreateInstance(
- classElement,
- instanceArguments,
- typeInformation,
- constructor.hasNode
- ? sourceInformationBuilder.buildCreate(constructor.node)
- // TODO(johnniwinther): Provide source information for creation
- // through synthetic constructors.
- : null);
- irBuilder.add(new ir.LetPrim(instance));
- }
-
- // --- Call constructor bodies ---
- for (ConstructorElement target in constructorList) {
- ConstructorBodyElement bodyElement = getConstructorBody(target);
- if (bodyElement == null) continue; // Skip if constructor has no body.
- List<ir.Primitive> bodyArguments = <ir.Primitive>[];
- for (Local param in getConstructorBodyParameters(bodyElement)) {
- bodyArguments.add(irBuilder.environment.lookup(param));
- }
- Selector selector = new Selector.call(
- target.memberName, new CallStructure(bodyArguments.length));
- irBuilder.addPrimitive(new ir.InvokeMethodDirectly(
- instance, bodyElement, selector, bodyArguments, null));
- }
-
- // --- step 4: return the created object ----
- irBuilder.buildReturn(
- value: instance,
- sourceInformation:
- sourceInformationBuilder.buildImplicitReturn(constructor));
-
- return irBuilder.makeFunctionDefinition(
- sourceInformationBuilder.buildVariableDeclaration());
- });
- }
-
- /// Make a visitor suitable for translating ASTs taken from [context].
- ///
- /// Every visitor can only be applied to nodes in one context, because
- /// the [elements] field is specific to that context.
- IrBuilderVisitor makeVisitorForContext(AstElement context) {
- ResolvedAst resolvedAst = context.resolvedAst;
- return new IrBuilderVisitor(resolvedAst, compiler,
- sourceInformationBuilder.forContext(resolvedAst), typeMaskSystem);
- }
-
- /// Builds the IR for an [expression] taken from a different [context].
- ///
- /// Such expressions need to be compiled with a different [sourceFile] and
- /// [elements] mapping.
- ir.Primitive inlineExpression(AstElement context, ast.Expression expression) {
- IrBuilderVisitor visitor = makeVisitorForContext(context);
- return visitor.withBuilder(irBuilder, () => visitor.visit(expression));
- }
-
- /// Evaluate the implicit super call in the given mixin constructor.
- void forwardSynthesizedMixinConstructor(
- ConstructorElement constructor,
- List<ConstructorElement> supers,
- Map<FieldElement, ir.Primitive> fieldValues) {
- assert(constructor.enclosingClass.implementation.isMixinApplication);
- assert(constructor.isSynthesized);
- ConstructorElement target = constructor.definingConstructor.implementation;
- // The resolver gives us the exact same FunctionSignature for the two
- // constructors. The parameters for the synthesized constructor
- // are already in the environment, so the target constructor's parameters
- // are also in the environment since their elements are the same.
- assert(constructor.functionSignature == target.functionSignature);
- IrBuilderVisitor visitor = makeVisitorForContext(target);
- visitor.withBuilder(irBuilder, () {
- visitor.evaluateConstructorFieldInitializers(target, supers, fieldValues);
- });
- }
-
- /// In preparation of inlining (part of) [target], the [arguments] are moved
- /// into the environment bindings for the corresponding parameters.
- ///
- /// Defaults for optional arguments are evaluated in order to ensure
- /// all parameters are available in the environment.
- void loadArguments(ConstructorElement target, CallStructure call,
- List<ir.Primitive> arguments) {
- assert(target.isImplementation);
- assert(target.declaration == resolvedAst.element);
- FunctionSignature signature = target.functionSignature;
-
- // Establish a scope in case parameters are captured.
- ClosureScope scope = getClosureScopeForFunction(target);
- irBuilder.enterScope(scope);
-
- // Load required parameters
- int index = 0;
- signature.forEachRequiredParameter((ParameterElement param) {
- irBuilder.declareLocalVariable(param, initialValue: arguments[index]);
- index++;
- });
-
- // Load optional parameters, evaluating default values for omitted ones.
- signature.forEachOptionalParameter((ParameterElement param) {
- ir.Primitive value;
- // Load argument if provided.
- if (signature.optionalParametersAreNamed) {
- int nameIndex = call.namedArguments.indexOf(param.name);
- if (nameIndex != -1) {
- int translatedIndex = call.positionalArgumentCount + nameIndex;
- value = arguments[translatedIndex];
- }
- } else if (index < arguments.length) {
- value = arguments[index];
- }
- // Load default if argument was not provided.
- if (value == null) {
- if (param.initializer != null) {
- value = visit(param.initializer);
- } else {
- value = irBuilder.buildNullConstant();
- }
- }
- irBuilder.declareLocalVariable(param, initialValue: value);
- index++;
- });
- }
-
- /// Evaluates a call to the given constructor from an initializer list.
- ///
- /// Calls [loadArguments] and [evaluateConstructorFieldInitializers] in a
- /// visitor that has the proper [TreeElements] mapping.
- void evaluateConstructorCallFromInitializer(
- ConstructorElement target,
- CallStructure call,
- List<ir.Primitive> arguments,
- List<ConstructorElement> supers,
- Map<FieldElement, ir.Primitive> fieldValues) {
- IrBuilderVisitor visitor = makeVisitorForContext(target);
- visitor.withBuilder(irBuilder, () {
- visitor.loadArguments(target, call, arguments);
- visitor.evaluateConstructorFieldInitializers(target, supers, fieldValues);
- });
- }
-
- /// Evaluates all field initializers on [constructor] and all constructors
- /// invoked through `this()` or `super()` ("superconstructors").
- ///
- /// The resulting field values will be available in [fieldValues]. The values
- /// are not stored in any fields.
- ///
- /// This procedure assumes that the parameters to [constructor] are available
- /// in the IR builder's environment.
- ///
- /// The parameters to superconstructors are, however, assumed *not* to be in
- /// the environment, but will be put there by this procedure.
- ///
- /// All constructors will be added to [supers], with superconstructors first.
- void evaluateConstructorFieldInitializers(
- ConstructorElement constructor,
- List<ConstructorElement> supers,
- Map<FieldElement, ir.Primitive> fieldValues) {
- assert(constructor.isImplementation);
- assert(constructor.declaration == resolvedAst.element);
- ClassElement enclosingClass = constructor.enclosingClass.implementation;
- // Evaluate declaration-site field initializers, unless this constructor
- // redirects to another using a `this()` initializer. In that case, these
- // will be initialized by the effective target constructor.
- if (!constructor.isRedirectingGenerative) {
- enclosingClass.forEachInstanceField((ClassElement c, FieldElement field) {
- if (field.initializer != null) {
- fieldValues[field] = inlineExpression(field, field.initializer);
- } else {
- if (backend.isNativeOrExtendsNative(c)) {
- // Native field is initialized elsewhere.
- } else {
- // Fields without an initializer default to null.
- // This value will be overwritten below if an initializer is found.
- fieldValues[field] = irBuilder.buildNullConstant();
- }
- }
- });
- }
- // If this is a mixin constructor, it does not have its own parameter list
- // or initializer list. Directly forward to the super constructor.
- // Note that the declaration-site initializers originating from the
- // mixed-in class were handled above.
- if (enclosingClass.isMixinApplication) {
- forwardSynthesizedMixinConstructor(constructor, supers, fieldValues);
- return;
- }
- // Evaluate initializing parameters, e.g. `Foo(this.x)`.
- constructor.functionSignature
- .orderedForEachParameter((ParameterElement parameter) {
- if (parameter.isInitializingFormal) {
- InitializingFormalElement fieldParameter = parameter;
- fieldValues[fieldParameter.fieldElement] =
- irBuilder.buildLocalGet(parameter);
- }
- });
- // Evaluate constructor initializers, e.g. `Foo() : x = 50`.
- ast.FunctionExpression node = constructor.node;
- bool hasConstructorCall = false; // Has this() or super() initializer?
- if (node != null && node.initializers != null) {
- for (ast.Node initializer in node.initializers) {
- if (initializer is ast.SendSet) {
- // Field initializer.
- FieldElement field = elements[initializer];
- fieldValues[field] = visit(initializer.arguments.head);
- } else if (initializer is ast.Send) {
- // Super or this initializer.
- ConstructorElement target = elements[initializer].implementation;
- Selector selector = elements.getSelector(initializer);
- List<ir.Primitive> arguments = initializer.arguments.mapToList(visit);
- evaluateConstructorCallFromInitializer(
- target, selector.callStructure, arguments, supers, fieldValues);
- hasConstructorCall = true;
- } else {
- reporter.internalError(
- initializer, "Unexpected initializer type $initializer");
- }
- }
- }
- // If no super() or this() was found, also call default superconstructor.
- if (!hasConstructorCall && !enclosingClass.isObject) {
- ClassElement superClass = enclosingClass.superclass;
- FunctionElement target = superClass.lookupDefaultConstructor();
- if (target == null) {
- reporter.internalError(superClass, "No default constructor available.");
- }
- target = target.implementation;
- evaluateConstructorCallFromInitializer(
- target, CallStructure.NO_ARGS, const [], supers, fieldValues);
- }
- // Add this constructor after the superconstructors.
- supers.add(constructor);
- }
-
- TryBoxedVariables _analyzeTryBoxedVariables(ast.Node node) {
- TryBoxedVariables variables = new TryBoxedVariables(elements);
- try {
- variables.analyze(node);
- } catch (e) {
- bailoutMessage = variables.bailoutMessage;
- rethrow;
- }
- return variables;
- }
-
- /// Builds the IR for the body of a constructor.
- ///
- /// This function is invoked from one or more "factory" constructors built by
- /// [buildConstructor].
- ir.FunctionDefinition buildConstructorBody(ConstructorBodyElement body) {
- ConstructorElement constructor = body.constructor;
- ast.FunctionExpression node = constructor.node;
- closureClassMap = compiler.closureToClassMapper
- .computeClosureToClassMapping(constructor.resolvedAst);
-
- // We compute variables boxed in mutable variables on entry to each try
- // block, not including variables captured by a closure (which are boxed
- // in the heap). This duplicates some of the work of closure conversion
- // without directly using the results. This duplication is wasteful and
- // error-prone.
- // TODO(kmillikin): We should combine closure conversion and try/catch
- // variable analysis in some way.
- TryBoxedVariables variables = _analyzeTryBoxedVariables(node);
- tryStatements = variables.tryStatements;
- IrBuilder builder = getBuilderFor(body);
-
- return withBuilder(builder, () {
- irBuilder.buildConstructorBodyHeader(
- getConstructorBodyParameters(body), getClosureScopeForNode(node));
- visit(node.body);
- return irBuilder.makeFunctionDefinition(
- sourceInformationBuilder.buildVariableDeclaration());
- });
- }
-
- ir.FunctionDefinition buildFunction(FunctionElement element) {
- assert(invariant(element, element.isImplementation));
- ast.FunctionExpression node = element.node;
-
- assert(!element.isSynthesized);
- assert(node != null);
- assert(elements[node] != null);
-
- closureClassMap = compiler.closureToClassMapper
- .computeClosureToClassMapping(element.resolvedAst);
- TryBoxedVariables variables = _analyzeTryBoxedVariables(node);
- tryStatements = variables.tryStatements;
- IrBuilder builder = getBuilderFor(element);
- return withBuilder(
- builder, () => _makeFunctionBody(builder, element, node));
- }
-
- ir.FunctionDefinition buildStaticFieldInitializer(FieldElement element) {
- if (!backend.constants.lazyStatics.contains(element)) {
- return null; // Nothing to do.
- }
- closureClassMap = compiler.closureToClassMapper
- .computeClosureToClassMapping(element.resolvedAst);
- IrBuilder builder = getBuilderFor(element);
- return withBuilder(builder, () {
- irBuilder.buildFunctionHeader(<Local>[]);
- ir.Primitive initialValue = visit(element.initializer);
- ast.VariableDefinitions node = element.node;
- ast.SendSet sendSet = node.definitions.nodes.head;
- irBuilder.buildReturn(
- value: initialValue,
- sourceInformation:
- sourceInformationBuilder.buildReturn(sendSet.assignmentOperator));
- return irBuilder.makeFunctionDefinition(
- sourceInformationBuilder.buildVariableDeclaration());
- });
- }
-
- /// Builds the IR for a constant taken from a different [context].
- ///
- /// Such constants need to be compiled with a different [sourceFile] and
- /// [elements] mapping.
- ir.Primitive inlineConstant(AstElement context, ast.Expression exp) {
- IrBuilderVisitor visitor = makeVisitorForContext(context);
- return visitor.withBuilder(irBuilder, () => visitor.translateConstant(exp));
- }
-
- /// Creates a primitive for the default value of [parameter].
- ir.Primitive translateDefaultValue(ParameterElement parameter) {
- if (parameter.initializer == null ||
- // TODO(sigmund): JS doesn't support default values, so this should be
- // reported as an error earlier (Issue #25759).
- backend.isJsInterop(parameter.functionDeclaration)) {
- return irBuilder.buildNullConstant();
- } else {
- return inlineConstant(parameter.executableContext, parameter.initializer);
- }
- }
-
- /// Normalizes the argument list of a static invocation.
- ///
- /// A static invocation is one where the target is known. The argument list
- /// [arguments] is normalized by adding default values for optional arguments
- /// that are not passed, and by sorting it in place so that named arguments
- /// appear in a canonical order. A [CallStructure] reflecting this order
- /// is returned.
- CallStructure normalizeStaticArguments(CallStructure callStructure,
- FunctionElement target, List<ir.Primitive> arguments) {
- target = target.implementation;
- FunctionSignature signature = target.functionSignature;
- if (!signature.optionalParametersAreNamed &&
- signature.parameterCount == arguments.length) {
- return callStructure;
- }
-
- if (!signature.optionalParametersAreNamed) {
- int i = signature.requiredParameterCount;
- signature.forEachOptionalParameter((ParameterElement element) {
- if (i < callStructure.positionalArgumentCount) {
- ++i;
- } else {
- arguments.add(translateDefaultValue(element));
- }
- });
- return new CallStructure(signature.parameterCount);
- }
-
- int offset = signature.requiredParameterCount;
- List<ir.Primitive> namedArguments = arguments.sublist(offset);
- arguments.length = offset;
- List<String> normalizedNames = <String>[];
- // Iterate over the optional parameters of the signature, and try to
- // find them in the callStructure's named arguments. If found, we use the
- // value in the temporary list, otherwise the default value.
- signature.orderedOptionalParameters.forEach((ParameterElement element) {
- int nameIndex = callStructure.namedArguments.indexOf(element.name);
- arguments.add(nameIndex == -1
- ? translateDefaultValue(element)
- : namedArguments[nameIndex]);
- normalizedNames.add(element.name);
- });
- return new CallStructure(signature.parameterCount, normalizedNames);
- }
-
- /// Normalizes the argument list of a dynamic invocation.
- ///
- /// A dynamic invocation is one where the target is not known. The argument
- /// list [arguments] is normalized by sorting it in place so that the named
- /// arguments appear in a canonical order. A [CallStructure] reflecting this
- /// order is returned.
- CallStructure normalizeDynamicArguments(
- CallStructure callStructure, List<ir.Primitive> arguments) {
- assert(arguments.length == callStructure.argumentCount);
- if (callStructure.namedArguments.isEmpty) return callStructure;
- int destinationIndex = callStructure.positionalArgumentCount;
- List<ir.Primitive> namedArguments = arguments.sublist(destinationIndex);
- for (String argName in callStructure.getOrderedNamedArguments()) {
- int sourceIndex = callStructure.namedArguments.indexOf(argName);
- arguments[destinationIndex++] = namedArguments[sourceIndex];
- }
- return new CallStructure(
- callStructure.argumentCount, callStructure.getOrderedNamedArguments());
- }
-
- /// Read the value of [field].
- ir.Primitive buildStaticFieldGet(FieldElement field, SourceInformation src) {
- ConstantValue constant = getConstantForVariable(field);
- if (constant != null && !field.isAssignable) {
- typeMaskSystem.associateConstantValueWithElement(constant, field);
- return irBuilder.buildConstant(constant, sourceInformation: src);
- } else if (backend.constants.lazyStatics.contains(field)) {
- return irBuilder.addPrimitive(new ir.GetLazyStatic(field,
- sourceInformation: src,
- isFinal: compiler.world.fieldNeverChanges(field)));
- } else {
- return irBuilder.addPrimitive(new ir.GetStatic(field,
- sourceInformation: src,
- isFinal: compiler.world.fieldNeverChanges(field)));
- }
- }
-
- ir.FunctionDefinition _makeFunctionBody(
- IrBuilder builder, FunctionElement element, ast.FunctionExpression node) {
- FunctionSignature signature = element.functionSignature;
- List<Local> parameters = <Local>[];
- signature.orderedForEachParameter(
- (LocalParameterElement e) => parameters.add(e));
-
- bool requiresRuntimeTypes = false;
- if (element.isFactoryConstructor) {
- requiresRuntimeTypes =
- builder.program.requiresRuntimeTypesFor(element.enclosingElement);
- if (requiresRuntimeTypes) {
- // Type arguments are passed in as extra parameters.
- for (DartType typeVariable in element.enclosingClass.typeVariables) {
- parameters.add(new closure.TypeVariableLocal(typeVariable, element));
- }
- }
- }
-
- irBuilder.buildFunctionHeader(parameters,
- closureScope: getClosureScopeForNode(node),
- env: getClosureEnvironment());
-
- if (element == helpers.jsArrayTypedConstructor) {
- // Generate a body for JSArray<E>.typed(allocation):
- //
- // t1 = setRuntimeTypeInfo(allocation, TypeExpression($E));
- // return Refinement(t1, <JSArray>);
- //
- assert(parameters.length == 1 || parameters.length == 2);
- ir.Primitive allocation = irBuilder.buildLocalGet(parameters[0]);
-
- // Only call setRuntimeTypeInfo if JSArray requires the type parameter.
- if (requiresRuntimeTypes) {
- assert(parameters.length == 2);
- closure.TypeVariableLocal typeParameter = parameters[1];
- ir.Primitive typeArgument =
- irBuilder.buildTypeVariableAccess(typeParameter.typeVariable);
-
- ir.Primitive typeInformation = irBuilder.addPrimitive(
- new ir.TypeExpression(ir.TypeExpressionKind.INSTANCE,
- element.enclosingClass.thisType, <ir.Primitive>[typeArgument]));
-
- MethodElement helper = helpers.setRuntimeTypeInfo;
- CallStructure callStructure = CallStructure.TWO_ARGS;
- Selector selector = new Selector.call(helper.memberName, callStructure);
- allocation = irBuilder.buildInvokeStatic(
- helper,
- selector,
- <ir.Primitive>[allocation, typeInformation],
- sourceInformationBuilder.buildGeneric(node));
- }
-
- ir.Primitive refinement = irBuilder.addPrimitive(
- new ir.Refinement(allocation, typeMaskSystem.arrayType));
-
- irBuilder.buildReturn(
- value: refinement,
- sourceInformation:
- sourceInformationBuilder.buildImplicitReturn(element));
- } else {
- visit(node.body);
- }
- return irBuilder.makeFunctionDefinition(
- sourceInformationBuilder.buildVariableDeclaration());
- }
-
- /// Builds the IR for creating an instance of the closure class corresponding
- /// to the given nested function.
- closure.ClosureClassElement makeSubFunction(ast.FunctionExpression node) {
- closure.ClosureClassMap innerMap =
- compiler.closureToClassMapper.getMappingForNestedFunction(node);
- closure.ClosureClassElement closureClass = innerMap.closureClassElement;
- return closureClass;
- }
-
- ir.Primitive visitFunctionExpression(ast.FunctionExpression node) {
- return irBuilder.buildFunctionExpression(
- makeSubFunction(node), sourceInformationBuilder.buildCreate(node));
- }
-
- visitFunctionDeclaration(ast.FunctionDeclaration node) {
- LocalFunctionElement element = elements[node.function];
- Object inner = makeSubFunction(node.function);
- irBuilder.declareLocalFunction(
- element, inner, sourceInformationBuilder.buildCreate(node.function));
- }
-
- // ## Statements ##
- visitBlock(ast.Block node) {
- irBuilder.buildBlock(node.statements.nodes, build);
- }
-
- ir.Primitive visitBreakStatement(ast.BreakStatement node) {
- if (!irBuilder.buildBreak(elements.getTargetOf(node))) {
- reporter.internalError(node, "'break' target not found");
- }
- return null;
- }
-
- ir.Primitive visitContinueStatement(ast.ContinueStatement node) {
- if (!irBuilder.buildContinue(elements.getTargetOf(node))) {
- reporter.internalError(node, "'continue' target not found");
- }
- return null;
- }
-
- // Build(EmptyStatement, C) = C
- ir.Primitive visitEmptyStatement(ast.EmptyStatement node) {
- assert(irBuilder.isOpen);
- return null;
- }
-
- // Build(ExpressionStatement(e), C) = C'
- // where (C', _) = Build(e, C)
- ir.Primitive visitExpressionStatement(ast.ExpressionStatement node) {
- assert(irBuilder.isOpen);
- if (node.expression is ast.Throw) {
- // Throw expressions that occur as statements are translated differently
- // from ones that occur as subexpressions. This is achieved by peeking
- // at statement-level expressions here.
- irBuilder.buildThrow(visit(node.expression));
- } else {
- visit(node.expression);
- }
- return null;
- }
-
- ir.Primitive visitRethrow(ast.Rethrow node) {
- assert(irBuilder.isOpen);
- irBuilder.buildRethrow();
- return null;
- }
-
- /// Construct a method that executes the forwarding call to the target
- /// constructor. This is only required, if the forwarding factory
- /// constructor can potentially be the target of a reflective call, because
- /// the builder shortcuts calls to redirecting factories at the call site
- /// (see [handleConstructorInvoke]).
- visitRedirectingFactoryBody(ast.RedirectingFactoryBody node) {
- ConstructorElement targetConstructor =
- elements.getRedirectingTargetConstructor(node).implementation;
- ConstructorElement redirectingConstructor =
- irBuilder.state.currentElement.implementation;
- List<ir.Primitive> arguments = <ir.Primitive>[];
- FunctionSignature redirectingSignature =
- redirectingConstructor.functionSignature;
- List<String> namedParameters = <String>[];
- redirectingSignature.forEachParameter((ParameterElement parameter) {
- arguments.add(irBuilder.environment.lookup(parameter));
- if (parameter.isNamed) {
- namedParameters.add(parameter.name);
- }
- });
- ClassElement cls = redirectingConstructor.enclosingClass;
- InterfaceType targetType =
- redirectingConstructor.computeEffectiveTargetType(cls.thisType);
- CallStructure callStructure =
- new CallStructure(redirectingSignature.parameterCount, namedParameters);
- callStructure =
- normalizeStaticArguments(callStructure, targetConstructor, arguments);
- ir.Primitive instance = irBuilder.buildConstructorInvocation(
- targetConstructor,
- callStructure,
- targetType,
- arguments,
- sourceInformationBuilder.buildNew(node));
- irBuilder.buildReturn(
- value: instance,
- sourceInformation: sourceInformationBuilder.buildReturn(node));
- }
-
- visitFor(ast.For node) {
- List<LocalElement> loopVariables = <LocalElement>[];
- if (node.initializer is ast.VariableDefinitions) {
- ast.VariableDefinitions definitions = node.initializer;
- for (ast.Node node in definitions.definitions.nodes) {
- LocalElement loopVariable = elements[node];
- loopVariables.add(loopVariable);
- }
- }
-
- JumpTarget target = elements.getTargetDefinition(node);
- irBuilder.buildFor(
- buildInitializer: subbuild(node.initializer),
- buildCondition: subbuild(node.condition),
- buildBody: subbuild(node.body),
- buildUpdate: subbuildSequence(node.update),
- closureScope: getClosureScopeForNode(node),
- loopVariables: loopVariables,
- target: target);
- }
-
- visitIf(ast.If node) {
- irBuilder.buildIf(build(node.condition), subbuild(node.thenPart),
- subbuild(node.elsePart), sourceInformationBuilder.buildIf(node));
- }
-
- visitLabeledStatement(ast.LabeledStatement node) {
- ast.Statement body = node.statement;
- if (body is ast.Loop) {
- visit(body);
- } else {
- JumpTarget target = elements.getTargetDefinition(body);
- irBuilder.buildLabeledStatement(
- buildBody: subbuild(body), target: target);
- }
- }
-
- visitDoWhile(ast.DoWhile node) {
- irBuilder.buildDoWhile(
- buildBody: subbuild(node.body),
- buildCondition: subbuild(node.condition),
- target: elements.getTargetDefinition(node),
- closureScope: getClosureScopeForNode(node));
- }
-
- visitWhile(ast.While node) {
- irBuilder.buildWhile(
- buildCondition: subbuild(node.condition),
- buildBody: subbuild(node.body),
- target: elements.getTargetDefinition(node),
- closureScope: getClosureScopeForNode(node));
- }
-
- visitAsyncForIn(ast.AsyncForIn node) {
- // Translate await for into a loop over a StreamIterator. The source
- // statement:
- //
- // await for (<decl> in <stream>) <body>
- //
- // is translated as if it were:
- //
- // var iterator = new StreamIterator(<stream>);
- // try {
- // while (await iterator.hasNext()) {
- // <decl> = await iterator.current;
- // <body>
- // }
- // } finally {
- // await iterator.cancel();
- // }
- ir.Primitive stream = visit(node.expression);
- ir.Primitive dummyTypeArgument = irBuilder.buildNullConstant();
- ConstructorElement constructor = helpers.streamIteratorConstructor;
- ir.Primitive iterator = irBuilder.addPrimitive(new ir.InvokeConstructor(
- constructor.enclosingClass.thisType,
- constructor,
- new Selector.callConstructor(constructor.memberName, 1),
- <ir.Primitive>[stream, dummyTypeArgument],
- sourceInformationBuilder.buildGeneric(node)));
-
- buildTryBody(IrBuilder builder) {
- ir.Node buildLoopCondition(IrBuilder builder) {
- ir.Primitive moveNext = builder.buildDynamicInvocation(
- iterator,
- Selectors.moveNext,
- elements.getMoveNextTypeMask(node),
- <ir.Primitive>[],
- sourceInformationBuilder.buildForInMoveNext(node));
- return builder.addPrimitive(new ir.Await(moveNext));
- }
-
- ir.Node buildLoopBody(IrBuilder builder) {
- return withBuilder(builder, () {
- ir.Primitive current = irBuilder.buildDynamicInvocation(
- iterator,
- Selectors.current,
- elements.getCurrentTypeMask(node),
- <ir.Primitive>[],
- sourceInformationBuilder.buildForInCurrent(node));
- Element variable = elements.getForInVariable(node);
- SourceInformation sourceInformation =
- sourceInformationBuilder.buildForInSet(node);
- if (Elements.isLocal(variable)) {
- if (node.declaredIdentifier.asVariableDefinitions() != null) {
- irBuilder.declareLocalVariable(variable);
- }
- irBuilder.buildLocalVariableSet(
- variable, current, sourceInformation);
- } else if (Elements.isError(variable) ||
- Elements.isMalformed(variable)) {
- Selector selector =
- new Selector.setter(new Name(variable.name, variable.library));
- List<ir.Primitive> args = <ir.Primitive>[current];
- // Note the comparison below. It can be the case that an element
- // isError and isMalformed.
- if (Elements.isError(variable)) {
- irBuilder.buildStaticNoSuchMethod(
- selector, args, sourceInformation);
- } else {
- irBuilder.buildErroneousInvocation(
- variable, selector, args, sourceInformation);
- }
- } else if (Elements.isStaticOrTopLevel(variable)) {
- if (variable.isField) {
- irBuilder.addPrimitive(new ir.SetStatic(variable, current));
- } else {
- irBuilder.buildStaticSetterSet(
- variable, current, sourceInformation);
- }
- } else {
- ir.Primitive receiver = irBuilder.buildThis();
- ast.Node identifier = node.declaredIdentifier;
- irBuilder.buildDynamicSet(
- receiver,
- elements.getSelector(identifier),
- elements.getTypeMask(identifier),
- current,
- sourceInformation);
- }
- visit(node.body);
- });
- }
-
- builder.buildWhile(
- buildCondition: buildLoopCondition,
- buildBody: buildLoopBody,
- target: elements.getTargetDefinition(node),
- closureScope: getClosureScopeForNode(node));
- }
-
- ir.Node buildFinallyBody(IrBuilder builder) {
- ir.Primitive cancellation = builder.buildDynamicInvocation(
- iterator,
- Selectors.cancel,
- backend.dynamicType,
- <ir.Primitive>[],
- sourceInformationBuilder.buildGeneric(node));
- return builder.addPrimitive(new ir.Await(cancellation));
- }
-
- irBuilder.buildTryFinally(
- new TryStatementInfo(), buildTryBody, buildFinallyBody);
- }
-
- visitAwait(ast.Await node) {
- assert(irBuilder.isOpen);
- ir.Primitive value = visit(node.expression);
- return irBuilder.addPrimitive(new ir.Await(value));
- }
-
- visitYield(ast.Yield node) {
- assert(irBuilder.isOpen);
- ir.Primitive value = visit(node.expression);
- return irBuilder.addPrimitive(new ir.Yield(value, node.hasStar));
- }
-
- visitSyncForIn(ast.SyncForIn node) {
- // [node.declaredIdentifier] can be either an [ast.VariableDefinitions]
- // (defining a new local variable) or a send designating some existing
- // variable.
- ast.Node identifier = node.declaredIdentifier;
- ast.VariableDefinitions variableDeclaration =
- identifier.asVariableDefinitions();
- Element variableElement = elements.getForInVariable(node);
- Selector selector = elements.getSelector(identifier);
-
- irBuilder.buildForIn(
- buildExpression: subbuild(node.expression),
- buildVariableDeclaration: subbuild(variableDeclaration),
- variableElement: variableElement,
- variableSelector: selector,
- variableMask: elements.getTypeMask(identifier),
- variableSetSourceInformation:
- sourceInformationBuilder.buildForInSet(node),
- currentMask: elements.getCurrentTypeMask(node),
- currentSourceInformation:
- sourceInformationBuilder.buildForInCurrent(node),
- moveNextMask: elements.getMoveNextTypeMask(node),
- moveNextSourceInformation:
- sourceInformationBuilder.buildForInMoveNext(node),
- iteratorMask: elements.getIteratorTypeMask(node),
- iteratorSourceInformation:
- sourceInformationBuilder.buildForInIterator(node),
- buildBody: subbuild(node.body),
- target: elements.getTargetDefinition(node),
- closureScope: getClosureScopeForNode(node));
- }
-
- /// If compiling with trusted type annotations, assumes that [value] is
- /// now known to be `null` or an instance of [type].
- ///
- /// This is also where we should add type checks in checked mode, but this
- /// is not supported yet.
- ir.Primitive checkType(ir.Primitive value, DartType dartType) {
- if (!compiler.options.trustTypeAnnotations) return value;
- TypeMask type = typeMaskSystem.subtypesOf(dartType).nullable();
- return irBuilder.addPrimitive(new ir.Refinement(value, type));
- }
-
- ir.Primitive checkTypeVsElement(ir.Primitive value, TypedElement element) {
- return checkType(value, element.type);
- }
-
- ir.Primitive visitVariableDefinitions(ast.VariableDefinitions node) {
- assert(irBuilder.isOpen);
- for (ast.Node definition in node.definitions.nodes) {
- Element element = elements[definition];
- ir.Primitive initialValue;
- // Definitions are either SendSets if there is an initializer, or
- // Identifiers if there is no initializer.
- if (definition is ast.SendSet) {
- assert(!definition.arguments.isEmpty);
- assert(definition.arguments.tail.isEmpty);
- initialValue = visit(definition.arguments.head);
- initialValue = checkTypeVsElement(initialValue, element);
- } else {
- assert(definition is ast.Identifier);
- }
- irBuilder.declareLocalVariable(element, initialValue: initialValue);
- }
- return null;
- }
-
- static final RegExp nativeRedirectionRegExp =
- new RegExp(r'^[a-zA-Z][a-zA-Z_$0-9]*$');
-
- // Build(Return(e), C) = C'[InvokeContinuation(return, x)]
- // where (C', x) = Build(e, C)
- //
- // Return without a subexpression is translated as if it were return null.
- visitReturn(ast.Return node) {
- assert(irBuilder.isOpen);
- SourceInformation source = sourceInformationBuilder.buildReturn(node);
- if (node.beginToken.value == 'native') {
- FunctionElement function = irBuilder.state.currentElement;
- assert(backend.isNative(function));
- ast.Node nativeBody = node.expression;
- if (nativeBody != null) {
- ast.LiteralString jsCode = nativeBody.asLiteralString();
- String javaScriptCode = jsCode.dartString.slowToString();
- assert(invariant(
- nativeBody, !nativeRedirectionRegExp.hasMatch(javaScriptCode),
- message: "Deprecated syntax, use @JSName('name') instead."));
- assert(invariant(
- nativeBody, function.functionSignature.parameterCount == 0,
- message: 'native "..." syntax is restricted to '
- 'functions with zero parameters.'));
- irBuilder.buildNativeFunctionBody(function, javaScriptCode,
- sourceInformationBuilder.buildForeignCode(node));
- } else {
- String name = backend.nativeData.getFixedBackendName(function);
- irBuilder.buildRedirectingNativeFunctionBody(function, name, source);
- }
- } else {
- irBuilder.buildReturn(
- value: build(node.expression), sourceInformation: source);
- }
- }
-
- visitSwitchStatement(ast.SwitchStatement node) {
- // Dart switch cases can be labeled and be the target of continue from
- // within the switch. Such cases are 'recursive'. If there are any
- // recursive cases, we implement the switch using a pair of switches with
- // the second one switching over a state variable in a loop. The first
- // switch contains the non-recursive cases, and the second switch contains
- // the recursive ones.
- //
- // For example, for the Dart switch:
- //
- // switch (E) {
- // case 0:
- // BODY0;
- // break;
- // LABEL0: case 1:
- // BODY1;
- // break;
- // case 2:
- // BODY2;
- // continue LABEL1;
- // LABEL1: case 3:
- // BODY3;
- // continue LABEL0;
- // default:
- // BODY4;
- // }
- //
- // We translate it as if it were the JavaScript:
- //
- // var state = -1;
- // switch (E) {
- // case 0:
- // BODY0;
- // break;
- // case 1:
- // state = 0; // Recursive, label ID = 0.
- // break;
- // case 2:
- // BODY2;
- // state = 1; // Continue to label ID = 1.
- // break;
- // case 3:
- // state = 1; // Recursive, label ID = 1.
- // break;
- // default:
- // BODY4;
- // }
- // L: while (state != -1) {
- // case 0:
- // BODY1;
- // break L; // Break from switch becomes break from loop.
- // case 1:
- // BODY2;
- // state = 0; // Continue to label ID = 0.
- // break;
- // }
- assert(irBuilder.isOpen);
- // Preprocess: compute a list of cases that are the target of continue.
- // These are the so-called 'recursive' cases.
- List<JumpTarget> continueTargets = <JumpTarget>[];
- List<ast.Node> switchCases = node.cases.nodes.toList();
- for (ast.SwitchCase switchCase in switchCases) {
- for (ast.Node labelOrCase in switchCase.labelsAndCases) {
- if (labelOrCase is ast.Label) {
- LabelDefinition definition = elements.getLabelDefinition(labelOrCase);
- if (definition != null && definition.isContinueTarget) {
- continueTargets.add(definition.target);
- }
- }
- }
- }
-
- // If any cases are continue targets, use an anonymous local value to
- // implement a state machine. The initial value is -1.
- ir.Primitive initial;
- int stateIndex;
- if (continueTargets.isNotEmpty) {
- initial = irBuilder.buildIntegerConstant(-1);
- stateIndex = irBuilder.environment.length;
- irBuilder.environment.extend(null, initial);
- }
-
- // Use a simple switch for the non-recursive cases. A break will go to the
- // join-point after the switch. A continue to a labeled case will assign
- // to the state variable and go to the join-point.
- ir.Primitive value = visit(node.expression);
- JumpCollector join = new ForwardJumpCollector(irBuilder.environment,
- target: elements.getTargetDefinition(node));
- irBuilder.state.breakCollectors.add(join);
- for (int i = 0; i < continueTargets.length; ++i) {
- // The state value is i, the case's position in the list of recursive
- // cases.
- irBuilder.state.continueCollectors
- .add(new GotoJumpCollector(continueTargets[i], stateIndex, i, join));
- }
-
- // For each non-default case use a pair of functions, one to translate the
- // condition and one to translate the body. For the default case use a
- // function to translate the body. Use continueTargetIterator as a pointer
- // to the next recursive case.
- Iterator<JumpTarget> continueTargetIterator = continueTargets.iterator;
- continueTargetIterator.moveNext();
- List<SwitchCaseInfo> cases = <SwitchCaseInfo>[];
- SubbuildFunction buildDefaultBody;
- for (ast.SwitchCase switchCase in switchCases) {
- JumpTarget nextContinueTarget = continueTargetIterator.current;
- if (switchCase.isDefaultCase) {
- if (nextContinueTarget != null &&
- switchCase == nextContinueTarget.statement) {
- // In this simple switch, recursive cases are as if they immediately
- // continued to themselves.
- buildDefaultBody = nested(() {
- irBuilder.buildContinue(nextContinueTarget);
- });
- continueTargetIterator.moveNext();
- } else {
- // Non-recursive cases consist of the translation of the body.
- // For the default case, there is implicitly a break if control
- // flow reaches the end.
- buildDefaultBody = nested(() {
- irBuilder.buildSequence(switchCase.statements, visit);
- if (irBuilder.isOpen) irBuilder.jumpTo(join);
- });
- }
- continue;
- }
-
- ir.Primitive buildCondition(IrBuilder builder) {
- // There can be multiple cases sharing the same body, because empty
- // cases are allowed to fall through to the next one. Each case is
- // a comparison, build a short-circuited disjunction of all of them.
- return withBuilder(builder, () {
- ir.Primitive condition;
- for (ast.Node labelOrCase in switchCase.labelsAndCases) {
- if (labelOrCase is ast.CaseMatch) {
- ir.Primitive buildComparison() {
- ir.Primitive constant =
- translateConstant(labelOrCase.expression);
- return irBuilder.buildIdentical(value, constant);
- }
-
- if (condition == null) {
- condition = buildComparison();
- } else {
- condition = irBuilder.buildLogicalOperator(
- condition,
- nested(buildComparison),
- sourceInformationBuilder.buildSwitchCase(switchCase),
- isLazyOr: true);
- }
- }
- }
- return condition;
- });
- }
-
- SubbuildFunction buildBody;
- if (nextContinueTarget != null &&
- switchCase == nextContinueTarget.statement) {
- // Recursive cases are as if they immediately continued to themselves.
- buildBody = nested(() {
- irBuilder.buildContinue(nextContinueTarget);
- });
- continueTargetIterator.moveNext();
- } else {
- // Non-recursive cases consist of the translation of the body. It is a
- // runtime error if control-flow reaches the end of the body of any but
- // the last case.
- buildBody = (IrBuilder builder) {
- withBuilder(builder, () {
- irBuilder.buildSequence(switchCase.statements, visit);
- if (irBuilder.isOpen) {
- if (switchCase == switchCases.last) {
- irBuilder.jumpTo(join);
- } else {
- Element error = helpers.fallThroughError;
- ir.Primitive exception = irBuilder.buildInvokeStatic(
- error,
- new Selector.fromElement(error),
- <ir.Primitive>[],
- sourceInformationBuilder.buildGeneric(node));
- irBuilder.buildThrow(exception);
- }
- }
- });
- return null;
- };
- }
-
- cases.add(new SwitchCaseInfo(buildCondition, buildBody,
- sourceInformationBuilder.buildSwitchCase(switchCase)));
- }
-
- irBuilder.buildSimpleSwitch(join, cases, buildDefaultBody);
- irBuilder.state.breakCollectors.removeLast();
- irBuilder.state.continueCollectors.length -= continueTargets.length;
- if (continueTargets.isEmpty) return;
-
- // If there were recursive cases build a while loop whose body is a
- // switch containing (only) the recursive cases. The condition is
- // 'state != initialValue' so the loop is not taken when the state variable
- // has not been assigned.
- //
- // 'loop' is the join-point of the exits from the inner switch which will
- // perform another iteration of the loop. 'exit' is the join-point of the
- // breaks from the switch, outside the loop.
- JumpCollector loop = new ForwardJumpCollector(irBuilder.environment);
- JumpCollector exit = new ForwardJumpCollector(irBuilder.environment,
- target: elements.getTargetDefinition(node));
- irBuilder.state.breakCollectors.add(exit);
- for (int i = 0; i < continueTargets.length; ++i) {
- irBuilder.state.continueCollectors
- .add(new GotoJumpCollector(continueTargets[i], stateIndex, i, loop));
- }
- cases.clear();
- for (int i = 0; i < continueTargets.length; ++i) {
- // The conditions compare to the recursive case index.
- ir.Primitive buildCondition(IrBuilder builder) {
- ir.Primitive constant = builder.buildIntegerConstant(i);
- return builder.buildIdentical(
- builder.environment.index2value[stateIndex], constant);
- }
-
- ir.Primitive buildBody(IrBuilder builder) {
- withBuilder(builder, () {
- ast.SwitchCase switchCase = continueTargets[i].statement;
- irBuilder.buildSequence(switchCase.statements, visit);
- if (irBuilder.isOpen) {
- if (switchCase == switchCases.last) {
- irBuilder.jumpTo(exit);
- } else {
- Element error = helpers.fallThroughError;
- ir.Primitive exception = irBuilder.buildInvokeStatic(
- error,
- new Selector.fromElement(error),
- <ir.Primitive>[],
- sourceInformationBuilder.buildGeneric(node));
- irBuilder.buildThrow(exception);
- }
- }
- });
- return null;
- }
-
- cases.add(new SwitchCaseInfo(buildCondition, buildBody,
- sourceInformationBuilder.buildSwitch(node)));
- }
-
- // A loop with a simple switch in the body.
- IrBuilder whileBuilder = irBuilder.makeDelimitedBuilder();
- whileBuilder.buildWhile(buildCondition: (IrBuilder builder) {
- ir.Primitive condition = builder.buildIdentical(
- builder.environment.index2value[stateIndex], initial);
- return builder.buildNegation(
- condition, sourceInformationBuilder.buildSwitch(node));
- }, buildBody: (IrBuilder builder) {
- builder.buildSimpleSwitch(loop, cases, null);
- });
- // Jump to the exit continuation. This jump is the body of the loop exit
- // continuation, so the loop exit continuation can be eta-reduced. The
- // jump is here for simplicity because `buildWhile` does not expose the
- // loop's exit continuation directly and has already emitted all jumps
- // to it anyway.
- whileBuilder.jumpTo(exit);
- irBuilder.add(new ir.LetCont(exit.continuation, whileBuilder.root));
- irBuilder.environment = exit.environment;
- irBuilder.environment.discard(1); // Discard the state variable.
- irBuilder.state.breakCollectors.removeLast();
- irBuilder.state.continueCollectors.length -= continueTargets.length;
- }
-
- visitTryStatement(ast.TryStatement node) {
- List<CatchClauseInfo> catchClauseInfos = <CatchClauseInfo>[];
- for (ast.CatchBlock catchClause in node.catchBlocks.nodes) {
- LocalVariableElement exceptionVariable;
- if (catchClause.exception != null) {
- exceptionVariable = elements[catchClause.exception];
- }
- LocalVariableElement stackTraceVariable;
- if (catchClause.trace != null) {
- stackTraceVariable = elements[catchClause.trace];
- }
- DartType type;
- if (catchClause.onKeyword != null) {
- type = elements.getType(catchClause.type);
- }
- catchClauseInfos.add(new CatchClauseInfo(
- type: type,
- exceptionVariable: exceptionVariable,
- stackTraceVariable: stackTraceVariable,
- buildCatchBlock: subbuild(catchClause.block),
- sourceInformation: sourceInformationBuilder.buildCatch(catchClause)));
- }
-
- assert(!node.catchBlocks.isEmpty || node.finallyBlock != null);
- if (!node.catchBlocks.isEmpty && node.finallyBlock != null) {
- // Try/catch/finally is encoded in terms of try/catch and try/finally:
- //
- // try tryBlock catch (ex, st) catchBlock finally finallyBlock
- // ==>
- // try { try tryBlock catch (ex, st) catchBlock } finally finallyBlock
- irBuilder.buildTryFinally(tryStatements[node.finallyBlock],
- (IrBuilder inner) {
- inner.buildTryCatch(tryStatements[node.catchBlocks],
- subbuild(node.tryBlock), catchClauseInfos);
- }, subbuild(node.finallyBlock));
- } else if (!node.catchBlocks.isEmpty) {
- irBuilder.buildTryCatch(tryStatements[node.catchBlocks],
- subbuild(node.tryBlock), catchClauseInfos);
- } else {
- irBuilder.buildTryFinally(tryStatements[node.finallyBlock],
- subbuild(node.tryBlock), subbuild(node.finallyBlock));
- }
- }
-
- // ## Expressions ##
- ir.Primitive visitConditional(ast.Conditional node) {
- return irBuilder.buildConditional(
- build(node.condition),
- subbuild(node.thenExpression),
- subbuild(node.elseExpression),
- sourceInformationBuilder.buildIf(node));
- }
-
- // For all simple literals:
- // Build(Literal(c), C) = C[let val x = Constant(c) in [], x]
- ir.Primitive visitLiteralBool(ast.LiteralBool node) {
- assert(irBuilder.isOpen);
- return irBuilder.buildBooleanConstant(node.value);
- }
-
- ir.Primitive visitLiteralDouble(ast.LiteralDouble node) {
- assert(irBuilder.isOpen);
- return irBuilder.buildDoubleConstant(node.value);
- }
-
- ir.Primitive visitLiteralInt(ast.LiteralInt node) {
- assert(irBuilder.isOpen);
- return irBuilder.buildIntegerConstant(node.value);
- }
-
- ir.Primitive visitLiteralNull(ast.LiteralNull node) {
- assert(irBuilder.isOpen);
- return irBuilder.buildNullConstant();
- }
-
- ir.Primitive visitLiteralString(ast.LiteralString node) {
- assert(irBuilder.isOpen);
- return irBuilder.buildDartStringConstant(node.dartString);
- }
-
- ConstantValue getConstantForNode(ast.Node node) {
- return irBuilder.state.constants.getConstantValueForNode(node, elements);
- }
-
- ConstantValue getConstantForVariable(VariableElement element) {
- ConstantExpression constant = element.constant;
- if (constant != null) {
- return irBuilder.state.constants.getConstantValue(constant);
- }
- return null;
- }
-
- ir.Primitive buildConstantExpression(
- ConstantExpression expression, SourceInformation sourceInformation) {
- return irBuilder.buildConstant(
- irBuilder.state.constants.getConstantValue(expression),
- sourceInformation: sourceInformation);
- }
-
- /// Returns the allocation site-specific type for a given allocation.
- ///
- /// Currently, it is an error to call this with anything that is not the
- /// allocation site for a List object (a literal list or a call to one
- /// of the List constructors).
- TypeMask getAllocationSiteType(ast.Node node) {
- return compiler.typesTask
- .getGuaranteedTypeOfNode(elements.analyzedElement, node);
- }
-
- ir.Primitive visitLiteralList(ast.LiteralList node) {
- if (node.isConst) {
- return translateConstant(node);
- }
- List<ir.Primitive> values = node.elements.nodes.mapToList(visit);
- InterfaceType type = elements.getType(node);
- TypeMask allocationSiteType = getAllocationSiteType(node);
- // TODO(sra): In checked mode, the elements must be checked as though
- // operator[]= is called.
- ir.Primitive list = irBuilder.buildListLiteral(type, values,
- allocationSiteType: allocationSiteType);
- if (type.treatAsRaw) return list;
- // Call JSArray<E>.typed(allocation) to install the reified type.
- ConstructorElement constructor = helpers.jsArrayTypedConstructor;
- ir.Primitive tagged = irBuilder.buildConstructorInvocation(
- constructor.effectiveTarget,
- CallStructure.ONE_ARG,
- constructor.computeEffectiveTargetType(type),
- <ir.Primitive>[list],
- sourceInformationBuilder.buildNew(node));
-
- if (allocationSiteType == null) return tagged;
-
- return irBuilder
- .addPrimitive(new ir.Refinement(tagged, allocationSiteType));
- }
-
- ir.Primitive visitLiteralMap(ast.LiteralMap node) {
- assert(irBuilder.isOpen);
- if (node.isConst) {
- return translateConstant(node);
- }
-
- InterfaceType type = elements.getType(node);
-
- if (node.entries.nodes.isEmpty) {
- if (type.treatAsRaw) {
- return irBuilder.buildStaticFunctionInvocation(
- helpers.mapLiteralUntypedEmptyMaker,
- <ir.Primitive>[],
- sourceInformationBuilder.buildNew(node));
- } else {
- ConstructorElement constructor = helpers.mapLiteralConstructorEmpty;
- return irBuilder.buildConstructorInvocation(
- constructor.effectiveTarget,
- CallStructure.NO_ARGS,
- constructor.computeEffectiveTargetType(type),
- <ir.Primitive>[],
- sourceInformationBuilder.buildNew(node));
- }
- }
-
- List<ir.Primitive> keysAndValues = <ir.Primitive>[];
- for (ast.LiteralMapEntry entry in node.entries.nodes.toList()) {
- keysAndValues.add(visit(entry.key));
- keysAndValues.add(visit(entry.value));
- }
- ir.Primitive keysAndValuesList =
- irBuilder.buildListLiteral(null, keysAndValues);
-
- if (type.treatAsRaw) {
- return irBuilder.buildStaticFunctionInvocation(
- helpers.mapLiteralUntypedMaker,
- <ir.Primitive>[keysAndValuesList],
- sourceInformationBuilder.buildNew(node));
- } else {
- ConstructorElement constructor = helpers.mapLiteralConstructor;
- return irBuilder.buildConstructorInvocation(
- constructor.effectiveTarget,
- CallStructure.ONE_ARG,
- constructor.computeEffectiveTargetType(type),
- <ir.Primitive>[keysAndValuesList],
- sourceInformationBuilder.buildNew(node));
- }
- }
-
- ir.Primitive visitLiteralSymbol(ast.LiteralSymbol node) {
- assert(irBuilder.isOpen);
- return translateConstant(node);
- }
-
- ir.Primitive visitParenthesizedExpression(ast.ParenthesizedExpression node) {
- assert(irBuilder.isOpen);
- return visit(node.expression);
- }
-
- // Stores the result of visiting a CascadeReceiver, so we can return it from
- // its enclosing Cascade.
- ir.Primitive _currentCascadeReceiver;
-
- ir.Primitive visitCascadeReceiver(ast.CascadeReceiver node) {
- assert(irBuilder.isOpen);
- return _currentCascadeReceiver = visit(node.expression);
- }
-
- ir.Primitive visitCascade(ast.Cascade node) {
- assert(irBuilder.isOpen);
- var oldCascadeReceiver = _currentCascadeReceiver;
- // Throw away the result of visiting the expression.
- // Instead we return the result of visiting the CascadeReceiver.
- visit(node.expression);
- ir.Primitive receiver = _currentCascadeReceiver;
- _currentCascadeReceiver = oldCascadeReceiver;
- return receiver;
- }
-
- @override
- ir.Primitive visitAssert(ast.Assert node) {
- assert(irBuilder.isOpen);
- if (compiler.options.enableUserAssertions) {
- return giveup(node, 'assert in checked mode not implemented');
- } else {
- // The call to assert and its argument expression must be ignored
- // in production mode.
- // Assertions can only occur in expression statements, so no value needs
- // to be returned.
- return null;
- }
- }
-
- // ## Sends ##
- @override
- void previsitDeferredAccess(ast.Send node, PrefixElement prefix, _) {
- if (prefix != null) buildCheckDeferredIsLoaded(prefix, node);
- }
-
- /// Create a call to check that a deferred import has already been loaded.
- ir.Primitive buildCheckDeferredIsLoaded(PrefixElement prefix, ast.Send node) {
- SourceInformation sourceInformation =
- sourceInformationBuilder.buildCall(node, node.selector);
- ir.Primitive name = irBuilder.buildStringConstant(
- compiler.deferredLoadTask.getImportDeferName(node, prefix));
- ir.Primitive uri =
- irBuilder.buildStringConstant('${prefix.deferredImport.uri}');
- return irBuilder.buildStaticFunctionInvocation(
- helpers.checkDeferredIsLoaded,
- <ir.Primitive>[name, uri],
- sourceInformation);
- }
-
- ir.Primitive visitNamedArgument(ast.NamedArgument node) {
- assert(irBuilder.isOpen);
- return visit(node.expression);
- }
-
- @override
- ir.Primitive visitExpressionInvoke(ast.Send node, ast.Node expression,
- ast.NodeList argumentsNode, CallStructure callStructure, _) {
- ir.Primitive receiver = visit(expression);
- List<ir.Primitive> arguments = argumentsNode.nodes.mapToList(visit);
- callStructure = normalizeDynamicArguments(callStructure, arguments);
- return irBuilder.buildCallInvocation(receiver, callStructure, arguments,
- sourceInformationBuilder.buildCall(node, argumentsNode));
- }
-
- /// Returns `true` if [node] is a super call.
- // TODO(johnniwinther): Remove the need for this.
- bool isSuperCall(ast.Send node) {
- return node != null && node.receiver != null && node.receiver.isSuper();
- }
-
- @override
- ir.Primitive handleConstantGet(
- ast.Node node, ConstantExpression constant, _) {
- return buildConstantExpression(
- constant, sourceInformationBuilder.buildGet(node));
- }
-
- /// If [node] is null, returns this.
- /// Otherwise visits [node] and returns the result.
- ir.Primitive translateReceiver(ast.Expression node) {
- return node != null ? visit(node) : irBuilder.buildThis();
- }
-
- @override
- ir.Primitive handleDynamicGet(
- ast.Send node, ast.Node receiver, Name name, _) {
- return irBuilder.buildDynamicGet(
- translateReceiver(receiver),
- new Selector.getter(name),
- elements.getTypeMask(node),
- sourceInformationBuilder.buildGet(node));
- }
-
- @override
- ir.Primitive visitIfNotNullDynamicPropertyGet(
- ast.Send node, ast.Node receiver, Name name, _) {
- ir.Primitive target = visit(receiver);
- return irBuilder.buildIfNotNullSend(
- target,
- nested(() => irBuilder.buildDynamicGet(
- target,
- new Selector.getter(name),
- elements.getTypeMask(node),
- sourceInformationBuilder.buildGet(node))),
- sourceInformationBuilder.buildIf(node));
- }
-
- @override
- ir.Primitive visitDynamicTypeLiteralGet(
- ast.Send node, ConstantExpression constant, _) {
- return buildConstantExpression(
- constant, sourceInformationBuilder.buildGet(node));
- }
-
- @override
- ir.Primitive visitLocalVariableGet(
- ast.Send node, LocalVariableElement element, _) {
- return element.isConst
- ? irBuilder.buildConstant(getConstantForVariable(element),
- sourceInformation: sourceInformationBuilder.buildGet(node))
- : irBuilder.buildLocalGet(element);
- }
-
- ir.Primitive handleLocalGet(ast.Send node, LocalElement element, _) {
- return irBuilder.buildLocalGet(element);
- }
-
- @override
- ir.Primitive handleStaticFunctionGet(
- ast.Send node, MethodElement function, _) {
- return irBuilder.addPrimitive(new ir.GetStatic(function, isFinal: true));
- }
-
- @override
- ir.Primitive handleStaticGetterGet(ast.Send node, FunctionElement getter, _) {
- return buildStaticGetterGet(
- getter, node, sourceInformationBuilder.buildGet(node));
- }
-
- /// Create a getter invocation of the static getter [getter]. This also
- /// handles the special case where [getter] is the `loadLibrary`
- /// pseudo-function on library prefixes of deferred imports.
- ir.Primitive buildStaticGetterGet(MethodElement getter, ast.Send node,
- SourceInformation sourceInformation) {
- if (getter.isDeferredLoaderGetter) {
- PrefixElement prefix = getter.enclosingElement;
- ir.Primitive loadId = irBuilder.buildStringConstant(
- compiler.deferredLoadTask.getImportDeferName(node, prefix));
- return irBuilder.buildStaticFunctionInvocation(
- compiler.loadLibraryFunction,
- <ir.Primitive>[loadId],
- sourceInformation);
- } else {
- return irBuilder.buildStaticGetterGet(getter, sourceInformation);
- }
- }
-
- @override
- ir.Primitive visitSuperFieldGet(ast.Send node, FieldElement field, _) {
- return irBuilder.buildSuperFieldGet(
- field, sourceInformationBuilder.buildGet(node));
- }
-
- @override
- ir.Primitive visitSuperGetterGet(ast.Send node, FunctionElement getter, _) {
- return irBuilder.buildSuperGetterGet(
- getter, sourceInformationBuilder.buildGet(node));
- }
-
- @override
- ir.Primitive visitSuperMethodGet(ast.Send node, MethodElement method, _) {
- return irBuilder.buildSuperMethodGet(
- method, sourceInformationBuilder.buildGet(node));
- }
-
- @override
- ir.Primitive visitUnresolvedSuperGet(ast.Send node, Element element, _) {
- return buildSuperNoSuchMethod(
- elements.getSelector(node),
- elements.getTypeMask(node),
- [],
- sourceInformationBuilder.buildGet(node));
- }
-
- @override
- ir.Primitive visitUnresolvedSuperSet(
- ast.Send node, Element element, ast.Node rhs, _) {
- return buildSuperNoSuchMethod(
- elements.getSelector(node),
- elements.getTypeMask(node),
- [visit(rhs)],
- sourceInformationBuilder.buildAssignment(node));
- }
-
- @override
- ir.Primitive visitThisGet(ast.Identifier node, _) {
- if (irBuilder.state.thisParameter == null) {
- // TODO(asgerf,johnniwinther): Should be in a visitInvalidThis method.
- // 'this' in static context. Just translate to null.
- assert(compiler.compilationFailed);
- return irBuilder.buildNullConstant();
- }
- return irBuilder.buildThis();
- }
-
- ir.Primitive translateTypeVariableTypeLiteral(
- TypeVariableElement element, SourceInformation sourceInformation) {
- return irBuilder.buildReifyTypeVariable(element.type, sourceInformation);
- }
-
- @override
- ir.Primitive visitTypeVariableTypeLiteralGet(
- ast.Send node, TypeVariableElement element, _) {
- return translateTypeVariableTypeLiteral(
- element, sourceInformationBuilder.buildGet(node));
- }
-
- ir.Primitive translateLogicalOperator(ast.Expression left,
- ast.Expression right, SourceInformation sourceInformation,
- {bool isLazyOr}) {
- ir.Primitive leftValue = visit(left);
-
- ir.Primitive buildRightValue(IrBuilder rightBuilder) {
- return withBuilder(rightBuilder, () => visit(right));
- }
-
- return irBuilder.buildLogicalOperator(
- leftValue, buildRightValue, sourceInformation,
- isLazyOr: isLazyOr);
- }
-
- @override
- ir.Primitive visitIfNull(ast.Send node, ast.Node left, ast.Node right, _) {
- return irBuilder.buildIfNull(
- build(left), subbuild(right), sourceInformationBuilder.buildIf(node));
- }
-
- @override
- ir.Primitive visitLogicalAnd(
- ast.Send node, ast.Node left, ast.Node right, _) {
- return translateLogicalOperator(
- left, right, sourceInformationBuilder.buildIf(node),
- isLazyOr: false);
- }
-
- @override
- ir.Primitive visitLogicalOr(ast.Send node, ast.Node left, ast.Node right, _) {
- return translateLogicalOperator(
- left, right, sourceInformationBuilder.buildIf(node),
- isLazyOr: true);
- }
-
- @override
- ir.Primitive visitAs(ast.Send node, ast.Node expression, DartType type, _) {
- ir.Primitive receiver = visit(expression);
- return irBuilder.buildTypeOperator(
- receiver, type, sourceInformationBuilder.buildAs(node),
- isTypeTest: false);
- }
-
- @override
- ir.Primitive visitIs(ast.Send node, ast.Node expression, DartType type, _) {
- ir.Primitive value = visit(expression);
- return irBuilder.buildTypeOperator(
- value, type, sourceInformationBuilder.buildIs(node),
- isTypeTest: true);
- }
-
- @override
- ir.Primitive visitIsNot(
- ast.Send node, ast.Node expression, DartType type, _) {
- ir.Primitive value = visit(expression);
- ir.Primitive check = irBuilder.buildTypeOperator(
- value, type, sourceInformationBuilder.buildIs(node),
- isTypeTest: true);
- return irBuilder.buildNegation(
- check, sourceInformationBuilder.buildIf(node));
- }
-
- ir.Primitive translateBinary(ast.Send node, ast.Node left,
- op.BinaryOperator operator, ast.Node right) {
- ir.Primitive receiver = visit(left);
- Selector selector = new Selector.binaryOperator(operator.selectorName);
- List<ir.Primitive> arguments = <ir.Primitive>[visit(right)];
- CallStructure callStructure =
- normalizeDynamicArguments(selector.callStructure, arguments);
- return irBuilder.buildDynamicInvocation(
- receiver,
- new Selector(selector.kind, selector.memberName, callStructure),
- elements.getTypeMask(node),
- arguments,
- sourceInformationBuilder.buildCall(node, node.selector));
- }
-
- @override
- ir.Primitive visitBinary(ast.Send node, ast.Node left,
- op.BinaryOperator operator, ast.Node right, _) {
- return translateBinary(node, left, operator, right);
- }
-
- @override
- ir.Primitive visitIndex(ast.Send node, ast.Node receiver, ast.Node index, _) {
- ir.Primitive target = visit(receiver);
- Selector selector = new Selector.index();
- List<ir.Primitive> arguments = <ir.Primitive>[visit(index)];
- CallStructure callStructure =
- normalizeDynamicArguments(selector.callStructure, arguments);
- return irBuilder.buildDynamicInvocation(
- target,
- new Selector(selector.kind, selector.memberName, callStructure),
- elements.getTypeMask(node),
- arguments,
- sourceInformationBuilder.buildCall(receiver, node.selector));
- }
-
- ir.Primitive translateSuperBinary(
- FunctionElement function,
- op.BinaryOperator operator,
- ast.Node argument,
- SourceInformation sourceInformation) {
- List<ir.Primitive> arguments = <ir.Primitive>[visit(argument)];
- return irBuilder.buildSuperMethodInvocation(
- function, CallStructure.ONE_ARG, arguments, sourceInformation);
- }
-
- @override
- ir.Primitive visitSuperBinary(ast.Send node, FunctionElement function,
- op.BinaryOperator operator, ast.Node argument, _) {
- return translateSuperBinary(function, operator, argument,
- sourceInformationBuilder.buildBinary(node));
- }
-
- @override
- ir.Primitive visitSuperIndex(
- ast.Send node, FunctionElement function, ast.Node index, _) {
- return irBuilder.buildSuperIndex(
- function, visit(index), sourceInformationBuilder.buildIndex(node));
- }
-
- @override
- ir.Primitive visitEquals(ast.Send node, ast.Node left, ast.Node right, _) {
- return translateBinary(node, left, op.BinaryOperator.EQ, right);
- }
-
- @override
- ir.Primitive visitSuperEquals(
- ast.Send node, FunctionElement function, ast.Node argument, _) {
- return translateSuperBinary(function, op.BinaryOperator.EQ, argument,
- sourceInformationBuilder.buildBinary(node));
- }
-
- @override
- ir.Primitive visitNot(ast.Send node, ast.Node expression, _) {
- return irBuilder.buildNegation(
- visit(expression), sourceInformationBuilder.buildIf(node));
- }
-
- @override
- ir.Primitive visitNotEquals(ast.Send node, ast.Node left, ast.Node right, _) {
- return irBuilder.buildNegation(
- translateBinary(node, left, op.BinaryOperator.NOT_EQ, right),
- sourceInformationBuilder.buildIf(node));
- }
-
- @override
- ir.Primitive visitSuperNotEquals(
- ast.Send node, FunctionElement function, ast.Node argument, _) {
- return irBuilder.buildNegation(
- translateSuperBinary(function, op.BinaryOperator.NOT_EQ, argument,
- sourceInformationBuilder.buildBinary(node)),
- sourceInformationBuilder.buildIf(node));
- }
-
- @override
- ir.Primitive visitUnary(
- ast.Send node, op.UnaryOperator operator, ast.Node expression, _) {
- // TODO(johnniwinther): Clean up the creation of selectors.
- Selector selector = operator.selector;
- ir.Primitive receiver = translateReceiver(expression);
- return irBuilder.buildDynamicInvocation(
- receiver,
- selector,
- elements.getTypeMask(node),
- const [],
- sourceInformationBuilder.buildCall(expression, node));
- }
-
- @override
- ir.Primitive visitSuperUnary(
- ast.Send node, op.UnaryOperator operator, FunctionElement function, _) {
- return irBuilder.buildSuperMethodInvocation(function, CallStructure.NO_ARGS,
- const [], sourceInformationBuilder.buildCall(node, node));
- }
-
- // TODO(johnniwinther): Handle this in the [IrBuilder] to ensure the correct
- // semantic correlation between arguments and invocation.
- CallStructure translateDynamicArguments(ast.NodeList nodeList,
- CallStructure callStructure, List<ir.Primitive> arguments) {
- assert(arguments.isEmpty);
- for (ast.Node node in nodeList) arguments.add(visit(node));
- return normalizeDynamicArguments(callStructure, arguments);
- }
-
- // TODO(johnniwinther): Handle this in the [IrBuilder] to ensure the correct
- // semantic correlation between arguments and invocation.
- CallStructure translateStaticArguments(ast.NodeList nodeList, Element element,
- CallStructure callStructure, List<ir.Primitive> arguments) {
- assert(arguments.isEmpty);
- for (ast.Node node in nodeList) arguments.add(visit(node));
- return normalizeStaticArguments(callStructure, element, arguments);
- }
-
- ir.Primitive translateCallInvoke(
- ir.Primitive target,
- ast.NodeList argumentsNode,
- CallStructure callStructure,
- SourceInformation sourceInformation) {
- List<ir.Primitive> arguments = <ir.Primitive>[];
- callStructure =
- translateDynamicArguments(argumentsNode, callStructure, arguments);
- return irBuilder.buildCallInvocation(
- target, callStructure, arguments, sourceInformation);
- }
-
- @override
- ir.Primitive handleConstantInvoke(ast.Send node, ConstantExpression constant,
- ast.NodeList arguments, CallStructure callStructure, _) {
- ir.Primitive target = buildConstantExpression(
- constant, sourceInformationBuilder.buildGet(node));
- return translateCallInvoke(target, arguments, callStructure,
- sourceInformationBuilder.buildCall(node, arguments));
- }
-
- @override
- ir.Primitive handleConstructorInvoke(
- ast.NewExpression node,
- ConstructorElement constructor,
- DartType type,
- ast.NodeList argumentsNode,
- CallStructure callStructure,
- _) {
- // TODO(sigmund): move these checks down after visiting arguments
- // (see issue #25355)
- ast.Send send = node.send;
- // If an allocation refers to a type using a deferred import prefix (e.g.
- // `new lib.A()`), we must ensure that the deferred import has already been
- // loaded.
- var prefix =
- compiler.deferredLoadTask.deferredPrefixElement(send, elements);
- if (prefix != null) buildCheckDeferredIsLoaded(prefix, send);
-
- // We also emit deferred import checks when using redirecting factories that
- // refer to deferred prefixes.
- if (constructor.isRedirectingFactory && !constructor.isCyclicRedirection) {
- ConstructorElement current = constructor;
- while (current.isRedirectingFactory) {
- var prefix = current.redirectionDeferredPrefix;
- if (prefix != null) buildCheckDeferredIsLoaded(prefix, send);
- current = current.immediateRedirectionTarget;
- }
- }
-
- List<ir.Primitive> arguments = argumentsNode.nodes.mapToList(visit);
- if (constructor.isGenerativeConstructor &&
- backend.isNativeOrExtendsNative(constructor.enclosingClass)) {
- arguments.insert(0, irBuilder.buildNullConstant());
- }
- // Use default values from the effective target, not the immediate target.
- ConstructorElement target;
- if (constructor == compiler.symbolConstructor) {
- // The Symbol constructor should perform validation of its argument
- // which is not expressible as a Dart const constructor. Instead, the
- // libraries contain a dummy const constructor implementation that
- // doesn't perform validation and the compiler compiles a call to
- // (non-const) Symbol.validated when it sees new Symbol(...).
- target = helpers.symbolValidatedConstructor;
- } else {
- target = constructor.implementation;
- }
- while (target.isRedirectingFactory && !target.isCyclicRedirection) {
- target = target.effectiveTarget.implementation;
- }
-
- callStructure = normalizeStaticArguments(callStructure, target, arguments);
- TypeMask allocationSiteType;
-
- if (Elements.isFixedListConstructorCall(constructor, send, compiler) ||
- Elements.isGrowableListConstructorCall(constructor, send, compiler) ||
- Elements.isFilledListConstructorCall(constructor, send, compiler) ||
- Elements.isConstructorOfTypedArraySubclass(constructor, compiler)) {
- allocationSiteType = getAllocationSiteType(send);
- }
- ConstructorElement constructorImplementation = constructor.implementation;
- return irBuilder.buildConstructorInvocation(
- target,
- callStructure,
- constructorImplementation.computeEffectiveTargetType(type),
- arguments,
- sourceInformationBuilder.buildNew(node),
- allocationSiteType: allocationSiteType);
- }
-
- @override
- ir.Primitive handleDynamicInvoke(ast.Send node, ast.Node receiver,
- ast.NodeList argumentsNode, Selector selector, _) {
- ir.Primitive target = translateReceiver(receiver);
- List<ir.Primitive> arguments = <ir.Primitive>[];
- CallStructure callStructure = translateDynamicArguments(
- argumentsNode, selector.callStructure, arguments);
- return irBuilder.buildDynamicInvocation(
- target,
- new Selector(selector.kind, selector.memberName, callStructure),
- elements.getTypeMask(node),
- arguments,
- sourceInformationBuilder.buildCall(node, node.selector));
- }
-
- @override
- ir.Primitive visitIfNotNullDynamicPropertyInvoke(ast.Send node,
- ast.Node receiver, ast.NodeList argumentsNode, Selector selector, _) {
- ir.Primitive target = visit(receiver);
- return irBuilder.buildIfNotNullSend(target, nested(() {
- List<ir.Primitive> arguments = <ir.Primitive>[];
- CallStructure callStructure = translateDynamicArguments(
- argumentsNode, selector.callStructure, arguments);
- return irBuilder.buildDynamicInvocation(
- target,
- new Selector(selector.kind, selector.memberName, callStructure),
- elements.getTypeMask(node),
- arguments,
- sourceInformationBuilder.buildCall(node, node.selector));
- }), sourceInformationBuilder.buildIf(node));
- }
-
- ir.Primitive handleLocalInvoke(ast.Send node, LocalElement element,
- ast.NodeList argumentsNode, CallStructure callStructure, _) {
- ir.Primitive function = irBuilder.buildLocalGet(element);
- List<ir.Primitive> arguments = <ir.Primitive>[];
- callStructure =
- translateDynamicArguments(argumentsNode, callStructure, arguments);
- return irBuilder.buildCallInvocation(function, callStructure, arguments,
- sourceInformationBuilder.buildCall(node, argumentsNode));
- }
-
- @override
- ir.Primitive handleStaticFieldGet(ast.Send node, FieldElement field, _) {
- return buildStaticFieldGet(field, sourceInformationBuilder.buildGet(node));
- }
-
- @override
- ir.Primitive handleStaticFieldInvoke(ast.Send node, FieldElement field,
- ast.NodeList argumentsNode, CallStructure callStructure, _) {
- SourceInformation src = sourceInformationBuilder.buildGet(node);
- ir.Primitive target = buildStaticFieldGet(field, src);
- List<ir.Primitive> arguments = <ir.Primitive>[];
- callStructure =
- translateDynamicArguments(argumentsNode, callStructure, arguments);
- return irBuilder.buildCallInvocation(target, callStructure, arguments,
- sourceInformationBuilder.buildCall(node, argumentsNode));
- }
-
- @override
- ir.Primitive handleStaticFunctionInvoke(ast.Send node, MethodElement function,
- ast.NodeList argumentsNode, CallStructure callStructure, _) {
- if (compiler.backend.isForeign(function)) {
- return handleForeignCode(node, function, argumentsNode, callStructure);
- } else {
- List<ir.Primitive> arguments = <ir.Primitive>[];
- callStructure = translateStaticArguments(
- argumentsNode, function, callStructure, arguments);
- Selector selector = new Selector.call(function.memberName, callStructure);
- return irBuilder.buildInvokeStatic(function, selector, arguments,
- sourceInformationBuilder.buildCall(node, node.selector));
- }
- }
-
- @override
- ir.Primitive handleStaticFunctionIncompatibleInvoke(
- ast.Send node,
- MethodElement function,
- ast.NodeList arguments,
- CallStructure callStructure,
- _) {
- return irBuilder.buildStaticNoSuchMethod(
- elements.getSelector(node),
- arguments.nodes.mapToList(visit),
- sourceInformationBuilder.buildCall(node, node.selector));
- }
-
- @override
- ir.Primitive handleStaticGetterInvoke(ast.Send node, FunctionElement getter,
- ast.NodeList argumentsNode, CallStructure callStructure, _) {
- ir.Primitive target = buildStaticGetterGet(
- getter, node, sourceInformationBuilder.buildGet(node));
- List<ir.Primitive> arguments = <ir.Primitive>[];
- callStructure =
- translateDynamicArguments(argumentsNode, callStructure, arguments);
- return irBuilder.buildCallInvocation(target, callStructure, arguments,
- sourceInformationBuilder.buildCall(node, argumentsNode));
- }
-
- @override
- ir.Primitive visitSuperFieldInvoke(ast.Send node, FieldElement field,
- ast.NodeList argumentsNode, CallStructure callStructure, _) {
- ir.Primitive target = irBuilder.buildSuperFieldGet(
- field, sourceInformationBuilder.buildGet(node));
- List<ir.Primitive> arguments = <ir.Primitive>[];
- callStructure =
- translateDynamicArguments(argumentsNode, callStructure, arguments);
- return irBuilder.buildCallInvocation(target, callStructure, arguments,
- sourceInformationBuilder.buildCall(node, argumentsNode));
- }
-
- @override
- ir.Primitive visitSuperGetterInvoke(ast.Send node, FunctionElement getter,
- ast.NodeList argumentsNode, CallStructure callStructure, _) {
- ir.Primitive target = irBuilder.buildSuperGetterGet(
- getter, sourceInformationBuilder.buildGet(node));
- List<ir.Primitive> arguments = <ir.Primitive>[];
- callStructure =
- translateDynamicArguments(argumentsNode, callStructure, arguments);
- return irBuilder.buildCallInvocation(target, callStructure, arguments,
- sourceInformationBuilder.buildCall(node, argumentsNode));
- }
-
- @override
- ir.Primitive visitSuperMethodInvoke(ast.Send node, MethodElement method,
- ast.NodeList argumentsNode, CallStructure callStructure, _) {
- List<ir.Primitive> arguments = <ir.Primitive>[];
- callStructure = translateStaticArguments(
- argumentsNode, method, callStructure, arguments);
- return irBuilder.buildSuperMethodInvocation(method, callStructure,
- arguments, sourceInformationBuilder.buildCall(node, node.selector));
- }
-
- @override
- ir.Primitive visitSuperMethodIncompatibleInvoke(
- ast.Send node,
- MethodElement method,
- ast.NodeList arguments,
- CallStructure callStructure,
- _) {
- List<ir.Primitive> normalizedArguments = <ir.Primitive>[];
- CallStructure normalizedCallStructure = translateDynamicArguments(
- arguments, callStructure, normalizedArguments);
- return buildSuperNoSuchMethod(
- new Selector.call(method.memberName, normalizedCallStructure),
- elements.getTypeMask(node),
- normalizedArguments,
- sourceInformationBuilder.buildCall(node, arguments));
- }
-
- @override
- ir.Primitive visitUnresolvedSuperInvoke(ast.Send node, Element element,
- ast.NodeList argumentsNode, Selector selector, _) {
- List<ir.Primitive> arguments = <ir.Primitive>[];
- CallStructure callStructure = translateDynamicArguments(
- argumentsNode, selector.callStructure, arguments);
- // TODO(johnniwinther): Supply a member name to the visit function instead
- // of looking it up in elements.
- return buildSuperNoSuchMethod(
- new Selector.call(elements.getSelector(node).memberName, callStructure),
- elements.getTypeMask(node),
- arguments,
- sourceInformationBuilder.buildCall(node, argumentsNode));
- }
-
- @override
- ir.Primitive visitThisInvoke(
- ast.Send node, ast.NodeList arguments, CallStructure callStructure, _) {
- return translateCallInvoke(irBuilder.buildThis(), arguments, callStructure,
- sourceInformationBuilder.buildCall(node, arguments));
- }
-
- @override
- ir.Primitive visitTypeVariableTypeLiteralInvoke(
- ast.Send node,
- TypeVariableElement element,
- ast.NodeList arguments,
- CallStructure callStructure,
- _) {
- return translateCallInvoke(
- translateTypeVariableTypeLiteral(
- element, sourceInformationBuilder.buildGet(node)),
- arguments,
- callStructure,
- sourceInformationBuilder.buildCall(node, arguments));
- }
-
- @override
- ir.Primitive visitIndexSet(
- ast.SendSet node, ast.Node receiver, ast.Node index, ast.Node rhs, _) {
- return irBuilder.buildDynamicIndexSet(
- visit(receiver),
- elements.getTypeMask(node),
- visit(index),
- visit(rhs),
- sourceInformationBuilder.buildIndexSet(node));
- }
-
- @override
- ir.Primitive visitSuperIndexSet(ast.SendSet node, FunctionElement function,
- ast.Node index, ast.Node rhs, _) {
- return irBuilder.buildSuperIndexSet(function, visit(index), visit(rhs),
- sourceInformationBuilder.buildIndexSet(node));
- }
-
- ir.Primitive translateIfNull(ast.SendSet node, ir.Primitive getValue(),
- ast.Node rhs, void setValue(ir.Primitive value)) {
- ir.Primitive value = getValue();
- // Unlike other compound operators if-null conditionally will not do the
- // assignment operation.
- return irBuilder.buildIfNull(value, nested(() {
- ir.Primitive newValue = build(rhs);
- setValue(newValue);
- return newValue;
- }), sourceInformationBuilder.buildIf(node));
- }
-
- ir.Primitive translateCompounds(ast.SendSet node, ir.Primitive getValue(),
- CompoundRhs rhs, void setValue(ir.Primitive value)) {
- ir.Primitive value = getValue();
- op.BinaryOperator operator = rhs.operator;
- assert(operator.kind != op.BinaryOperatorKind.IF_NULL);
-
- Selector operatorSelector =
- new Selector.binaryOperator(operator.selectorName);
- ir.Primitive rhsValue;
- if (rhs.kind == CompoundKind.ASSIGNMENT) {
- rhsValue = visit(rhs.rhs);
- } else {
- rhsValue = irBuilder.buildIntegerConstant(1);
- }
- List<ir.Primitive> arguments = <ir.Primitive>[rhsValue];
- CallStructure callStructure =
- normalizeDynamicArguments(operatorSelector.callStructure, arguments);
- TypeMask operatorTypeMask =
- elements.getOperatorTypeMaskInComplexSendSet(node);
- SourceInformation operatorSourceInformation =
- sourceInformationBuilder.buildCall(node, node.assignmentOperator);
- ir.Primitive result = irBuilder.buildDynamicInvocation(
- value,
- new Selector(
- operatorSelector.kind, operatorSelector.memberName, callStructure),
- operatorTypeMask,
- arguments,
- operatorSourceInformation);
- setValue(result);
- return rhs.kind == CompoundKind.POSTFIX ? value : result;
- }
-
- ir.Primitive translateSetIfNull(ast.SendSet node, ir.Primitive getValue(),
- ast.Node rhs, void setValue(ir.Primitive value)) {
- ir.Primitive value = getValue();
- // Unlike other compound operators if-null conditionally will not do the
- // assignment operation.
- return irBuilder.buildIfNull(value, nested(() {
- ir.Primitive newValue = build(rhs);
- setValue(newValue);
- return newValue;
- }), sourceInformationBuilder.buildIf(node));
- }
-
- @override
- ir.Primitive handleSuperIndexSetIfNull(
- ast.SendSet node,
- Element indexFunction,
- Element indexSetFunction,
- ast.Node index,
- ast.Node rhs,
- arg,
- {bool isGetterValid,
- bool isSetterValid}) {
- return translateSetIfNull(
- node,
- () {
- if (isGetterValid) {
- return irBuilder.buildSuperMethodGet(
- indexFunction, sourceInformationBuilder.buildIndex(node));
- } else {
- return buildSuperNoSuchGetter(
- indexFunction,
- elements.getGetterTypeMaskInComplexSendSet(node),
- sourceInformationBuilder.buildIndex(node));
- }
- },
- rhs,
- (ir.Primitive result) {
- if (isSetterValid) {
- return irBuilder.buildSuperMethodGet(
- indexSetFunction, sourceInformationBuilder.buildIndexSet(node));
- } else {
- return buildSuperNoSuchSetter(
- indexSetFunction,
- elements.getTypeMask(node),
- result,
- sourceInformationBuilder.buildIndexSet(node));
- }
- });
- }
-
- @override
- ir.Primitive visitIndexSetIfNull(
- ast.SendSet node, ast.Node receiver, ast.Node index, ast.Node rhs, arg) {
- ir.Primitive target = visit(receiver);
- ir.Primitive indexValue = visit(index);
- return translateSetIfNull(
- node,
- () {
- Selector selector = new Selector.index();
- List<ir.Primitive> arguments = <ir.Primitive>[indexValue];
- CallStructure callStructure =
- normalizeDynamicArguments(selector.callStructure, arguments);
- return irBuilder.buildDynamicInvocation(
- target,
- new Selector(selector.kind, selector.memberName, callStructure),
- elements.getGetterTypeMaskInComplexSendSet(node),
- arguments,
- sourceInformationBuilder.buildCall(receiver, node));
- },
- rhs,
- (ir.Primitive result) {
- irBuilder.buildDynamicIndexSet(target, elements.getTypeMask(node),
- indexValue, result, sourceInformationBuilder.buildIndexSet(node));
- });
- }
-
- @override
- ir.Primitive handleDynamicSet(
- ast.SendSet node, ast.Node receiver, Name name, ast.Node rhs, _) {
- return irBuilder.buildDynamicSet(
- translateReceiver(receiver),
- new Selector.setter(name),
- elements.getTypeMask(node),
- visit(rhs),
- sourceInformationBuilder.buildAssignment(node));
- }
-
- @override
- ir.Primitive visitIfNotNullDynamicPropertySet(
- ast.SendSet node, ast.Node receiver, Name name, ast.Node rhs, _) {
- ir.Primitive target = visit(receiver);
- return irBuilder.buildIfNotNullSend(
- target,
- nested(() => irBuilder.buildDynamicSet(
- target,
- new Selector.setter(name),
- elements.getTypeMask(node),
- visit(rhs),
- sourceInformationBuilder.buildAssignment(node))),
- sourceInformationBuilder.buildIf(node));
- }
-
- @override
- ir.Primitive handleLocalSet(
- ast.SendSet node, LocalElement element, ast.Node rhs, _) {
- ir.Primitive value = visit(rhs);
- value = checkTypeVsElement(value, element);
- return irBuilder.buildLocalVariableSet(
- element, value, sourceInformationBuilder.buildAssignment(node));
- }
-
- @override
- ir.Primitive handleStaticFieldSet(
- ast.SendSet node, FieldElement field, ast.Node rhs, _) {
- ir.Primitive value = visit(rhs);
- irBuilder.addPrimitive(new ir.SetStatic(
- field, value, sourceInformationBuilder.buildAssignment(node)));
- return value;
- }
-
- @override
- ir.Primitive visitSuperFieldSet(
- ast.SendSet node, FieldElement field, ast.Node rhs, _) {
- return irBuilder.buildSuperFieldSet(
- field, visit(rhs), sourceInformationBuilder.buildAssignment(node));
- }
-
- @override
- ir.Primitive visitSuperSetterSet(
- ast.SendSet node, FunctionElement setter, ast.Node rhs, _) {
- return irBuilder.buildSuperSetterSet(
- setter, visit(rhs), sourceInformationBuilder.buildAssignment(node));
- }
-
- @override
- ir.Primitive visitUnresolvedSuperIndexSet(
- ast.Send node, Element element, ast.Node index, ast.Node rhs, arg) {
- return giveup(node, 'visitUnresolvedSuperIndexSet');
- }
-
- @override
- ir.Primitive handleStaticSetterSet(
- ast.SendSet node, FunctionElement setter, ast.Node rhs, _) {
- return irBuilder.buildStaticSetterSet(
- setter, visit(rhs), sourceInformationBuilder.buildAssignment(node));
- }
-
- @override
- ir.Primitive handleTypeLiteralConstantCompounds(
- ast.SendSet node, ConstantExpression constant, CompoundRhs rhs, arg) {
- SourceInformation src = sourceInformationBuilder.buildGet(node);
- return translateCompounds(
- node,
- () {
- return buildConstantExpression(constant, src);
- },
- rhs,
- (ir.Primitive value) {
- // The binary operator will throw before this.
- });
- }
-
- @override
- ir.Primitive handleTypeLiteralConstantSetIfNulls(
- ast.SendSet node, ConstantExpression constant, ast.Node rhs, _) {
- // The type literal is never `null`.
- return buildConstantExpression(
- constant, sourceInformationBuilder.buildGet(node));
- }
-
- @override
- ir.Primitive handleDynamicCompounds(
- ast.SendSet node, ast.Node receiver, Name name, CompoundRhs rhs, arg) {
- ir.Primitive target = translateReceiver(receiver);
- ir.Primitive helper() {
- return translateCompounds(
- node,
- () {
- return irBuilder.buildDynamicGet(
- target,
- new Selector.getter(name),
- elements.getGetterTypeMaskInComplexSendSet(node),
- sourceInformationBuilder.buildGet(node));
- },
- rhs,
- (ir.Primitive result) {
- irBuilder.buildDynamicSet(
- target,
- new Selector.setter(name),
- elements.getTypeMask(node),
- result,
- sourceInformationBuilder.buildAssignment(node));
- });
- }
-
- return node.isConditional
- ? irBuilder.buildIfNotNullSend(
- target, nested(helper), sourceInformationBuilder.buildIf(node))
- : helper();
- }
-
- @override
- ir.Primitive handleDynamicSetIfNulls(
- ast.Send node, ast.Node receiver, Name name, ast.Node rhs, _) {
- ir.Primitive target = translateReceiver(receiver);
- ir.Primitive helper() {
- return translateSetIfNull(
- node,
- () {
- return irBuilder.buildDynamicGet(
- target,
- new Selector.getter(name),
- elements.getGetterTypeMaskInComplexSendSet(node),
- sourceInformationBuilder.buildGet(node));
- },
- rhs,
- (ir.Primitive result) {
- irBuilder.buildDynamicSet(
- target,
- new Selector.setter(name),
- elements.getTypeMask(node),
- result,
- sourceInformationBuilder.buildAssignment(node));
- });
- }
-
- return node.isConditional
- ? irBuilder.buildIfNotNullSend(
- target, nested(helper), sourceInformationBuilder.buildIf(node))
- : helper();
- }
-
- ir.Primitive buildLocalNoSuchSetter(LocalElement local, ir.Primitive value,
- SourceInformation sourceInformation) {
- Selector selector = new Selector.setter(
- new Name(local.name, local.library, isSetter: true));
- return irBuilder.buildStaticNoSuchMethod(
- selector, [value], sourceInformation);
- }
-
- @override
- ir.Primitive handleLocalCompounds(
- ast.SendSet node, LocalElement local, CompoundRhs rhs, arg,
- {bool isSetterValid}) {
- return translateCompounds(
- node,
- () {
- return irBuilder.buildLocalGet(local);
- },
- rhs,
- (ir.Primitive result) {
- if (isSetterValid) {
- irBuilder.buildLocalVariableSet(
- local, result, sourceInformationBuilder.buildAssignment(node));
- } else {
- Selector selector = new Selector.setter(
- new Name(local.name, local.library, isSetter: true));
- irBuilder.buildStaticNoSuchMethod(selector, <ir.Primitive>[result],
- sourceInformationBuilder.buildAssignment(node));
- }
- });
- }
-
- @override
- ir.Primitive handleLocalSetIfNulls(
- ast.SendSet node, LocalElement local, ast.Node rhs, _,
- {bool isSetterValid}) {
- return translateSetIfNull(
- node,
- () {
- return irBuilder.buildLocalGet(local,
- sourceInformation: sourceInformationBuilder.buildGet(node));
- },
- rhs,
- (ir.Primitive result) {
- SourceInformation sourceInformation =
- sourceInformationBuilder.buildAssignment(node);
- if (isSetterValid) {
- irBuilder.buildLocalVariableSet(local, result, sourceInformation);
- } else {
- Selector selector = new Selector.setter(
- new Name(local.name, local.library, isSetter: true));
- irBuilder.buildStaticNoSuchMethod(
- selector, <ir.Primitive>[result], sourceInformation);
- }
- });
- }
-
- @override
- ir.Primitive handleStaticCompounds(
- ast.SendSet node,
- Element getter,
- CompoundGetter getterKind,
- Element setter,
- CompoundSetter setterKind,
- CompoundRhs rhs,
- arg) {
- return translateCompounds(
- node,
- () {
- SourceInformation sourceInformation =
- sourceInformationBuilder.buildGet(node);
- switch (getterKind) {
- case CompoundGetter.FIELD:
- return buildStaticFieldGet(getter, sourceInformation);
- case CompoundGetter.GETTER:
- return buildStaticGetterGet(getter, node, sourceInformation);
- case CompoundGetter.METHOD:
- return irBuilder.addPrimitive(new ir.GetStatic(getter,
- sourceInformation: sourceInformation, isFinal: true));
- case CompoundGetter.UNRESOLVED:
- return irBuilder.buildStaticNoSuchMethod(
- new Selector.getter(new Name(getter.name, getter.library)),
- <ir.Primitive>[],
- sourceInformation);
- }
- },
- rhs,
- (ir.Primitive result) {
- SourceInformation sourceInformation =
- sourceInformationBuilder.buildAssignment(node);
- switch (setterKind) {
- case CompoundSetter.FIELD:
- irBuilder.addPrimitive(
- new ir.SetStatic(setter, result, sourceInformation));
- return;
- case CompoundSetter.SETTER:
- irBuilder.buildStaticSetterSet(setter, result, sourceInformation);
- return;
- case CompoundSetter.INVALID:
- irBuilder.buildStaticNoSuchMethod(
- new Selector.setter(new Name(setter.name, setter.library)),
- <ir.Primitive>[result],
- sourceInformation);
- return;
- }
- });
- }
-
- @override
- ir.Primitive handleStaticSetIfNulls(
- ast.SendSet node,
- Element getter,
- CompoundGetter getterKind,
- Element setter,
- CompoundSetter setterKind,
- ast.Node rhs,
- _) {
- return translateSetIfNull(
- node,
- () {
- SourceInformation sourceInformation =
- sourceInformationBuilder.buildGet(node);
- switch (getterKind) {
- case CompoundGetter.FIELD:
- return buildStaticFieldGet(getter, sourceInformation);
- case CompoundGetter.GETTER:
- return buildStaticGetterGet(getter, node, sourceInformation);
- case CompoundGetter.METHOD:
- return irBuilder.addPrimitive(new ir.GetStatic(getter,
- sourceInformation: sourceInformation, isFinal: true));
- case CompoundGetter.UNRESOLVED:
- return irBuilder.buildStaticNoSuchMethod(
- new Selector.getter(new Name(getter.name, getter.library)),
- <ir.Primitive>[],
- sourceInformation);
- }
- },
- rhs,
- (ir.Primitive result) {
- SourceInformation sourceInformation =
- sourceInformationBuilder.buildAssignment(node);
- switch (setterKind) {
- case CompoundSetter.FIELD:
- irBuilder.addPrimitive(
- new ir.SetStatic(setter, result, sourceInformation));
- return;
- case CompoundSetter.SETTER:
- irBuilder.buildStaticSetterSet(setter, result, sourceInformation);
- return;
- case CompoundSetter.INVALID:
- irBuilder.buildStaticNoSuchMethod(
- new Selector.setter(new Name(setter.name, setter.library)),
- <ir.Primitive>[result],
- sourceInformation);
- return;
- }
- });
- }
-
- ir.Primitive buildSuperNoSuchGetter(
- Element element, TypeMask mask, SourceInformation sourceInformation) {
- return buildSuperNoSuchMethod(
- new Selector.getter(new Name(element.name, element.library)),
- mask,
- const <ir.Primitive>[],
- sourceInformation);
- }
-
- ir.Primitive buildSuperNoSuchSetter(Element element, TypeMask mask,
- ir.Primitive value, SourceInformation sourceInformation) {
- return buildSuperNoSuchMethod(
- new Selector.setter(new Name(element.name, element.library)),
- mask,
- <ir.Primitive>[value],
- sourceInformation);
- }
-
- @override
- ir.Primitive handleSuperCompounds(
- ast.SendSet node,
- Element getter,
- CompoundGetter getterKind,
- Element setter,
- CompoundSetter setterKind,
- CompoundRhs rhs,
- arg) {
- return translateCompounds(
- node,
- () {
- switch (getterKind) {
- case CompoundGetter.FIELD:
- return irBuilder.buildSuperFieldGet(
- getter, sourceInformationBuilder.buildGet(node));
- case CompoundGetter.GETTER:
- return irBuilder.buildSuperGetterGet(
- getter, sourceInformationBuilder.buildGet(node));
- case CompoundGetter.METHOD:
- return irBuilder.buildSuperMethodGet(
- getter, sourceInformationBuilder.buildGet(node));
- case CompoundGetter.UNRESOLVED:
- return buildSuperNoSuchGetter(
- getter,
- elements.getGetterTypeMaskInComplexSendSet(node),
- sourceInformationBuilder.buildGet(node));
- }
- },
- rhs,
- (ir.Primitive result) {
- switch (setterKind) {
- case CompoundSetter.FIELD:
- irBuilder.buildSuperFieldSet(setter, result,
- sourceInformationBuilder.buildAssignment(node));
- return;
- case CompoundSetter.SETTER:
- irBuilder.buildSuperSetterSet(setter, result,
- sourceInformationBuilder.buildAssignment(node));
- return;
- case CompoundSetter.INVALID:
- buildSuperNoSuchSetter(setter, elements.getTypeMask(node), result,
- sourceInformationBuilder.buildAssignment(node));
- return;
- }
- });
- }
-
- @override
- ir.Primitive handleSuperSetIfNulls(
- ast.SendSet node,
- Element getter,
- CompoundGetter getterKind,
- Element setter,
- CompoundSetter setterKind,
- ast.Node rhs,
- _) {
- return translateSetIfNull(
- node,
- () {
- switch (getterKind) {
- case CompoundGetter.FIELD:
- return irBuilder.buildSuperFieldGet(
- getter, sourceInformationBuilder.buildGet(node));
- case CompoundGetter.GETTER:
- return irBuilder.buildSuperGetterGet(
- getter, sourceInformationBuilder.buildGet(node));
- case CompoundGetter.METHOD:
- return irBuilder.buildSuperMethodGet(
- getter, sourceInformationBuilder.buildGet(node));
- case CompoundGetter.UNRESOLVED:
- return buildSuperNoSuchGetter(
- getter,
- elements.getGetterTypeMaskInComplexSendSet(node),
- sourceInformationBuilder.buildGet(node));
- }
- },
- rhs,
- (ir.Primitive result) {
- switch (setterKind) {
- case CompoundSetter.FIELD:
- irBuilder.buildSuperFieldSet(setter, result,
- sourceInformationBuilder.buildAssignment(node));
- return;
- case CompoundSetter.SETTER:
- irBuilder.buildSuperSetterSet(setter, result,
- sourceInformationBuilder.buildAssignment(node));
- return;
- case CompoundSetter.INVALID:
- buildSuperNoSuchSetter(setter, elements.getTypeMask(node), result,
- sourceInformationBuilder.buildAssignment(node));
- return;
- }
- });
- }
-
- @override
- ir.Primitive handleTypeVariableTypeLiteralCompounds(ast.SendSet node,
- TypeVariableElement typeVariable, CompoundRhs rhs, arg) {
- return translateCompounds(
- node,
- () {
- return irBuilder.buildReifyTypeVariable(
- typeVariable.type, sourceInformationBuilder.buildGet(node));
- },
- rhs,
- (ir.Primitive value) {
- // The binary operator will throw before this.
- });
- }
-
- @override
- ir.Primitive visitTypeVariableTypeLiteralSetIfNull(
- ast.Send node, TypeVariableElement element, ast.Node rhs, _) {
- // The type variable is never `null`.
- return translateTypeVariableTypeLiteral(
- element, sourceInformationBuilder.buildGet(node));
- }
-
- @override
- ir.Primitive handleIndexCompounds(ast.SendSet node, ast.Node receiver,
- ast.Node index, CompoundRhs rhs, arg) {
- ir.Primitive target = visit(receiver);
- ir.Primitive indexValue = visit(index);
- return translateCompounds(
- node,
- () {
- Selector selector = new Selector.index();
- List<ir.Primitive> arguments = <ir.Primitive>[indexValue];
- CallStructure callStructure =
- normalizeDynamicArguments(selector.callStructure, arguments);
- return irBuilder.buildDynamicInvocation(
- target,
- new Selector(selector.kind, selector.memberName, callStructure),
- elements.getGetterTypeMaskInComplexSendSet(node),
- arguments,
- sourceInformationBuilder.buildCall(receiver, node));
- },
- rhs,
- (ir.Primitive result) {
- irBuilder.buildDynamicIndexSet(target, elements.getTypeMask(node),
- indexValue, result, sourceInformationBuilder.buildIndexSet(node));
- });
- }
-
- @override
- ir.Primitive handleSuperIndexCompounds(
- ast.SendSet node,
- Element indexFunction,
- Element indexSetFunction,
- ast.Node index,
- CompoundRhs rhs,
- arg,
- {bool isGetterValid,
- bool isSetterValid}) {
- ir.Primitive indexValue = visit(index);
- return translateCompounds(
- node,
- () {
- if (isGetterValid) {
- return irBuilder.buildSuperIndex(indexFunction, indexValue,
- sourceInformationBuilder.buildIndex(node));
- } else {
- return buildSuperNoSuchMethod(
- new Selector.index(),
- elements.getGetterTypeMaskInComplexSendSet(node),
- <ir.Primitive>[indexValue],
- sourceInformationBuilder.buildIndex(node));
- }
- },
- rhs,
- (ir.Primitive result) {
- if (isSetterValid) {
- irBuilder.buildSuperIndexSet(indexSetFunction, indexValue, result,
- sourceInformationBuilder.buildIndexSet(node));
- } else {
- buildSuperNoSuchMethod(
- new Selector.indexSet(),
- elements.getTypeMask(node),
- <ir.Primitive>[indexValue, result],
- sourceInformationBuilder.buildIndexSet(node));
- }
- });
- }
-
- /// Build code to handle foreign code, that is, native JavaScript code, or
- /// builtin values and operations of the backend.
- ir.Primitive handleForeignCode(ast.Send node, MethodElement function,
- ast.NodeList argumentList, CallStructure callStructure) {
- void validateArgumentCount({int minimum, int exactly}) {
- assert((minimum == null) != (exactly == null));
- int count = 0;
- int maximum;
- if (exactly != null) {
- minimum = exactly;
- maximum = exactly;
- }
- for (ast.Node argument in argumentList) {
- count++;
- if (maximum != null && count > maximum) {
- internalError(argument, 'Additional argument.');
- }
- }
- if (count < minimum) {
- internalError(node, 'Expected at least $minimum arguments.');
- }
- }
-
- /// Call a helper method from the isolate library. The isolate library uses
- /// its own isolate structure, that encapsulates dart2js's isolate.
- ir.Primitive buildIsolateHelperInvocation(
- MethodElement element, CallStructure callStructure) {
- if (element == null) {
- reporter.internalError(node, 'Isolate library and compiler mismatch.');
- }
- List<ir.Primitive> arguments = <ir.Primitive>[];
- callStructure = translateStaticArguments(
- argumentList, element, callStructure, arguments);
- Selector selector = new Selector.call(element.memberName, callStructure);
- return irBuilder.buildInvokeStatic(element, selector, arguments,
- sourceInformationBuilder.buildCall(node, node.selector));
- }
-
- /// Lookup the value of the enum described by [node].
- getEnumValue(ast.Node node, EnumClassElement enumClass, List values) {
- Element element = elements[node];
- if (element is! EnumConstantElement ||
- element.enclosingClass != enumClass) {
- internalError(node, 'expected a JsBuiltin enum value');
- }
- EnumConstantElement enumConstant = element;
- int index = enumConstant.index;
- return values[index];
- }
-
- /// Returns the String the node evaluates to, or throws an error if the
- /// result is not a string constant.
- String expectStringConstant(ast.Node node) {
- ir.Primitive nameValue = visit(node);
- if (nameValue is ir.Constant && nameValue.value.isString) {
- StringConstantValue constantValue = nameValue.value;
- return constantValue.primitiveValue.slowToString();
- } else {
- return internalError(node, 'expected a literal string');
- }
- }
-
- Link<ast.Node> argumentNodes = argumentList.nodes;
- NativeBehavior behavior = elements.getNativeData(node);
- switch (function.name) {
- case 'JS':
- validateArgumentCount(minimum: 2);
- // The first two arguments are the type and the foreign code template,
- // which already have been analyzed by the resolver and can be retrieved
- // using [NativeBehavior]. We can ignore these arguments in the backend.
- List<ir.Primitive> arguments =
- argumentNodes.skip(2).mapToList(visit, growable: false);
- if (behavior.codeTemplate.positionalArgumentCount != arguments.length) {
- reporter.reportErrorMessage(node, MessageKind.GENERIC, {
- 'text': 'Mismatch between number of placeholders'
- ' and number of arguments.'
- });
- return irBuilder.buildNullConstant();
- }
-
- if (HasCapturedPlaceholders.check(behavior.codeTemplate.ast)) {
- reporter.reportErrorMessage(node, MessageKind.JS_PLACEHOLDER_CAPTURE);
- return irBuilder.buildNullConstant();
- }
-
- return irBuilder.buildForeignCode(behavior.codeTemplate, arguments,
- behavior, sourceInformationBuilder.buildForeignCode(node));
-
- case 'DART_CLOSURE_TO_JS':
- // TODO(ahe): This should probably take care to wrap the closure in
- // another closure that saves the current isolate.
- case 'RAW_DART_FUNCTION_REF':
- validateArgumentCount(exactly: 1);
-
- ast.Node argument = node.arguments.single;
- FunctionElement closure = elements[argument].implementation;
- if (!Elements.isStaticOrTopLevelFunction(closure)) {
- internalError(argument, 'only static or toplevel function supported');
- }
- if (closure.functionSignature.hasOptionalParameters) {
- internalError(
- argument, 'closures with optional parameters not supported');
- }
- return irBuilder.buildForeignCode(
- js.js.expressionTemplateYielding(
- backend.emitter.staticFunctionAccess(closure)),
- <ir.Primitive>[],
- NativeBehavior.PURE,
- sourceInformationBuilder.buildForeignCode(node),
- dependency: closure);
-
- case 'JS_BUILTIN':
- // The first argument is a description of the type and effect of the
- // builtin, which has already been analyzed in the frontend. The second
- // argument must be a [JsBuiltin] value. All other arguments are
- // values used by the JavaScript template that is associated with the
- // builtin.
- validateArgumentCount(minimum: 2);
-
- ast.Node builtin = argumentNodes.tail.head;
- JsBuiltin value =
- getEnumValue(builtin, helpers.jsBuiltinEnum, JsBuiltin.values);
- js.Template template = backend.emitter.builtinTemplateFor(value);
- List<ir.Primitive> arguments =
- argumentNodes.skip(2).mapToList(visit, growable: false);
- return irBuilder.buildForeignCode(template, arguments, behavior,
- sourceInformationBuilder.buildForeignCode(node));
-
- case 'JS_EMBEDDED_GLOBAL':
- validateArgumentCount(exactly: 2);
-
- String name = expectStringConstant(argumentNodes.tail.head);
- js.Expression access =
- backend.emitter.generateEmbeddedGlobalAccess(name);
- js.Template template = js.js.expressionTemplateYielding(access);
- return irBuilder.buildForeignCode(template, <ir.Primitive>[], behavior,
- sourceInformationBuilder.buildForeignCode(node));
-
- case 'JS_INTERCEPTOR_CONSTANT':
- validateArgumentCount(exactly: 1);
-
- ast.Node argument = argumentNodes.head;
- ir.Primitive argumentValue = visit(argument);
- if (argumentValue is ir.Constant && argumentValue.value.isType) {
- TypeConstantValue constant = argumentValue.value;
- ConstantValue interceptorValue =
- new InterceptorConstantValue(constant.representedType);
- return irBuilder.buildConstant(interceptorValue);
- }
- return internalError(argument, 'expected Type as argument');
-
- case 'JS_EFFECT':
- return irBuilder.buildNullConstant();
-
- case 'JS_GET_NAME':
- validateArgumentCount(exactly: 1);
-
- ast.Node argument = argumentNodes.head;
- JsGetName id =
- getEnumValue(argument, helpers.jsGetNameEnum, JsGetName.values);
- js.Name name = backend.namer.getNameForJsGetName(argument, id);
- ConstantValue nameConstant = new SyntheticConstantValue(
- SyntheticConstantKind.NAME, js.js.quoteName(name));
-
- return irBuilder.buildConstant(nameConstant);
-
- case 'JS_GET_FLAG':
- validateArgumentCount(exactly: 1);
-
- String name = expectStringConstant(argumentNodes.first);
- bool value = false;
- switch (name) {
- case 'MUST_RETAIN_METADATA':
- value = backend.mustRetainMetadata;
- break;
- case 'USE_CONTENT_SECURITY_POLICY':
- value = compiler.options.useContentSecurityPolicy;
- break;
- default:
- internalError(node, 'Unknown internal flag "$name".');
- }
- return irBuilder.buildBooleanConstant(value);
-
- case 'JS_STRING_CONCAT':
- validateArgumentCount(exactly: 2);
- List<ir.Primitive> arguments = argumentNodes.mapToList(visit);
- return irBuilder.buildStringConcatenation(
- arguments, sourceInformationBuilder.buildForeignCode(node));
-
- case 'JS_CURRENT_ISOLATE_CONTEXT':
- validateArgumentCount(exactly: 0);
-
- if (!compiler.hasIsolateSupport) {
- // If the isolate library is not used, we just generate code
- // to fetch the current isolate.
- continue getStaticState;
- }
- return buildIsolateHelperInvocation(
- helpers.currentIsolate, CallStructure.NO_ARGS);
-
- getStaticState:
- case 'JS_GET_STATIC_STATE':
- validateArgumentCount(exactly: 0);
-
- return irBuilder.buildForeignCode(
- js.js.parseForeignJS(backend.namer.staticStateHolder),
- const <ir.Primitive>[],
- NativeBehavior.DEPENDS_OTHER,
- sourceInformationBuilder.buildForeignCode(node));
-
- case 'JS_SET_STATIC_STATE':
- validateArgumentCount(exactly: 1);
-
- ir.Primitive value = visit(argumentNodes.single);
- String isolateName = backend.namer.staticStateHolder;
- return irBuilder.buildForeignCode(
- js.js.parseForeignJS("$isolateName = #"),
- <ir.Primitive>[value],
- NativeBehavior.CHANGES_OTHER,
- sourceInformationBuilder.buildForeignCode(node));
-
- case 'JS_CALL_IN_ISOLATE':
- validateArgumentCount(exactly: 2);
-
- if (!compiler.hasIsolateSupport) {
- ir.Primitive closure = visit(argumentNodes.tail.head);
- return irBuilder.buildCallInvocation(
- closure,
- CallStructure.NO_ARGS,
- const <ir.Primitive>[],
- sourceInformationBuilder.buildForeignCode(node));
- }
- return buildIsolateHelperInvocation(
- helpers.callInIsolate, CallStructure.TWO_ARGS);
-
- default:
- return giveup(node, 'unplemented native construct: ${function.name}');
- }
- }
-
- /// Evaluates a string interpolation and appends each part to [accumulator]
- /// (after stringify conversion).
- void buildStringParts(ast.Node node, List<ir.Primitive> accumulator) {
- if (node is ast.StringJuxtaposition) {
- buildStringParts(node.first, accumulator);
- buildStringParts(node.second, accumulator);
- } else if (node is ast.StringInterpolation) {
- buildStringParts(node.string, accumulator);
- for (ast.StringInterpolationPart part in node.parts) {
- buildStringParts(part.expression, accumulator);
- buildStringParts(part.string, accumulator);
- }
- } else if (node is ast.LiteralString) {
- // Empty strings often occur at the end of a string interpolation,
- // do not bother to include them.
- if (!node.dartString.isEmpty) {
- accumulator.add(irBuilder.buildDartStringConstant(node.dartString));
- }
- } else if (node is ast.ParenthesizedExpression) {
- buildStringParts(node.expression, accumulator);
- } else {
- ir.Primitive value = visit(node);
- accumulator.add(irBuilder.buildStaticFunctionInvocation(
- helpers.stringInterpolationHelper,
- <ir.Primitive>[value],
- sourceInformationBuilder.buildStringInterpolation(node)));
- }
- }
-
- ir.Primitive visitStringJuxtaposition(ast.StringJuxtaposition node) {
- assert(irBuilder.isOpen);
- List<ir.Primitive> parts = <ir.Primitive>[];
- buildStringParts(node, parts);
- return irBuilder.buildStringConcatenation(
- parts, sourceInformationBuilder.buildStringInterpolation(node));
- }
-
- ir.Primitive visitStringInterpolation(ast.StringInterpolation node) {
- assert(irBuilder.isOpen);
- List<ir.Primitive> parts = <ir.Primitive>[];
- buildStringParts(node, parts);
- return irBuilder.buildStringConcatenation(
- parts, sourceInformationBuilder.buildStringInterpolation(node));
- }
-
- ir.Primitive translateConstant(ast.Node node) {
- assert(irBuilder.isOpen);
- return irBuilder.buildConstant(getConstantForNode(node),
- sourceInformation: sourceInformationBuilder.buildGet(node));
- }
-
- ir.Primitive visitThrow(ast.Throw node) {
- assert(irBuilder.isOpen);
- // This function is not called for throw expressions occurring as
- // statements.
- return irBuilder.buildNonTailThrow(visit(node.expression));
- }
-
- ir.Primitive buildSuperNoSuchMethod(Selector selector, TypeMask mask,
- List<ir.Primitive> arguments, SourceInformation sourceInformation) {
- ClassElement cls = elements.analyzedElement.enclosingClass;
- MethodElement element = cls.lookupSuperMember(Identifiers.noSuchMethod_);
- if (!Selectors.noSuchMethod_.signatureApplies(element)) {
- element = compiler.coreClasses.objectClass
- .lookupMember(Identifiers.noSuchMethod_);
- }
- return irBuilder.buildSuperMethodInvocation(
- element,
- Selectors.noSuchMethod_.callStructure,
- [irBuilder.buildInvocationMirror(selector, arguments)],
- sourceInformation);
- }
-
- @override
- ir.Primitive visitUnresolvedCompound(ast.Send node, Element element,
- op.AssignmentOperator operator, ast.Node rhs, _) {
- return irBuilder.buildStaticNoSuchMethod(
- new Selector.getter(new Name(element.name, element.library)),
- [],
- sourceInformationBuilder.buildGet(node));
- }
-
- @override
- ir.Primitive visitUnresolvedClassConstructorInvoke(
- ast.NewExpression node,
- Element element,
- DartType type,
- ast.NodeList arguments,
- Selector selector,
- _) {
- // If the class is missing it's a runtime error.
- ir.Primitive message =
- irBuilder.buildStringConstant("Unresolved class: '${element.name}'");
- return irBuilder.buildStaticFunctionInvocation(helpers.throwRuntimeError,
- <ir.Primitive>[message], sourceInformationBuilder.buildNew(node));
- }
-
- @override
- ir.Primitive visitUnresolvedConstructorInvoke(
- ast.NewExpression node,
- Element constructor,
- DartType type,
- ast.NodeList argumentsNode,
- Selector selector,
- _) {
- // If the class is there but the constructor is missing, it's an NSM error.
- List<ir.Primitive> arguments = <ir.Primitive>[];
- CallStructure callStructure = translateDynamicArguments(
- argumentsNode, selector.callStructure, arguments);
- return irBuilder.buildStaticNoSuchMethod(
- new Selector(selector.kind, selector.memberName, callStructure),
- arguments,
- sourceInformationBuilder.buildNew(node));
- }
-
- @override
- ir.Primitive visitConstructorIncompatibleInvoke(
- ast.NewExpression node,
- ConstructorElement constructor,
- DartType type,
- ast.NodeList argumentsNode,
- CallStructure callStructure,
- _) {
- List<ir.Primitive> arguments = <ir.Primitive>[];
- callStructure =
- translateDynamicArguments(argumentsNode, callStructure, arguments);
- return irBuilder.buildStaticNoSuchMethod(
- new Selector.call(constructor.memberName, callStructure),
- arguments,
- sourceInformationBuilder.buildNew(node));
- }
-
- @override
- ir.Primitive visitUnresolvedGet(ast.Send node, Element element, _) {
- return irBuilder.buildStaticNoSuchMethod(elements.getSelector(node), [],
- sourceInformationBuilder.buildGet(node));
- }
-
- @override
- ir.Primitive visitUnresolvedInvoke(ast.Send node, Element element,
- ast.NodeList arguments, Selector selector, _) {
- return irBuilder.buildStaticNoSuchMethod(
- elements.getSelector(node),
- arguments.nodes.mapToList(visit),
- sourceInformationBuilder.buildCall(node, node.selector));
- }
-
- @override
- ir.Primitive visitUnresolvedRedirectingFactoryConstructorInvoke(
- ast.NewExpression node,
- ConstructorElement constructor,
- InterfaceType type,
- ast.NodeList argumentsNode,
- CallStructure callStructure,
- _) {
- String nameString = Elements.reconstructConstructorName(constructor);
- Name name = new Name(nameString, constructor.library);
- List<ir.Primitive> arguments = <ir.Primitive>[];
- callStructure =
- translateDynamicArguments(argumentsNode, callStructure, arguments);
- return irBuilder.buildStaticNoSuchMethod(
- new Selector.call(name, callStructure),
- arguments,
- sourceInformationBuilder.buildNew(node));
- }
-
- @override
- ir.Primitive visitUnresolvedSet(
- ast.Send node, Element element, ast.Node rhs, _) {
- return irBuilder.buildStaticNoSuchMethod(elements.getSelector(node),
- [visit(rhs)], sourceInformationBuilder.buildAssignment(node));
- }
-
- @override
- ir.Primitive visitUnresolvedSuperIndex(
- ast.Send node, Element function, ast.Node index, _) {
- // Assume the index getter is missing.
- return buildSuperNoSuchMethod(
- new Selector.index(),
- elements.getTypeMask(node),
- [visit(index)],
- sourceInformationBuilder.buildIndex(node));
- }
-
- @override
- ir.Primitive visitUnresolvedSuperBinary(ast.Send node, Element element,
- op.BinaryOperator operator, ast.Node argument, _) {
- return buildSuperNoSuchMethod(
- elements.getSelector(node),
- elements.getTypeMask(node),
- [visit(argument)],
- sourceInformationBuilder.buildCall(node, node.selector));
- }
-
- @override
- ir.Primitive visitUnresolvedSuperUnary(
- ast.Send node, op.UnaryOperator operator, Element element, _) {
- return buildSuperNoSuchMethod(
- elements.getSelector(node),
- elements.getTypeMask(node),
- [],
- sourceInformationBuilder.buildCall(node, node.selector));
- }
-
- @override
- ir.Primitive bulkHandleNode(ast.Node node, String message, _) {
- return giveup(node, "Unhandled node: ${message.replaceAll('#', '$node')}");
- }
-
- @override
- ir.Primitive bulkHandleError(ast.Node node, ErroneousElement error, _) {
- return irBuilder.buildNullConstant();
- }
-
- @override
- ir.Primitive visitClassTypeLiteralSet(
- ast.SendSet node, TypeConstantExpression constant, ast.Node rhs, _) {
- InterfaceType type = constant.type;
- ClassElement element = type.element;
- return irBuilder.buildStaticNoSuchMethod(
- new Selector.setter(element.memberName),
- [visit(rhs)],
- sourceInformationBuilder.buildAssignment(node));
- }
-
- @override
- ir.Primitive visitTypedefTypeLiteralSet(
- ast.SendSet node, TypeConstantExpression constant, ast.Node rhs, _) {
- TypedefType type = constant.type;
- TypedefElement element = type.element;
- return irBuilder.buildStaticNoSuchMethod(
- new Selector.setter(element.memberName),
- [visit(rhs)],
- sourceInformationBuilder.buildAssignment(node));
- }
-
- @override
- ir.Primitive visitTypeVariableTypeLiteralSet(
- ast.SendSet node, TypeVariableElement element, ast.Node rhs, _) {
- return irBuilder.buildStaticNoSuchMethod(
- new Selector.setter(element.memberName),
- [visit(rhs)],
- sourceInformationBuilder.buildAssignment(node));
- }
-
- @override
- ir.Primitive visitDynamicTypeLiteralSet(
- ast.SendSet node, ConstantExpression constant, ast.Node rhs, _) {
- return irBuilder.buildStaticNoSuchMethod(
- new Selector.setter(Names.dynamic_),
- [visit(rhs)],
- sourceInformationBuilder.buildAssignment(node));
- }
-
- @override
- ir.Primitive visitAbstractClassConstructorInvoke(
- ast.NewExpression node,
- ConstructorElement element,
- InterfaceType type,
- ast.NodeList arguments,
- CallStructure callStructure,
- _) {
- for (ast.Node argument in arguments) visit(argument);
- ir.Primitive name =
- irBuilder.buildStringConstant(element.enclosingClass.name);
- return irBuilder.buildStaticFunctionInvocation(
- helpers.throwAbstractClassInstantiationError,
- <ir.Primitive>[name],
- sourceInformationBuilder.buildNew(node));
- }
-
- @override
- ir.Primitive handleFinalStaticFieldSet(
- ast.SendSet node, FieldElement field, ast.Node rhs, _) {
- // TODO(asgerf): Include class name somehow for static class members?
- return irBuilder.buildStaticNoSuchMethod(
- new Selector.setter(field.memberName),
- [visit(rhs)],
- sourceInformationBuilder.buildAssignment(node));
- }
-
- @override
- ir.Primitive visitFinalSuperFieldSet(
- ast.SendSet node, FieldElement field, ast.Node rhs, _) {
- return buildSuperNoSuchMethod(
- new Selector.setter(field.memberName),
- elements.getTypeMask(node),
- [visit(rhs)],
- sourceInformationBuilder.buildAssignment(node));
- }
-
- @override
- ir.Primitive handleImmutableLocalSet(
- ast.SendSet node, LocalElement local, ast.Node rhs, _) {
- return irBuilder.buildStaticNoSuchMethod(
- new Selector.setter(new Name(local.name, local.library)),
- [visit(rhs)],
- sourceInformationBuilder.buildAssignment(node));
- }
-
- @override
- ir.Primitive handleStaticFunctionSet(
- ast.Send node, MethodElement function, ast.Node rhs, _) {
- return irBuilder.buildStaticNoSuchMethod(
- new Selector.setter(function.memberName),
- [visit(rhs)],
- sourceInformationBuilder.buildAssignment(node));
- }
-
- @override
- ir.Primitive handleStaticGetterSet(
- ast.SendSet node, GetterElement getter, ast.Node rhs, _) {
- return irBuilder.buildStaticNoSuchMethod(
- new Selector.setter(getter.memberName),
- [visit(rhs)],
- sourceInformationBuilder.buildAssignment(node));
- }
-
- @override
- ir.Primitive handleStaticSetterGet(ast.Send node, SetterElement setter, _) {
- return irBuilder.buildStaticNoSuchMethod(
- new Selector.getter(setter.memberName),
- [],
- sourceInformationBuilder.buildGet(node));
- }
-
- @override
- ir.Primitive handleStaticSetterInvoke(ast.Send node, SetterElement setter,
- ast.NodeList argumentsNode, CallStructure callStructure, _) {
- // Translate as a method call.
- List<ir.Primitive> arguments = argumentsNode.nodes.mapToList(visit);
- return irBuilder.buildStaticNoSuchMethod(
- new Selector.call(setter.memberName, callStructure),
- arguments,
- sourceInformationBuilder.buildCall(node, argumentsNode));
- }
-
- @override
- ir.Primitive visitSuperGetterSet(
- ast.SendSet node, GetterElement getter, ast.Node rhs, _) {
- return buildSuperNoSuchMethod(
- new Selector.setter(getter.memberName),
- elements.getTypeMask(node),
- [visit(rhs)],
- sourceInformationBuilder.buildAssignment(node));
- }
-
- @override
- ir.Primitive visitSuperMethodSet(
- ast.Send node, MethodElement method, ast.Node rhs, _) {
- return buildSuperNoSuchMethod(
- new Selector.setter(method.memberName),
- elements.getTypeMask(node),
- [visit(rhs)],
- sourceInformationBuilder.buildAssignment(node));
- }
-
- @override
- ir.Primitive visitSuperSetterGet(ast.Send node, SetterElement setter, _) {
- return buildSuperNoSuchMethod(
- new Selector.getter(setter.memberName),
- elements.getTypeMask(node),
- [],
- sourceInformationBuilder.buildGet(node));
- }
-
- @override
- ir.Primitive visitSuperSetterInvoke(ast.Send node, SetterElement setter,
- ast.NodeList argumentsNode, CallStructure callStructure, _) {
- List<ir.Primitive> arguments = <ir.Primitive>[];
- callStructure =
- translateDynamicArguments(argumentsNode, callStructure, arguments);
- return buildSuperNoSuchMethod(
- new Selector.call(setter.memberName, callStructure),
- elements.getTypeMask(node),
- arguments,
- sourceInformationBuilder.buildCall(node, argumentsNode));
- }
-
- ir.FunctionDefinition nullIfGiveup(ir.FunctionDefinition action()) {
- try {
- return action();
- } catch (e) {
- if (e == ABORT_IRNODE_BUILDER) {
- return null;
- }
- rethrow;
- }
- }
-
- internalError(ast.Node node, String message) {
- reporter.internalError(node, message);
- }
-
- @override
- visitNode(ast.Node node) {
- giveup(node, "Unhandled node");
- }
-
- dynamic giveup(ast.Node node, [String reason]) {
- bailoutMessage = '($node): $reason';
- throw ABORT_IRNODE_BUILDER;
- }
-}
-
-final String ABORT_IRNODE_BUILDER = "IrNode builder aborted";
-
-/// Determines which local variables should be boxed in a mutable variable
-/// inside a given try block.
-class TryBoxedVariables extends ast.Visitor {
- final TreeElements elements;
- TryBoxedVariables(this.elements);
-
- FunctionElement currentFunction;
- bool insideInitializer = false;
- Set<Local> capturedVariables = new Set<Local>();
-
- /// A map containing variables boxed inside try blocks.
- ///
- /// The map is keyed by the [NodeList] of catch clauses for try/catch and
- /// by the finally block for try/finally. try/catch/finally is treated
- /// as a try/catch nested in the try block of a try/finally.
- Map<ast.Node, TryStatementInfo> tryStatements =
- <ast.Node, TryStatementInfo>{};
-
- List<TryStatementInfo> tryNestingStack = <TryStatementInfo>[];
- bool get inTryStatement => tryNestingStack.isNotEmpty;
-
- String bailoutMessage = null;
-
- giveup(ast.Node node, [String reason]) {
- bailoutMessage = '($node): $reason';
- throw ABORT_IRNODE_BUILDER;
- }
-
- void markAsCaptured(Local local) {
- capturedVariables.add(local);
- }
-
- analyze(ast.Node node) {
- visit(node);
- // Variables that are captured by a closure are boxed for their entire
- // lifetime, so they never need to be boxed on entry to a try block.
- // They are not filtered out before this because we cannot identify all
- // of them in the same pass (they may be captured by a closure after the
- // try statement).
- for (TryStatementInfo info in tryStatements.values) {
- info.boxedOnEntry.removeAll(capturedVariables);
- }
- }
-
- visit(ast.Node node) => node.accept(this);
-
- visitNode(ast.Node node) {
- node.visitChildren(this);
- }
-
- void handleSend(ast.Send node) {
- Element element = elements[node];
- if (Elements.isLocal(element) &&
- !element.isConst &&
- element.enclosingElement != currentFunction) {
- LocalElement local = element;
- markAsCaptured(local);
- }
- }
-
- visitSend(ast.Send node) {
- handleSend(node);
- node.visitChildren(this);
- }
-
- visitSendSet(ast.SendSet node) {
- handleSend(node);
- Element element = elements[node];
- if (Elements.isLocal(element)) {
- LocalElement local = element;
- if (insideInitializer &&
- (local.isRegularParameter || local.isInitializingFormal) &&
- local.enclosingElement == currentFunction) {
- assert(local.enclosingElement.isConstructor);
- // Initializers in an initializer-list can communicate via parameters.
- // If a parameter is stored in an initializer list we box it.
- // TODO(sigurdm): Fix this.
- // Though these variables do not outlive the activation of the
- // function, they still need to be boxed. As a simplification, we
- // treat them as if they are captured by a closure (i.e., they do
- // outlive the activation of the function).
- markAsCaptured(local);
- } else if (inTryStatement) {
- assert(local.isRegularParameter ||
- local.isVariable ||
- local.isInitializingFormal);
- // Search for the position of the try block containing the variable
- // declaration, or -1 if it is declared outside the outermost try.
- int i = tryNestingStack.length - 1;
- while (i >= 0 && !tryNestingStack[i].declared.contains(local)) {
- --i;
- }
- // If there is a next inner try, then the variable should be boxed on
- // entry to it.
- if (i + 1 < tryNestingStack.length) {
- tryNestingStack[i + 1].boxedOnEntry.add(local);
- }
- }
- }
- node.visitChildren(this);
- }
-
- visitFunctionExpression(ast.FunctionExpression node) {
- FunctionElement savedFunction = currentFunction;
- currentFunction = elements[node];
-
- if (currentFunction.asyncMarker != AsyncMarker.SYNC &&
- currentFunction.asyncMarker != AsyncMarker.SYNC_STAR &&
- currentFunction.asyncMarker != AsyncMarker.ASYNC) {
- giveup(node, "cannot handle async* functions");
- }
-
- if (node.initializers != null) {
- visit(node.initializers);
- }
- visit(node.body);
- currentFunction = savedFunction;
- }
-
- visitTryStatement(ast.TryStatement node) {
- // Try/catch/finally is treated as two simpler constructs: try/catch and
- // try/finally. The encoding is:
- //
- // try S0 catch (ex, st) S1 finally S2
- // ==>
- // try { try S0 catch (ex, st) S1 } finally S2
- //
- // The analysis associates variables assigned in S0 with the catch clauses
- // and variables assigned in S0 and S1 with the finally block.
- TryStatementInfo enterTryFor(ast.Node node) {
- TryStatementInfo info = new TryStatementInfo();
- tryStatements[node] = info;
- tryNestingStack.add(info);
- return info;
- }
-
- void leaveTryFor(TryStatementInfo info) {
- assert(tryNestingStack.last == info);
- tryNestingStack.removeLast();
- }
-
- bool hasCatch = !node.catchBlocks.isEmpty;
- bool hasFinally = node.finallyBlock != null;
- TryStatementInfo catchInfo, finallyInfo;
- // There is a nesting stack of try blocks, so the outer try/finally block
- // is added first.
- if (hasFinally) finallyInfo = enterTryFor(node.finallyBlock);
- if (hasCatch) catchInfo = enterTryFor(node.catchBlocks);
- visit(node.tryBlock);
-
- if (hasCatch) {
- leaveTryFor(catchInfo);
- visit(node.catchBlocks);
- }
- if (hasFinally) {
- leaveTryFor(finallyInfo);
- visit(node.finallyBlock);
- }
- }
-
- visitVariableDefinitions(ast.VariableDefinitions node) {
- if (inTryStatement) {
- for (ast.Node definition in node.definitions.nodes) {
- LocalVariableElement local = elements[definition];
- assert(local != null);
- // In the closure conversion pass we check for isInitializingFormal,
- // but I'm not sure it can arise.
- assert(!local.isInitializingFormal);
- tryNestingStack.last.declared.add(local);
- }
- }
- node.visitChildren(this);
- }
-}
-
-/// The [IrBuilder]s view on the information about the program that has been
-/// computed in resolution and and type interence.
-class GlobalProgramInformation {
- final Compiler _compiler;
- JavaScriptBackend get _backend => _compiler.backend;
-
- GlobalProgramInformation(this._compiler);
-
- /// Returns [true], if the analysis could not determine that the type
- /// arguments for the class [cls] are never used in the program.
- bool requiresRuntimeTypesFor(ClassElement cls) {
- return cls.typeVariables.isNotEmpty && _backend.classNeedsRti(cls);
- }
-
- FunctionElement get throwTypeErrorHelper => _backend.helpers.throwTypeError;
- Element get throwNoSuchMethod => _backend.helpers.throwNoSuchMethod;
-
- ClassElement get nullClass => _compiler.coreClasses.nullClass;
-
- DartType unaliasType(DartType type) => type.unaliased;
-
- TypeMask getTypeMaskForForeign(NativeBehavior behavior) {
- if (behavior == null) {
- return _backend.dynamicType;
- }
- return TypeMaskFactory.fromNativeBehavior(behavior, _compiler);
- }
-
- bool isArrayType(TypeMask type) {
- return type.satisfies(_backend.helpers.jsArrayClass, _compiler.world);
- }
-
- TypeMask getTypeMaskForNativeFunction(FunctionElement function) {
- return _compiler.typesTask.getGuaranteedReturnTypeOfElement(function);
- }
-
- FieldElement locateSingleField(Selector selector, TypeMask type) {
- return _compiler.world.locateSingleField(selector, type);
- }
-
- bool fieldNeverChanges(FieldElement field) {
- return _compiler.world.fieldNeverChanges(field);
- }
-
- Element get closureConverter {
- return _backend.helpers.closureConverter;
- }
-
- void addNativeMethod(FunctionElement function) {
- _backend.emitter.nativeEmitter.nativeMethods.add(function);
- }
-
- bool get trustJSInteropTypeAnnotations =>
- _compiler.options.trustJSInteropTypeAnnotations;
-
- bool isNative(ClassElement element) => _backend.isNative(element);
-
- bool isJsInterop(FunctionElement element) => _backend.isJsInterop(element);
-
- bool isJsInteropAnonymous(FunctionElement element) =>
- _backend.jsInteropAnalysis.hasAnonymousAnnotation(element.contextClass);
-
- String getJsInteropTargetPath(FunctionElement element) {
- return '${_backend.namer.fixedBackendPath(element)}.'
- '${_backend.nativeData.getFixedBackendName(element)}';
- }
-
- DartType get jsJavascriptObjectType =>
- _backend.helpers.jsJavaScriptObjectClass.thisType;
-}
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart ('k') | pkg/compiler/lib/src/cps_ir/cps_ir_integrity.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698