// Copyright (c) 2016, 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.

// ignore: implementation_imports
import 'package:front_end/src/api_prototype/static_weak_references.dart'
    as ir
    show StaticWeakReferences;
import 'package:js_runtime/synced/embedded_names.dart';
import 'package:js_shared/synced/embedded_names.dart'
    show JsBuiltin, JsGetName, TYPES;
import 'package:kernel/ast.dart' as ir;
import 'package:kernel/type_environment.dart' as ir;

import '../closure.dart';
import '../common.dart';
import '../common/codegen.dart' show CodegenRegistry;
import '../common/elements.dart';
import '../common/names.dart';
import '../constants/constant_system.dart' as constant_system;
import '../constants/values.dart';
import '../deferred_load/output_unit.dart' show OutputUnit;
import '../dump_info.dart';
import '../elements/entities.dart';
import '../elements/jumps.dart';
import '../elements/names.dart';
import '../elements/types.dart';
import '../inferrer/abstract_value_domain.dart';
import '../inferrer/types.dart';
import '../io/source_information.dart';
import '../ir/util.dart';
import '../js/js.dart' as js;
import '../js_backend/backend.dart' show FunctionInlineCache;
import '../js_backend/field_analysis.dart'
    show FieldAnalysisData, JFieldAnalysis;
import '../js_backend/interceptor_data.dart';
import '../js_backend/inferred_data.dart';
import '../js_backend/namer.dart' show ModularNamer;
import '../js_backend/native_data.dart';
import '../js_backend/runtime_types_resolution.dart';
import '../js_emitter/code_emitter_task.dart' show ModularEmitter;
import '../js_model/class_type_variable_access.dart';
import '../js_model/element_map.dart';
import '../js_model/elements.dart' show JGeneratorBody, JParameterStub;
import '../js_model/js_strategy.dart';
import '../js_model/js_world.dart' show JClosedWorld;
import '../js_model/locals.dart' show GlobalLocalsMap, JumpVisitor;
import '../js_model/type_recipe.dart';
import '../js_model/records.dart' show RecordData, JRecordGetter;
import '../kernel/invocation_mirror.dart';
import '../native/behavior.dart';
import '../native/js.dart';
import '../options.dart';
import '../tracer.dart';
import '../universe/call_structure.dart';
import '../universe/feature.dart';
import '../universe/record_shape.dart';
import '../universe/selector.dart';
import '../universe/target_checks.dart' show TargetChecks;
import '../universe/use.dart' show ConstantUse, StaticUse, TypeUse;
import 'branch_builder.dart';
import 'jump_handler.dart';
import 'locals_handler.dart';
import 'loop_handler.dart';
import 'metrics.dart';
import 'nodes.dart';
import 'string_builder.dart';
import 'switch_continue_analysis.dart';
import 'type_builder.dart';

// TODO(johnniwinther): Merge this with [KernelInliningState].
class StackFrame {
  final StackFrame? parent;
  final MemberEntity member;
  final AsyncMarker asyncMarker;
  final KernelToLocalsMap localsMap;
  // [ir.Let] and [ir.LocalInitializer] bindings.
  final Map<ir.VariableDeclaration, HInstruction> letBindings;
  final KernelToTypeInferenceMap typeInferenceMap;
  final SourceInformationBuilder sourceInformationBuilder;
  final ir.StaticTypeContext? staticTypeContext;

  StackFrame(
    this.parent,
    this.member,
    this.asyncMarker,
    this.localsMap,
    this.letBindings,
    this.typeInferenceMap,
    this.sourceInformationBuilder,
    this.staticTypeContext,
  );
}

class KernelSsaGraphBuilder extends ir.VisitorDefault<void>
    with ir.VisitorVoidMixin {
  /// Holds the resulting SSA graph.
  final HGraph graph = HGraph();

  /// True if the builder is processing nodes inside a try statement. This is
  /// important for generating control flow out of a try block like returns or
  /// breaks.
  bool _inTryStatement = false;

  /// Used to track the locals while building the graph.
  late LocalsHandler localsHandler;

  /// A stack of instructions.
  ///
  /// We build the SSA graph by simulating a stack machine.
  List<HInstruction> stack = [];

  /// The count of nested loops we are currently building.
  ///
  /// The loop nesting is consulted when inlining a function invocation. The
  /// inlining heuristics take this information into account.
  int loopDepth = 0;

  /// A mapping from jump targets to their handlers.
  Map<JumpTarget, JumpHandler> jumpTargets = {};

  final CompilerOptions options;
  final DiagnosticReporter reporter;
  final ModularEmitter _emitter;
  final ModularNamer _namer;
  final MemberEntity targetElement;
  final MemberEntity _initialTargetElement;
  final JClosedWorld closedWorld;
  final CodegenRegistry registry;
  final ClosureData _closureDataLookup;
  final RecordData _recordData;
  final Tracer _tracer;

  /// A stack of [InterfaceType]s that have been seen during inlining of
  /// factory constructors.  These types are preserved in [HInvokeStatic]s and
  /// [HCreate]s inside the inline code and registered during code generation
  /// for these nodes.
  // TODO(karlklose): consider removing this and keeping the (substituted) types
  // of the type variables in an environment (like the [LocalsHandler]).
  final List<InterfaceType> _currentImplicitInstantiations = [];

  /// Used to report information about inlining (which occurs while building the
  /// SSA graph), when dump-info is enabled.
  final InfoReporter? _infoReporter;

  final SsaMetrics _metrics;

  HInstruction? _rethrowableException;

  final SourceInformationStrategy _sourceInformationStrategy;
  final JsToElementMap _elementMap;
  final GlobalTypeInferenceResults globalInferenceResults;
  late final LoopHandler _loopHandler;
  late final TypeBuilder _typeBuilder;

  /// True if we are visiting the expression of a throw statement; we assume
  /// this is a slow path.
  bool _inExpressionOfThrow = false;

  final List<KernelInliningState> _inliningStack = [];
  Local? _returnLocal;
  DartType? _returnType;

  StackFrame? _currentFrame;

  final FunctionInlineCache _inlineCache;
  final InlineDataCache _inlineDataCache;

  KernelSsaGraphBuilder(
    this.options,
    this.reporter,
    this._initialTargetElement,
    InterfaceType? instanceType,
    this._infoReporter,
    this._metrics,
    this._elementMap,
    this.globalInferenceResults,
    this.closedWorld,
    this.registry,
    this._namer,
    this._emitter,
    this._tracer,
    this._sourceInformationStrategy,
    this._inlineCache,
    this._inlineDataCache,
  ) : targetElement = _effectiveTargetElementFor(_initialTargetElement),
      _closureDataLookup = closedWorld.closureDataLookup,
      _recordData = closedWorld.recordData {
    _enterFrame(targetElement, null);
    _loopHandler = KernelLoopHandler(this);
    _typeBuilder = KernelTypeBuilder(this, _elementMap);
    graph.element = targetElement;
    graph.sourceInformation =
        _sourceInformationBuilder.buildVariableDeclaration();
    localsHandler = LocalsHandler(
      this,
      targetElement,
      targetElement,
      instanceType,
      _nativeData,
      _interceptorData,
    );
  }

  KernelToLocalsMap get _localsMap => _currentFrame!.localsMap;

  Map<ir.VariableDeclaration, HInstruction> get _letBindings =>
      _currentFrame!.letBindings;

  JCommonElements get _commonElements => _elementMap.commonElements;

  JElementEnvironment get _elementEnvironment => _elementMap.elementEnvironment;

  JFieldAnalysis get _fieldAnalysis => closedWorld.fieldAnalysis;

  KernelToTypeInferenceMap get _typeInferenceMap =>
      _currentFrame!.typeInferenceMap;

  SourceInformationBuilder get _sourceInformationBuilder =>
      _currentFrame!.sourceInformationBuilder;

  AbstractValueDomain get _abstractValueDomain =>
      closedWorld.abstractValueDomain;

  NativeData get _nativeData => closedWorld.nativeData;

  InterceptorData get _interceptorData => closedWorld.interceptorData;

  RuntimeTypesNeed get _rtiNeed => closedWorld.rtiNeed;

  GlobalLocalsMap get _globalLocalsMap =>
      globalInferenceResults.globalLocalsMap;

  InferredData get _inferredData => globalInferenceResults.inferredData;

  DartTypes get dartTypes => closedWorld.dartTypes;

  void push(HInstruction instruction) {
    add(instruction);
    stack.add(instruction);
  }

  HInstruction pop() {
    return stack.removeLast();
  }

  /// Pushes a boolean checking [expression] against null.
  void pushCheckNull(HInstruction expression) {
    push(
      HIdentity(
        expression,
        graph.addConstantNull(closedWorld),
        _abstractValueDomain.boolType,
      ),
    );
  }

  HBasicBlock? _current;

  /// The current block to add instructions to. Might be null, if we are
  /// visiting dead code, but see [_isReachable].
  HBasicBlock? get current => _current;

  set current(HBasicBlock? c) {
    _isReachable = c != null;
    _current = c;
  }

  /// The most recently opened block. Has the same value as [current] while
  /// the block is open, but unlike [current], it isn't cleared when the
  /// current block is closed.
  late HBasicBlock lastOpenedBlock;

  /// Indicates whether the current block is dead (because it has a throw or a
  /// return further up). If this is false, then [current] may be null. If the
  /// block is dead then it may also be aborted, but for simplicity we only
  /// abort on statement boundaries, not in the middle of expressions. See
  /// [isAborted].
  bool _isReachable = true;

  /// Is the current statement or expression nested in a [ir.BlockExpression]?
  bool _inBlockExpression = false;

  HLocalValue? lastAddedParameter;

  Map<Local, HInstruction> parameters = {};
  late Set<Local> elidedParameters;

  HBasicBlock addNewBlock() {
    HBasicBlock block = graph.addNewBlock();
    // If adding a new block during building of an expression, it is due to
    // conditional expressions or short-circuit logical operators.
    return block;
  }

  void open(HBasicBlock block) {
    block.open();
    current = block;
    lastOpenedBlock = block;
  }

  HBasicBlock close(HControlFlow end) {
    HBasicBlock result = current!;
    current!.close(end);
    current = null;
    return result;
  }

  HBasicBlock _closeAndGotoExit(HControlFlow end) {
    HBasicBlock result = current!;
    current!.close(end);
    current = null;
    result.addSuccessor(graph.exit);
    return result;
  }

  void goto(HBasicBlock from, HBasicBlock to) {
    from.close(HGoto());
    from.addSuccessor(to);
  }

  void _prepareEntryBlock() {
    HBasicBlock block = graph.addNewBlock();
    // Create `graph.entry` as an initially empty block. `graph.entry` is
    // treated specially (holding parameters, local variables and constants)
    // but cannot receive constants before it has been closed. By closing it
    // here, we can use constants in the code that sets up the function.
    open(graph.entry);
    close(HGoto()).addSuccessor(block);
    open(block);
  }

  bool isAborted() {
    return current == null;
  }

  /// Creates a new block, transitions to it from any current block, and
  /// opens the new block.
  HBasicBlock openNewBlock() {
    HBasicBlock newBlock = addNewBlock();
    if (!isAborted()) goto(current!, newBlock);
    open(newBlock);
    return newBlock;
  }

  void add(HInstruction instruction) {
    current!.add(instruction);
  }

  HLocalValue addParameter(
    Entity? parameter,
    AbstractValue type, {
    bool isElided = false,
  }) {
    HLocalValue result =
        isElided
            ? HLocalValue(parameter, type)
            : HParameterValue(parameter, type);
    if (lastAddedParameter == null) {
      graph.entry.addBefore(graph.entry.first, result);
    } else {
      graph.entry.addAfter(lastAddedParameter, result);
    }
    lastAddedParameter = result;
    return result;
  }

  HSubGraphBlockInformation? wrapStatementGraph(SubGraph? statements) {
    if (statements == null) return null;
    return HSubGraphBlockInformation(statements);
  }

  HExpressionInformation? wrapExpressionGraph(SubExpression? expression) {
    if (expression == null) return null;
    return HSubExpressionBlockInformation(expression);
  }

  HLiteralList _buildLiteralList(List<HInstruction> inputs) {
    return HLiteralList(inputs, _abstractValueDomain.growableListType);
  }

  /// Called when control flow is about to change, in which case we need to
  /// specify special successors if we are already in a try/catch/finally block.
  void _handleInTryStatement() {
    if (!_inTryStatement) return;
    HBasicBlock block = close(HExitTry());
    HBasicBlock newBlock = graph.addNewBlock();
    block.addSuccessor(newBlock);
    open(newBlock);
  }

  DartType _getStaticType(ir.Expression node) {
    // TODO(johnniwinther): Substitute the type by the this type and type
    // arguments of the current frame.
    ir.DartType type = node.getStaticType(_currentFrame!.staticTypeContext!);
    return _elementMap.getDartType(type);
  }

  DartType _getStaticForInIteratorType(ir.ForInStatement node) {
    // TODO(johnniwinther): Substitute the type by the this type and type
    // arguments of the current frame.
    ir.DartType type = node.getIteratorType(_currentFrame!.staticTypeContext!);
    return _elementMap.getDartType(type);
  }

  DartType _getStaticForInElementType(ir.ForInStatement node) {
    // TODO(johnniwinther): Substitute the type by the this type and type
    // arguments of the current frame.
    ir.DartType type = node.getElementType(_currentFrame!.staticTypeContext!);
    return _elementMap.getDartType(type);
  }

  static MemberEntity _effectiveTargetElementFor(MemberEntity member) {
    if (member is JGeneratorBody) return member.function;
    return member;
  }

  void _enterFrame(
    MemberEntity member,
    SourceInformation? callSourceInformation,
  ) {
    AsyncMarker asyncMarker = AsyncMarker.sync;
    final function = getFunctionNode(_elementMap, member);
    if (function != null) {
      asyncMarker = getAsyncMarker(function);
    }
    final elementMap = closedWorld.elementMap;
    final memberNode = elementMap.getMemberContextNode(member);
    _currentFrame = StackFrame(
      _currentFrame,
      member,
      asyncMarker,
      _globalLocalsMap.getLocalsMap(member),
      {},
      KernelToTypeInferenceMapImpl(member, globalInferenceResults),
      _currentFrame != null
          ? _currentFrame!.sourceInformationBuilder.forContext(
            member,
            callSourceInformation,
          )
          : _sourceInformationStrategy.createBuilderForContext(member),
      memberNode != null
          ? ir.StaticTypeContext(
            memberNode,
            elementMap.typeEnvironment,
            cache: ir.StaticTypeCacheImpl(),
          )
          : null,
    );
  }

  void _leaveFrame() {
    _currentFrame = _currentFrame!.parent;
  }

  HGraph? build() {
    return reporter.withCurrentElement(_localsMap.currentMember, () {
      // TODO(het): no reason to do this here...
      HInstruction.idCounter = 0;
      MemberDefinition definition = _elementMap.getMemberDefinition(
        _initialTargetElement,
      );

      switch (definition.kind) {
        case MemberKind.regular:
        case MemberKind.closureCall:
          ir.Node target = definition.node;
          if (target is ir.Procedure) {
            if (target.isExternal) {
              // Skip interop extension type object literal constructors as
              // that's handled within `visitStaticInvocation`.
              // TODO(54968): We should handle the lowering for object literal
              // constructors in the interop transformer somehow instead and
              // avoid assuming all such members are object literal constructors
              // or otherwise paying the cost to verify by indexing extension
              // types.
              final isObjectLiteralConstructor =
                  target.isExtensionTypeMember &&
                  target.function.namedParameters.isNotEmpty;
              if (isObjectLiteralConstructor) return null;
              _buildExternalFunctionNode(
                targetElement as FunctionEntity,
                _ensureDefaultArgumentValues(target.function),
              );
            } else {
              _buildFunctionNode(
                targetElement as FunctionEntity,
                _ensureDefaultArgumentValues(target.function),
              );
            }
          } else if (target is ir.Field) {
            FieldAnalysisData fieldData = closedWorld.fieldAnalysis
                .getFieldData(targetElement as FieldEntity);

            if (fieldData.initialValue != null) {
              registry.registerConstantUse(
                ConstantUse.init(fieldData.initialValue!),
              );
              if (targetElement.isStatic || targetElement.isTopLevel) {
                /// No code is created for this field: All references inline the
                /// constant value.
                return null;
              }
            } else if (fieldData.isLazy) {
              // The generated initializer needs be wrapped in the cyclic-error
              // helper.
              registry.registerStaticUse(
                StaticUse.staticInvoke(
                  closedWorld.commonElements.cyclicThrowHelper,
                  CallStructure.oneArg,
                ),
              );
              registry.registerStaticUse(
                StaticUse.staticInvoke(
                  closedWorld.commonElements.throwLateFieldADI,
                  CallStructure.oneArg,
                ),
              );
            }
            if (targetElement.isInstanceMember) {
              if (fieldData.isEffectivelyFinal ||
                  !closedWorld.annotationsData
                      .getParameterCheckPolicy(targetElement)
                      .isEmitted) {
                // No need for a checked setter.
                return null;
              }
            }
            if (targetElement.isInstanceMember) {
              _buildInstanceFieldSetter(target);
            } else {
              _buildStaticFieldInitializer(target);
            }
          } else if (target is ir.LocalFunction) {
            _buildFunctionNode(
              targetElement as FunctionEntity,
              _ensureDefaultArgumentValues(target.function),
            );
          } else {
            throw 'No case implemented to handle target: '
                '$target for $targetElement';
          }
          break;
        case MemberKind.constructor:
          final constructor = definition.node as ir.Constructor;
          _ensureDefaultArgumentValues(constructor.function);
          _buildConstructor(targetElement as ConstructorEntity, constructor);
          break;
        case MemberKind.constructorBody:
          final constructor = definition.node as ir.Constructor;
          _ensureDefaultArgumentValues(constructor.function);
          _buildConstructorBody(constructor);
          break;
        case MemberKind.closureField:
          // Closure fields have no setter and therefore never require any code.
          return null;
        case MemberKind.signature:
          ir.Node target = definition.node;
          ir.FunctionNode originalClosureNode;
          if (target is ir.Procedure) {
            originalClosureNode = target.function;
          } else if (target is ir.LocalFunction) {
            originalClosureNode = target.function;
          } else {
            failedAt(
              targetElement,
              "Unexpected function signature: "
              "$targetElement inside a non-closure: $target",
            );
          }
          _buildMethodSignatureNewRti(originalClosureNode);
          break;
        case MemberKind.parameterStub:
          _buildParameterStub(
            _initialTargetElement as JParameterStub,
            _functionNodeOf(definition.node)!,
          );
        case MemberKind.generatorBody:
          _buildGeneratorBody(
            _initialTargetElement as JGeneratorBody,
            _functionNodeOf(definition.node)!,
          );
          break;
        case MemberKind.recordGetter:
          _buildRecordGetter(
            _initialTargetElement as JRecordGetter,
            definition as RecordGetterDefinition,
          );
          break;
      }
      assert(graph.isValid(), "Invalid graph for $_initialTargetElement.");

      if (_tracer.isEnabled) {
        MemberEntity member = _initialTargetElement;
        String name = member.name ?? '<null>';
        if (member.isInstanceMember ||
            member is ConstructorEntity ||
            member.isStatic) {
          name = "${member.enclosingClass!.name}.$name";
          if (definition.kind == MemberKind.constructorBody) {
            name += " (body)";
          }
        }
        _tracer.traceCompilation(name);
        _tracer.traceGraph('builder', graph);
      }

      return graph;
    });
  }

  ir.FunctionNode? _functionNodeOf(ir.Node node) {
    if (node is ir.Member) return node.function;
    if (node is ir.LocalFunction) return node.function;
    return null;
  }

  ir.FunctionNode _ensureDefaultArgumentValues(ir.FunctionNode function) {
    // Register all [function]'s default argument values.
    //
    // Default values might be (or contain) functions that are not referenced
    // from anywhere else so we need to ensure these are enqueued.  Stubs and
    // `Function.apply` data are created after the codegen queue is closed, so
    // we force these functions into the queue by registering the constants as
    // used in advance. See language/cyclic_default_values_test.dart for an
    // example.
    //
    // TODO(sra): We could be more precise if stubs and `Function.apply` data
    // were generated by the codegen enqueuer. In practice even in huge programs
    // there are only very small number of constants created here that are not
    // actually used.
    void registerDefaultValue(ir.VariableDeclaration node) {
      final constantValue = _elementMap.getConstantValue(
        node.initializer,
        implicitNull: true,
      );
      assert(
        constantValue != null,
        failedAt(
          _elementMap.getMethod(function.parent as ir.Procedure),
          'No constant computed for $node',
        ),
      );
      registry.registerConstantUse(ConstantUse.init(constantValue!));
    }

    function.positionalParameters
        .skip(function.requiredParameterCount)
        .forEach(registerDefaultValue);
    function.namedParameters.forEach(registerDefaultValue);
    return function;
  }

  void _buildInstanceFieldSetter(ir.Field node) {
    assert(!node.isStatic);
    FieldEntity field = _elementMap.getMember(node) as FieldEntity;
    _openFunction(field, checks: TargetChecks.none);
    HInstruction thisInstruction = localsHandler.readThis(
      sourceInformation: _sourceInformationBuilder.buildGet(node),
    );
    // Use dynamic type because the type computed by the inferrer is
    // narrowed to the type annotation.
    HInstruction parameter = HParameterValue(
      field,
      _abstractValueDomain.dynamicType,
    );
    // Add the parameter as the last instruction of the entry block.
    // If the method is intercepted, we want the actual receiver
    // to be the first parameter.
    graph.entry.addBefore(graph.entry.last, parameter);
    DartType type = _getDartTypeIfValid(node.type);
    HInstruction value = _typeBuilder.potentiallyCheckOrTrustTypeOfParameter(
      field,
      parameter,
      type,
    );
    // TODO(sra): Pass source information to
    // [potentiallyCheckOrTrustTypeOfParameter].
    // TODO(sra): The source information should indicate the field and
    // possibly its type but not the initializer.
    value.sourceInformation ??= _sourceInformationBuilder.buildSet(node);
    value = _potentiallyAssertNotNull(field, node, value, type);
    if (!_fieldAnalysis.getFieldData(field).isElided) {
      add(HFieldSet(field, thisInstruction, value));
    }
    _closeFunction();
  }

  void _buildStaticFieldInitializer(ir.Field node) {
    assert(node.isStatic);
    graph.isLazyInitializer = true;
    FieldEntity field = _elementMap.getMember(node) as FieldEntity;
    _openFunction(field, checks: TargetChecks.none);
    if (node.initializer != null) {
      node.initializer!.accept(this);
      HInstruction fieldValue = pop();
      HInstruction checkInstruction = _typeBuilder
          .potentiallyCheckOrTrustTypeOfAssignment(
            field,
            fieldValue,
            _getDartTypeIfValid(node.type),
          );
      stack.add(checkInstruction);
    } else {
      stack.add(graph.addConstantNull(closedWorld));
    }
    HInstruction value = pop();
    _closeAndGotoExit(
      HReturn(value, _sourceInformationBuilder.buildReturn(node)),
    );
    _closeFunction();
  }

  DartType _getDartTypeIfValid(ir.DartType type) {
    if (type is ir.InvalidType) return dartTypes.dynamicType();
    return _elementMap.getDartType(type);
  }

  /// Pops the most recent instruction from the stack and ensures that it is a
  /// non-null bool.
  HInstruction popBoolified() {
    HInstruction value = pop();
    return _typeBuilder.potentiallyCheckOrTrustTypeOfCondition(
      _currentFrame!.member,
      value,
    );
  }

  /// Extend current method parameters with parameters for the class type
  /// parameters.  If the class has type parameters but does not need them, bind
  /// to `dynamic` (represented as `null`) so the bindings are available for
  /// building types up the inheritance chain of generative constructors.
  void _addClassTypeVariablesIfNeeded(MemberEntity member) {
    if (member is! ConstructorEntity && member is! ConstructorBodyEntity) {
      return;
    }
    ClassEntity cls = member.enclosingClass!;
    InterfaceType thisType = _elementEnvironment.getThisType(cls);
    if (thisType.typeArguments.isEmpty) {
      return;
    }
    bool needsTypeArguments = _rtiNeed.classNeedsTypeArguments(cls);
    for (var typeVariable in thisType.typeArguments) {
      final typeVariableType = typeVariable as TypeVariableType;
      HInstruction param;
      if (needsTypeArguments) {
        param = addParameter(
          typeVariableType.element,
          _abstractValueDomain.nonNullType,
        );
      } else {
        // Unused, so bind to `dynamic`.
        param = graph.addConstantNull(closedWorld);
      }
      Local local = localsHandler.getTypeVariableAsLocal(typeVariableType);
      localsHandler.directLocals[local] = param;
    }
  }

  /// Extend current method parameters with parameters for the function type
  /// variables.
  void _addFunctionTypeVariablesIfNeeded(MemberEntity member) {
    if (member is! FunctionEntity) return;

    FunctionEntity function = member;
    List<TypeVariableType> typeVariables = _elementEnvironment
        .getFunctionTypeVariables(function);
    if (typeVariables.isEmpty) {
      return;
    }
    bool needsTypeArguments = _rtiNeed.methodNeedsTypeArguments(function);
    bool elideTypeParameters = function.parameterStructure.typeParameters == 0;
    for (TypeVariableType typeVariable in typeVariables) {
      HInstruction param;
      bool erased = false;
      if (elideTypeParameters) {
        // Add elided type parameters.
        param = _computeTypeArgumentDefaultValue(function, typeVariable);
        erased = true;
      } else if (needsTypeArguments) {
        param = addParameter(
          typeVariable.element,
          _abstractValueDomain.nonNullType,
        );
      } else {
        // Unused, so bind to bound.
        param = _computeTypeArgumentDefaultValue(function, typeVariable);
        erased = true;
      }
      Local local = localsHandler.getTypeVariableAsLocal(typeVariable);
      localsHandler.directLocals[local] = param;
      if (!erased) {
        _functionTypeParameterLocals.add(local);
      }
    }
  }

  // Locals for function type parameters that can be forwarded, in argument
  // position order.
  final List<Local> _functionTypeParameterLocals = [];

  /// Builds a generative constructor.
  ///
  /// Generative constructors are built in stages, in effect inlining the
  /// initializers and constructor bodies up the inheritance chain.
  ///
  ///  1. Extend method parameters with parameters the class's type parameters.
  ///
  ///  2. Add type checks for value parameters (might need result of (1)).
  ///
  ///  3. Walk inheritance chain to build bindings for type parameters of
  ///     superclasses and mixed-in classes.
  ///
  ///  4. Collect initializer values. Walk up inheritance chain to collect field
  ///     initializers from field declarations, initializing parameters and
  ///     initializer.
  ///
  ///  5. Create reified type information for instance.
  ///
  ///  6. Allocate instance and assign initializers and reified type information
  ///     to fields by calling JavaScript constructor.
  ///
  ///  7. Walk inheritance chain to call or inline constructor bodies.
  ///
  /// All the bindings are put in the constructor's locals handler. The
  /// implication is that a class cannot be extended or mixed-in twice. If we in
  /// future support repeated uses of a mixin class, we should do so by cloning
  /// the mixin class in the Kernel input.
  void _buildConstructor(ConstructorEntity constructor, ir.Constructor node) {
    final sourceInformation = _sourceInformationBuilder.buildCreate(node);
    ClassEntity cls = constructor.enclosingClass;

    if (_inliningStack.isEmpty) {
      _openFunction(
        constructor,
        functionNode: node.function,
        parameterStructure: constructor.parameterStructure,
        checks: TargetChecks.none,
      );
    }

    // [constructorData.fieldValues] accumulates the field initializer values,
    // which may be overwritten by initializer-list initializers.
    ConstructorData constructorData = ConstructorData();
    _buildInitializers(node, constructorData);

    List<HInstruction> constructorArguments = [];
    // Doing this instead of fieldValues.forEach because we haven't defined the
    // order of the arguments here. We can define that with JElements.
    bool isCustomElement =
        _nativeData.isNativeOrExtendsNative(cls) &&
        !_nativeData.isJsInteropClass(cls);
    InterfaceType thisType = _elementEnvironment.getThisType(cls);
    List<FieldEntity> fields = [];
    _elementEnvironment.forEachInstanceField(cls, (
      ClassEntity enclosingClass,
      FieldEntity member,
    ) {
      HInstruction? value = constructorData.fieldValues[member];
      FieldAnalysisData fieldData = _fieldAnalysis.getFieldData(member);
      if (value == null) {
        assert(
          fieldData.isInitializedInAllocator ||
              isCustomElement ||
              reporter.hasReportedError,
          'No initializer value for field $member',
        );
      } else {
        if (!fieldData.isElided) {
          fields.add(member);
          DartType type = _elementEnvironment.getFieldType(member);
          type = localsHandler.substInContext(type);
          constructorArguments.add(
            _typeBuilder.potentiallyCheckOrTrustTypeOfAssignment(
              member,
              value,
              type,
            ),
          );
        }
      }
    });

    _addImplicitInstantiation(thisType);
    List<InterfaceType> instantiatedTypes = List<InterfaceType>.from(
      _currentImplicitInstantiations,
    );

    HInstruction newObject;
    if (isCustomElement) {
      // Bulk assign to the initialized fields.
      newObject = graph.explicitReceiverParameter!;
      // Null guard ensures an error if we are being called from an explicit
      // 'new' of the constructor instead of via an upgrade. It is optimized out
      // if there are field initializers.
      newObject = HNullCheck(
        newObject,
        _abstractValueDomain.excludeNull(newObject.instructionType),
      )..sourceInformation = sourceInformation;
      add(newObject);
      for (int i = 0; i < fields.length; i++) {
        final value = constructorArguments[i];
        add(HFieldSet(fields[i], newObject, value));
      }
    } else {
      // Create the runtime type information, if needed.
      bool needsTypeArguments = closedWorld.rtiNeed.classNeedsTypeArguments(
        cls,
      );
      if (needsTypeArguments) {
        InterfaceType thisType = _elementEnvironment.getThisType(cls);
        HInstruction typeArgument = _typeBuilder.analyzeTypeArgument(
          thisType,
          sourceElement,
          sourceInformation: sourceInformation,
        );
        constructorArguments.add(typeArgument);
      }
      newObject = HCreate(
        cls,
        constructorArguments,
        _abstractValueDomain.createNonNullExact(cls),
        sourceInformation,
        instantiatedTypes: instantiatedTypes,
        hasRtiInput: needsTypeArguments,
      );

      add(newObject);
    }
    _removeImplicitInstantiation(thisType);

    HInstruction? interceptor;
    // Generate calls to the constructor bodies.
    for (ir.Constructor body in constructorData.constructorChain.reversed) {
      if (_isEmptyStatement(body.function.body)) continue;

      List<HInstruction> bodyCallInputs = [];
      if (isCustomElement) {
        if (interceptor == null) {
          ConstantValue constant = InterceptorConstantValue(cls);
          interceptor = graph.addConstant(constant, closedWorld);
        }
        bodyCallInputs.add(interceptor);
      }
      bodyCallInputs.add(newObject);

      // Pass uncaptured arguments first, captured arguments in a box, then type
      // arguments.

      ConstructorEntity inlinedConstructor = _elementMap.getConstructor(body);

      _inlinedFrom(
        inlinedConstructor,
        _sourceInformationBuilder.buildCall(body, body),
        () {
          final constructorBody = _elementMap.getConstructorBody(body);

          void handleParameter(
            ir.VariableDeclaration node, {
            required bool isElided,
          }) {
            if (isElided) return;

            Local parameter = _localsMap.getLocalVariable(node);
            // If [parameter] is boxed, it will be a field in the box passed as
            // the last parameter. So no need to directly pass it.
            if (!localsHandler.isBoxed(parameter)) {
              bodyCallInputs.add(localsHandler.readLocal(parameter));
            }
          }

          // Provide the parameters to the generative constructor body.
          forEachOrderedParameter(
            _elementMap,
            constructorBody,
            handleParameter,
          );

          // If there are locals that escape (i.e. mutated in closures), we pass the
          // box to the constructor.
          CapturedScope scopeData = _closureDataLookup.getCapturedScope(
            constructorBody,
          );
          if (scopeData.requiresContextBox) {
            bodyCallInputs.add(localsHandler.readLocal(scopeData.contextBox!));
          }

          // Pass type arguments.
          ClassEntity inlinedConstructorClass = constructorBody.enclosingClass!;
          if (closedWorld.rtiNeed.classNeedsTypeArguments(
            inlinedConstructorClass,
          )) {
            InterfaceType thisType = _elementEnvironment.getThisType(
              inlinedConstructorClass,
            );
            for (DartType typeVariable in thisType.typeArguments) {
              DartType result = localsHandler.substInContext(typeVariable);
              HInstruction argument = _typeBuilder.analyzeTypeArgument(
                result,
                sourceElement,
              );
              bodyCallInputs.add(argument);
            }
          }

          if (!isCustomElement && // TODO(13836): Fix inlining.
              _tryInlineMethod(
                constructorBody,
                null,
                null,
                bodyCallInputs,
                null,
                node,
                sourceInformation,
              )) {
            pop();
          } else {
            _invokeConstructorBody(
              body,
              bodyCallInputs,
              _sourceInformationBuilder.buildDeclaration(constructor),
            );
          }
        },
      );
    }

    if (_inliningStack.isEmpty) {
      _closeAndGotoExit(HReturn(newObject, sourceInformation));
      _closeFunction();
    } else {
      localsHandler.updateLocal(
        _returnLocal!,
        newObject,
        sourceInformation: sourceInformation,
      );
    }
  }

  static bool _isEmptyStatement(ir.Statement? body) {
    if (body is ir.EmptyStatement) return true;
    if (body is ir.Block) return body.statements.every(_isEmptyStatement);
    return false;
  }

  void _invokeConstructorBody(
    ir.Constructor constructor,
    List<HInstruction> inputs,
    SourceInformation? sourceInformation,
  ) {
    MemberEntity constructorBody = _elementMap.getConstructorBody(constructor);
    HInvokeConstructorBody invoke = HInvokeConstructorBody(
      constructorBody as ConstructorBodyEntity,
      inputs,
      _abstractValueDomain.nonNullType,
      sourceInformation,
    );
    add(invoke);
  }

  /// Sets context for generating code that is the result of inlining
  /// [inlinedTarget].
  void _inlinedFrom(
    MemberEntity inlinedTarget,
    SourceInformation? callSourceInformation,
    void Function() f,
  ) {
    reporter.withCurrentElement(inlinedTarget, () {
      _enterFrame(inlinedTarget, callSourceInformation);
      f();
      _leaveFrame();
    });
  }

  void _ensureTypeVariablesForInitializers(
    ConstructorData constructorData,
    ClassEntity enclosingClass,
  ) {
    if (!constructorData.includedClasses.add(enclosingClass)) return;
    if (_rtiNeed.classNeedsTypeArguments(enclosingClass)) {
      // If [enclosingClass] needs RTI, we have to give a value to its type
      // parameters. For a super constructor call, the type is the supertype
      // of current class. For a redirecting constructor, the type is the
      // current type. [LocalsHandler.substInContext] takes care of both.
      InterfaceType thisType = _elementEnvironment.getThisType(enclosingClass);
      final type = localsHandler.substInContext(thisType) as InterfaceType;
      List<DartType> arguments = type.typeArguments;
      List<DartType> typeVariables = thisType.typeArguments;
      assert(arguments.length == typeVariables.length);
      Iterator<DartType> variables = typeVariables.iterator;
      for (var argument in type.typeArguments) {
        variables.moveNext();
        final typeVariable = variables.current as TypeVariableType;
        localsHandler.updateLocal(
          localsHandler.getTypeVariableAsLocal(typeVariable),
          _typeBuilder.analyzeTypeArgument(argument, sourceElement),
        );
      }
    }
  }

  /// Collects the values for field initializers for the direct fields of
  /// [clazz].
  void _collectFieldValues(ir.Class clazz, ConstructorData constructorData) {
    ClassEntity cls = _elementMap.getClass(clazz);
    _elementEnvironment.forEachDirectInstanceField(cls, (FieldEntity field) {
      _ensureTypeVariablesForInitializers(
        constructorData,
        field.enclosingClass!,
      );

      MemberDefinition definition = _elementMap.getMemberDefinition(field);
      ir.Field node;
      switch (definition.kind) {
        case MemberKind.regular:
          node = definition.node as ir.Field;
          break;
        case MemberKind.constructor:
        case MemberKind.constructorBody:
        case MemberKind.closureCall:
        case MemberKind.closureField:
        case MemberKind.signature:
        case MemberKind.generatorBody:
        case MemberKind.recordGetter:
        case MemberKind.parameterStub:
          failedAt(field, "Unexpected member definition $definition.");
      }

      bool ignoreAllocatorAnalysis = false;
      if (_nativeData.isNativeOrExtendsNative(cls)) {
        // @Native classes have 'fields' which are really getters/setter.  Do
        // not try to initialize e.g. 'tagName'.
        if (_nativeData.isNativeClass(cls)) return;
        // Fields that survive this test are fields of custom elements.
        ignoreAllocatorAnalysis = true;
      }

      if (ignoreAllocatorAnalysis ||
          !_fieldAnalysis.getFieldData(field).isInitializedInAllocator) {
        final initializer = node.initializer;
        if (initializer == null) {
          constructorData.fieldValues[field] = graph.addConstantNull(
            closedWorld,
          );
        } else {
          // Compile the initializer in the context of the field so we know that
          // class type parameters are accessed as values.
          // TODO(sra): It would be sufficient to know the context was a field
          // initializer.
          _inlinedFrom(
            field,
            _sourceInformationBuilder.buildAssignment(initializer),
            () {
              initializer.accept(this);
              constructorData.fieldValues[field] = pop();
            },
          );
        }
      }
    });
  }

  static bool _isRedirectingConstructor(ir.Constructor constructor) =>
      constructor.initializers.any(
        (initializer) => initializer is ir.RedirectingInitializer,
      );

  /// Collects field initializers all the way up the inheritance chain.
  void _buildInitializers(
    ir.Constructor constructor,
    ConstructorData constructorData,
  ) {
    assert(
      _elementMap.getConstructor(constructor) == _localsMap.currentMember,
      failedAt(
        _localsMap.currentMember,
        'Expected ${_localsMap.currentMember} '
        'but found ${_elementMap.getConstructor(constructor)}.',
      ),
    );
    constructorData.constructorChain.add(constructor);

    if (!_isRedirectingConstructor(constructor)) {
      // Compute values for field initializers, but only if this is not a
      // redirecting constructor, since the target will compute the fields.
      _collectFieldValues(constructor.enclosingClass, constructorData);
    }
    var foundSuperOrRedirectCall = false;
    for (var initializer in constructor.initializers) {
      if (initializer is ir.FieldInitializer) {
        FieldEntity field = _elementMap.getField(initializer.field);
        if (!_fieldAnalysis.getFieldData(field).isInitializedInAllocator) {
          initializer.value.accept(this);
          constructorData.fieldValues[field] = pop();
        }
      } else if (initializer is ir.SuperInitializer) {
        assert(!foundSuperOrRedirectCall);
        foundSuperOrRedirectCall = true;
        _inlineSuperInitializer(initializer, constructorData, constructor);
      } else if (initializer is ir.RedirectingInitializer) {
        assert(!foundSuperOrRedirectCall);
        foundSuperOrRedirectCall = true;
        _inlineRedirectingInitializer(
          initializer,
          constructorData,
          constructor,
        );
      } else if (initializer is ir.LocalInitializer) {
        // LocalInitializer is like a let-expression that is in scope for the
        // rest of the initializers.
        ir.VariableDeclaration variable = initializer.variable;
        assert(variable.isFinal);
        variable.initializer!.accept(this);
        HInstruction value = pop();
        // TODO(sra): Apply inferred type information.
        _letBindings[variable] = value;
      } else if (initializer is ir.AssertInitializer) {
        initializer.statement.accept(this);
      } else if (initializer is ir.InvalidInitializer) {
        assert(false, 'ir.InvalidInitializer not handled');
      } else {
        assert(false, 'Unhandled initializer ir.${initializer.runtimeType}');
      }
    }

    if (!foundSuperOrRedirectCall) {
      assert(
        _elementMap.getClass(constructor.enclosingClass) ==
                _elementMap.commonElements.objectClass ||
            constructor.isExternal ||
            constructor.initializers.any(_ErroneousInitializerVisitor.check),
        'All constructors should have super- or redirecting- initializers,'
        ' except Object()'
        ' ${constructor.initializers}',
      );
    }
  }

  List<HInstruction> _normalizeAndBuildArguments(
    ir.FunctionNode function,
    ir.Arguments arguments,
  ) {
    List<HInstruction> builtArguments = [];
    var positionalIndex = 0;
    for (var parameter in function.positionalParameters) {
      if (positionalIndex < arguments.positional.length) {
        arguments.positional[positionalIndex++].accept(this);
        builtArguments.add(pop());
      } else {
        builtArguments.add(_defaultValueForParameter(parameter));
      }
    }
    // Evaluate named arguments in given order.
    Map<String, HInstruction> namedArguments = _visitNamedArguments(arguments);
    // And add them to `builtArguments` in calling-convention order.
    function.namedParameters.toList()
      ..sort(namedOrdering)
      ..forEach((ir.VariableDeclaration parameter) {
        var argument = namedArguments[parameter.name];
        argument ??= _defaultValueForParameter(parameter);
        builtArguments.add(argument);
      });

    return builtArguments;
  }

  /// Inlines the given redirecting [constructor]'s initializers by collecting
  /// its field values and building its constructor initializers. We visit super
  /// constructors all the way up to the [Object] constructor.
  void _inlineRedirectingInitializer(
    ir.RedirectingInitializer initializer,
    ConstructorData constructorData,
    ir.Constructor caller,
  ) {
    ir.Constructor superOrRedirectConstructor = initializer.target;
    List<HInstruction> arguments = _normalizeAndBuildArguments(
      superOrRedirectConstructor.function,
      initializer.arguments,
    );

    // Redirecting initializer already has [localsHandler] bindings for type
    // parameters from the redirecting constructor.

    // For redirecting constructors, the fields will be initialized later by the
    // effective target, so we don't do it here.

    _inlineSuperOrRedirectCommon(
      initializer,
      superOrRedirectConstructor,
      arguments,
      constructorData,
      caller,
    );
  }

  /// Inlines the given super [constructor]'s initializers by collecting its
  /// field values and building its constructor initializers. We visit super
  /// constructors all the way up to the [Object] constructor.
  void _inlineSuperInitializer(
    ir.SuperInitializer initializer,
    ConstructorData constructorData,
    ir.Constructor caller,
  ) {
    ir.Constructor target = initializer.target;
    List<HInstruction> arguments = _normalizeAndBuildArguments(
      target.function,
      initializer.arguments,
    );

    ir.Class callerClass = caller.enclosingClass;
    ir.Supertype supertype = callerClass.supertype!;

    // The class of the super-constructor may not be the supertype class. In
    // this case, we must go up the class hierarchy until we reach the class
    // containing the super-constructor.
    while (supertype.classNode != target.enclosingClass) {
      // Fields from unnamed mixin application classes (ie Object&Foo) get
      // "collected" with the regular supertype fields, so we must bind type
      // parameters from both the supertype and the supertype's mixin classes
      // before collecting the field values.
      _collectFieldValues(supertype.classNode, constructorData);
      supertype = supertype.classNode.supertype!;
    }

    _inlineSuperOrRedirectCommon(
      initializer,
      target,
      arguments,
      constructorData,
      caller,
    );
  }

  void _inlineSuperOrRedirectCommon(
    ir.Initializer initializer,
    ir.Constructor constructor,
    List<HInstruction> arguments,
    ConstructorData constructorData,
    ir.Constructor caller,
  ) {
    var index = 0;

    ConstructorEntity element = _elementMap.getConstructor(constructor);
    final oldScopeMember = localsHandler.scopeMember;

    _inlinedFrom(
      element,
      _sourceInformationBuilder.buildCall(initializer, initializer),
      () {
        void handleParameter(ir.VariableDeclaration node) {
          Local parameter = _localsMap.getLocalVariable(node);
          HInstruction argument = arguments[index++];
          // Because we are inlining the initializer, we must update
          // what was given as parameter. This will be used in case
          // there is a parameter check expression in the initializer.
          parameters[parameter] = argument;
          localsHandler.updateLocal(parameter, argument);
        }

        constructor.function.positionalParameters.forEach(handleParameter);
        constructor.function.namedParameters.toList()
          ..sort(namedOrdering)
          ..forEach(handleParameter);

        _ensureTypeVariablesForInitializers(
          constructorData,
          element.enclosingClass,
        );

        // Set the locals handler state as if we were inlining the constructor.
        localsHandler.setupScope(element);
        localsHandler.enterScope(
          _closureDataLookup.getCapturedScope(element),
          _sourceInformationBuilder.buildDeclaration(element),
        );
        _buildInitializers(constructor, constructorData);
      },
    );
    localsHandler.setupScope(oldScopeMember);
  }

  /// Constructs a special signature function for a closure.
  void _buildMethodSignatureNewRti(ir.FunctionNode originalClosureNode) {
    // The signature function has no corresponding ir.Node, so we just use the
    // targetElement to set up the type environment.
    _openFunction(targetElement, checks: TargetChecks.none);
    FunctionType functionType = _elementMap.getFunctionType(
      originalClosureNode,
    );
    HInstruction rti = _typeBuilder.analyzeTypeArgument(
      functionType,
      sourceElement,
    );
    close(
      HReturn(rti, _sourceInformationBuilder.buildReturn(originalClosureNode)),
    ).addSuccessor(graph.exit);
    _closeFunction();
  }

  /// Constructs a parameter stub based on the signature of [stubMember].
  void _buildParameterStub(
    JParameterStub stubMember,
    ir.FunctionNode targetFunctionNode,
  ) {
    final stubTarget = stubMember.target;
    final stubParameterStructure = stubMember.parameterStructure;

    _openFunction(
      stubMember,
      functionNode: targetFunctionNode,
      parameterStructure: stubParameterStructure,
      checks: TargetChecks.none,
    );

    final sourceInformation = _sourceInformationBuilder.buildStub(
      stubTarget,
      stubParameterStructure.callStructure,
    );
    final isIntercepted = closedWorld.interceptorData.isInterceptedMethod(
      stubMember,
    );
    final isNativeOrJsInterop = closedWorld.nativeData.hasFixedBackendName(
      stubTarget,
    );

    List<HInstruction> invokeInputs = [];

    if (stubMember.isInstanceMember) {
      if (isIntercepted) {
        // Intercepted instance members need to include the receiver parameter
        // in the set of inputs.
        final receiverParameter = graph.explicitReceiverParameter!;
        final interceptor = _interceptorFor(
          receiverParameter,
          sourceInformation,
        );
        if (!isNativeOrJsInterop) {
          // Intercepted stubbed native calls are invoked directly on the
          // receiver rather than forwarding to another interceptor.
          invokeInputs.add(interceptor);
        }
        invokeInputs.add(receiverParameter);
      } else {
        // Non-intercepted instance member calls use `this` as the receiver.
        // Use `graph.thisInstruction` which accounts for `this` being different
        // in closures.
        invokeInputs.add(graph.thisInstruction!);
      }
    }

    final stubNamedParameters = stubParameterStructure.requiredNamedParameters;

    final parameterLocals = parameters.keys.toList();
    int? indexOfLastOptionalArgumentInParameters =
        invokeInputs.length + stubParameterStructure.positionalParameters;

    void updateLocalIfNecessary(DartType type, Local local) {
      if (!isNativeOrJsInterop) return;
      type = type.withoutNullability;
      if (type is FunctionType) {
        push(
          HInvokeStatic(
            _commonElements.closureConverter,
            [
              localsHandler.readLocal(local),
              graph.addConstantInt(type.parameterTypes.length, closedWorld),
            ],
            _abstractValueDomain.functionType,
            const [],
            targetCanThrow: false,
          ),
        );
        localsHandler.updateLocal(
          local,
          pop(),
          sourceInformation: sourceInformation,
        );
      }
    }

    int count = 0;
    _elementEnvironment.forEachParameter(stubTarget, (
      DartType type,
      String? name,
      ConstantValue? value,
    ) {
      if (count < stubParameterStructure.positionalParameters) {
        final local = parameterLocals[count];
        updateLocalIfNecessary(type, local);
        invokeInputs.add(localsHandler.readLocal(local));
      } else if (stubNamedParameters.contains(name)) {
        // The locals may not match the order of this forEach so find the right
        // one linearly.
        final local = parameterLocals.firstWhere(
          (parameter) => parameter.name == name,
        );
        updateLocalIfNecessary(type, local);
        invokeInputs.add(localsHandler.readLocal(local));
        indexOfLastOptionalArgumentInParameters = invokeInputs.length;
      } else if (value == null) {
        invokeInputs.add(graph.addConstantNull(closedWorld));
      } else {
        final defaultValue = graph.addConstant(value, closedWorld);
        invokeInputs.add(defaultValue);
        if (!defaultValue.isConstantNull()) {
          indexOfLastOptionalArgumentInParameters = invokeInputs.length;
        }
      }
      count++;
    });

    final targetTypeArguments = closedWorld.elementEnvironment
        .getFunctionTypeVariables(stubTarget);

    if (targetTypeArguments.isNotEmpty) {
      if (stubParameterStructure.typeParameters == 0) {
        // This stub does not include type parameters so use RTI to make the
        // appropriate defaults.
        for (final typeVariable in targetTypeArguments) {
          invokeInputs.add(
            _typeBuilder.analyzeTypeArgument(typeVariable, stubMember),
          );
        }
      } else {
        // `_functionTypeParameterLocals` might be empty if type arguments are
        // elided from the target member.
        for (final local in _functionTypeParameterLocals) {
          invokeInputs.add(localsHandler.readLocal(local));
        }
      }
    }

    // We treat the return type of all these invocations as dynamic.
    // Though we can know the return type of the target method, this doesn't
    // help us emit better code.
    final returnType = _abstractValueDomain.dynamicType;

    if (isNativeOrJsInterop) {
      // Native calls don't pass trailing null optional parameters.
      final nativeInputs = invokeInputs.sublist(
        0,
        indexOfLastOptionalArgumentInParameters,
      );
      push(
        HInvokeExternal(
          stubTarget,
          nativeInputs,
          returnType,
          closedWorld.nativeData.getNativeMethodBehavior(stubTarget),
          sourceInformation: sourceInformation,
        ),
      );
      _maybeAddInteropNullAssertionForMember(
        stubTarget,
        nativeInputs.length,
        sourceInformation: sourceInformation,
      );
    } else if (stubTarget.isInstanceMember) {
      if (stubTarget.enclosingClass!.isClosure) {
        push(
          HInvokeClosure(
            stubTarget.parameterStructure.callStructure.callSelector,
            _abstractValueDomain.dynamicType,
            invokeInputs,
            returnType,
            targetTypeArguments,
          ),
        );
      } else if (stubMember.needsSuper) {
        push(
          HInvokeSuper(
            stubTarget,
            stubMember.enclosingClass!,
            Selector.fromElement(stubTarget),
            invokeInputs,
            isIntercepted,
            returnType,
            targetTypeArguments,
            sourceInformation,
            isSetter: false,
          ),
        );
      } else {
        push(
          HInvokeDynamicMethod(
            Selector.fromElement(stubTarget),
            _abstractValueDomain.dynamicType,
            invokeInputs,
            returnType,
            targetTypeArguments,
            sourceInformation,
            isIntercepted: isIntercepted,
          )..element = stubTarget,
        );
      }
    } else {
      push(
        HInvokeStatic(
          stubTarget,
          invokeInputs,
          returnType,
          targetTypeArguments,
          isIntercepted: isIntercepted,
          targetCanThrow: !_inferredData.getCannotThrow(stubTarget),
        ),
      );
    }

    close(HReturn(pop(), sourceInformation)).addSuccessor(graph.exit);

    _closeFunction();
  }

  /// Builds generative constructor body.
  void _buildConstructorBody(ir.Constructor constructor) {
    FunctionEntity constructorBody = _elementMap.getConstructorBody(
      constructor,
    );
    _openFunction(
      constructorBody,
      functionNode: constructor.function,
      parameterStructure: constructorBody.parameterStructure,
      checks: TargetChecks.none,
    );
    if (!constructorBody.isExternal) {
      constructor.function.body!.accept(this);
    }
    _closeFunction();
  }

  void _buildRecordGetter(
    JRecordGetter getter,
    RecordGetterDefinition definition,
  ) {
    ClassEntity getterClass = getter.enclosingClass!;
    int indexInShape = definition.indexInShape;
    final representation = _recordData.representationForClass(getterClass)!;
    final path = _recordData.pathForAccess(representation.shape, indexInShape);

    // TODO(50081): Attribute all synthetic records code to the nearest class
    // declared in Dart. Worst case, it can all be attributed to the `Record`
    // interface.
    SourceInformation? sourceInformation;

    // Manually set up entry. This does not work...
    //
    //     _openFunction(getter, checks: TargetChecks.none);
    //
    // ...since we don't have a scope model for the localsHandler. What we
    // should have is a lightweight localsHandler for synthetic methods.
    //
    // TODO(51310): Split [_openFunction] into parts which can be used for
    // synthetic methods.

    _prepareEntryBlock();

    // Create a 'this' parameter.
    //
    // Intercepted getters have two parameters (this, receiver) and other
    // getters have one (this). Add them at the beginning of the entry block.

    final typeOfThis = _abstractValueDomain.createNonNullSubclass(getterClass);
    HThis thisInstruction = HThis(null, typeOfThis);
    graph.thisInstruction = thisInstruction;
    graph.entry.addAtEntry(thisInstruction);
    lastAddedParameter = thisInstruction;

    if (_interceptorData.isInterceptedMethod(getter)) {
      SyntheticLocal parameter = localsHandler.createLocal('receiver');
      HParameterValue value = HParameterValue(parameter, typeOfThis);
      graph.explicitReceiverParameter = value;
      graph.entry.addAfter(thisInstruction, value);
      lastAddedParameter = value;
    }

    HInstruction receiver = thisInstruction;

    AbstractValue resultType = _abstractValueDomain.dynamicType;

    if (path.index == null) {
      HFieldGet fieldGet = HFieldGet(
        path.field,
        receiver,
        resultType,
        sourceInformation,
        isAssignable: false,
      );
      push(fieldGet);
    } else {
      HFieldGet fieldGet = HFieldGet(
        path.field,
        receiver,
        _abstractValueDomain.constListType,
        sourceInformation,
        isAssignable: false,
      );
      push(fieldGet);
      final list = pop();
      push(
        HIndex(
          list,
          graph.addConstantInt(path.index!, closedWorld),
          resultType,
        ),
      );
    }

    HInstruction value = pop();
    _closeAndGotoExit(HReturn(value, sourceInformation));
    _closeFunction();
  }

  /// Builds an SSA graph for FunctionNodes, found in FunctionExpressions and
  /// Procedures.
  void _buildFunctionNode(
    FunctionEntity function,
    ir.FunctionNode functionNode,
  ) {
    if (functionNode.asyncMarker != ir.AsyncMarker.Sync) {
      if (functionNode.asyncMarker == ir.AsyncMarker.SyncStar) {
        _buildSyncStarGenerator(function, functionNode);
      } else {
        _buildGenerator(function, functionNode);
      }
      return;
    }

    _openFunction(
      function,
      functionNode: functionNode,
      parameterStructure: function.parameterStructure,
      checks: _checksForFunction(function),
    );

    if (options.experimentUnreachableMethodsThrow) {
      var emptyParameters = parameters.values.where(
        (parameter) =>
            _abstractValueDomain
                .isEmpty(parameter.instructionType)
                .isDefinitelyTrue,
      );
      if (emptyParameters.isNotEmpty) {
        _addComment('$emptyParameters inferred as [empty]');
        add(
          HInvokeStatic(
            _commonElements.assertUnreachableMethod,
            [],
            _abstractValueDomain.dynamicType,
            const [],
          ),
        );
        _closeFunction();
        return;
      }
    }
    functionNode.body!.accept(this);
    _closeFunction();
  }

  /// Adds a JavaScript comment to the output. The comment will be omitted in
  /// minified mode.  Each line in [text] is preceded with `//` and indented.
  /// Use sparingly. In order for the comment to be retained it is modeled as
  /// having side effects which will inhibit code motion.
  // TODO(sra): Figure out how to keep comment anchored without effects.
  void _addComment(String text) {
    add(
      HForeignCode(
        js.js.statementTemplateYielding(js.Comment(text)),
        _abstractValueDomain.dynamicType,
        [],
        isStatement: true,
      ),
    );
  }

  /// Builds an SSA graph for a sync*/async/async* generator.  We generate a
  /// entry function which tail-calls a body function. The entry contains
  /// per-invocation checks and the body, which is later transformed, contains
  /// the reentrant 'state machine' code.
  void _buildGenerator(FunctionEntity function, ir.FunctionNode functionNode) {
    _openFunction(
      function,
      functionNode: functionNode,
      parameterStructure: function.parameterStructure,
      checks: _checksForFunction(function),
    );

    // Prepare to tail-call the body.

    // Is 'buildAsyncBody' the best location for the entry?
    var sourceInformation = _sourceInformationBuilder.buildAsyncBody();

    // Forward all the parameters to the body.
    List<HInstruction> inputs = [];
    if (graph.thisInstruction != null) {
      inputs.add(graph.thisInstruction!);
    }
    if (graph.explicitReceiverParameter != null) {
      inputs.add(graph.explicitReceiverParameter!);
    }
    for (Local local in parameters.keys) {
      if (!elidedParameters.contains(local)) {
        inputs.add(localsHandler.readLocal(local));
      }
    }
    for (Local local in _functionTypeParameterLocals) {
      inputs.add(localsHandler.readLocal(local));
    }

    // Add the type parameter for the generator's element type.
    DartType elementType = _elementEnvironment.getAsyncOrSyncStarElementType(
      function,
      _returnType!,
    );

    // TODO(sra): [elementType] can contain free type variables that are erased
    // due to no rtiNeed. We will get getter code if these type variables are
    // substituted with an <any> or <erased> type.
    if (elementType.containsFreeTypeVariables) {
      // Type must be computed in the entry function, where the type variables
      // are in scope, and passed to the body function.
      inputs.add(_typeBuilder.analyzeTypeArgument(elementType, function));
    } else {
      // Types with no type variables can be emitted as part of the generator,
      // avoiding an extra argument.
      if (_generatedEntryIsEmpty()) {
        // If the entry function is empty (e.g. no argument checks) and the type
        // can be generated in body, 'inline' the body by generating it in
        // place. This works because the subsequent transformation of the code
        // is 'correct' for the empty entry function code.
        graph.needsAsyncRewrite = true;
        graph.asyncElementType = elementType;
        functionNode.body!.accept(this);
        _closeFunction();
        return;
      }
    }

    JGeneratorBody body = _elementMap.getGeneratorBody(function);
    push(
      HInvokeGeneratorBody(
        body,
        inputs,
        _abstractValueDomain.dynamicType, // TODO: better type.
        sourceInformation,
      ),
    );

    _closeAndGotoExit(HReturn(pop(), sourceInformation));

    _closeFunction();
  }

  /// Builds an SSA graph for a sync* method.  A sync* method is split into an
  /// entry function and a body function. The entry function calls the body
  /// function and wraps the result in an `_SyncStarIterable<T>`. The body
  /// function is a separate entity (GeneratorBodyEntity) that is compiled via
  /// SSA and the transformed into a reentrant state-machine.
  ///
  /// Here we generate the entry function which is approximately like this:
  ///
  ///     Iterable<T> foo(parameters) {
  ///       return _makeSyncStarIterable<T>(foo$body(parameters));
  ///     }
  void _buildSyncStarGenerator(
    FunctionEntity function,
    ir.FunctionNode functionNode,
  ) {
    _openFunction(
      function,
      functionNode: functionNode,
      parameterStructure: function.parameterStructure,
      checks: _checksForFunction(function),
    );

    // Prepare to call the body generator.

    // Is 'buildAsyncBody' the best location for the entry?
    var sourceInformation = _sourceInformationBuilder.buildAsyncBody();

    // Forward all the parameters to the body.
    List<HInstruction> inputs = [];
    if (graph.thisInstruction != null) {
      inputs.add(graph.thisInstruction!);
    }
    if (graph.explicitReceiverParameter != null) {
      inputs.add(graph.explicitReceiverParameter!);
    }
    for (Local local in parameters.keys) {
      if (!elidedParameters.contains(local)) {
        inputs.add(localsHandler.readLocal(local));
      }
    }
    for (Local local in _functionTypeParameterLocals) {
      inputs.add(localsHandler.readLocal(local));
    }

    JGeneratorBody body = _elementMap.getGeneratorBody(function);
    push(
      HInvokeGeneratorBody(
        body,
        inputs,
        _abstractValueDomain.dynamicType, // Untyped JavaScript thunk.
        sourceInformation,
      ),
    );

    // Call `_makeSyncStarIterable<T>(body)`. This usually gets inlined.

    final elementType = _elementEnvironment.getAsyncOrSyncStarElementType(
      function,
      _returnType!,
    );
    FunctionEntity method = _commonElements.syncStarIterableFactory;
    List<HInstruction> arguments = [pop()];
    List<DartType> typeArguments = const [];
    if (_rtiNeed.methodNeedsTypeArguments(method)) {
      typeArguments = [elementType];
      _addTypeArguments(arguments, typeArguments, sourceInformation);
    }
    _pushStaticInvocation(
      method,
      arguments,
      _typeInferenceMap.getReturnTypeOf(method),
      typeArguments,
      sourceInformation: sourceInformation,
    );

    _closeAndGotoExit(HReturn(pop(), sourceInformation));

    _closeFunction();
  }

  /// Builds an SSA graph for a async/async* generator body.
  void _buildGeneratorBody(
    JGeneratorBody function,
    ir.FunctionNode functionNode,
  ) {
    FunctionEntity entry = function.function;
    _openFunction(
      entry,
      functionNode: functionNode,
      parameterStructure: function.parameterStructure,
      checks: TargetChecks.none,
    );
    graph.needsAsyncRewrite = true;
    if (!function.elementType.containsFreeTypeVariables) {
      // We can generate the element type in place
      graph.asyncElementType = function.elementType;
    }
    functionNode.body!.accept(this);
    _closeFunction();
  }

  bool _generatedEntryIsEmpty() {
    HBasicBlock block = current!;
    // If `block.id` is not 1 then we generated some control flow.
    if (block.id != 1) return false;
    for (HInstruction? node = block.first; node != null; node = node.next) {
      if (node is HGoto) continue;
      if (node is HLoadType) continue; // Orphaned if check is redundant.
      return false;
    }
    return true;
  }

  void _potentiallyAddFunctionParameterTypeChecks(
    MemberEntity member,
    ir.FunctionNode function,
    TargetChecks targetChecks,
  ) {
    // Put the type checks in the first successor of the entry,
    // because that is where the type guards will also be inserted.
    // This way we ensure that a type guard will dominate the type
    // check.

    if (targetChecks.checkTypeParameters) {
      _checkTypeVariableBounds(targetElement as FunctionEntity);
    }

    MemberDefinition definition = _elementMap.getMemberDefinition(
      targetElement,
    );
    bool nodeIsConstructorBody = definition.kind == MemberKind.constructorBody;

    void handleParameter(ir.VariableDeclaration variable) {
      Local local = _localsMap.getLocalVariable(variable);
      if (nodeIsConstructorBody &&
          _closureDataLookup
              .getCapturedScope(targetElement)
              .isBoxedVariable(_localsMap, local)) {
        // If local is boxed, then `variable` will be a field inside the box
        // passed as the last parameter, so no need to update our locals
        // handler or check types at this point.
        return;
      }
      if (elidedParameters.contains(local)) {
        // Elided parameters are initialized to a default value that is
        // statically checked.
        return;
      }

      HInstruction newParameter = localsHandler.readLocal(local);
      DartType type = _getDartTypeIfValid(variable.type);

      if (targetChecks.checkAllParameters ||
          (targetChecks.checkCovariantParameters &&
              (variable.isCovariantByClass ||
                  variable.isCovariantByDeclaration))) {
        newParameter = _typeBuilder.potentiallyCheckOrTrustTypeOfParameter(
          targetElement,
          newParameter,
          type,
        );
      } else {
        newParameter = _typeBuilder.trustTypeOfParameter(
          targetElement,
          newParameter,
          type,
        );
      }
      // TODO(sra): Hoist out of loop.
      newParameter = _potentiallyAssertNotNull(
        member,
        variable,
        newParameter,
        type,
      );
      localsHandler.updateLocal(local, newParameter);
    }

    function.positionalParameters.forEach(handleParameter);
    function.namedParameters.toList().forEach(handleParameter);
  }

  void _checkTypeVariableBounds(FunctionEntity method) {
    if (_rtiNeed.methodNeedsTypeArguments(method) &&
        closedWorld.annotationsData.getParameterCheckPolicy(method).isEmitted) {
      ir.FunctionNode function = getFunctionNode(_elementMap, method)!;
      for (ir.TypeParameter typeParameter in function.typeParameters) {
        Local local = _localsMap.getLocalTypeVariableEntity(
          _elementMap
              .getTypeVariableType(
                ir.TypeParameterType(typeParameter, ir.Nullability.nonNullable),
              )
              .element,
        );
        HInstruction newParameter = localsHandler.directLocals[local]!;
        DartType bound = _getDartTypeIfValid(typeParameter.bound);
        if (!dartTypes.isTopType(bound)) {
          registry.registerTypeUse(TypeUse.typeVariableBoundCheck(bound));
          // TODO(sigmund): method name here is not minified, should it be?
          _checkTypeBound(newParameter, bound, local.name!, method.name!);
        }
      }
    }
  }

  /// In mixed mode, inserts an assertion of the form `assert(x != null)` for
  /// parameters in opt-in libraries that have a static type that cannot be
  /// nullable under a strong interpretation.
  HInstruction _potentiallyAssertNotNull(
    MemberEntity member,
    ir.TreeNode context,
    HInstruction value,
    DartType type,
  ) {
    if (!options.enableNullAssertions) return value;
    if (!dartTypes.isNonNullableIfSound(type)) return value;

    // `operator==` is usually augmented to handle a `null`-argument before this
    // test would be inserted.  There are a few exceptions (Object,
    // Interceptor), where the body of the `==` method is designed to handle a
    // `null` argument. In the usual case the null assertion is unnecessary and
    // will be optimized away. In the exception cases a null assertion would be
    // incorrect. Either way we should not do a null-assertion on the parameter
    // of any `operator==` method.
    if (member.name == '==') return value;

    if (options.enableUserAssertions) {
      pushCheckNull(value);
      push(HNot(pop(), _abstractValueDomain.boolType));
      var sourceInformation = _sourceInformationBuilder.buildAssert(context);
      _pushStaticInvocation(
        _commonElements.assertHelper,
        [pop()],
        _typeInferenceMap.getReturnTypeOf(_commonElements.assertHelper),
        const <DartType>[],
        sourceInformation: sourceInformation,
      );
      pop();
      return value;
    } else {
      HInstruction nullCheck = HNullCheck(
        value,
        _abstractValueDomain.excludeNull(value.instructionType),
      )..sourceInformation = value.sourceInformation;
      add(nullCheck);
      return nullCheck;
    }
  }

  /// Builds an SSA graph for FunctionNodes of external methods.
  void _buildExternalFunctionNode(
    FunctionEntity function,
    ir.FunctionNode functionNode,
  ) {
    assert(functionNode.body == null);

    if (closedWorld.nativeData.isNativeMember(targetElement)) {
      _buildExternalNativeFunctionNode(function, functionNode);
      return;
    }

    if (function.name == '==') {
      if (_buildSpecialRuntimeEqualsMethod(function, functionNode)) return;
    }

    // `external` functions in `dart:_foreign_helper` are queued for compilation
    // in a modular or staged compile, so just generate an empty function. The
    // actual call sites for these methods are recognized and replaced, so the
    // method generated here is never called.
    if (_commonElements.isForeignHelper(function)) {
      _openFunction(
        function,
        functionNode: functionNode,
        parameterStructure: function.parameterStructure,
        checks: _checksForFunction(function),
      );
      _closeFunction();
      return;
    }

    failedAt(currentElementSpannable, 'Unknown external method $function');
  }

  bool _buildSpecialRuntimeEqualsMethod(
    FunctionEntity function,
    ir.FunctionNode functionNode,
  ) {
    assert(function.name == '==');

    if (function.enclosingClass == _commonElements.jsNullClass) {
      _openFunction(
        function,
        functionNode: functionNode,
        parameterStructure: function.parameterStructure,
        checks: _checksForFunction(function),
      );
      HInstruction instance = graph.addConstantNull(closedWorld);
      HInstruction parameter = parameters.values.first;
      HInstruction value = HIdentity(
        instance,
        parameter,
        _abstractValueDomain.boolType,
      );
      add(value);
      _closeAndGotoExit(
        HReturn(value, _sourceInformationBuilder.buildReturn(functionNode)),
      );
      _closeFunction();
      return true;
    }

    return false;
  }

  /// Builds an SSA graph for FunctionNodes of external methods that are
  /// 'native' or 'js-interop' methods. This produces a graph for a method with
  /// Dart calling conventions that forwards to the actual JavaScript `external`
  /// method.
  void _buildExternalNativeFunctionNode(
    FunctionEntity function,
    ir.FunctionNode functionNode,
  ) {
    bool isJsInterop = closedWorld.nativeData.isJsInteropMember(function);

    _openFunction(
      function,
      functionNode: functionNode,
      parameterStructure: function.parameterStructure,
      checks: _checksForFunction(function),
    );

    List<HInstruction> inputs = [];
    if (targetElement.isInstanceMember) {
      inputs.add(
        localsHandler.readThis(
          sourceInformation: _sourceInformationBuilder.buildGet(functionNode),
        ),
      );
    }

    void handleParameter(ir.VariableDeclaration param) {
      Local local = _localsMap.getLocalVariable(param);
      // Convert Dart function to JavaScript function.
      HInstruction argument = localsHandler.readLocal(local);
      ir.DartType type = param.type;
      if (!isJsInterop && type is ir.FunctionType) {
        int arity = type.positionalParameters.length;
        _pushStaticInvocation(
          _commonElements.closureConverter,
          [argument, graph.addConstantInt(arity, closedWorld)],
          _abstractValueDomain.dynamicType,
          const <DartType>[],
          sourceInformation: null,
        );
        argument = pop();
      }
      inputs.add(argument);
    }

    for (
      int position = 0;
      position < function.parameterStructure.positionalParameters;
      position++
    ) {
      handleParameter(functionNode.positionalParameters[position]);
    }
    if (functionNode.namedParameters.isNotEmpty) {
      List<ir.VariableDeclaration> namedParameters =
          functionNode.namedParameters
              // Filter elided parameters.
              .where(
                (p) => function.parameterStructure.namedParameters.contains(
                  p.name,
                ),
              )
              .toList();
      // Sort by file offset to visit parameters in declaration order.
      namedParameters.sort(nativeOrdering);
      namedParameters.forEach(handleParameter);
    }

    NativeBehavior nativeBehavior = _nativeData.getNativeMethodBehavior(
      function,
    );
    AbstractValue returnType = _typeInferenceMap.typeFromNativeBehavior(
      nativeBehavior,
      closedWorld,
    );

    push(
      HInvokeExternal(
        targetElement as FunctionEntity,
        inputs,
        returnType,
        nativeBehavior,
        sourceInformation: null,
      ),
    );
    HInstruction value;
    final sourceInformation = _sourceInformationBuilder.buildCall(
      functionNode,
      functionNode,
    );
    if (options.nativeNullAssertions && nodeIsInWebLibrary(functionNode)) {
      value = pop();
      DartType type = _getDartTypeIfValid(functionNode.returnType);
      if (dartTypes.isNonNullableIfSound(type)) {
        push(
          HNullCheck(
            value,
            _abstractValueDomain.excludeNull(returnType),
            sticky: true,
          )..sourceInformation = sourceInformation,
        );
        value = pop();
      }
    } else if (_nativeData.isJsInteropMember(targetElement)) {
      if (targetElement.isInstanceMember) {
        _maybeAddInteropNullAssertionForMember(
          targetElement as FunctionEntity,
          inputs.length,
          sourceInformation: sourceInformation,
        );
      } else {
        _maybeAddInteropNullAssertionForStatic(
          _getDartTypeIfValid(functionNode.returnType),
          sourceInformation: sourceInformation,
        );
      }
      value = pop();
    } else {
      value = pop();
    }
    if (targetElement.isSetter) {
      _closeAndGotoExit(HGoto());
    } else {
      _emitReturn(value, _sourceInformationBuilder.buildReturn(functionNode));
    }

    _closeFunction();
  }

  void _addImplicitInstantiation(DartType? type) {
    if (type is InterfaceType) {
      _currentImplicitInstantiations.add(type);
    } else {
      assert(type == null);
    }
  }

  void _removeImplicitInstantiation(DartType? type) {
    if (type != null) {
      _currentImplicitInstantiations.removeLast();
    }
  }

  TargetChecks _checksForFunction(FunctionEntity function) {
    if (!function.isInstanceMember) {
      // Static methods with no tear-off can be generated with no checks.
      final access = closedWorld.getMemberAccess(function);
      if (access != null && access.reads.isEmpty) {
        return TargetChecks.none;
      }
    }
    // TODO(sra): Instance methods can be generated with reduced checks if
    // called only from non-dynamic call-sites.
    return TargetChecks.dynamicChecks;
  }

  void _openFunction(
    MemberEntity member, {
    ir.FunctionNode? functionNode,
    ParameterStructure? parameterStructure,
    required TargetChecks checks,
  }) {
    Map<Local, AbstractValue> parameterMap = {};
    List<ir.VariableDeclaration> elidedParameters = [];
    Set<Local> elidedParameterSet = {};
    if (functionNode != null) {
      void handleParameter(
        ir.VariableDeclaration node, {
        required bool isOptional,
        required bool isElided,
      }) {
        Local local = _localsMap.getLocalVariable(node);
        if (isElided) {
          elidedParameters.add(node);
          elidedParameterSet.add(local);
        }
        parameterMap[local] = _typeInferenceMap.getInferredTypeOfParameter(
          local,
        );
      }

      forEachOrderedParameterByFunctionNode(
        functionNode,
        parameterStructure!,
        handleParameter,
      );

      _returnType = _elementMap.getDartType(functionNode.returnType);
    }

    _prepareEntryBlock();

    localsHandler.startFunction(
      targetElement,
      parameterMap,
      elidedParameterSet,
      _sourceInformationBuilder.buildDeclaration(targetElement),
      isGenerativeConstructorBody: targetElement is ConstructorBodyEntity,
    );

    ir.Member? memberContextNode = _elementMap.getMemberContextNode(member);
    if (memberContextNode != null) {
      for (ir.VariableDeclaration node in elidedParameters) {
        Local local = _localsMap.getLocalVariable(node);
        localsHandler.updateLocal(local, _defaultValueForParameter(node));
      }
    }

    _addClassTypeVariablesIfNeeded(member);
    _addFunctionTypeVariablesIfNeeded(member);

    // If [member] is `operator==` we explicitly add a null check at the
    // beginning of the method. This is to avoid having call sites do the null
    // check. The null check is added before the argument type checks since in
    // strong mode, the parameter type might be non-nullable.
    if (member is FunctionEntity && member.name == '==') {
      if (functionNode == null) {
        throw StateError("'==' should have functionNode");
      }
      if (!_commonElements.operatorEqHandlesNullArgument(member)) {
        _handleIf(
          visitCondition: () {
            final parameter = parameters.values.first;
            push(
              HIdentity(
                parameter,
                graph.addConstantNull(closedWorld),
                _abstractValueDomain.boolType,
              ),
            );
          },
          visitThen: () {
            _closeAndGotoExit(
              HReturn(
                graph.addConstantBool(false, closedWorld),
                _sourceInformationBuilder.buildReturn(functionNode),
              ),
            );
          },
          visitElse: null,
          sourceInformation: _sourceInformationBuilder.buildIf(functionNode),
        );
      }
    }

    if (functionNode != null) {
      _potentiallyAddFunctionParameterTypeChecks(member, functionNode, checks);
    }
    _insertCoverageCall(member);
  }

  void _closeFunction() {
    if (!isAborted()) _closeAndGotoExit(HGoto());
    graph.finalize();
  }

  @override
  void defaultNode(ir.Node node) {
    throw UnsupportedError('Unhandled node $node (${node.runtimeType})');
  }

  /// Returns the current source element. This is used by the type builder.
  // TODO(efortuna): Update this when we implement inlining.
  // TODO(sra): Re-implement type builder using Kernel types and the
  // `target` for context.
  MemberEntity get sourceElement => _currentFrame!.member;

  @override
  void visitCheckLibraryIsLoaded(ir.CheckLibraryIsLoaded node) {
    ImportEntity import = _elementMap.getImport(node.import);
    String loadId = closedWorld.outputUnitData.getImportDeferName(
      _elementMap.getSpannable(targetElement, node),
      import,
    );
    HInstruction prefixConstant = graph.addConstantString(loadId, closedWorld);
    _pushStaticInvocation(
      _commonElements.checkDeferredIsLoaded,
      [prefixConstant],
      _typeInferenceMap.getReturnTypeOf(_commonElements.checkDeferredIsLoaded),
      const <DartType>[],
      sourceInformation: null,
    );
  }

  @override
  void visitLoadLibrary(ir.LoadLibrary node) {
    String loadId = closedWorld.outputUnitData.getImportDeferName(
      _elementMap.getSpannable(targetElement, node),
      _elementMap.getImport(node.import),
    );

    final priority = closedWorld.annotationsData.getLoadLibraryPriority(node);

    final sourceInformation = _sourceInformationBuilder.buildCall(node, node);

    push(
      HInvokeStatic(
        _commonElements.loadDeferredLibrary,
        [
          graph.addConstantString(loadId, closedWorld),
          graph.addConstantString(priority, closedWorld),
        ],
        _abstractValueDomain.nonNullType,
        const <DartType>[],
        targetCanThrow: false,
      )..sourceInformation = sourceInformation,
    );
  }

  @override
  void visitBlock(ir.Block node) {
    assert(!isAborted());
    // [block] can be unreachable at the beginning of a block if an
    // ir.BlockExpression that is a subexpression of an expression that contains
    // a throwing prior subexpression, e.g. `[throw e, {...[]}]`.
    if (!_isReachable) return;

    localsHandler.enterScope(
      _closureDataLookup.getCapturedBlockScope(node),
      _sourceInformationBuilder.buildBlock(node),
    );

    for (ir.Statement statement in node.statements) {
      statement.accept(this);
      if (!_isReachable) {
        // The block has been aborted by a return or a throw.
        if (stack.isNotEmpty) {
          reporter.internalError(
            noLocationSpannable,
            'Non-empty instruction stack.',
          );
        }
        return;
      }
    }
    assert(!current!.isClosed);
    if (stack.isNotEmpty) {
      reporter.internalError(
        noLocationSpannable,
        'Non-empty instruction stack',
      );
    }
  }

  @override
  void visitEmptyStatement(ir.EmptyStatement node) {
    // Empty statement adds no instructions to current block.
  }

  @override
  void visitExpressionStatement(ir.ExpressionStatement node) {
    if (!_isReachable) return;
    ir.Expression expression = node.expression;

    // Handle a `throw` expression in statement-position, with control flow to
    // the exit. (In expression position the throw does not create control-flow
    // out of CFG region for the expression).
    if (expression is ir.Throw &&
        _inliningStack.isEmpty &&
        !_inBlockExpression) {
      _visitThrowExpression(expression.expression);
      _handleInTryStatement();
      final sourceInformation = _sourceInformationBuilder.buildThrow(
        node.expression,
      );
      _closeAndGotoExit(
        HThrow(
          pop(),
          sourceInformation,
          withoutHelperFrame: closedWorld.annotationsData
              .throwWithoutHelperFrame(node),
        ),
      );
    } else {
      expression.accept(this);
      pop();
    }
  }

  @override
  void visitConstantExpression(ir.ConstantExpression node) {
    ConstantValue value = _elementMap.getConstantValue(node)!;
    final sourceInformation = _sourceInformationBuilder.buildGet(node);
    if (!closedWorld.outputUnitData.hasOnlyNonDeferredImportPathsToConstant(
      targetElement,
      value,
    )) {
      OutputUnit outputUnit = closedWorld.outputUnitData.outputUnitForConstant(
        value,
      );
      final deferredConstant = DeferredGlobalConstantValue(value, outputUnit);
      registry.registerConstantUse(ConstantUse.deferred(deferredConstant));
      stack.add(
        graph.addDeferredConstant(
          deferredConstant,
          sourceInformation,
          closedWorld,
        ),
      );
    } else {
      stack.add(
        graph.addConstant(
          value,
          closedWorld,
          sourceInformation: sourceInformation,
        ),
      );
    }
  }

  @override
  void visitReturnStatement(ir.ReturnStatement node) {
    final sourceInformation = _sourceInformationBuilder.buildReturn(node);
    HInstruction? value;
    if (node.expression != null) {
      node.expression!.accept(this);
      value = pop();
      if (_currentFrame!.asyncMarker == AsyncMarker.async) {
        // TODO(johnniwinther): Is this special-casing of async still needed
        // or should we use the general check below?
        /*if (options.enableTypeAssertions &&
            !isValidAsyncReturnType(_returnType)) {
          generateTypeError(
              "Async function returned a Future,"
              " was declared to return a ${_returnType}.",
              sourceInformation);
          pop();
          return;
        }*/
      } else {
        value = _typeBuilder.potentiallyCheckOrTrustTypeOfAssignment(
          _currentFrame!.member,
          value,
          _returnType!,
        );
      }
    }
    _handleInTryStatement();
    if (_inliningStack.isEmpty && targetElement.isSetter) {
      if (node.parent is ir.FunctionNode) {
        // An arrow function definition of a setter has a ReturnStatement as a
        // body, e.g. "set foo(x) => this._x = x;". There is no way to access
        // the returned value, so don't emit a return.
        return;
      }
    }
    // TODO(43456): Better unreachable code removal. `_isReachable` removes
    // more code, but also `return`s that pattern-match against more compact
    // arrow functions. The `return`s also help the JavaScript VM.
    // TODO(b/276976255): Using `_isReachable` causes a test failure.
    if (!isAborted()) {
      _emitReturn(value, sourceInformation);
    }
  }

  @override
  void visitForStatement(ir.ForStatement node) {
    assert(_isReachable);
    void buildInitializer() {
      for (ir.VariableDeclaration declaration in node.variables) {
        declaration.accept(this);
      }
    }

    HInstruction buildCondition() {
      if (node.condition == null) {
        return graph.addConstantBool(true, closedWorld);
      }
      node.condition!.accept(this);
      return popBoolified();
    }

    void buildUpdate() {
      for (ir.Expression expression in node.updates) {
        expression.accept(this);
        assert(!isAborted());
        // The result of the update instruction isn't used, and can just
        // be dropped.
        pop();
      }
    }

    void buildBody() {
      node.body.accept(this);
    }

    final jumpTarget = _localsMap.getJumpTargetForFor(node);
    _loopHandler.handleLoop(
      node,
      _closureDataLookup.getCapturedLoopScope(node),
      jumpTarget,
      buildInitializer,
      buildCondition,
      buildUpdate,
      buildBody,
      _sourceInformationBuilder.buildLoop(node),
    );
  }

  @override
  void visitForInStatement(ir.ForInStatement node) {
    if (node.isAsync) {
      _buildAsyncForIn(node);
    } else if (_typeInferenceMap.isJsIndexableIterator(
      node,
      _abstractValueDomain,
    )) {
      // If the expression being iterated over is a JS indexable type, we can
      // generate an optimized version of for-in that uses indexing.
      _buildForInIndexable(node);
    } else {
      _buildForInIterator(node);
    }
  }

  /// Builds the graph for a for-in node with an indexable expression.
  ///
  /// In this case we build:
  ///
  ///    int end = a.length;
  ///    for (int i = 0;
  ///         i < a.length;
  ///         checkConcurrentModificationError(a.length == end, a), ++i) {
  ///      <declaredIdentifier> = a[i];
  ///      <body>
  ///    }
  void _buildForInIndexable(ir.ForInStatement node) {
    SyntheticLocal indexVariable = localsHandler.createLocal('_i');

    // These variables are shared by initializer, condition, body and update.
    late final HInstruction array; // Set in buildInitializer.
    late final bool isFixed; // Set in buildInitializer.
    HInstruction? originalLength; // Set for growable lists.

    HInstruction buildGetLength(SourceInformation? sourceInformation) {
      HGetLength result = HGetLength(
        array,
        _abstractValueDomain.positiveIntType,
        isAssignable: !isFixed,
      )..sourceInformation = sourceInformation;
      add(result);
      return result;
    }

    void buildConcurrentModificationErrorCheck() {
      if (originalLength == null) return;
      // The static call checkConcurrentModificationError() is expanded in
      // codegen to:
      //
      //     array.length == _end || throwConcurrentModificationError(array)
      //
      final sourceInformation = _sourceInformationBuilder.buildForInMoveNext(
        node,
      );
      HInstruction length = buildGetLength(sourceInformation);
      push(
        HIdentity(length, originalLength!, _abstractValueDomain.boolType)
          ..sourceInformation = sourceInformation,
      );
      _pushStaticInvocation(
        _commonElements.checkConcurrentModificationError,
        [pop(), array],
        _typeInferenceMap.getReturnTypeOf(
          _commonElements.checkConcurrentModificationError,
        ),
        const <DartType>[],
        sourceInformation: sourceInformation,
      );
      pop();
    }

    void buildInitializer() {
      final sourceInformation = _sourceInformationBuilder.buildForInIterator(
        node,
      );

      node.iterable.accept(this);
      array = pop();
      isFixed =
          _abstractValueDomain
              .isFixedLengthJsIndexable(array.instructionType)
              .isDefinitelyTrue;
      localsHandler.updateLocal(
        indexVariable,
        graph.addConstantInt(0, closedWorld),
        sourceInformation: sourceInformation,
      );
      originalLength = buildGetLength(sourceInformation);
    }

    HInstruction buildCondition() {
      final sourceInformation = _sourceInformationBuilder.buildForInMoveNext(
        node,
      );
      HInstruction index = localsHandler.readLocal(
        indexVariable,
        sourceInformation: sourceInformation,
      );
      HInstruction length = buildGetLength(sourceInformation);
      HInstruction compare = HLess(index, length, _abstractValueDomain.boolType)
        ..sourceInformation = sourceInformation;
      add(compare);
      return compare;
    }

    void buildBody() {
      // If we had mechanically inlined ArrayIterator.moveNext(), it would have
      // inserted the ConcurrentModificationError check as part of the
      // condition.  It is not necessary on the first iteration since there is
      // no code between calls to `get iterator` and `moveNext`, so the test is
      // moved to the loop update.

      // Find a type for the element. Use the element type of the indexer of the
      // array, as this is stronger than the Iterator's `get current` type, for
      // example, `get current` includes null.
      // TODO(sra): The element type of a container type mask might be better.
      AbstractValue type = _typeInferenceMap.inferredIndexType(node);

      final sourceInformation = _sourceInformationBuilder.buildForInCurrent(
        node,
      );
      HInstruction index = localsHandler.readLocal(
        indexVariable,
        sourceInformation: sourceInformation,
      );
      // No bound check is necessary on indexer as it is immediately guarded by
      // the condition.
      HInstruction value = HIndex(array, index, type)
        ..sourceInformation = sourceInformation;
      final staticType =
          _abstractValueDomain
              .createFromStaticType(
                _getStaticForInElementType(node),
                nullable: true,
              )
              .abstractValue;
      value.instructionType = _abstractValueDomain.intersection(
        value.instructionType,
        staticType,
      );
      add(value);

      Local loopVariableLocal = _localsMap.getLocalVariable(node.variable);
      localsHandler.updateLocal(
        loopVariableLocal,
        value,
        sourceInformation: sourceInformation,
      );
      // Hint to name loop value after name of loop variable.
      if (loopVariableLocal is! SyntheticLocal) {
        value.sourceElement ??= loopVariableLocal;
      }

      node.body.accept(this);
    }

    void buildUpdate() {
      // See buildBody as to why we check here.
      buildConcurrentModificationErrorCheck();

      // TODO(sra): It would be slightly shorter to generate `a[i++]` in the
      // body (and that more closely follows what an inlined iterator would do)
      // but the code is horrible as `i+1` is carried around the loop in an
      // additional variable.
      final sourceInformation = _sourceInformationBuilder.buildForInSet(node);
      HInstruction index = localsHandler.readLocal(
        indexVariable,
        sourceInformation: sourceInformation,
      );
      HInstruction one = graph.addConstantInt(1, closedWorld);
      HInstruction addInstruction = HAdd(
        index,
        one,
        _abstractValueDomain.positiveIntType,
      )..sourceInformation = sourceInformation;
      add(addInstruction);
      localsHandler.updateLocal(
        indexVariable,
        addInstruction,
        sourceInformation: sourceInformation,
      );
    }

    _loopHandler.handleLoop(
      node,
      _closureDataLookup.getCapturedLoopScope(node),
      _localsMap.getJumpTargetForForIn(node),
      buildInitializer,
      buildCondition,
      buildUpdate,
      buildBody,
      _sourceInformationBuilder.buildLoop(node),
    );
  }

  void _buildForInIterator(ir.ForInStatement node) {
    // Generate a structure equivalent to:
    //   Iterator<E> $iter = <iterable>.iterator;
    //   while ($iter.moveNext()) {
    //     <variable> = $iter.current;
    //     <body>
    //   }

    // The iterator is shared between initializer, condition and body.
    late final HInstruction iterator;
    final iteratorType = _getStaticForInIteratorType(node);

    void buildInitializer() {
      final receiverType = _typeInferenceMap.typeOfIterator(node);
      node.iterable.accept(this);
      HInstruction receiver = pop();
      _pushDynamicInvocation(
        node,
        _getStaticType(node.iterable),
        receiverType,
        Selectors.iterator,
        [receiver],
        const <DartType>[],
        _sourceInformationBuilder.buildForInIterator(node),
      );
      iterator = pop();
    }

    HInstruction buildCondition() {
      final receiverType = _typeInferenceMap.typeOfIteratorMoveNext(node);
      _pushDynamicInvocation(
        node,
        iteratorType,
        receiverType,
        Selectors.moveNext,
        [iterator],
        const <DartType>[],
        _sourceInformationBuilder.buildForInMoveNext(node),
      );
      return popBoolified();
    }

    void buildBody() {
      final sourceInformation = _sourceInformationBuilder.buildForInCurrent(
        node,
      );
      final receiverType = _typeInferenceMap.typeOfIteratorCurrent(node);
      _pushDynamicInvocation(
        node,
        iteratorType,
        receiverType,
        Selectors.current,
        [iterator],
        const <DartType>[],
        sourceInformation,
      );

      Local loopVariableLocal = _localsMap.getLocalVariable(node.variable);
      HInstruction value = _typeBuilder.potentiallyCheckOrTrustTypeOfAssignment(
        _currentFrame!.member,
        pop(),
        _getDartTypeIfValid(node.variable.type),
      );
      localsHandler.updateLocal(
        loopVariableLocal,
        value,
        sourceInformation: sourceInformation,
      );
      // Hint to name loop value after name of loop variable.
      if (loopVariableLocal is! SyntheticLocal) {
        value.sourceElement ??= loopVariableLocal;
      }
      node.body.accept(this);
    }

    _loopHandler.handleLoop(
      node,
      _closureDataLookup.getCapturedLoopScope(node),
      _localsMap.getJumpTargetForForIn(node),
      buildInitializer,
      buildCondition,
      () {},
      buildBody,
      _sourceInformationBuilder.buildLoop(node),
    );
  }

  void _buildAsyncForIn(ir.ForInStatement node) {
    // The async-for is implemented with a StreamIterator.
    HInstruction streamIterator;

    node.iterable.accept(this);

    List<HInstruction> arguments = [pop()];
    ClassEntity cls = _commonElements.streamIterator;
    DartType typeArg = _elementMap.getDartType(node.variable.type);
    final instanceType =
        localsHandler.substInContext(dartTypes.interfaceType(cls, [typeArg]))
            as InterfaceType;
    _addImplicitInstantiation(instanceType);
    final sourceInformation = _sourceInformationBuilder.buildForInIterator(
      node,
    );
    // TODO(johnniwinther): Pass type arguments to constructors like calling
    // a generic method.
    if (_rtiNeed.classNeedsTypeArguments(cls)) {
      _addTypeArguments(arguments, [typeArg], sourceInformation);
    }
    ConstructorEntity constructor = _commonElements.streamIteratorConstructor;
    _pushStaticInvocation(
      constructor,
      arguments,
      _typeInferenceMap.getReturnTypeOf(constructor),
      const <DartType>[],
      instanceType: instanceType,
      sourceInformation: sourceInformation,
    );

    streamIterator = pop();

    void buildInitializer() {}

    HInstruction buildCondition() {
      final receiverType = _typeInferenceMap.typeOfIteratorMoveNext(node);
      _pushDynamicInvocation(
        node,
        instanceType,
        receiverType,
        Selectors.moveNext,
        [streamIterator],
        const <DartType>[],
        _sourceInformationBuilder.buildForInMoveNext(node),
      );
      HInstruction future = pop();
      push(HAwait(future, _abstractValueDomain.dynamicType));
      return popBoolified();
    }

    void buildBody() {
      final receiverType = _typeInferenceMap.typeOfIteratorCurrent(node);
      _pushDynamicInvocation(
        node,
        instanceType,
        receiverType,
        Selectors.current,
        [streamIterator],
        const <DartType>[],
        _sourceInformationBuilder.buildForInIterator(node),
      );
      localsHandler.updateLocal(
        _localsMap.getLocalVariable(node.variable),
        pop(),
      );
      node.body.accept(this);
    }

    void buildUpdate() {}

    // Creates a synthetic try/finally block in case anything async goes amiss.
    TryCatchFinallyBuilder tryBuilder = TryCatchFinallyBuilder(
      this,
      _sourceInformationBuilder.buildLoop(node),
    );
    // Build fake try body:
    _loopHandler.handleLoop(
      node,
      _closureDataLookup.getCapturedLoopScope(node),
      _localsMap.getJumpTargetForForIn(node),
      buildInitializer,
      buildCondition,
      buildUpdate,
      buildBody,
      _sourceInformationBuilder.buildLoop(node),
    );

    void finalizerFunction() {
      _pushDynamicInvocation(
        node,
        instanceType,
        null,
        Selectors.cancel,
        [streamIterator],
        const <DartType>[],
        _sourceInformationBuilder
        // ignore:deprecated_member_use_from_same_package
        .buildGeneric(node),
      );
      add(HAwait(pop(), _abstractValueDomain.dynamicType));
    }

    tryBuilder
      ..closeTryBody()
      ..buildFinallyBlock(finalizerFunction)
      ..cleanUp();
  }

  HInstruction _callSetRuntimeTypeInfo(
    HInstruction typeInfo,
    HInstruction newObject,
    SourceInformation? sourceInformation,
  ) {
    // Set the runtime type information on the object.
    FunctionEntity typeInfoSetterFn = _commonElements.setArrayType;
    // TODO(efortuna): Insert source information in this static invocation.
    _pushStaticInvocation(
      typeInfoSetterFn,
      [newObject, typeInfo],
      _abstractValueDomain.dynamicType,
      const <DartType>[],
      sourceInformation: sourceInformation,
    );

    // The new object will now be referenced through the
    // `setArrayType` call. We therefore set the type of that
    // instruction to be of the object's type.
    assert(
      stack.last is HInvokeStatic || stack.last == newObject,
      failedAt(
        currentElementSpannable,
        "Unexpected `stack.last`: Found ${stack.last}, "
        "expected $newObject or an HInvokeStatic. "
        "State: typeInfo=$typeInfo, stack=$stack.",
      ),
    );
    stack.last.instructionType = newObject.instructionType;
    return pop();
  }

  @override
  void visitWhileStatement(ir.WhileStatement node) {
    assert(_isReachable);
    HInstruction buildCondition() {
      node.condition.accept(this);
      return popBoolified();
    }

    _loopHandler.handleLoop(
      node,
      _closureDataLookup.getCapturedLoopScope(node),
      _localsMap.getJumpTargetForWhile(node),
      () {},
      buildCondition,
      () {},
      () {
        node.body.accept(this);
      },
      _sourceInformationBuilder.buildLoop(node),
    );
  }

  @override
  void visitDoStatement(ir.DoStatement node) {
    final sourceInformation = _sourceInformationBuilder.buildLoop(node);
    // TODO(efortuna): I think this can be rewritten using
    // LoopHandler.handleLoop with some tricks about when the "update" happens.
    LocalsHandler savedLocals = LocalsHandler.from(localsHandler);
    CapturedLoopScope loopClosureInfo = _closureDataLookup.getCapturedLoopScope(
      node,
    );
    localsHandler.startLoop(loopClosureInfo, sourceInformation);
    final target = _localsMap.getJumpTargetForDo(node);
    JumpHandler jumpHandler = _loopHandler.beginLoopHeader(node, target);
    final currentBlock = current!;
    final loopInfo = currentBlock.loopInformation!;
    HBasicBlock loopEntryBlock = currentBlock;
    HBasicBlock bodyEntryBlock = currentBlock;
    bool hasContinues = target != null && target.isContinueTarget;
    if (hasContinues) {
      // Add extra block to hang labels on.
      // It doesn't currently work if they are on the same block as the
      // HLoopInfo. The handling of HLabeledBlockInformation will visit a
      // SubGraph that starts at the same block again, so the HLoopInfo is
      // either handled twice, or it's handled after the labeled block info,
      // both of which generate the wrong code.
      // Using a separate block is just a simple workaround.
      bodyEntryBlock = openNewBlock();
    }
    localsHandler.enterLoopBody(loopClosureInfo, sourceInformation);
    node.body.accept(this);

    // If there are no continues we could avoid the creation of the condition
    // block. This could also lead to a block having multiple entries and exits.
    HBasicBlock bodyExitBlock;
    bool isAbortingBody = false;
    if (current != null) {
      bodyExitBlock = close(HGoto());
    } else {
      isAbortingBody = true;
      bodyExitBlock = lastOpenedBlock;
    }

    SubExpression conditionExpression;
    bool loopIsDegenerate = isAbortingBody && !hasContinues;
    if (!loopIsDegenerate) {
      HBasicBlock conditionBlock = addNewBlock();

      List<LocalsHandler> continueHandlers = <LocalsHandler>[];
      jumpHandler.forEachContinue((
        HContinue instruction,
        LocalsHandler locals,
      ) {
        instruction.block!.addSuccessor(conditionBlock);
        continueHandlers.add(locals);
      });

      if (!isAbortingBody) {
        bodyExitBlock.addSuccessor(conditionBlock);
      }

      if (continueHandlers.isNotEmpty) {
        if (!isAbortingBody) continueHandlers.add(localsHandler);
        localsHandler = savedLocals.mergeMultiple(
          continueHandlers,
          conditionBlock,
        );
        SubGraph bodyGraph = SubGraph(bodyEntryBlock, bodyExitBlock);
        List<LabelDefinition> labels = jumpHandler.labels;
        HSubGraphBlockInformation bodyInfo = HSubGraphBlockInformation(
          bodyGraph,
        );
        HLabeledBlockInformation info;
        if (labels.isNotEmpty) {
          info = HLabeledBlockInformation(bodyInfo, labels, isContinue: true);
        } else {
          info = HLabeledBlockInformation.implicit(
            bodyInfo,
            target,
            isContinue: true,
          );
        }
        bodyEntryBlock.setBlockFlow(info, conditionBlock);
      }
      open(conditionBlock);

      node.condition.accept(this);
      assert(!isAborted());
      HInstruction conditionInstruction = popBoolified();
      HBasicBlock conditionEndBlock = close(HLoopBranch(conditionInstruction));

      HBasicBlock avoidCriticalEdge = addNewBlock();
      conditionEndBlock.addSuccessor(avoidCriticalEdge);
      open(avoidCriticalEdge);
      close(HGoto());
      avoidCriticalEdge.addSuccessor(loopEntryBlock); // The back-edge.

      conditionExpression = SubExpression(conditionBlock, conditionEndBlock);

      // Avoid a critical edge from the condition to the loop-exit body.
      HBasicBlock conditionExitBlock = addNewBlock();
      open(conditionExitBlock);
      close(HGoto());
      conditionEndBlock.addSuccessor(conditionExitBlock);

      _loopHandler.endLoop(
        loopEntryBlock,
        conditionExitBlock,
        jumpHandler,
        localsHandler,
      );

      loopEntryBlock.postProcessLoopHeader();
      SubGraph bodyGraph = SubGraph(loopEntryBlock, bodyExitBlock);
      final newLoopInfo = loopEntryBlock.loopInformation!;
      HLoopBlockInformation loopBlockInfo = HLoopBlockInformation(
        LoopBlockInformationKind.doWhileLoop,
        null,
        wrapExpressionGraph(conditionExpression),
        wrapStatementGraph(bodyGraph),
        null,
        newLoopInfo.target,
        newLoopInfo.labels,
        sourceInformation,
      );
      loopEntryBlock.setBlockFlow(loopBlockInfo, current);
      loopInfo.loopBlockInformation = loopBlockInfo;
    } else {
      // Since the loop has no back edge, we remove the loop information on the
      // header.
      loopEntryBlock.loopInformation = null;

      if (jumpHandler.hasAnyBreak()) {
        // Null branchBlock because the body of the do-while loop always aborts,
        // so we never get to the condition.
        _loopHandler.endLoop(loopEntryBlock, null, jumpHandler, localsHandler);

        // Since the body of the loop has a break, we attach a synthesized label
        // to the body.
        SubGraph bodyGraph = SubGraph(bodyEntryBlock, bodyExitBlock);
        JumpTarget target = _localsMap.getJumpTargetForDo(node)!;
        final label = target.addLabel('loop', isBreakTarget: true);
        HLabeledBlockInformation info = HLabeledBlockInformation(
          HSubGraphBlockInformation(bodyGraph),
          <LabelDefinition>[label],
        );
        loopEntryBlock.setBlockFlow(info, current);
        jumpHandler.forEachBreak((HBreak breakInstruction, _) {
          HBasicBlock block = breakInstruction.block!;
          block.addAtExit(HBreak.toLabel(label, sourceInformation));
          block.remove(breakInstruction);
        });
      }
    }
    jumpHandler.close();
  }

  @override
  void visitIfStatement(ir.IfStatement node) {
    _handleIf(
      visitCondition: () => node.condition.accept(this),
      visitThen: () => node.then.accept(this),
      visitElse: () => node.otherwise?.accept(this),
      sourceInformation: _sourceInformationBuilder.buildIf(node),
    );
  }

  void _handleIf({
    ir.Node? node,
    required void Function() visitCondition,
    required void Function() visitThen,
    void Function()? visitElse,
    SourceInformation? sourceInformation,
  }) {
    SsaBranchBuilder branchBuilder = SsaBranchBuilder(
      this,
      node == null ? null : _elementMap.getSpannable(targetElement, node),
    );
    branchBuilder.handleIf(
      visitCondition,
      visitThen,
      visitElse,
      sourceInformation: sourceInformation,
    );
  }

  @override
  void visitAsExpression(ir.AsExpression node) {
    // Recognize these special cases, where expression e has static type `T?`:
    //
    //     e as T
    //     (e as dynamic) as T
    //
    // These patterns can only fail if `e` results in a `null` value.  The
    // second pattern occurs when `e as dynamic` is used get an implicit
    // downcast in order to make use of the different policies for explicit and
    // implicit downcasts.
    //
    // The pattern match is syntactic which ensures the type bindings are
    // consistent, i.e. from the same instance of a type variable scope.
    ir.Expression operand = _skipCastsToDynamic(node.operand);
    operand.accept(this);

    bool isNullRemovalPattern = false;

    final operandType = _getStaticType(operand);
    DartType type = _elementMap.getDartType(node.type);
    if (!options.experimentNullSafetyChecks && !node.isCovarianceCheck) {
      if (_elementMap.types.isSubtype(operandType, type)) {
        // Skip unneeded casts.
        return;
      }
      if (_elementMap.types.isSubtype(
        operandType,
        _elementMap.types.nullableType(type),
      )) {
        isNullRemovalPattern = true;
      }
    }

    final sourceInformation = _sourceInformationBuilder.buildAs(node);
    HInstruction expressionInstruction = pop();

    if (node.type is ir.InvalidType) {
      _generateTypeError('invalid type', sourceInformation);
      return;
    }

    CheckPolicy policy;
    final currentFrame = _currentFrame!;
    if (node.isTypeError) {
      policy = closedWorld.annotationsData.getImplicitDowncastCheckPolicy(
        currentFrame.member,
      );
    } else {
      policy = closedWorld.annotationsData.getExplicitCastCheckPolicy(
        currentFrame.member,
      );
    }

    if (!policy.isEmitted) {
      stack.add(expressionInstruction);
      return;
    }

    void generateCheck() {
      HInstruction converted = _typeBuilder.buildAsCheck(
        expressionInstruction,
        localsHandler.substInContext(type),
        isTypeError: node.isTypeError,
        sourceInformation: sourceInformation,
      );
      if (converted != expressionInstruction) {
        add(converted);
      }
      stack.add(converted);
    }

    if (isNullRemovalPattern) {
      // Generate a conditional to test only `null` values:
      //
      //     temp = e;
      //     temp == null ? temp as T : temp
      SsaBranchBuilder(this).handleConditional(
        () {
          push(
            HIdentity(
              expressionInstruction,
              graph.addConstantNull(closedWorld),
              _abstractValueDomain.boolType,
            ),
          );
        },
        generateCheck,
        () {
          stack.add(expressionInstruction);
        },
      );
    } else {
      generateCheck();
    }
  }

  static ir.Expression _skipCastsToDynamic(ir.Expression node) {
    if (node is ir.AsExpression && node.type is ir.DynamicType) {
      return _skipCastsToDynamic(node.operand);
    }
    return node;
  }

  @override
  void visitNullCheck(ir.NullCheck node) {
    node.operand.accept(this);
    HInstruction expression = pop();
    final sourceInformation = _sourceInformationBuilder.buildUnary(node);
    push(
      HNullCheck(
        expression,
        _abstractValueDomain.excludeNull(expression.instructionType),
      )..sourceInformation = sourceInformation,
    );
  }

  void _generateError(
    FunctionEntity function,
    String message,
    AbstractValue typeMask,
    SourceInformation? sourceInformation,
  ) {
    HInstruction errorMessage = graph.addConstantString(message, closedWorld);
    _pushStaticInvocation(
      function,
      [errorMessage],
      typeMask,
      const <DartType>[],
      sourceInformation: sourceInformation,
    );
  }

  void _generateTypeError(
    String message,
    SourceInformation? sourceInformation,
  ) {
    _generateError(
      _commonElements.throwTypeError,
      message,
      _typeInferenceMap.getReturnTypeOf(_commonElements.throwTypeError),
      sourceInformation,
    );
  }

  void _generateUnsupportedError(
    String message,
    SourceInformation? sourceInformation,
  ) {
    _generateError(
      _commonElements.throwUnsupportedError,
      message,
      _typeInferenceMap.getReturnTypeOf(_commonElements.throwUnsupportedError),
      sourceInformation,
    );
  }

  @override
  void visitAssertStatement(ir.AssertStatement node) {
    if (!options.enableUserAssertions) return;
    var sourceInformation = _sourceInformationBuilder.buildAssert(node);
    if (node.message == null) {
      node.condition.accept(this);
      _pushStaticInvocation(
        _commonElements.assertHelper,
        [pop()],
        _typeInferenceMap.getReturnTypeOf(_commonElements.assertHelper),
        const <DartType>[],
        sourceInformation: sourceInformation,
      );
      pop();
      return;
    }

    // if (assertTest(condition)) assertThrow(message);
    void buildCondition() {
      node.condition.accept(this);
      _pushStaticInvocation(
        _commonElements.assertTest,
        [pop()],
        _typeInferenceMap.getReturnTypeOf(_commonElements.assertTest),
        const <DartType>[],
        sourceInformation: sourceInformation,
      );
    }

    void fail() {
      node.message!.accept(this);
      _pushStaticInvocation(
        _commonElements.assertThrow,
        [pop()],
        _typeInferenceMap.getReturnTypeOf(_commonElements.assertThrow),
        const <DartType>[],
        sourceInformation: sourceInformation,
      );
      pop();
    }

    _handleIf(visitCondition: buildCondition, visitThen: fail);
  }

  /// Creates a [JumpHandler] for a statement. The node must be a jump
  /// target. If there are no breaks or continues targeting the statement,
  /// a special "null handler" is returned.
  ///
  /// [isLoopJump] is true when the jump handler is for a loop. This is used
  /// to distinguish the synthesized loop created for a switch statement with
  /// continue statements from simple switch statements.
  JumpHandler createJumpHandler(
    ir.TreeNode node,
    JumpTarget? target, {
    bool isLoopJump = false,
  }) {
    if (target == null) {
      // No breaks or continues to this node.
      return NullJumpHandler(reporter);
    }
    if (isLoopJump && node is ir.SwitchStatement) {
      return KernelSwitchCaseJumpHandler(this, target, node, _localsMap);
    }

    return JumpHandler(this, target);
  }

  @override
  void visitBreakStatement(ir.BreakStatement node) {
    assert(!isAborted());
    _handleInTryStatement();
    JumpTarget target = _localsMap.getJumpTargetForBreak(node);
    JumpHandler handler = jumpTargets[target]!;
    final sourceInformation = _sourceInformationBuilder.buildGoto(node);
    if (_localsMap.generateContinueForBreak(node)) {
      if (handler.labels.isNotEmpty) {
        handler.generateContinue(sourceInformation, handler.labels.first);
      } else {
        handler.generateContinue(sourceInformation);
      }
    } else {
      if (handler.labels.isNotEmpty) {
        handler.generateBreak(sourceInformation, handler.labels.first);
      } else {
        handler.generateBreak(sourceInformation);
      }
    }
  }

  @override
  void visitLabeledStatement(ir.LabeledStatement node) {
    ir.Statement body = node.body;
    if (JumpVisitor.canBeBreakTarget(body)) {
      // loops and switches handle breaks on their own
      body.accept(this);
      return;
    }
    final jumpTarget = _localsMap.getJumpTargetForLabel(node);
    if (jumpTarget == null) {
      // The label is not needed.
      body.accept(this);
      return;
    }

    JumpHandler handler = createJumpHandler(node, jumpTarget);

    LocalsHandler beforeLocals = LocalsHandler.from(localsHandler);

    HBasicBlock newBlock = openNewBlock();
    body.accept(this);
    SubGraph bodyGraph = SubGraph(newBlock, lastOpenedBlock);

    // Create join block only if reached, otherwise it won't have a dominator.
    late final HBasicBlock joinBlock = graph.addNewBlock();
    List<LocalsHandler> breakHandlers = [];
    handler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) {
      breakInstruction.block!.addSuccessor(joinBlock);
      breakHandlers.add(locals);
    });

    if (!isAborted()) {
      goto(current!, joinBlock);
      breakHandlers.add(localsHandler);
    }

    if (breakHandlers.isNotEmpty) {
      open(joinBlock);
      localsHandler = beforeLocals.mergeMultiple(breakHandlers, joinBlock);

      // There was at least one reachable break, so the label is needed.
      newBlock.setBlockFlow(
        HLabeledBlockInformation(
          HSubGraphBlockInformation(bodyGraph),
          handler.labels,
        ),
        joinBlock,
      );
    }
    handler.close();
  }

  /// Loop through the cases in a switch and create a mapping of case
  /// expressions to constants.
  Map<ir.Expression, ConstantValue> _buildSwitchCaseConstants(
    ir.SwitchStatement switchStatement,
  ) {
    Map<ir.Expression, ConstantValue> constants = {};
    for (ir.SwitchCase switchCase in switchStatement.cases) {
      for (ir.Expression caseExpression in switchCase.expressions) {
        final constant = _elementMap.getConstantValue(caseExpression)!;
        constants[caseExpression] = constant;
      }
    }
    return constants;
  }

  @override
  void visitContinueSwitchStatement(ir.ContinueSwitchStatement node) {
    _handleInTryStatement();
    JumpTarget target = _localsMap.getJumpTargetForContinueSwitch(node);
    final handler = jumpTargets[target]!;
    assert(target.labels.isNotEmpty);
    handler.generateContinue(
      _sourceInformationBuilder.buildGoto(node),
      target.labels.first,
    );
  }

  @override
  void visitSwitchStatement(ir.SwitchStatement node) {
    final sourceInformation = _sourceInformationBuilder.buildSwitch(node);
    // The switch case indices must match those computed in
    // [KernelSwitchCaseJumpHandler].
    bool hasContinue = false;
    Map<ir.SwitchCase, int> caseIndex = {};
    int switchIndex = 1;
    bool hasDefault = false;
    for (ir.SwitchCase switchCase in node.cases) {
      if (_isDefaultCase(switchCase)) {
        hasDefault = true;
      }
      if (SwitchContinueAnalysis.containsContinue(switchCase.body)) {
        hasContinue = true;
      }
      caseIndex[switchCase] = switchIndex;
      switchIndex++;
    }

    JumpHandler jumpHandler = createJumpHandler(
      node,
      _localsMap.getJumpTargetForSwitch(node),
    );
    if (!hasContinue) {
      // If the switch statement has no switch cases targeted by continue
      // statements we encode the switch statement directly.
      _buildSimpleSwitchStatement(node, jumpHandler, sourceInformation);
    } else {
      _buildComplexSwitchStatement(
        node,
        jumpHandler,
        caseIndex,
        hasDefault,
        sourceInformation,
      );
    }
  }

  /// Helper for building switch statements.
  static bool _isDefaultCase(ir.SwitchCase? switchCase) =>
      switchCase == null || switchCase.isDefault;

  /// Helper for building switch statements.
  HInstruction _buildExpression(ir.SwitchStatement switchStatement) {
    switchStatement.expression.accept(this);
    return pop();
  }

  /// Helper method for creating the list of constants that make up the
  /// switch case branches.
  List<ConstantValue> _getSwitchConstants(
    ir.SwitchStatement parentSwitch,
    ir.SwitchCase? switchCase,
  ) {
    Map<ir.Expression, ConstantValue> constantsLookup =
        _buildSwitchCaseConstants(parentSwitch);
    List<ConstantValue> constantList = [];
    if (switchCase != null) {
      for (var expression in switchCase.expressions) {
        constantList.add(constantsLookup[expression]!);
      }
    }
    return constantList;
  }

  /// Builds a simple switch statement which does not handle uses of continue
  /// statements to labeled switch cases.
  void _buildSimpleSwitchStatement(
    ir.SwitchStatement switchStatement,
    JumpHandler jumpHandler,
    SourceInformation? sourceInformation,
  ) {
    void buildSwitchCase(ir.SwitchCase? switchCase) {
      switchCase!.body.accept(this);
    }

    _handleSwitch(
      switchStatement,
      jumpHandler,
      _buildExpression,
      switchStatement.cases,
      _getSwitchConstants,
      _isDefaultCase,
      buildSwitchCase,
      sourceInformation,
    );
    jumpHandler.close();
  }

  /// Builds a switch statement that can handle arbitrary uses of continue
  /// statements to labeled switch cases.
  void _buildComplexSwitchStatement(
    ir.SwitchStatement switchStatement,
    JumpHandler jumpHandler,
    Map<ir.SwitchCase, int> caseIndex,
    bool hasDefault,
    SourceInformation? sourceInformation,
  ) {
    // If the switch statement has switch cases targeted by continue
    // statements we create the following encoding:
    //
    //   switch (e) {
    //     l_1: case e0: s_1; break;
    //     l_2: case e1: s_2; continue l_i;
    //     ...
    //     l_n: default: s_n; continue l_j;
    //   }
    //
    // is encoded as
    //
    //   var target;
    //   switch (e) {
    //     case e1: target = 1; break;
    //     case e2: target = 2; break;
    //     ...
    //     default: target = n; break;
    //   }
    //   l: while (true) {
    //    switch (target) {
    //       case 1: s_1; break l;
    //       case 2: s_2; target = i; continue l;
    //       ...
    //       case n: s_n; target = j; continue l;
    //     }
    //   }
    //
    // This is because JS does not have this same "continue label" semantics so
    // we encode it in the form of a state machine.

    // TODO(https://dartbug.com/51777): Consider alternative with single switch
    // statement.

    JumpTarget switchTarget =
        _localsMap.getJumpTargetForSwitch(switchStatement)!;
    localsHandler.updateLocal(switchTarget, graph.addConstantNull(closedWorld));

    var switchCases = List<ir.SwitchCase?>.from(switchStatement.cases);
    if (!hasDefault) {
      // Use null as the marker for a synthetic default clause.
      // The synthetic default is added because otherwise there would be no
      // good place to give a default value to the local.
      switchCases = List<ir.SwitchCase?>.from(switchCases);
      switchCases.add(null);
    }

    void buildSwitchCase(ir.SwitchCase? switchCase) {
      SourceInformation? caseSourceInformation = sourceInformation;
      if (switchCase != null) {
        caseSourceInformation = _sourceInformationBuilder.buildGoto(switchCase);
        // Generate 'target = i; break;' for switch case i.
        int index = caseIndex[switchCase]!;
        HInstruction value = graph.addConstantInt(index, closedWorld);
        localsHandler.updateLocal(
          switchTarget,
          value,
          sourceInformation: caseSourceInformation,
        );
      } else {
        // Generate synthetic default case 'target = null; break;'.
        HInstruction nullValue = graph.addConstantNull(closedWorld);
        localsHandler.updateLocal(
          switchTarget,
          nullValue,
          sourceInformation: caseSourceInformation,
        );
      }
      jumpTargets[switchTarget]!.generateBreak(caseSourceInformation);
    }

    _handleSwitch(
      switchStatement,
      jumpHandler,
      _buildExpression,
      switchCases,
      _getSwitchConstants,
      _isDefaultCase,
      buildSwitchCase,
      sourceInformation,
    );
    jumpHandler.close();

    HInstruction buildCondition() => graph.addConstantBool(true, closedWorld);

    void buildSwitch() {
      HInstruction buildExpression(ir.SwitchStatement notUsed) {
        return localsHandler.readLocal(switchTarget);
      }

      List<ConstantValue> getConstants(
        ir.SwitchStatement parentSwitch,
        ir.SwitchCase? switchCase,
      ) {
        return [constant_system.createIntFromInt(caseIndex[switchCase]!)];
      }

      void buildSwitchCase(ir.SwitchCase? switchCase) {
        switchCase!.body.accept(this);
        if (!isAborted()) {
          // Ensure that we break the loop if the case falls through. (This
          // is only possible for the last case.)
          jumpTargets[switchTarget]!.generateBreak(sourceInformation);
        }
      }

      // Pass a [NullJumpHandler] because the target for the contained break
      // is not the generated switch statement but instead the loop generated
      // in the call to [handleLoop] below.
      _handleSwitch(
        switchStatement, // nor is buildExpression.
        NullJumpHandler(reporter),
        buildExpression,
        switchStatement.cases,
        getConstants,
        (_) => false, // No case is default.
        buildSwitchCase,
        sourceInformation,
      );
    }

    void buildLoop() {
      _loopHandler.handleLoop(
        switchStatement,
        _closureDataLookup.getCapturedLoopScope(switchStatement),
        switchTarget,
        () {},
        buildCondition,
        () {},
        buildSwitch,
        _sourceInformationBuilder.buildLoop(switchStatement),
      );
    }

    if (hasDefault) {
      buildLoop();
    } else {
      // If the switch statement has no default case, surround the loop with
      // a test of the target. So:
      // `if (target) while (true) ...` If there's no default case, target is
      // null, so we don't drop into the while loop.
      void buildCondition() {
        js.Template code = js.js.parseForeignJS('#');
        push(
          HForeignCode(code, _abstractValueDomain.boolType, [
            localsHandler.readLocal(switchTarget),
          ], nativeBehavior: NativeBehavior.pure),
        );
      }

      _handleIf(
        node: switchStatement,
        visitCondition: buildCondition,
        visitThen: buildLoop,
        visitElse: () => {},
        sourceInformation: sourceInformation,
      );
    }
  }

  /// Creates a switch statement.
  ///
  /// [jumpHandler] is the [JumpHandler] for the created switch statement.
  /// [buildSwitchCase] creates the statements for the switch case.
  void _handleSwitch(
    ir.SwitchStatement switchStatement,
    JumpHandler jumpHandler,
    HInstruction Function(ir.SwitchStatement statement) buildExpression,
    List<ir.SwitchCase?> switchCases,
    List<ConstantValue> Function(
      ir.SwitchStatement parentSwitch,
      ir.SwitchCase? switchCase,
    )
    getConstants,
    bool Function(ir.SwitchCase? switchCase) isDefaultCase,
    void Function(ir.SwitchCase? switchCase) buildSwitchCase,
    SourceInformation? sourceInformation,
  ) {
    HBasicBlock expressionStart = openNewBlock();
    HInstruction expression = buildExpression(switchStatement);

    if (switchCases.isEmpty) {
      return;
    }

    HSwitch switchInstruction = HSwitch(expression);
    HBasicBlock expressionEnd = close(switchInstruction);
    LocalsHandler savedLocals = localsHandler;

    List<HStatementInformation> statements = [];
    bool hasDefault = false;
    for (ir.SwitchCase? switchCase in switchCases) {
      HBasicBlock block = graph.addNewBlock();
      for (ConstantValue constant in getConstants(
        switchStatement,
        switchCase,
      )) {
        HConstant hConstant = graph.addConstant(constant, closedWorld);
        switchInstruction.inputs.add(hConstant);
        hConstant.usedBy.add(switchInstruction);
        expressionEnd.addSuccessor(block);
      }

      if (isDefaultCase(switchCase)) {
        // An HSwitch has n inputs and n+1 successors, the last being the
        // default case.
        expressionEnd.addSuccessor(block);
        hasDefault = true;
      }
      open(block);
      localsHandler = LocalsHandler.from(savedLocals);
      buildSwitchCase(switchCase);
      if (!isAborted() &&
          // TODO(johnniwinther): Reinsert this if `isReachable` is no longer
          // set to `false` when `_tryInlineMethod` sees an always throwing
          // method.
          //switchCase == switchCases.last &&
          !isDefaultCase(switchCase)) {
        // If there is no default, we will add one later to avoid
        // the critical edge. So we generate a break statement to make
        // sure the last case does not fall through to the default case.
        jumpHandler.generateBreak(sourceInformation);
      }
      statements.add(
        HSubGraphBlockInformation(SubGraph(block, lastOpenedBlock)),
      );
    }

    // Add a join-block if necessary.
    // We create [joinBlock] early, and then go through the cases that might
    // want to jump to it. In each case, if we add [joinBlock] as a successor
    // of another block, we also add an element to [caseHandlers] that is used
    // to create the phis in [joinBlock].
    // If we never jump to the join block, [caseHandlers] will stay empty, and
    // the join block is never added to the graph.
    HBasicBlock? joinBlock = HBasicBlock();
    List<LocalsHandler> caseHandlers = [];
    jumpHandler.forEachBreak((HBreak instruction, LocalsHandler locals) {
      instruction.block!.addSuccessor(joinBlock!);
      caseHandlers.add(locals);
    });
    jumpHandler.forEachContinue((HContinue instruction, LocalsHandler locals) {
      assert(
        false,
        failedAt(
          _elementMap.getSpannable(targetElement, switchStatement),
          'Continue cannot target a switch.',
        ),
      );
    });
    if (!isAborted()) {
      current!.close(HGoto());
      lastOpenedBlock.addSuccessor(joinBlock);
      caseHandlers.add(localsHandler);
    }
    if (!hasDefault) {
      // Always create a default case, to avoid a critical edge in the
      // graph.
      HBasicBlock defaultCase = addNewBlock();
      expressionEnd.addSuccessor(defaultCase);
      open(defaultCase);
      close(HGoto());
      defaultCase.addSuccessor(joinBlock);
      caseHandlers.add(savedLocals);
      statements.add(
        HSubGraphBlockInformation(SubGraph(defaultCase, defaultCase)),
      );
    }
    assert(caseHandlers.length == joinBlock.predecessors.length);
    if (caseHandlers.isNotEmpty) {
      graph.addBlock(joinBlock);
      open(joinBlock);
      if (caseHandlers.length == 1) {
        localsHandler = caseHandlers[0];
      } else {
        localsHandler = savedLocals.mergeMultiple(caseHandlers, joinBlock);
      }
    } else {
      // The joinBlock is not used.
      joinBlock = null;
    }

    HSubExpressionBlockInformation expressionInfo =
        HSubExpressionBlockInformation(
          SubExpression(expressionStart, expressionEnd),
        );
    expressionStart.setBlockFlow(
      HSwitchBlockInformation(
        expressionInfo,
        statements,
        jumpHandler.target,
        jumpHandler.labels,
        sourceInformation,
      ),
      joinBlock,
    );

    jumpHandler.close();
  }

  @override
  void visitConditionalExpression(ir.ConditionalExpression node) {
    SsaBranchBuilder brancher = SsaBranchBuilder(this);
    brancher.handleConditional(
      () => node.condition.accept(this),
      () => node.then.accept(this),
      () => node.otherwise.accept(this),
    );
  }

  @override
  void visitLogicalExpression(ir.LogicalExpression node) {
    SsaBranchBuilder brancher = SsaBranchBuilder(this);
    _handleLogicalExpression(
      node.left,
      () => node.right.accept(this),
      brancher,
      node.operatorEnum,
      _sourceInformationBuilder.buildBinary(node),
    );
  }

  /// Optimizes logical binary expression where the left has the same logical
  /// binary operator.
  ///
  /// This method transforms the operator by optimizing the case where [left] is
  /// a logical "and" or logical "or". Then it uses [branchBuilder] to build the
  /// graph for the optimized expression.
  ///
  /// For example, `(x && y) && z` is transformed into `x && (y && z)`:
  ///
  void _handleLogicalExpression(
    ir.Expression left,
    void Function() visitRight,
    SsaBranchBuilder brancher,
    ir.LogicalExpressionOperator operatorEnum,
    SourceInformation? sourceInformation,
  ) {
    if (left is ir.LogicalExpression && left.operatorEnum == operatorEnum) {
      ir.Expression innerLeft = left.left;
      ir.Expression middle = left.right;
      _handleLogicalExpression(
        innerLeft,
        () => _handleLogicalExpression(
          middle,
          visitRight,
          brancher,
          operatorEnum,
          _sourceInformationBuilder.buildBinary(middle),
        ),
        brancher,
        operatorEnum,
        sourceInformation,
      );
    } else {
      brancher.handleLogicalBinary(
        () => left.accept(this),
        visitRight,
        sourceInformation,
        isAnd: operatorEnum == ir.LogicalExpressionOperator.AND,
      );
    }
  }

  @override
  void visitIntLiteral(ir.IntLiteral node) {
    stack.add(graph.addConstantIntAsUnsigned(node.value, closedWorld));
  }

  @override
  void visitDoubleLiteral(ir.DoubleLiteral node) {
    stack.add(graph.addConstantDouble(node.value, closedWorld));
  }

  @override
  void visitBoolLiteral(ir.BoolLiteral node) {
    stack.add(graph.addConstantBool(node.value, closedWorld));
  }

  @override
  void visitStringLiteral(ir.StringLiteral node) {
    stack.add(graph.addConstantString(node.value, closedWorld));
  }

  @override
  void visitSymbolLiteral(ir.SymbolLiteral node) {
    stack.add(
      graph.addConstant(_elementMap.getConstantValue(node)!, closedWorld),
    );
    registry.registerConstSymbol(node.value);
  }

  @override
  void visitNullLiteral(ir.NullLiteral node) {
    stack.add(graph.addConstantNull(closedWorld));
  }

  /// Set the runtime type information if necessary.
  HInstruction _setListRuntimeTypeInfoIfNeeded(
    HInstruction object,
    InterfaceType type,
    SourceInformation? sourceInformation,
  ) {
    // [type] could be `List<T>`, so ensure it is `JSArray<T>`.
    InterfaceType arrayType = dartTypes.interfaceType(
      _commonElements.jsArrayClass,
      type.typeArguments,
    );
    if (!_rtiNeed.classNeedsTypeArguments(type.element) ||
        _equivalentToMissingRti(arrayType)) {
      return object;
    }
    HInstruction rti = _typeBuilder.analyzeTypeArgument(
      arrayType,
      sourceElement,
    );

    // TODO(15489): Register at codegen.
    registry.registerInstantiation(type);
    return _callSetRuntimeTypeInfo(rti, object, sourceInformation);
  }

  @override
  void visitListLiteral(ir.ListLiteral node) {
    HInstruction listInstruction;
    if (node.isConst) {
      listInstruction = graph.addConstant(
        _elementMap.getConstantValue(node)!,
        closedWorld,
      );
    } else {
      List<HInstruction> elements = [];
      for (ir.Expression element in node.expressions) {
        element.accept(this);
        elements.add(pop());
      }
      listInstruction = _buildLiteralList(elements);
      add(listInstruction);
      final sourceInformation = _sourceInformationBuilder.buildListLiteral(
        node,
      );
      final type =
          localsHandler.substInContext(
                _commonElements.listType(
                  _elementMap.getDartType(node.typeArgument),
                ),
              )
              as InterfaceType;
      listInstruction = _setListRuntimeTypeInfoIfNeeded(
        listInstruction,
        type,
        sourceInformation,
      );
    }

    AbstractValue type = _typeInferenceMap.typeOfListLiteral(
      node,
      _abstractValueDomain,
    );
    if (_abstractValueDomain.containsAll(type).isDefinitelyFalse) {
      listInstruction.instructionType = type;
    }
    stack.add(listInstruction);
  }

  @override
  void visitSetLiteral(ir.SetLiteral node) {
    if (node.isConst) {
      stack.add(
        graph.addConstant(_elementMap.getConstantValue(node)!, closedWorld),
      );
      return;
    }

    // The set literal constructors take the elements as a List.
    List<HInstruction> elements = [];
    for (ir.Expression element in node.expressions) {
      element.accept(this);
      elements.add(pop());
    }

    // The constructor is a procedure because it's a factory.
    FunctionEntity constructor;
    List<HInstruction> inputs = [];
    if (elements.isEmpty) {
      constructor = _commonElements.setLiteralConstructorEmpty;
    } else {
      constructor = _commonElements.setLiteralConstructor;
      HLiteralList argList = _buildLiteralList(elements);
      add(argList);
      inputs.add(argList);
    }

    assert(
      constructor is ConstructorEntity && constructor.isFactoryConstructor,
    );

    final type =
        localsHandler.substInContext(
              _commonElements.setType(
                _elementMap.getDartType(node.typeArgument),
              ),
            )
            as InterfaceType;
    final cls = constructor.enclosingClass!;

    if (_rtiNeed.classNeedsTypeArguments(cls)) {
      List<HInstruction> typeInputs = [];
      for (var argument in type.typeArguments) {
        typeInputs.add(
          _typeBuilder.analyzeTypeArgument(argument, sourceElement),
        );
      }

      // We lift this common call pattern into a helper function to save space
      // in the output.
      if (typeInputs.every(
        (HInstruction input) =>
            input.isNull(_abstractValueDomain).isDefinitelyTrue,
      )) {
        if (elements.isEmpty) {
          constructor = _commonElements.setLiteralUntypedEmptyMaker;
        } else {
          constructor = _commonElements.setLiteralUntypedMaker;
        }
      } else {
        inputs.addAll(typeInputs);
      }
    }

    // If runtime type information is needed and the set literal has no type
    // parameter, 'constructor' is a static function that forwards the call to
    // the factory constructor without a type parameter.
    assert(
      constructor.isFunction ||
          (constructor is ConstructorEntity &&
              constructor.isFactoryConstructor),
    );

    // The instruction type will always be a subtype of the setLiteralClass, but
    // type inference might discover a more specific type or find nothing (in
    // dart2js unit tests).

    AbstractValue setType = _abstractValueDomain.createNonNullSubtype(
      _commonElements.setLiteralClass,
    );
    AbstractValue returnTypeMask = _typeInferenceMap.getReturnTypeOf(
      constructor,
    );
    AbstractValue instructionType = _abstractValueDomain.intersection(
      setType,
      returnTypeMask,
    );

    _addImplicitInstantiation(type);
    _pushStaticInvocation(
      constructor,
      inputs,
      instructionType,
      const <DartType>[],
      sourceInformation: _sourceInformationBuilder.buildNew(node),
    );
    _removeImplicitInstantiation(type);
  }

  @override
  void visitMapLiteral(ir.MapLiteral node) {
    if (node.isConst) {
      stack.add(
        graph.addConstant(_elementMap.getConstantValue(node)!, closedWorld),
      );
      return;
    }

    // The map literal constructors take the key-value pairs as a List
    List<HInstruction> constructorArgs = [];
    for (ir.MapLiteralEntry mapEntry in node.entries) {
      mapEntry.key.accept(this);
      constructorArgs.add(pop());
      mapEntry.value.accept(this);
      constructorArgs.add(pop());
    }

    // The constructor is a procedure because it's a factory.
    FunctionEntity constructor;
    List<HInstruction> inputs = [];
    if (constructorArgs.isEmpty) {
      constructor = _commonElements.mapLiteralConstructorEmpty;
    } else {
      constructor = _commonElements.mapLiteralConstructor;
      HLiteralList argList = _buildLiteralList(constructorArgs);
      add(argList);
      inputs.add(argList);
    }

    assert(
      constructor is ConstructorEntity && constructor.isFactoryConstructor,
    );

    final type =
        localsHandler.substInContext(
              _commonElements.mapType(
                _elementMap.getDartType(node.keyType),
                _elementMap.getDartType(node.valueType),
              ),
            )
            as InterfaceType;
    final cls = constructor.enclosingClass!;

    if (_rtiNeed.classNeedsTypeArguments(cls)) {
      List<HInstruction> typeInputs = [];
      for (var argument in type.typeArguments) {
        typeInputs.add(
          _typeBuilder.analyzeTypeArgument(argument, sourceElement),
        );
      }

      // We lift this common call pattern into a helper function to save space
      // in the output.
      if (typeInputs.every(
        (HInstruction input) =>
            input.isNull(_abstractValueDomain).isDefinitelyTrue,
      )) {
        if (constructorArgs.isEmpty) {
          constructor = _commonElements.mapLiteralUntypedEmptyMaker;
        } else {
          constructor = _commonElements.mapLiteralUntypedMaker;
        }
      } else {
        inputs.addAll(typeInputs);
      }
    }

    // If runtime type information is needed and the map literal has no type
    // parameters, 'constructor' is a static function that forwards the call to
    // the factory constructor without type parameters.
    assert(
      constructor.isFunction ||
          (constructor is ConstructorEntity &&
              constructor.isFactoryConstructor),
    );

    // The instruction type will always be a subtype of the mapLiteralClass, but
    // type inference might discover a more specific type, or find nothing (in
    // dart2js unit tests).

    AbstractValue mapType = _abstractValueDomain.createNonNullSubtype(
      _commonElements.mapLiteralClass,
    );
    AbstractValue returnTypeMask = _typeInferenceMap.getReturnTypeOf(
      constructor,
    );
    AbstractValue instructionType = _abstractValueDomain.intersection(
      mapType,
      returnTypeMask,
    );

    _addImplicitInstantiation(type);
    _pushStaticInvocation(
      constructor,
      inputs,
      instructionType,
      const <DartType>[],
      sourceInformation: _sourceInformationBuilder.buildNew(node),
    );
    _removeImplicitInstantiation(type);
  }

  @override
  void visitMapLiteralEntry(ir.MapLiteralEntry node) {
    failedAt(
      currentElementSpannable,
      'ir.MapEntry should be handled in visitMapLiteral',
    );
  }

  @override
  void visitRecordLiteral(ir.RecordLiteral node) {
    SourceInformation? sourceInformation = _sourceInformationBuilder
        .buildCreate(node);
    assert(!node.isConst);

    List<HInstruction> inputs = [];
    for (ir.Expression expression in node.positional) {
      expression.accept(this);
      inputs.add(pop());
    }
    for (ir.NamedExpression namedExpression in node.named) {
      namedExpression.value.accept(this);
      inputs.add(pop());
    }

    // TODO(50701): Choose class depending in inferred type of record fields
    // which might be better than the static type.
    RecordType dartType =
        _elementMap.getDartType(node.recordType) as RecordType;
    if (dartType.containsTypeVariables) {
      dartType = localsHandler.substInContext(dartType) as RecordType;
    }

    final recordRepresentation = _recordData.representationForStaticType(
      dartType,
    );
    ClassEntity recordClass = recordRepresentation.cls;

    if (recordRepresentation.usesList) {
      // TODO(50081): Can we use `.constListType`?
      push(HLiteralList(inputs, _abstractValueDomain.fixedListType));
      inputs = [pop()];
    }

    AbstractValue type =
        _typeInferenceMap.typeOfRecordLiteral(node, _abstractValueDomain) ??
        _abstractValueDomain
            .createFromStaticType(dartType, nullable: true)
            .abstractValue;

    final allocation = HCreate(recordClass, inputs, type, sourceInformation);

    // TODO(50701): With traced record types there might be a better type.

    push(allocation);
  }

  @override
  void visitRecordIndexGet(ir.RecordIndexGet node) {
    final shape = recordShapeOfRecordType(node.receiverType);
    return _handleRecordFieldGet(node, node.receiver, shape, node.index);
  }

  @override
  void visitRecordNameGet(ir.RecordNameGet node) {
    final shape = recordShapeOfRecordType(node.receiverType);
    int index = shape.indexOfFieldName(node.name);
    return _handleRecordFieldGet(node, node.receiver, shape, index);
  }

  void _handleRecordFieldGet(
    ir.Expression node,
    ir.TreeNode receiverNode,
    RecordShape shape,
    int indexInShape,
  ) {
    receiverNode.accept(this);
    HInstruction receiver = pop();

    SourceInformation? sourceInformation = _sourceInformationBuilder.buildGet(
      node,
    );

    if (_recordData.representationForShape(shape) != null) {
      final recordType =
          _typeInferenceMap.receiverTypeOfGet(node) ??
          _abstractValueDomain
              .createFromStaticType(_getStaticType(node), nullable: true)
              .abstractValue;
      final fieldType = _abstractValueDomain.getGetterTypeInRecord(
        recordType,
        shape.getterNameOfIndex(indexInShape),
      );

      final path = _recordData.pathForAccess(shape, indexInShape);
      if (path.index == null) {
        HFieldGet fieldGet = HFieldGet(
          path.field,
          receiver,
          fieldType,
          sourceInformation,
          isAssignable: false,
        );
        push(fieldGet);
      } else {
        HFieldGet fieldGet = HFieldGet(
          path.field,
          receiver,
          _abstractValueDomain.constListType,
          sourceInformation,
          isAssignable: false,
        );
        push(fieldGet);
        final list = pop();
        push(
          HIndex(
            list,
            graph.addConstantInt(indexInShape, closedWorld),
            fieldType,
          ),
        );
      }
    } else {
      // There are no records with this shape, so the path here must be
      // infeasible.
      push(
        HInvokeStatic(
          _commonElements.assertUnreachableMethod,
          [],
          _abstractValueDomain.emptyType,
          const [],
        )..sourceInformation = sourceInformation,
      );
      // TODO(50081): Should we make subsequent code unreachable?
    }
  }

  @override
  void visitTypeLiteral(ir.TypeLiteral node) {
    final sourceInformation = _sourceInformationBuilder.buildGet(node);
    ir.DartType type = node.type;
    DartType dartType = _elementMap.getDartType(type);
    if (!dartType.containsTypeVariables) {
      final constant = _elementMap.getConstantValue(node)!;
      stack.add(
        graph.addConstant(
          constant,
          closedWorld,
          sourceInformation: sourceInformation,
        ),
      );
      return;
    }
    // For other types (e.g. TypeParameterType, function types from expanded
    // typedefs), look-up or construct a reified type representation and convert
    // to a RuntimeType.

    dartType = localsHandler.substInContext(dartType);
    HInstruction value = _typeBuilder.analyzeTypeArgument(
      dartType,
      sourceElement,
      sourceInformation: sourceInformation,
    );
    _pushStaticInvocation(
      _commonElements.createRuntimeType,
      [value],
      _typeInferenceMap.getReturnTypeOf(_commonElements.createRuntimeType),
      const <DartType>[],
      sourceInformation: sourceInformation,
    );
  }

  @override
  void visitStaticGet(ir.StaticGet node) {
    ir.Member staticTarget = node.target;
    final sourceInformation = _sourceInformationBuilder.buildGet(node);
    if (staticTarget is ir.Procedure &&
        staticTarget.kind == ir.ProcedureKind.Getter) {
      final getter = _elementMap.getMember(staticTarget) as FunctionEntity;
      // Invoke the getter
      _pushStaticInvocation(
        getter,
        const [],
        _typeInferenceMap.getReturnTypeOf(getter),
        const <DartType>[],
        sourceInformation: sourceInformation,
      );
    } else if (staticTarget is ir.Field) {
      FieldEntity field = _elementMap.getField(staticTarget);
      FieldAnalysisData fieldData = _fieldAnalysis.getFieldData(field);
      if (fieldData.isEager) {
        push(
          HStatic(
            field,
            _typeInferenceMap.getInferredTypeOf(field),
            sourceInformation,
          ),
        );
      } else if (fieldData.isEffectivelyConstant) {
        OutputUnit outputUnit = closedWorld.outputUnitData.outputUnitForMember(
          field,
        );
        final initialValue = fieldData.initialValue!;
        // TODO(sigmund): this is not equivalent to what the old FE does: if
        // there is no prefix the old FE wouldn't treat this in any special
        // way. Also, if the prefix points to a constant in the main output
        // unit, the old FE would still generate a deferred wrapper here.
        if (!closedWorld.outputUnitData.hasOnlyNonDeferredImportPaths(
          targetElement,
          field,
        )) {
          final deferredConstant = DeferredGlobalConstantValue(
            initialValue,
            outputUnit,
          );
          registry.registerConstantUse(ConstantUse.deferred(deferredConstant));
          stack.add(
            graph.addDeferredConstant(
              deferredConstant,
              sourceInformation,
              closedWorld,
            ),
          );
        } else {
          stack.add(
            graph.addConstant(
              initialValue,
              closedWorld,
              sourceInformation: sourceInformation,
            ),
          );
        }
      } else {
        assert(
          fieldData.isLazy,
          "Unexpected field data for $field: $fieldData",
        );
        push(
          HLazyStatic(
            field,
            _typeInferenceMap.getInferredTypeOf(field),
            sourceInformation,
          ),
        );
      }
    } else {
      // TODO(johnniwinther): This is a constant tear off, so we should have
      // created a constant value instead. Remove this case when we use CFE
      // constants.
      final member = _elementMap.getMember(staticTarget);
      push(
        HStatic(
          member,
          _typeInferenceMap.getInferredTypeOf(member),
          sourceInformation,
        ),
      );
    }
  }

  @override
  void visitStaticTearOff(ir.StaticTearOff node) {
    // TODO(johnniwinther): This is a constant tear off, so we should have
    // created a constant value instead. Remove this case when we use CFE
    // constants.
    ir.Member staticTarget = node.target;
    final sourceInformation = _sourceInformationBuilder.buildGet(node);
    final member = _elementMap.getMember(staticTarget);
    push(
      HStatic(
        member,
        _typeInferenceMap.getInferredTypeOf(member),
        sourceInformation,
      ),
    );
  }

  @override
  void visitStaticSet(ir.StaticSet node) {
    node.value.accept(this);
    HInstruction value = pop();

    ir.Member staticTarget = node.target;
    if (staticTarget is ir.Procedure) {
      final setter = _elementMap.getMember(staticTarget) as FunctionEntity;
      // Invoke the setter
      _pushStaticInvocation(
        setter,
        [value],
        _typeInferenceMap.getReturnTypeOf(setter),
        const <DartType>[],
        sourceInformation: _sourceInformationBuilder.buildSet(node),
      );
      pop();
    } else {
      final target = _elementMap.getMember(staticTarget) as FieldEntity;
      if (!_fieldAnalysis.getFieldData(target).isElided) {
        add(
          HStaticStore(
            target,
            _typeBuilder.potentiallyCheckOrTrustTypeOfAssignment(
              target,
              value,
              _getDartTypeIfValid(staticTarget.setterType),
            ),
          ),
        );
      }
    }
    stack.add(value);
  }

  void _handlePropertyGet(
    ir.Expression node,
    ir.Expression receiver,
    ir.Name name,
  ) {
    receiver.accept(this);
    HInstruction receiverInstruction = pop();
    _pushDynamicInvocation(
      node,
      _getStaticType(receiver),
      _typeInferenceMap.receiverTypeOfGet(node),
      Selector.getter(_elementMap.getName(name)),
      [receiverInstruction],
      const <DartType>[],
      _sourceInformationBuilder.buildGet(node),
    );
  }

  @override
  void visitInstanceGet(ir.InstanceGet node) {
    _handlePropertyGet(node, node.receiver, node.name);
  }

  @override
  void visitInstanceTearOff(ir.InstanceTearOff node) {
    _handlePropertyGet(node, node.receiver, node.name);
  }

  @override
  void visitDynamicGet(ir.DynamicGet node) {
    _handlePropertyGet(node, node.receiver, node.name);
  }

  @override
  void visitFunctionTearOff(ir.FunctionTearOff node) {
    _handlePropertyGet(node, node.receiver, ir.Name.callName);
  }

  @override
  void visitVariableGet(ir.VariableGet node) {
    ir.VariableDeclaration variable = node.variable;
    final letBinding = _letBindings[variable];
    if (letBinding != null) {
      stack.add(letBinding);
      return;
    }

    Local local = _localsMap.getLocalVariable(node.variable);
    stack.add(
      localsHandler.readLocal(
        local,
        sourceInformation: _sourceInformationBuilder.buildGet(node),
      ),
    );
  }

  void _handlePropertySet(
    ir.Expression node,
    ir.Expression receiver,
    ir.Name name,
    ir.Expression value,
  ) {
    receiver.accept(this);
    HInstruction receiverInstruction = pop();
    value.accept(this);
    HInstruction valueInstruction = pop();

    _pushDynamicInvocation(
      node,
      _getStaticType(receiver),
      _typeInferenceMap.receiverTypeOfSet(node, _abstractValueDomain),
      Selector.setter(_elementMap.getName(name)),
      [receiverInstruction, valueInstruction],
      const <DartType>[],
      _sourceInformationBuilder.buildAssignment(node),
    );

    pop();
    stack.add(valueInstruction);
  }

  @override
  void visitInstanceSet(ir.InstanceSet node) {
    _handlePropertySet(node, node.receiver, node.name, node.value);
  }

  @override
  void visitDynamicSet(ir.DynamicSet node) {
    _handlePropertySet(node, node.receiver, node.name, node.value);
  }

  @override
  void visitSuperPropertySet(ir.SuperPropertySet node) {
    final sourceInformation = _sourceInformationBuilder.buildAssignment(node);
    node.value.accept(this);
    HInstruction value = pop();

    final target = getEffectiveSuperTarget(node.interfaceTarget);
    MemberEntity member = _elementMap.getMember(target);
    _buildInvokeSuper(
      _elementMap.getSelector(node),
      _elementMap.getClass(_containingClass(node)),
      member,
      [value],
      const <DartType>[],
      sourceInformation,
    );
    pop();
    stack.add(value);
  }

  @override
  void visitVariableSet(ir.VariableSet node) {
    node.value.accept(this);
    HInstruction value = pop();
    _visitLocalSetter(
      node.variable,
      value,
      _sourceInformationBuilder.buildAssignment(node),
    );
  }

  @override
  void visitVariableDeclaration(ir.VariableDeclaration node) {
    Local local = _localsMap.getLocalVariable(node);
    if (node.initializer == null) {
      HInstruction initialValue = graph.addConstantNull(closedWorld);
      localsHandler.updateLocal(local, initialValue);
    } else if (node.isConst) {
      final constant = _elementMap.getConstantValue(node.initializer);
      assert(constant != null, failedAt(currentElementSpannable));
      HInstruction initialValue = graph.addConstant(constant!, closedWorld);
      localsHandler.updateLocal(local, initialValue);
    } else {
      node.initializer!.accept(this);
      HInstruction initialValue = pop();

      _visitLocalSetter(
        node,
        initialValue,
        _sourceInformationBuilder.buildAssignment(node),
      );

      // Ignore value
      pop();
    }
  }

  void _visitLocalSetter(
    ir.VariableDeclaration variable,
    HInstruction value,
    SourceInformation? sourceInformation,
  ) {
    Local local = _localsMap.getLocalVariable(variable);

    // Give the value a name if it doesn't have one already.
    value.sourceElement ??= local;

    stack.add(value);
    localsHandler.updateLocal(
      local,
      _typeBuilder.potentiallyCheckOrTrustTypeOfAssignment(
        _currentFrame!.member,
        value,
        _getDartTypeIfValid(variable.type),
      ),
      sourceInformation: sourceInformation,
    );
  }

  @override
  void visitLet(ir.Let node) {
    ir.VariableDeclaration variable = node.variable;
    variable.initializer!.accept(this);
    HInstruction initializedValue = pop();
    // TODO(sra): Apply inferred type information.
    _letBindings[variable] = initializedValue;
    // TODO(43456): Use `!_isReachable` for better dead code removal.
    if (isAborted()) {
      stack.add(graph.addConstantUnreachable(closedWorld));
    } else {
      node.body.accept(this);
    }
  }

  @override
  void visitBlockExpression(ir.BlockExpression node) {
    node.body.accept(this);
    // Body can be partially generated due to an exception exit and be missing
    // bindings referenced in the value.
    if (!_isReachable) {
      stack.add(graph.addConstantUnreachable(closedWorld));
    } else {
      final previous = _inBlockExpression;
      try {
        _inBlockExpression = true;
        node.value.accept(this);
      } finally {
        _inBlockExpression = previous;
      }
    }
  }

  /// Generate instructions to evaluate the positional arguments in source
  /// order.
  List<HInstruction> _visitPositionalArguments(ir.Arguments arguments) {
    List<HInstruction> result = [];
    for (ir.Expression argument in arguments.positional) {
      argument.accept(this);
      result.add(pop());
    }
    return result;
  }

  /// Generate instructions to evaluate the named arguments in source order.
  /// Returns a fresh map from parameter name to evaluated argument.
  Map<String, HInstruction> _visitNamedArguments(ir.Arguments arguments) {
    Map<String, HInstruction> values = {};
    for (ir.NamedExpression argument in arguments.named) {
      argument.value.accept(this);
      values[argument.name] = pop();
    }
    return values;
  }

  /// Builds the list of instructions for the expressions in the arguments to a
  /// dynamic target (member function).  Dynamic targets use stubs to add
  /// defaulted arguments, so (unlike static targets) we do not add the default
  /// values.
  List<HInstruction> _visitArgumentsForDynamicTarget(
    Selector selector,
    ir.Arguments arguments,
    List<DartType> typeArguments, [
    SourceInformation? sourceInformation,
  ]) {
    List<HInstruction> values = _visitPositionalArguments(arguments);

    if (arguments.named.isNotEmpty) {
      Map<String, HInstruction> namedValues = _visitNamedArguments(arguments);
      for (String name in selector.callStructure.getOrderedNamedArguments()) {
        values.add(namedValues[name]!);
      }
    }

    _addTypeArguments(values, typeArguments, sourceInformation);

    return values;
  }

  /// Build the argument list for JS-interop invocations, which have slightly
  /// different semantics than dart because of JS's null vs undefined and lack
  /// of named arguments. A `null` argument indicates an optional argument which
  /// was not provided.
  List<HInstruction?> _visitArgumentsForNativeStaticTarget(
    ir.FunctionNode target,
    ir.Arguments arguments,
  ) {
    // Visit arguments in source order, then re-order and fill in defaults.
    List<HInstruction?> values = List.from(
      _visitPositionalArguments(arguments),
    );

    if (target.namedParameters.isNotEmpty) {
      // Only anonymous factory or extension type literal constructors involving
      // JS interop are allowed to have named parameters. Otherwise, throw an
      // error.
      final member = target.parent as ir.Member;
      final function = _elementMap.getMember(member) as FunctionEntity;
      bool isAnonymousFactory =
          function is ConstructorEntity &&
          function.isFactoryConstructor &&
          _nativeData.isAnonymousJsInteropClass(function.enclosingClass);
      // JS interop checks assert that the only extension type interop member
      // that has named parameters is an object literal constructor.
      // TODO(54968): We should handle the lowering for object literal
      // constructors in the interop transformer somehow instead and avoid
      // assuming all such members are object literal constructors or
      // otherwise paying the cost to verify by indexing extension types.
      bool isObjectLiteralConstructor = member.isExtensionTypeMember;
      if (isAnonymousFactory || isObjectLiteralConstructor) {
        // TODO(sra): Have a "CompiledArguments" structure to just update with
        // what values we have rather than creating a map and de-populating it.
        Map<String, HInstruction> namedValues = _visitNamedArguments(arguments);

        // Visit named arguments in parameter-position order, selecting provided
        // or default value.
        var namedParameters = target.namedParameters.toList();
        assert(
          namedValues.keys.every(
            (k) => namedParameters.any((p) => p.name == k),
          ),
        );
        namedParameters.sort(nativeOrdering);
        for (ir.VariableDeclaration parameter in namedParameters) {
          final value = namedValues[parameter.name];
          values.add(value);
        }
      }
    }
    return values;
  }

  /// Fills [typeArguments] with the type arguments needed for [selector] and
  /// returns the selector corresponding to the passed type arguments.
  ///
  /// If [isImplicitCall] is `true`, the target of the invocation can be either
  /// the target of the [selector] or of the corresponding `.call` selector. In
  /// this case we need to check both selectors to see if we need to pass type
  /// arguments. This occurs for field/getter invocations.
  Selector _fillDynamicTypeArguments(
    Selector selector,
    ir.Arguments arguments,
    List<DartType> typeArguments, {
    bool isImplicitCall = false,
  }) {
    if (selector.typeArgumentCount > 0) {
      if (_rtiNeed.selectorNeedsTypeArguments(selector) ||
          (isImplicitCall &&
              _rtiNeed.selectorNeedsTypeArguments(selector.toCallSelector()))) {
        typeArguments.addAll(arguments.types.map(_elementMap.getDartType));
      } else {
        return selector.toNonGeneric();
      }
    }
    return selector;
  }

  List<DartType> _getConstructorTypeArguments(
    ConstructorEntity constructor,
    ir.Arguments arguments,
  ) {
    // TODO(johnniwinther): Pass type arguments to constructors like calling
    // a generic method.
    return const <DartType>[];
  }

  // TODO(johnniwinther): Remove this when type arguments are passed to
  // constructors like calling a generic method.
  List<DartType> _getClassTypeArguments(
    ClassEntity cls,
    ir.Arguments arguments,
  ) {
    if (_rtiNeed.classNeedsTypeArguments(cls)) {
      return arguments.types.map(_elementMap.getDartType).toList();
    }
    return const <DartType>[];
  }

  List<DartType> _getStaticTypeArguments(
    FunctionEntity function,
    ir.Arguments arguments,
  ) {
    if (_rtiNeed.methodNeedsTypeArguments(function)) {
      return arguments.types.map(_elementMap.getDartType).toList();
    }
    return const <DartType>[];
  }

  /// Build argument list in canonical order for a static [target], including
  /// filling in the default argument value.
  List<HInstruction> _visitArgumentsForStaticTarget(
    ir.FunctionNode target,
    ParameterStructure parameterStructure,
    ir.Arguments arguments,
    List<DartType> typeArguments,
    SourceInformation? sourceInformation,
  ) {
    // Visit arguments in source order, then re-order and fill in defaults.
    List<HInstruction> values = _visitPositionalArguments(arguments);

    while (values.length < parameterStructure.positionalParameters) {
      ir.VariableDeclaration parameter =
          target.positionalParameters[values.length];
      values.add(_defaultValueForParameter(parameter));
    }

    if (parameterStructure.namedParameters.isNotEmpty) {
      Map<String, HInstruction> namedValues = _visitNamedArguments(arguments);

      // Visit named arguments in parameter-position order, selecting provided
      // or default value.
      // TODO(sra): Ensure the stored order is canonical so we don't have to
      // sort. The old builder uses CallStructure.makeArgumentList which depends
      // on the old element model.
      List<ir.VariableDeclaration> namedParameters =
          target.namedParameters
              // Filter elided parameters.
              .where((p) => parameterStructure.namedParameters.contains(p.name))
              .toList()
            ..sort(namedOrdering);
      for (ir.VariableDeclaration parameter in namedParameters) {
        final value = namedValues[parameter.name];
        if (value == null) {
          values.add(_defaultValueForParameter(parameter));
        } else {
          values.add(value);
          namedValues.remove(parameter.name);
        }
      }
      assert(namedValues.isEmpty);
    } else {
      assert(arguments.named.isEmpty);
    }

    _addTypeArguments(values, typeArguments, sourceInformation);
    return values;
  }

  void _addTypeArguments(
    List<HInstruction?> values,
    List<DartType> typeArguments,
    SourceInformation? sourceInformation,
  ) {
    if (typeArguments.isEmpty) return;
    for (DartType type in typeArguments) {
      values.add(
        _typeBuilder.analyzeTypeArgument(
          type,
          sourceElement,
          sourceInformation: sourceInformation,
        ),
      );
    }
  }

  HInstruction _defaultValueForParameter(ir.VariableDeclaration parameter) {
    final constant = _elementMap.getConstantValue(
      parameter.initializer,
      implicitNull: true,
    );
    assert(constant != null, failedAt(currentElementSpannable));
    return graph.addConstant(constant!, closedWorld);
  }

  @override
  void visitStaticInvocation(ir.StaticInvocation node) {
    if (ir.StaticWeakReferences.isWeakReference(node)) {
      final weakTarget = ir.StaticWeakReferences.getWeakReferenceTarget(node);
      if (_elementMap.containsMethod(weakTarget)) {
        final argument = ir.StaticWeakReferences.getWeakReferenceArgument(node);
        argument.accept(this);
        return;
      }
      stack.add(graph.addConstantNull(closedWorld));
      return;
    }
    ir.Procedure target = node.target;
    final sourceInformation = _sourceInformationBuilder.buildCall(node, node);
    final function = _elementMap.getMember(target) as FunctionEntity;
    if (_commonElements.isForeignHelper(function)) {
      _handleInvokeStaticForeign(node, function, sourceInformation);
      return;
    }

    if (_commonElements.isExtractTypeArguments(function) &&
        _handleExtractTypeArguments(node, sourceInformation)) {
      return;
    }

    AbstractValue typeMask = _typeInferenceMap.getReturnTypeOf(function);

    List<DartType> typeArguments = _getStaticTypeArguments(
      function,
      node.arguments,
    );

    // Recognize e.g. `bool.fromEnvironment('x')`
    // TODO(sra): Can we delete this code now that the CFE does constant folding
    // for us during loading?
    if (function.isExternal &&
        function is ConstructorEntity &&
        function.isFromEnvironmentConstructor) {
      if (node.isConst) {
        // Just like all const constructors (see visitConstructorInvocation).
        stack.add(
          graph.addConstant(
            _elementMap.getConstantValue(node)!,
            closedWorld,
            sourceInformation: sourceInformation,
          ),
        );
      } else {
        _generateUnsupportedError(
          '${function.enclosingClass.name}.${function.name} '
          'can only be used as a const constructor',
          sourceInformation,
        );
      }
      return;
    }

    if (closedWorld.nativeData.isJsInteropMember(function)) {
      final arguments = _visitArgumentsForNativeStaticTarget(
        target.function,
        node.arguments,
      );

      if (function is ConstructorEntity && function.isFactoryConstructor) {
        _handleInvokeNativeFactoryConstructor(
          node,
          function,
          typeMask,
          arguments,
          sourceInformation,
        );
        return;
      }

      // Static methods currently ignore the type parameters.
      _pushStaticNativeInvocation(
        function,
        arguments,
        typeMask,
        typeArguments,
        sourceInformation: sourceInformation,
      );
    } else {
      final arguments = _visitArgumentsForStaticTarget(
        target.function,
        function.parameterStructure,
        node.arguments,
        typeArguments,
        sourceInformation,
      );

      if (function is ConstructorEntity && function.isFactoryConstructor) {
        _handleInvokeFactoryConstructor(
          node,
          function,
          typeMask,
          arguments,
          sourceInformation,
        );
        return;
      }

      // Static methods currently ignore the type parameters.
      _pushStaticInvocation(
        function,
        arguments,
        typeMask,
        typeArguments,
        sourceInformation: sourceInformation,
      );
    }
  }

  void _handleInvokeFactoryConstructor(
    ir.StaticInvocation invocation,
    ConstructorEntity function,
    AbstractValue typeMask,
    List<HInstruction> arguments,
    SourceInformation? sourceInformation,
  ) {
    // Recognize `JSArray<E>.typed(allocation)`.
    if (function == _commonElements.jsArrayTypedConstructor) {
      if (invocation.arguments.named.isEmpty) {
        if (invocation.arguments.positional.length == 1) {
          assert(arguments.length == 1);
          _handleInvokeJSArrayTypedConstructor(
            invocation,
            function,
            typeMask,
            arguments,
            sourceInformation,
          );
          return;
        }
      }
    }

    InterfaceType instanceType = _elementMap.createInterfaceType(
      invocation.target.enclosingClass!,
      invocation.arguments.types,
    );

    // Factory constructors take type parameters.
    List<DartType> typeArguments = _getConstructorTypeArguments(
      function,
      invocation.arguments,
    );

    // This could be a List factory constructor that returned a fresh list and
    // we have a call-site-specific type from type inference.
    var allocatedListType = globalInferenceResults.typeOfNewList(invocation);
    AbstractValue resultType = allocatedListType ?? typeMask;

    // TODO(johnniwinther): Remove this when type arguments are passed to
    // constructors like calling a generic method.
    _addTypeArguments(
      arguments,
      _getClassTypeArguments(function.enclosingClass, invocation.arguments),
      sourceInformation,
    );
    instanceType = localsHandler.substInContext(instanceType) as InterfaceType;
    _addImplicitInstantiation(instanceType);
    _pushStaticInvocation(
      function,
      arguments,
      resultType,
      typeArguments,
      sourceInformation: sourceInformation,
      instanceType: instanceType,
    );

    if (allocatedListType != null) {
      HInstruction newInstance = stack.last.nonCheck();
      if (newInstance is HInvokeStatic) {
        newInstance.setAllocation(true);
      }
      // Is the constructor call one from which we can extract the length
      // argument?
      bool isFixedList = false;

      if (_abstractValueDomain.isFixedArray(resultType).isDefinitelyTrue) {
        // These constructors all take a length as the first argument.
        if (_commonElements.isNamedListConstructor('filled', function) ||
            _commonElements.isNamedListConstructor('generate', function) ||
            _commonElements.isNamedJSArrayConstructor('fixed', function) ||
            _commonElements.isNamedJSArrayConstructor(
              'allocateFixed',
              function,
            )) {
          isFixedList = true;
        }
      }

      if (_abstractValueDomain.isTypedArray(resultType).isDefinitelyTrue) {
        // The unnamed constructors of typed arrays take a length as the first
        // argument.
        if (function.name == '') isFixedList = true;
        // TODO(sra): Can this misfire?
      }

      if (isFixedList) {
        if (newInstance is HInvokeStatic || newInstance is HForeignCode) {
          graph.allocatedFixedLists.add(newInstance);
        }
      }
    }
  }

  void _handleInvokeNativeFactoryConstructor(
    ir.StaticInvocation invocation,
    ConstructorEntity function,
    AbstractValue typeMask,
    List<HInstruction?> arguments,
    SourceInformation? sourceInformation,
  ) {
    InterfaceType instanceType = _elementMap.createInterfaceType(
      invocation.target.enclosingClass!,
      invocation.arguments.types,
    );

    // Factory constructors take type parameters.
    List<DartType> typeArguments = _getConstructorTypeArguments(
      function,
      invocation.arguments,
    );

    // TODO(johnniwinther): Remove this when type arguments are passed to
    // constructors like calling a generic method.
    _addTypeArguments(
      arguments,
      _getClassTypeArguments(function.enclosingClass, invocation.arguments),
      sourceInformation,
    );
    instanceType = localsHandler.substInContext(instanceType) as InterfaceType;
    _addImplicitInstantiation(instanceType);
    _pushStaticNativeInvocation(
      function,
      arguments,
      typeMask,
      typeArguments,
      sourceInformation: sourceInformation,
    );
  }

  /// Handle the `JSArray<E>.typed` constructor, which returns its argument,
  /// which must be a JSArray, with the JSArray type Rti information added on a
  /// property.
  void _handleInvokeJSArrayTypedConstructor(
    ir.StaticInvocation invocation,
    ConstructorEntity function,
    AbstractValue typeMask,
    List<HInstruction> arguments,
    SourceInformation? sourceInformation,
  ) {
    // TODO(sra): We rely here on inlining the identity-like factory
    // constructor. Instead simply select the single argument and add the type.

    // Factory constructors take type parameters.
    List<DartType> typeArguments = _getConstructorTypeArguments(
      function,
      invocation.arguments,
    );
    // TODO(johnniwinther): Remove this when type arguments are passed to
    // constructors like calling a generic method.
    _addTypeArguments(
      arguments,
      _getClassTypeArguments(function.enclosingClass, invocation.arguments),
      sourceInformation,
    );
    _pushStaticInvocation(
      function,
      arguments,
      typeMask,
      typeArguments,
      sourceInformation: sourceInformation,
    );

    InterfaceType type = _elementMap.createInterfaceType(
      invocation.target.enclosingClass!,
      invocation.arguments.types,
    );
    stack.add(_setListRuntimeTypeInfoIfNeeded(pop(), type, sourceInformation));
  }

  /// Replace calls to `extractTypeArguments` with equivalent code. Returns
  /// `true` if `extractTypeArguments` is handled.
  bool _handleExtractTypeArguments(
    ir.StaticInvocation invocation,
    SourceInformation? sourceInformation,
  ) {
    // Expand calls as follows:
    //
    //     r = extractTypeArguments<Map>(e, f)
    // -->
    //     environment = HInstanceEnvironment(e);
    //     T1 = HTypeEval( environment, 'Map.K');
    //     T2 = HTypeEval( environment, 'Map.V');
    //     r = f<T1, T2>();
    //
    // TODO(sra): Should we add a check before the variable extraction? We could
    // add a type check (which would permit `null`), or add an is-check with an
    // explicit throw.

    if (invocation.arguments.positional.length != 2) return false;
    if (invocation.arguments.named.isNotEmpty) return false;
    var types = invocation.arguments.types;
    if (types.length != 1) return false;

    // The type should be a single type name.
    ir.DartType type = types.first;
    DartType typeValue = dartTypes.eraseLegacy(
      localsHandler.substInContext(_elementMap.getDartType(type)),
    );
    if (typeValue is! InterfaceType) return false;
    InterfaceType interfaceType = typeValue;
    if (!dartTypes.treatAsRawType(interfaceType)) return false;

    ClassEntity cls = interfaceType.element;
    InterfaceType thisType = _elementEnvironment.getThisType(cls);

    List<HInstruction> arguments = _visitPositionalArguments(
      invocation.arguments,
    );

    HInstruction object = arguments[0];
    HInstruction closure = arguments[1];

    List<HInstruction> inputs = [closure];
    List<DartType> typeArguments = [];

    closedWorld.registerExtractTypeArguments(cls);
    HInstruction instanceType = HInstanceEnvironment(
      object,
      _abstractValueDomain.dynamicType,
    );
    add(instanceType);
    TypeEnvironmentStructure envStructure = FullTypeEnvironmentStructure(
      classType: thisType,
    );

    for (var variable in thisType.typeArguments) {
      assert(variable is TypeVariableType);
      typeArguments.add(variable);
      TypeRecipe recipe = TypeExpressionRecipe(variable);
      HInstruction typeEval = HTypeEval(
        instanceType,
        envStructure,
        recipe,
        _abstractValueDomain.dynamicType,
      );
      add(typeEval);
      inputs.add(typeEval);
    }

    // TODO(sra): In compliance mode, insert a check that [closure] is a
    // function of N type arguments.

    Selector selector = Selector.callClosure(
      0,
      const <String>[],
      typeArguments.length,
    );
    final receiverStaticType = _getStaticType(
      invocation.arguments.positional[1],
    );
    AbstractValue receiverType =
        _abstractValueDomain
            .createFromStaticType(receiverStaticType, nullable: true)
            .abstractValue;
    push(
      HInvokeClosure(
        selector,
        receiverType,
        inputs,
        _abstractValueDomain.dynamicType,
        typeArguments,
      ),
    );

    return true;
  }

  void _handleInvokeStaticForeign(
    ir.StaticInvocation invocation,
    MemberEntity member,
    SourceInformation? sourceInformation,
  ) {
    final name = member.name;
    if (name == 'JS') {
      _handleForeignJs(invocation, sourceInformation);
    } else if (name == 'DART_CLOSURE_TO_JS') {
      _handleForeignDartClosureToJs(
        invocation,
        'DART_CLOSURE_TO_JS',
        sourceInformation,
      );
    } else if (name == 'RAW_DART_FUNCTION_REF') {
      _handleForeignRawFunctionRef(
        invocation,
        'RAW_DART_FUNCTION_REF',
        sourceInformation,
      );
    } else if (name == 'JS_GET_NAME') {
      _handleForeignJsGetName(invocation, sourceInformation);
    } else if (name == 'JS_EMBEDDED_GLOBAL') {
      _handleForeignJsEmbeddedGlobal(invocation, sourceInformation);
    } else if (name == 'JS_BUILTIN') {
      _handleForeignJsBuiltin(invocation, sourceInformation);
    } else if (name == 'JS_TRUE') {
      _handleForeignJsBool(true, invocation, sourceInformation);
    } else if (name == 'JS_FALSE') {
      _handleForeignJsBool(false, invocation, sourceInformation);
    } else if (name == 'JS_EFFECT') {
      stack.add(
        graph.addConstantNull(closedWorld)
          ..sourceInformation = sourceInformation,
      );
    } else if (name == 'JS_INTERCEPTOR_CONSTANT') {
      _handleJsInterceptorConstant(invocation, sourceInformation);
    } else if (name == 'getInterceptor') {
      _handleForeignGetInterceptor(invocation, sourceInformation);
    } else if (name == 'getJSArrayInteropRti') {
      _handleForeignGetJSArrayInteropRti(invocation, sourceInformation);
    } else if (name == 'JS_RAW_EXCEPTION') {
      _handleJsRawException(invocation, sourceInformation);
    } else if (name == 'JS_STRING_CONCAT') {
      _handleJsStringConcat(invocation, sourceInformation);
    } else if (name == '_createInvocationMirror') {
      _handleCreateInvocationMirror(invocation, sourceInformation);
    } else if (name == 'TYPE_REF') {
      _handleForeignTypeRef(invocation, sourceInformation);
    } else if (name == 'LEGACY_TYPE_REF') {
      _handleForeignLegacyTypeRef(invocation, sourceInformation);
    } else if (name == 'createJsSentinel') {
      _handleForeignCreateJsSentinel(invocation, sourceInformation);
    } else if (name == 'isJsSentinel') {
      _handleForeignIsJsSentinel(invocation, sourceInformation);
    } else if (name == '_lateReadCheck') {
      _handleLateReadCheck(invocation, sourceInformation);
    } else if (name == '_lateWriteOnceCheck') {
      _handleLateWriteOnceCheck(invocation, sourceInformation);
    } else if (name == '_lateInitializeOnceCheck') {
      _handleLateInitializeOnceCheck(invocation, sourceInformation);
    } else if (name == 'HCharCodeAt') {
      _handleCharCodeAt(invocation, sourceInformation);
    } else if (name == 'HArrayFlagsGet') {
      _handleArrayFlagsGet(invocation, sourceInformation);
    } else if (name == 'HArrayFlagsSet') {
      _handleArrayFlagsSet(invocation, sourceInformation);
    } else if (name == 'HArrayFlagsCheck') {
      _handleArrayFlagsCheck(invocation, sourceInformation);
    } else {
      reporter.internalError(
        _elementMap.getSpannable(targetElement, invocation),
        "Unknown foreign: $name",
      );
    }
  }

  String _readStringLiteral(ir.Expression node) {
    if (node is ir.StringLiteral) {
      return node.value;
    }
    if (node is ir.ConstantExpression) {
      final constant = node.constant;
      if (constant is ir.StringConstant) {
        return constant.value;
      }
    }
    return reporter.internalError(
      _elementMap.getSpannable(targetElement, node),
      "Unexpected string literal: "
      "${node is ir.ConstantExpression ? node.constant : node}",
    );
  }

  int _readIntLiteral(ir.Expression node) {
    if (node is ir.IntLiteral) {
      return node.value;
    }
    if (node is ir.ConstantExpression) {
      final constant = node.constant;
      if (constant is ir.IntConstant) {
        return constant.value;
      } else if (constant is ir.DoubleConstant) {
        assert(
          constant.value.floor() == constant.value,
          "Unexpected int literal value ${constant.value}.",
        );
        return constant.value.toInt();
      }
    }
    return reporter.internalError(
      _elementMap.getSpannable(targetElement, node),
      "Unexpected int literal: "
      "${node is ir.ConstantExpression ? node.constant : node}",
    );
  }

  void _handleCreateInvocationMirror(
    ir.StaticInvocation invocation,
    SourceInformation? sourceInformation,
  ) {
    String name = _readStringLiteral(invocation.arguments.positional[0]);
    final typeArgumentsLiteral =
        invocation.arguments.positional[1] as ir.ListLiteral;
    List<DartType> typeArguments =
        typeArgumentsLiteral.expressions.map((ir.Expression expression) {
          final typeLiteral = expression as ir.TypeLiteral;
          return _elementMap.getDartType(typeLiteral.type);
        }).toList();

    final positionalArgumentsLiteral =
        invocation.arguments.positional[2] as ir.ListLiteral;
    ir.Expression namedArgumentsLiteral = invocation.arguments.positional[3];
    Map<String, ir.Expression> namedArguments = {};
    int kind = _readIntLiteral(invocation.arguments.positional[4]);

    Name memberName = Name(name, _currentFrame!.member.library.canonicalUri);
    Selector selector;
    switch (InvocationMirrorKind.values[kind]) {
      case InvocationMirrorKind.getter:
        selector = Selector.getter(memberName);
        break;
      case InvocationMirrorKind.setter:
        selector = Selector.setter(memberName);
        break;
      case InvocationMirrorKind.method:
        if (memberName == Names.indexName) {
          selector = Selector.index();
        } else if (memberName == Names.indexSetName) {
          selector = Selector.indexSet();
        } else {
          if (namedArgumentsLiteral is ir.MapLiteral) {
            for (var entry in namedArgumentsLiteral.entries) {
              String key = _readStringLiteral(entry.key);
              namedArguments[key] = entry.value;
            }
          } else if (namedArgumentsLiteral is ir.ConstantExpression &&
              namedArgumentsLiteral.constant is ir.MapConstant) {
            final constant = namedArgumentsLiteral.constant as ir.MapConstant;
            for (ir.ConstantMapEntry entry in constant.entries) {
              final key = entry.key as ir.StringConstant;
              namedArguments[key.value] = ir.ConstantExpression(entry.value);
            }
          } else {
            reporter.internalError(
              computeSourceSpanFromTreeNode(invocation),
              "Unexpected named arguments value in createInvocationMirror: "
              "$namedArgumentsLiteral.",
            );
          }
          CallStructure callStructure = CallStructure(
            positionalArgumentsLiteral.expressions.length,
            namedArguments.keys.toList(),
            typeArguments.length,
          );
          if (Selector.isOperatorName(name)) {
            selector = Selector(
              SelectorKind.operator,
              memberName,
              callStructure,
            );
          } else {
            selector = Selector.call(memberName, callStructure);
          }
        }
        break;
    }

    HConstant nameConstant = graph.addConstant(
      constant_system.createSymbol(closedWorld.commonElements, name),
      closedWorld,
    )..sourceInformation = sourceInformation;

    List<HInstruction> arguments = [];
    for (ir.Expression argument in positionalArgumentsLiteral.expressions) {
      argument.accept(this);
      arguments.add(pop());
    }
    if (namedArguments.isNotEmpty) {
      Map<String, HInstruction> namedValues = {};
      namedArguments.forEach((String name, ir.Expression value) {
        value.accept(this);
        namedValues[name] = pop();
      });
      for (String name in selector.callStructure.getOrderedNamedArguments()) {
        arguments.add(namedValues[name]!);
      }
    }

    _addTypeArguments(arguments, typeArguments, sourceInformation);

    HInstruction argumentsInstruction = _buildLiteralList(arguments)
      ..sourceInformation = sourceInformation;
    add(argumentsInstruction);

    List<HInstruction> argumentNames = <HInstruction>[];
    for (String argumentName
        in selector.callStructure.getOrderedNamedArguments()) {
      ConstantValue argumentNameConstant = constant_system.createString(
        argumentName,
      );
      argumentNames.add(
        graph.addConstant(argumentNameConstant, closedWorld)
          ..sourceInformation = sourceInformation,
      );
    }
    HInstruction argumentNamesInstruction = _buildLiteralList(argumentNames)
      ..sourceInformation = sourceInformation;
    add(argumentNamesInstruction);

    HInstruction typeArgumentCount = graph.addConstantInt(
      typeArguments.length,
      closedWorld,
    )..sourceInformation = sourceInformation;

    js.Name internalName = _namer.invocationName(selector);

    ConstantValue kindConstant = constant_system.createIntFromInt(
      selector.invocationMirrorKind.index,
    );

    _pushStaticInvocation(
      _commonElements.createUnmangledInvocationMirror,
      [
        nameConstant,
        graph.addConstantStringFromName(internalName, closedWorld)
          ..sourceInformation = sourceInformation,
        graph.addConstant(kindConstant, closedWorld)
          ..sourceInformation = sourceInformation,
        argumentsInstruction,
        argumentNamesInstruction,
        typeArgumentCount,
      ],
      _abstractValueDomain.dynamicType,
      const <DartType>[],
      sourceInformation: sourceInformation,
    );
  }

  bool _unexpectedForeignArguments(
    ir.StaticInvocation invocation, {
    required int minPositional,
    int? maxPositional,
    int typeArgumentCount = 0,
  }) {
    String pluralizeArguments(int count, [String adjective = '']) {
      if (count == 0) return 'no ${adjective}arguments';
      if (count == 1) return 'one ${adjective}argument';
      if (count == 2) return 'two ${adjective}arguments';
      return '$count ${adjective}arguments';
    }

    String name() => invocation.target.name.text;

    ir.Arguments arguments = invocation.arguments;
    bool bad = false;
    if (arguments.types.length != typeArgumentCount) {
      String expected = pluralizeArguments(typeArgumentCount, 'type ');
      String actual = pluralizeArguments(arguments.types.length, 'type ');
      reporter.reportErrorMessage(
        _elementMap.getSpannable(targetElement, invocation),
        MessageKind.generic,
        {'text': "Error: '${name()}' takes $expected, not $actual."},
      );
      bad = true;
    }
    if (arguments.positional.length < minPositional) {
      String phrase = pluralizeArguments(minPositional);
      if (maxPositional != minPositional) phrase = 'at least $phrase';
      reporter.reportErrorMessage(
        _elementMap.getSpannable(targetElement, invocation),
        MessageKind.generic,
        {'text': "Error: Too few arguments. '${name()}' takes $phrase."},
      );
      bad = true;
    }
    if (maxPositional != null && arguments.positional.length > maxPositional) {
      String phrase = pluralizeArguments(maxPositional);
      if (maxPositional != minPositional) phrase = 'at most $phrase';
      reporter.reportErrorMessage(
        _elementMap.getSpannable(targetElement, invocation),
        MessageKind.generic,
        {'text': "Error: Too many arguments. '${name()}' takes $phrase."},
      );
      bad = true;
    }
    if (arguments.named.isNotEmpty) {
      reporter.reportErrorMessage(
        _elementMap.getSpannable(targetElement, invocation),
        MessageKind.generic,
        {'text': "Error: '${name()}' does not take named arguments."},
      );
      bad = true;
    }
    return bad;
  }

  /// Returns the value of the string argument. The argument must evaluate to a
  /// constant.  If there is an error, the error is reported and `null` is
  /// returned.
  String? _foreignConstantStringArgument(
    ir.StaticInvocation invocation,
    int position,
    String methodName, [
    String adjective = '',
  ]) {
    ir.Expression argument = invocation.arguments.positional[position];
    argument.accept(this);
    HInstruction instruction = pop();

    if (instruction is HConstant) {
      ConstantValue constant = instruction.constant;
      if (constant is StringConstantValue) return constant.stringValue;
    }

    reporter.reportErrorMessage(
      _elementMap.getSpannable(targetElement, argument),
      MessageKind.generic,
      {
        'text':
            "Error: Expected String constant as ${adjective}argument "
            "to '$methodName'.",
      },
    );
    return null;
  }

  void _handleForeignDartClosureToJs(
    ir.StaticInvocation invocation,
    String name,
    SourceInformation? sourceInformation,
  ) {
    // TODO(sra): Do we need to wrap the closure in something that saves the
    // current isolate?
    _handleForeignRawFunctionRef(invocation, name, sourceInformation);
  }

  void _handleForeignRawFunctionRef(
    ir.StaticInvocation invocation,
    String name,
    SourceInformation? sourceInformation,
  ) {
    if (_unexpectedForeignArguments(
      invocation,
      minPositional: 1,
      maxPositional: 1,
    )) {
      // Result expected on stack.
      stack.add(
        graph.addConstantNull(closedWorld)
          ..sourceInformation = sourceInformation,
      );
      return;
    }

    ir.Expression closure = invocation.arguments.positional.single;
    String problem = 'requires a static method or top-level method';

    bool handleTarget(ir.Procedure procedure) {
      final function = procedure.function;
      if (function.requiredParameterCount ==
              function.positionalParameters.length &&
          function.namedParameters.isEmpty) {
        push(
          HFunctionReference(
            _elementMap.getMethod(procedure),
            _abstractValueDomain.dynamicType,
          )..sourceInformation = sourceInformation,
        );
        return true;
      }
      problem = 'does not handle a closure with optional parameters';
      return false;
    }

    if (closure is ir.StaticGet) {
      ir.Member staticTarget = closure.target;
      if (staticTarget is ir.Procedure) {
        if (staticTarget.kind == ir.ProcedureKind.Method) {
          if (handleTarget(staticTarget)) {
            return;
          }
        }
      }
    } else if (closure is ir.ConstantExpression) {
      final tearOff = closure.constant;
      if (tearOff is ir.StaticTearOffConstant) {
        ir.Procedure member = tearOff.target;
        if (handleTarget(member)) {
          return;
        }
      }
    }

    reporter.reportErrorMessage(
      _elementMap.getSpannable(targetElement, invocation),
      MessageKind.generic,
      {'text': "'$name' $problem."},
    );
    // Result expected on stack.
    stack.add(
      graph.addConstantNull(closedWorld)..sourceInformation = sourceInformation,
    );
    return;
  }

  void _handleJsRawException(
    ir.StaticInvocation invocation,
    SourceInformation? sourceInformation,
  ) {
    if (_unexpectedForeignArguments(
      invocation,
      minPositional: 0,
      maxPositional: 0,
    )) {
      // Result expected on stack.
      stack.add(
        graph.addConstantNull(closedWorld)
          ..sourceInformation = sourceInformation,
      );
      return;
    }

    if (_rethrowableException != null) {
      stack.add(_rethrowableException!);
      return;
    }

    reporter.reportErrorMessage(
      _elementMap.getSpannable(targetElement, invocation),
      MessageKind.generic,
      {'text': "Error: JS_RAW_EXCEPTION() must be in a 'catch' block."},
    );
    // Result expected on stack.
    stack.add(
      graph.addConstantNull(closedWorld)..sourceInformation = sourceInformation,
    );
  }

  void _handleForeignJsGetName(
    ir.StaticInvocation invocation,
    SourceInformation? sourceInformation,
  ) {
    if (_unexpectedForeignArguments(
      invocation,
      minPositional: 1,
      maxPositional: 1,
    )) {
      // Result expected on stack.
      stack.add(
        graph.addConstantNull(closedWorld)
          ..sourceInformation = sourceInformation,
      );
      return;
    }

    ir.Node argument = invocation.arguments.positional.first;
    argument.accept(this);
    HInstruction instruction = pop();

    if (instruction is HConstant) {
      final name = _getNameForJsGetName(instruction.constant, _namer)!;
      stack.add(
        graph.addConstantStringFromName(name, closedWorld)
          ..sourceInformation = sourceInformation,
      );
      return;
    }

    reporter.reportErrorMessage(
      _elementMap.getSpannable(targetElement, argument),
      MessageKind.generic,
      {'text': 'Error: Expected a JsGetName enum value.'},
    );
    // Result expected on stack.
    stack.add(
      graph.addConstantNull(closedWorld)..sourceInformation = sourceInformation,
    );
  }

  int? _extractEnumIndexFromConstantValue(
    ConstantValue constant,
    ClassEntity classElement,
  ) {
    if (constant is ConstructedConstantValue &&
        constant.type.element == classElement) {
      assert(constant.fields.isNotEmpty);
      for (var field in constant.fields.keys) {
        if (field.memberName.text == "index") {
          final indexConstant = constant.fields[field];
          if (indexConstant is IntConstantValue) {
            return indexConstant.intValue.toInt();
          }
          break;
        }
      }
    }
    return null;
  }

  /// Returns the [js.Name] for the `JsGetName` [constant] value.
  js.Name? _getNameForJsGetName(ConstantValue constant, ModularNamer namer) {
    final index = _extractEnumIndexFromConstantValue(
      constant,
      _commonElements.jsGetNameEnum,
    );
    if (index == null) return null;
    return namer.getNameForJsGetName(
      currentElementSpannable,
      JsGetName.values[index],
    );
  }

  void _handleForeignJsEmbeddedGlobal(
    ir.StaticInvocation invocation,
    SourceInformation? sourceInformation,
  ) {
    if (_unexpectedForeignArguments(
      invocation,
      minPositional: 2,
      maxPositional: 2,
    )) {
      // Result expected on stack.
      stack.add(
        graph.addConstantNull(closedWorld)
          ..sourceInformation = sourceInformation,
      );
      return;
    }
    final globalName =
        _foreignConstantStringArgument(
          invocation,
          1,
          'JS_EMBEDDED_GLOBAL',
          'second ',
        )!;
    js.Template expr = js.js.expressionTemplateYielding(
      _emitter.generateEmbeddedGlobalAccess(globalName),
    );

    NativeBehavior nativeBehavior = _elementMap
        .getNativeBehaviorForJsEmbeddedGlobalCall(invocation);

    AbstractValue ssaType = _typeInferenceMap.typeFromNativeBehavior(
      nativeBehavior,
      closedWorld,
    );
    push(
      HForeignCode(
        expr,
        ssaType,
        const <HInstruction>[],
        nativeBehavior: nativeBehavior,
      )..sourceInformation = sourceInformation,
    );
  }

  void _handleForeignJsBuiltin(
    ir.StaticInvocation invocation,
    SourceInformation? sourceInformation,
  ) {
    if (_unexpectedForeignArguments(invocation, minPositional: 2)) {
      // Result expected on stack.
      stack.add(
        graph.addConstantNull(closedWorld)
          ..sourceInformation = sourceInformation,
      );
      return;
    }

    List<ir.Expression> arguments = invocation.arguments.positional;
    ir.Expression nameArgument = arguments[1];

    nameArgument.accept(this);
    HInstruction instruction = pop();

    js.Template? template;
    if (instruction is HConstant) {
      template = _getJsBuiltinTemplate(instruction.constant, _emitter);
    }
    if (template == null) {
      reporter.reportErrorMessage(
        _elementMap.getSpannable(targetElement, nameArgument),
        MessageKind.generic,
        {'text': 'Error: Expected a JsBuiltin enum value.'},
      );
      // Result expected on stack.
      stack.add(
        graph.addConstantNull(closedWorld)
          ..sourceInformation = sourceInformation,
      );
      return;
    }

    List<HInstruction> inputs = [];
    for (ir.Expression argument in arguments.skip(2)) {
      argument.accept(this);
      inputs.add(pop());
    }

    NativeBehavior nativeBehavior = _elementMap
        .getNativeBehaviorForJsBuiltinCall(invocation);

    AbstractValue ssaType = _typeInferenceMap.typeFromNativeBehavior(
      nativeBehavior,
      closedWorld,
    );
    push(
      HForeignCode(template, ssaType, inputs, nativeBehavior: nativeBehavior)
        ..sourceInformation = sourceInformation,
    );
  }

  /// Returns the [js.Template] for the `JsBuiltin` [constant] value.
  js.Template? _getJsBuiltinTemplate(
    ConstantValue constant,
    ModularEmitter emitter,
  ) {
    final index = _extractEnumIndexFromConstantValue(
      constant,
      _commonElements.jsBuiltinEnum,
    );
    if (index == null) return null;
    return _templateForBuiltin(JsBuiltin.values[index]);
  }

  /// Returns the JS template for the given [builtin].
  js.Template? _templateForBuiltin(JsBuiltin builtin) {
    switch (builtin) {
      case JsBuiltin.dartObjectConstructor:
        ClassEntity objectClass = closedWorld.commonElements.objectClass;
        return js.js.expressionTemplateYielding(
          _emitter.constructorAccess(objectClass),
        );

      case JsBuiltin.dartClosureConstructor:
        ClassEntity closureClass = closedWorld.commonElements.closureClass;
        // TODO(sra): Should add a dependency on the constructor used as a
        // token.
        registry
        // ignore:deprecated_member_use_from_same_package
        .registerInstantiatedClass(closureClass);
        return js.js.expressionTemplateYielding(
          _emitter.constructorAccess(closureClass),
        );

      case JsBuiltin.getMetadata:
        String metadataAccess = _emitter.generateEmbeddedGlobalAccessString(
          METADATA,
        );
        return js.js.expressionTemplateFor("$metadataAccess[#]");

      case JsBuiltin.getType:
        String typesAccess = _emitter.generateEmbeddedGlobalAccessString(TYPES);
        return js.js.expressionTemplateFor("$typesAccess[#]");

      case JsBuiltin.isJsInteropTypeArgument:
        reporter.internalError(
          noLocationSpannable,
          "Unhandled Builtin: $builtin",
        );
    }
  }

  void _handleForeignJsBool(
    bool value,
    ir.StaticInvocation invocation,
    SourceInformation? sourceInformation,
  ) {
    _unexpectedForeignArguments(invocation, minPositional: 0, maxPositional: 0);
    stack.add(
      graph.addConstantBool(value, closedWorld)
        ..sourceInformation = sourceInformation,
    );
  }

  void _handleJsInterceptorConstant(
    ir.StaticInvocation invocation,
    SourceInformation? sourceInformation,
  ) {
    // Single argument must be a TypeConstant which is converted into a
    // InterceptorConstant.
    if (_unexpectedForeignArguments(
      invocation,
      minPositional: 1,
      maxPositional: 1,
    )) {
      // Result expected on stack.
      stack.add(
        graph.addConstantNull(closedWorld)
          ..sourceInformation = sourceInformation,
      );
      return;
    }
    ir.Expression argument = invocation.arguments.positional.single;
    argument.accept(this);
    HInstruction argumentInstruction = pop();
    if (argumentInstruction is HConstant) {
      ConstantValue argumentConstant = argumentInstruction.constant;
      if (argumentConstant is TypeConstantValue) {
        final interfaceType =
            argumentConstant.representedType.withoutNullability;
        if (interfaceType is InterfaceType) {
          // TODO(sra): Check that type is a subclass of [Interceptor].
          ConstantValue constant = InterceptorConstantValue(
            interfaceType.element,
          );
          HInstruction instruction = graph.addConstant(constant, closedWorld)
            ..sourceInformation = sourceInformation;
          stack.add(instruction);
          return;
        }
      }
    }

    reporter.reportErrorMessage(
      _elementMap.getSpannable(targetElement, invocation),
      MessageKind.wrongArgumentForJSInterceptorConstant,
    );
    stack.add(
      graph.addConstantNull(closedWorld)..sourceInformation = sourceInformation,
    );
  }

  void _handleForeignGetInterceptor(
    ir.StaticInvocation invocation,
    SourceInformation? sourceInformation,
  ) {
    // Single argument is the intercepted object.
    if (_unexpectedForeignArguments(
      invocation,
      minPositional: 1,
      maxPositional: 1,
    )) {
      // Result expected on stack.
      stack.add(
        graph.addConstantNull(closedWorld)
          ..sourceInformation = sourceInformation,
      );
      return;
    }
    ir.Expression argument = invocation.arguments.positional.single;
    argument.accept(this);
    HInstruction argumentInstruction = pop();

    HInstruction instruction = _interceptorFor(
      argumentInstruction,
      sourceInformation,
    )..sourceInformation = sourceInformation;
    stack.add(instruction);
  }

  void _handleForeignGetJSArrayInteropRti(
    ir.StaticInvocation invocation,
    SourceInformation? sourceInformation,
  ) {
    if (_unexpectedForeignArguments(
      invocation,
      minPositional: 0,
      maxPositional: 0,
    )) {
      // Result expected on stack.
      stack.add(
        graph.addConstantNull(closedWorld)
          ..sourceInformation = sourceInformation,
      );
      return;
    }
    // TODO(sra): This should be JSArray<any>, created via
    // _elementEnvironment.getJsInteropType(_elementEnvironment.jsArrayClass);
    InterfaceType interopType = dartTypes.interfaceType(
      _commonElements.jsArrayClass,
      [dartTypes.dynamicType()],
    );
    HInstruction rti = HLoadType.type(
      interopType,
      _abstractValueDomain.dynamicType,
    )..sourceInformation = sourceInformation;
    push(rti);
  }

  bool _equivalentToMissingRti(InterfaceType type) {
    assert(type.element == _commonElements.jsArrayClass);
    return dartTypes.isStrongTopType(type.typeArguments.single);
  }

  void _handleForeignJs(
    ir.StaticInvocation invocation,
    SourceInformation? sourceInformation,
  ) {
    if (_unexpectedForeignArguments(
      invocation,
      minPositional: 2,
      maxPositional: null,
      typeArgumentCount: 1,
    )) {
      // Result expected on stack.
      stack.add(
        graph.addConstantNull(closedWorld)
          ..sourceInformation = sourceInformation,
      );
      return;
    }

    NativeBehavior nativeBehavior = _elementMap.getNativeBehaviorForJsCall(
      invocation,
    );

    List<HInstruction> inputs = [];
    for (ir.Expression argument in invocation.arguments.positional.skip(2)) {
      argument.accept(this);
      inputs.add(pop());
    }

    final codeTemplate = nativeBehavior.codeTemplate!;

    if (codeTemplate.positionalArgumentCount != inputs.length) {
      reporter.reportErrorMessage(
        _elementMap.getSpannable(targetElement, invocation),
        MessageKind.generic,
        {
          'text':
              'Mismatch between number of placeholders'
              ' and number of arguments.',
        },
      );
      // Result expected on stack.
      stack.add(
        graph.addConstantNull(closedWorld)
          ..sourceInformation = sourceInformation,
      );
      return;
    }

    if (HasCapturedPlaceholders.check(codeTemplate.ast)) {
      reporter.reportErrorMessage(
        _elementMap.getSpannable(targetElement, invocation),
        MessageKind.jsPlaceholderCapture,
      );
    }

    AbstractValue ssaType = _typeInferenceMap.typeFromNativeBehavior(
      nativeBehavior,
      closedWorld,
    );

    HInstruction code = HForeignCode(
      codeTemplate,
      ssaType,
      inputs,
      isStatement: !codeTemplate.isExpression,
      effects: nativeBehavior.sideEffects,
      nativeBehavior: nativeBehavior,
    )..sourceInformation = sourceInformation;
    push(code);

    DartType type = _getDartTypeIfValid(invocation.arguments.types.single);
    final trustedMask = _typeBuilder.trustTypeMask(type);

    if (trustedMask != null) {
      // We only allow the type argument to narrow `dynamic`, which probably
      // comes from an unspecified return type in the NativeBehavior.
      if (_abstractValueDomain
          .containsAll(code.instructionType)
          .isPotentiallyTrue) {
        // Overwrite the type with the narrower type.
        code.instructionType = trustedMask;
      }
      // It is acceptable for the type parameter to be broader than the
      // specified type.
    }

    _maybeAddNullCheckOnJS(invocation);
  }

  /// If [invocation] is a `JS()` invocation in a web library and the static
  /// type is non-nullable, add a check to make sure it isn't null.
  void _maybeAddNullCheckOnJS(ir.StaticInvocation invocation) {
    if (options.nativeNullAssertions &&
        nodeIsInWebLibrary(invocation) &&
        closedWorld.dartTypes.isNonNullableIfSound(
          _getStaticType(invocation),
        )) {
      HInstruction code = pop();
      push(
        HNullCheck(
          code,
          _abstractValueDomain.excludeNull(code.instructionType),
          sticky: true,
        ),
      );
    }
  }

  void _maybeAddInteropNullAssertionForMember(
    FunctionEntity member,
    int argumentCount, {
    SourceInformation? sourceInformation,
  }) {
    if (options.interopNullAssertions) {
      final functionType = _elementEnvironment.getFunctionType(member);
      if (dartTypes.isNonNullableIfSound(functionType.returnType)) {
        final name = PublicName(
          _nativeData.computeUnescapedJSInteropName(member.name!),
        );
        _addInteropNullAssertionForSelector(
          Selector.call(name, CallStructure.unnamed(argumentCount)),
          sourceInformation: sourceInformation,
        );
      }
    }
  }

  void _maybeAddInteropNullAssertionForSelector(
    Selector selector, {
    SourceInformation? sourceInformation,
  }) {
    if (options.interopNullAssertions &&
        _nativeData.interopNullChecks[selector] ==
            InteropNullCheckKind.callerCheck) {
      _addInteropNullAssertion(sourceInformation: sourceInformation);
    }
  }

  void _addInteropNullAssertionForSelector(
    Selector selector, {
    SourceInformation? sourceInformation,
  }) {
    if (_nativeData.interopNullChecks[selector] ==
        InteropNullCheckKind.callerCheck) {
      _addInteropNullAssertion(sourceInformation: sourceInformation);
    }
  }

  void _maybeAddInteropNullAssertionForStatic(
    DartType returnType, {
    SourceInformation? sourceInformation,
  }) {
    if (options.interopNullAssertions &&
        closedWorld.dartTypes.isNonNullableIfSound(returnType)) {
      _addInteropNullAssertion(sourceInformation: sourceInformation);
    }
  }

  void _addInteropNullAssertion({SourceInformation? sourceInformation}) {
    final value = pop();
    _pushStaticInvocation(
      _commonElements.interopNullAssertion,
      [value],
      value.instructionType,
      const <DartType>[],
      sourceInformation: sourceInformation,
    );
  }

  void _handleJsStringConcat(
    ir.StaticInvocation invocation,
    SourceInformation? sourceInformation,
  ) {
    if (_unexpectedForeignArguments(
      invocation,
      minPositional: 2,
      maxPositional: 2,
    )) {
      // Result expected on stack.
      stack.add(
        graph.addConstantNull(closedWorld)
          ..sourceInformation = sourceInformation,
      );
      return;
    }
    List<HInstruction> inputs = _visitPositionalArguments(invocation.arguments);
    push(
      HStringConcat(inputs[0], inputs[1], _abstractValueDomain.stringType)
        ..sourceInformation = sourceInformation,
    );
  }

  void _handleCharCodeAt(
    ir.StaticInvocation invocation,
    SourceInformation? sourceInformation,
  ) {
    if (_unexpectedForeignArguments(
      invocation,
      minPositional: 2,
      maxPositional: 2,
    )) {
      // Result expected on stack.
      stack.add(
        graph.addConstantNull(closedWorld)
          ..sourceInformation = sourceInformation,
      );
      return;
    }
    List<HInstruction> inputs = _visitPositionalArguments(invocation.arguments);
    push(
      HCharCodeAt(inputs[0], inputs[1], _abstractValueDomain.uint31Type)
        ..sourceInformation = sourceInformation,
    );
  }

  void _handleArrayFlagsGet(
    ir.StaticInvocation invocation,
    SourceInformation? sourceInformation,
  ) {
    if (_unexpectedForeignArguments(
      invocation,
      minPositional: 1,
      maxPositional: 1,
    )) {
      // Result expected on stack.
      stack.add(graph.addConstantNull(closedWorld));
      return;
    }
    List<HInstruction> inputs = _visitPositionalArguments(invocation.arguments);
    final array = inputs.single;

    push(
      HArrayFlagsGet(array, _abstractValueDomain.uint31Type)
        ..sourceInformation = sourceInformation,
    );
  }

  void _handleArrayFlagsSet(
    ir.StaticInvocation invocation,
    SourceInformation? sourceInformation,
  ) {
    if (_unexpectedForeignArguments(
      invocation,
      minPositional: 2,
      maxPositional: 2,
      typeArgumentCount: 1,
    )) {
      // Result expected on stack.
      stack.add(graph.addConstantNull(closedWorld));
      return;
    }

    List<HInstruction> inputs = _visitPositionalArguments(invocation.arguments);
    final array = inputs[0];
    final flags = inputs[1];

    // TODO(sra): Use the flags to improve in the AbstractValue, which may
    // contain powerset domain bits outside of the conventional type
    // system. Perhaps do this in types_propagation.
    DartType type = _getDartTypeIfValid(invocation.arguments.types.single);
    AbstractValue? instructionType = _typeBuilder.trustTypeMask(type);
    // TODO(sra): Better type
    instructionType ??= _abstractValueDomain.dynamicType;

    push(
      HArrayFlagsSet(array, flags, instructionType)
        ..sourceInformation = sourceInformation,
    );
  }

  void _handleArrayFlagsCheck(
    ir.StaticInvocation invocation,
    SourceInformation? sourceInformation,
  ) {
    if (_unexpectedForeignArguments(
      invocation,
      minPositional: 4,
      maxPositional: 5,
      typeArgumentCount: 1,
    )) {
      // Result expected on stack.
      stack.add(graph.addConstantNull(closedWorld));
      return;
    }
    List<HInstruction> inputs = _visitPositionalArguments(invocation.arguments);
    final array = inputs[0];
    final arrayFlags = inputs[1];
    final checkFlags = inputs[2];
    final operation = inputs[3];
    final verb = inputs.length > 4 ? inputs[4] : null;

    // TODO(sra): Use the flags to improve in the AbstractValue, which may
    // contain powerset domain bits outside of the conventional type
    // system. Perhaps do this in types_propagation.
    DartType type = _getDartTypeIfValid(invocation.arguments.types.single);
    AbstractValue? instructionType = _typeBuilder.trustTypeMask(type);
    // TODO(sra): Better type
    instructionType ??= _abstractValueDomain.dynamicType;

    push(
      HArrayFlagsCheck(
        array,
        arrayFlags,
        checkFlags,
        operation,
        verb,
        instructionType,
      )..sourceInformation = sourceInformation,
    );
  }

  void _handleForeignTypeRef(
    ir.StaticInvocation invocation,
    SourceInformation? sourceInformation,
  ) {
    if (_unexpectedForeignArguments(
      invocation,
      minPositional: 0,
      maxPositional: 0,
      typeArgumentCount: 1,
    )) {
      stack.add(
        // Result expected on stack.
        graph.addConstantNull(closedWorld)
          ..sourceInformation = sourceInformation,
      );
      return;
    }
    DartType type = _elementMap.getDartType(invocation.arguments.types.single);
    push(
      HLoadType.type(type, _abstractValueDomain.dynamicType)
        ..sourceInformation = sourceInformation,
    );
  }

  void _handleForeignLegacyTypeRef(
    ir.StaticInvocation invocation,
    SourceInformation? sourceInformation,
  ) {
    if (_unexpectedForeignArguments(
      invocation,
      minPositional: 0,
      maxPositional: 0,
      typeArgumentCount: 1,
    )) {
      stack.add(
        // Result expected on stack.
        graph.addConstantNull(closedWorld)
          ..sourceInformation = sourceInformation,
      );
      return;
    }
    DartType type = closedWorld.dartTypes.legacyType(
      _elementMap.getDartType(invocation.arguments.types.single),
    );
    push(
      HLoadType.type(type, _abstractValueDomain.dynamicType)
        ..sourceInformation = sourceInformation,
    );
  }

  void _handleForeignCreateJsSentinel(
    ir.StaticInvocation invocation,
    SourceInformation? sourceInformation,
  ) {
    if (_unexpectedForeignArguments(
      invocation,
      minPositional: 0,
      maxPositional: 0,
      typeArgumentCount: 1,
    )) {
      stack.add(
        // Result expected on stack.
        graph.addConstantNull(closedWorld)
          ..sourceInformation = sourceInformation,
      );
      return;
    }

    stack.add(
      graph.addConstantLateSentinel(
        closedWorld,
        sourceInformation: sourceInformation,
      ),
    );
  }

  void _handleForeignIsJsSentinel(
    ir.StaticInvocation invocation,
    SourceInformation? sourceInformation,
  ) {
    if (_unexpectedForeignArguments(
      invocation,
      minPositional: 1,
      maxPositional: 1,
    )) {
      stack.add(
        // Result expected on stack.
        graph.addConstantNull(closedWorld)
          ..sourceInformation = sourceInformation,
      );
      return;
    }

    HInstruction checkedExpression =
        _visitPositionalArguments(invocation.arguments).single;
    push(
      HIsLateSentinel(checkedExpression, _abstractValueDomain.boolType)
        ..sourceInformation = sourceInformation,
    );
  }

  // TODO(fishythefish): Support specialization of late sentinels based on type.

  void _handleLateReadCheck(
    ir.StaticInvocation invocation,
    SourceInformation? sourceInformation,
  ) {
    if (_unexpectedForeignArguments(
      invocation,
      minPositional: 2,
      maxPositional: 2,
      typeArgumentCount: 1,
    )) {
      stack.add(
        // Result expected on stack.
        graph.addConstantNull(closedWorld)
          ..sourceInformation = sourceInformation,
      );
      return;
    }

    List<HInstruction> arguments = _visitPositionalArguments(
      invocation.arguments,
    );
    HInstruction value = arguments[0];
    final name = options.omitLateNames ? null : arguments[1];

    CheckPolicy policy = closedWorld.annotationsData
        .getLateVariableCheckPolicyAt(invocation);

    push(
      HLateReadCheck(
        value,
        name,
        policy.isTrusted,
        _abstractValueDomain.excludeLateSentinel(value.instructionType),
      )..sourceInformation = sourceInformation,
    );
  }

  void _handleLateWriteOnceCheck(
    ir.StaticInvocation invocation,
    SourceInformation? sourceInformation,
  ) {
    if (_unexpectedForeignArguments(
      invocation,
      minPositional: 2,
      maxPositional: 2,
    )) {
      stack.add(
        // Result expected on stack.
        graph.addConstantNull(closedWorld)
          ..sourceInformation = sourceInformation,
      );
      return;
    }

    List<HInstruction> arguments = _visitPositionalArguments(
      invocation.arguments,
    );
    HInstruction value = arguments[0];
    final name = options.omitLateNames ? null : arguments[1];

    CheckPolicy policy = closedWorld.annotationsData
        .getLateVariableCheckPolicyAt(invocation);

    push(
      HLateWriteOnceCheck(
        value,
        name,
        policy.isTrusted,
        _abstractValueDomain.dynamicType,
      )..sourceInformation = sourceInformation,
    );
  }

  void _handleLateInitializeOnceCheck(
    ir.StaticInvocation invocation,
    SourceInformation? sourceInformation,
  ) {
    if (_unexpectedForeignArguments(
      invocation,
      minPositional: 2,
      maxPositional: 2,
    )) {
      stack.add(
        // Result expected on stack.
        graph.addConstantNull(closedWorld)
          ..sourceInformation = sourceInformation,
      );
      return;
    }

    List<HInstruction> arguments = _visitPositionalArguments(
      invocation.arguments,
    );
    HInstruction value = arguments[0];
    final name = options.omitLateNames ? null : arguments[1];

    CheckPolicy policy = closedWorld.annotationsData
        .getLateVariableCheckPolicyAt(invocation);

    push(
      HLateInitializeOnceCheck(
        value,
        name,
        policy.isTrusted,
        _abstractValueDomain.dynamicType,
      )..sourceInformation = sourceInformation,
    );
  }

  void _pushStaticInvocation(
    FunctionEntity target,
    List<HInstruction> arguments,
    AbstractValue typeMask,
    List<DartType> typeArguments, {
    SourceInformation? sourceInformation,
    InterfaceType? instanceType,
  }) {
    // TODO(redemption): Pass current node if needed.
    if (_tryInlineMethod(
      target,
      null,
      null,
      arguments,
      typeArguments,
      null,
      sourceInformation,
      instanceType: instanceType,
    )) {
      return;
    }

    if (closedWorld.nativeData.isJsInteropMember(target)) {
      _pushStaticNativeInvocation(
        target,
        arguments,
        typeMask,
        typeArguments,
        sourceInformation: sourceInformation,
      );
      return;
    }

    HInvokeStatic instruction = HInvokeStatic(
      target,
      arguments,
      typeMask,
      typeArguments,
      targetCanThrow: !_inferredData.getCannotThrow(target),
    )..sourceInformation = sourceInformation;

    if (_currentImplicitInstantiations.isNotEmpty) {
      instruction.instantiatedTypes = List<InterfaceType>.from(
        _currentImplicitInstantiations,
      );
    }
    instruction.sideEffects = _inferredData.getSideEffectsOfElement(target);
    push(instruction);
  }

  void _pushStaticNativeInvocation(
    FunctionEntity target,
    List<HInstruction?> arguments,
    AbstractValue typeMask,
    List<DartType> typeArguments, {
    SourceInformation? sourceInformation,
  }) {
    _invokeJsInteropFunction(
      target,
      arguments,
      sourceInformation: sourceInformation,
    );
  }

  void _pushDynamicInvocation(
    ir.Node node,
    DartType staticReceiverType,
    AbstractValue? receiverType,
    Selector selector,
    List<HInstruction> arguments,
    List<DartType> typeArguments,
    SourceInformation? sourceInformation,
  ) {
    AbstractValue typeBound =
        _abstractValueDomain
            .createFromStaticType(staticReceiverType, nullable: true)
            .abstractValue;
    receiverType =
        receiverType == null
            ? typeBound
            : _abstractValueDomain.intersection(receiverType, typeBound);

    // We prefer to not inline certain operations on indexables,
    // because the constant folder will handle them better and turn
    // them into simpler instructions that allow further
    // optimizations.
    bool isOptimizableOperationOnIndexable(
      Selector selector,
      MemberEntity element,
    ) {
      bool isLength = selector.isGetter && selector.name == "length";
      if (isLength || selector.isIndex) {
        return closedWorld.classHierarchy.isSubtypeOf(
          element.enclosingClass!,
          _commonElements.jsIndexableClass,
        );
      } else if (selector.isIndexSet) {
        return closedWorld.classHierarchy.isSubtypeOf(
          element.enclosingClass!,
          _commonElements.jsMutableIndexableClass,
        );
      } else {
        return false;
      }
    }

    bool isOptimizableOperation(Selector selector, MemberEntity element) {
      final cls = element.enclosingClass;
      if (isOptimizableOperationOnIndexable(selector, element)) return true;
      if (!_interceptorData.interceptedClasses.contains(cls)) return false;
      if (selector.isOperator) return true;
      if (selector.isSetter) return true;
      if (selector.isIndex) return true;
      if (selector.isIndexSet) return true;
      if (element == _commonElements.jsArrayAdd ||
          element == _commonElements.jsArrayRemoveLast ||
          _commonElements.isJsStringSplit(element)) {
        return true;
      }
      return false;
    }

    final element = closedWorld.locateSingleMember(selector, receiverType);
    if (element != null &&
        element is FunctionEntity &&
        !(element.isGetter && selector.isCall) &&
        !(element.isFunction && selector.isGetter) &&
        !isOptimizableOperation(selector, element)) {
      if (_tryInlineMethod(
        element,
        selector,
        receiverType,
        arguments,
        typeArguments,
        node,
        sourceInformation,
      )) {
        return;
      }
    }

    HInstruction receiver = arguments.first;
    List<HInstruction> inputs = [];

    bool isIntercepted = closedWorld.interceptorData.isInterceptedSelector(
      selector,
    );

    if (isIntercepted) {
      HInterceptor interceptor = _interceptorFor(receiver, sourceInformation);
      inputs.add(interceptor);
    }
    inputs.addAll(arguments);

    AbstractValue resultType = _typeInferenceMap.resultTypeOfSelector(
      selector,
      receiverType,
    );
    HInvokeDynamic invoke;
    if (selector.isGetter) {
      _metrics.countGettersTotal.add();
      invoke = HInvokeDynamicGetter(
        selector,
        receiverType,
        element,
        inputs,
        isIntercepted,
        resultType,
        sourceInformation,
      );
    } else if (selector.isSetter) {
      _metrics.countSettersTotal.add();
      invoke = HInvokeDynamicSetter(
        selector,
        receiverType,
        element,
        inputs,
        isIntercepted,
        resultType,
        sourceInformation,
      );
    } else if (selector.isMaybeClosureCall) {
      assert(!isIntercepted);
      invoke = HInvokeClosure(
        selector,
        receiverType,
        inputs,
        resultType,
        typeArguments,
      )..sourceInformation = sourceInformation;
    } else {
      invoke = HInvokeDynamicMethod(
        selector,
        receiverType,
        inputs,
        resultType,
        typeArguments,
        sourceInformation,
        isIntercepted: isIntercepted,
      );
    }
    invoke.instructionContext = _currentFrame!.member;
    if (node is ir.InstanceInvocation) {
      invoke.isInvariant = node.isInvariant;
      invoke.isBoundsSafe = node.isBoundsSafe;
      if (node.receiver is ir.ThisExpression) {
        // If the receiver of an instance invocation is `this` then the call is
        // invariant with respect to the class type variables.
        invoke.isInvariant = true;
      }
    } else if (node is ir.InstanceSet) {
      if (node.receiver is ir.ThisExpression) {
        // If the receiver of an instance invocation is `this` then the call is
        // invariant with respect to the class type variables.
        invoke.isInvariant = true;
      }
    }

    if (node is ir.InstanceInvocation || node is ir.FunctionInvocation) {
      final staticType =
          _abstractValueDomain
              .createFromStaticType(
                _getStaticType(node as ir.Expression),
                nullable: true,
              )
              .abstractValue;
      // Narrow to front-end inferred type, but only if `receiverType` is
      // disjoint with LegacyJavaScriptObject.  Global type inference does not
      // trust the legacy js-interop methods, so we should not start doing so
      // here.
      if (!_possiblyLegacyJavaScriptObject(selector, receiverType)) {
        invoke.staticType = staticType;
        invoke.instructionType = _abstractValueDomain.intersection(
          resultType,
          staticType,
        );
      }
    }
    push(invoke);
    if (element != null &&
        _abstractValueDomain.isNull(resultType).isDefinitelyFalse) {
      _maybeAddInteropNullAssertionForSelector(
        selector,
        sourceInformation: sourceInformation,
      );
    }
  }

  bool _possiblyLegacyJavaScriptObject(Selector selector, AbstractValue type) {
    // Legacy js-interop cannot override `[]`.
    if (selector.isIndex) return false;

    if (_abstractValueDomain.isInterceptor(type).isDefinitelyFalse ||
        _abstractValueDomain.isPrimitive(type).isDefinitelyTrue) {
      return false;
    }

    return true;
  }

  void _invokeJsInteropFunction(
    FunctionEntity element,
    List<HInstruction?> arguments, {
    SourceInformation? sourceInformation,
  }) {
    assert(closedWorld.nativeData.isJsInteropMember(element));

    bool isAnonymousFactory =
        element is ConstructorEntity &&
        element.isFactoryConstructor &&
        _nativeData.isAnonymousJsInteropClass(element.enclosingClass);
    ir.Node node = _elementMap.getMemberDefinition(element).node;
    // JS interop checks assert that the only inline class interop member that
    // has named parameters is an object literal constructor. We could do a more
    // robust check by visiting all inline classes and recording descriptors,
    // but that's expensive.
    bool isObjectLiteralConstructor =
        node is ir.Procedure &&
        node.isExtensionTypeMember &&
        node.function.namedParameters.isNotEmpty;
    if (isAnonymousFactory || isObjectLiteralConstructor) {
      // Constructor that is syntactic sugar for creating a JavaScript object
      // literal.
      int i = 0;
      int positions = 0;
      List<HInstruction> filteredArguments = [];
      Map<String, js.Expression> parameterNameMap = {};

      // Note: we don't use `constructor.parameterStructure` here because
      // we don't elide parameters to js-interop external static targets
      // (including factory constructors.)
      // TODO(johnniwinther): can we elide those parameters? This should be
      // consistent with what we do with instance methods.
      final procedure = node as ir.Procedure;
      List<ir.VariableDeclaration> namedParameters =
          procedure.function.namedParameters.toList();

      namedParameters.sort(nativeOrdering);
      for (ir.VariableDeclaration variable in namedParameters) {
        String parameterName = variable.name!;
        // TODO(jacobr): consider throwing if parameter names do not match
        // names of properties in the class.
        final argument = arguments[i];
        if (argument != null) {
          filteredArguments.add(argument);
          var jsName = _nativeData.computeUnescapedJSInteropName(parameterName);
          parameterNameMap[jsName] = js.InterpolatedExpression(positions++);
        }
        i++;
      }
      var codeTemplate = js.Template(null, js.objectLiteral(parameterNameMap));

      var nativeBehavior = NativeBehavior()..codeTemplate = codeTemplate;
      registry.registerNativeMethod(element);
      // TODO(efortuna): Source information.
      push(
        HForeignCode(
          codeTemplate,
          _abstractValueDomain.dynamicType,
          filteredArguments,
          nativeBehavior: nativeBehavior,
        ),
      );
      return;
    }

    // Strip off trailing arguments that were not specified.
    // we could assert that the trailing arguments are all null.
    // TODO(jacobr): rewrite named arguments to an object literal matching
    // the factory constructor case.
    List<HInstruction> inputs = arguments.whereType<HInstruction>().toList();

    var nativeBehavior = NativeBehavior()..sideEffects.setAllSideEffects();

    DartType type =
        element is ConstructorEntity
            ? _elementEnvironment.getThisType(element.enclosingClass)
            : _elementEnvironment.getFunctionType(element).returnType;
    // Native behavior effects here are similar to native/behavior.dart.
    // The return type is dynamic because we don't trust js-interop type
    // declarations.
    nativeBehavior.typesReturned.add(dartTypes.dynamicType());

    // The allocation effects include the declared type if it is native (which
    // includes js interop types).
    final nonNullableType = type.withoutNullability;
    if (nonNullableType is InterfaceType &&
        _nativeData.isNativeClass(nonNullableType.element)) {
      nativeBehavior.typesInstantiated.add(nonNullableType);
    }

    // It also includes any other JS interop type. Technically, a JS interop API
    // could return anything, so the sound thing to do would be to assume that
    // anything that may come from JS as instantiated. In order to prevent the
    // resulting code bloat (e.g. from `dart:html`), we unsoundly assume that
    // only JS interop types are returned.
    nativeBehavior.typesInstantiated.add(
      _elementEnvironment.getThisType(
        _commonElements.jsLegacyJavaScriptObjectClass,
      ),
    );

    AbstractValue instructionType = _typeInferenceMap.typeFromNativeBehavior(
      nativeBehavior,
      closedWorld,
    );

    push(
      HInvokeExternal(
        element,
        inputs,
        instructionType,
        nativeBehavior,
        sourceInformation: sourceInformation,
      ),
    );
    _maybeAddInteropNullAssertionForStatic(
      type,
      sourceInformation: sourceInformation,
    );
  }

  @override
  void visitFunctionNode(ir.FunctionNode node) {
    final sourceInformation = _sourceInformationBuilder.buildCreate(node);
    ClosureRepresentationInfo closureInfo = _closureDataLookup.getClosureInfo(
      node.parent as ir.LocalFunction,
    );
    ClassEntity closureClassEntity = closureInfo.closureClassEntity!;

    List<HInstruction> capturedVariables = [];
    _elementEnvironment.forEachInstanceField(closureClassEntity, (
      _,
      FieldEntity field,
    ) {
      if (_fieldAnalysis.getFieldData(field).isElided) return;
      capturedVariables.add(
        localsHandler.readLocal(
          closureInfo.getLocalForField(_localsMap, field),
        ),
      );
    });

    AbstractValue type = _abstractValueDomain.createNonNullExact(
      closureClassEntity,
    );
    // TODO(efortuna): Add source information here.
    push(
      HCreate(
        closureClassEntity,
        capturedVariables,
        type,
        sourceInformation,
        callMethod: closureInfo.callMethod,
      ),
    );
  }

  @override
  void visitFunctionDeclaration(ir.FunctionDeclaration node) {
    assert(_isReachable);
    node.function.accept(this);
    Local local = _localsMap.getLocalVariable(node.variable);
    localsHandler.updateLocal(local, pop());
  }

  @override
  void visitFunctionExpression(ir.FunctionExpression node) {
    node.function.accept(this);
  }

  @override
  void visitInstantiation(ir.Instantiation node) {
    List<HInstruction> arguments = [];
    node.expression.accept(this);
    arguments.add(pop());

    // A generic function instantiation is created by calling a helper function
    // which takes the arguments.
    int typeArgumentCount = node.typeArguments.length;
    FunctionEntity target = _commonElements.getInstantiateFunction(
      typeArgumentCount,
    );

    final expressionType = _getStaticType(node.expression);
    final functionType = expressionType.withoutNullability as FunctionType;
    bool typeArgumentsNeeded = _rtiNeed.methodNeedsTypeArguments(target);

    List<DartType> typeArguments =
        node.typeArguments
            .map(
              (type) =>
                  typeArgumentsNeeded
                      ? _elementMap.getDartType(type)
                      : _commonElements.dynamicType,
            )
            .toList();
    registry.registerGenericInstantiation(
      GenericInstantiation(functionType, typeArguments),
    );

    // TODO(sra): Add instantiations to SourceInformationBuilder.
    SourceInformation? sourceInformation;

    // TODO(47484): Allow callee to have different calling convention for type
    // arguments.
    if (typeArgumentsNeeded) {
      _addTypeArguments(arguments, typeArguments, sourceInformation);
    }

    bool targetCanThrow = false; // TODO(sra): Is this true?

    // TODO(sra): Use [_pushStaticInvocation] to allow inlining. We don't now
    // because inference can't tell that the call has no side-effects.
    HInstruction instruction = HInvokeStatic(
      target,
      arguments,
      _abstractValueDomain.functionType,
      <DartType>[],
      targetCanThrow: targetCanThrow,
    );
    instruction.sourceInformation = sourceInformation;
    instruction.sideEffects
      ..clearAllDependencies()
      ..clearAllSideEffects();

    push(instruction);
  }

  void _handleMethodInvocation(
    ir.Expression node,
    ir.Expression receiver,
    ir.Arguments arguments, {
    bool isImplicitCall = false,
  }) {
    receiver.accept(this);
    HInstruction receiverInstruction = pop();
    Selector selector = _elementMap.getSelector(node);
    List<DartType> typeArguments = [];
    selector = _fillDynamicTypeArguments(
      selector,
      arguments,
      typeArguments,
      isImplicitCall: isImplicitCall,
    );
    _pushDynamicInvocation(
      node,
      _getStaticType(receiver),
      _typeInferenceMap.receiverTypeOfInvocation(node, _abstractValueDomain),
      selector,
      [
        receiverInstruction,
        ..._visitArgumentsForDynamicTarget(selector, arguments, typeArguments),
      ],
      typeArguments,
      _sourceInformationBuilder.buildCall(receiver, node),
    );
  }

  @override
  void visitInstanceInvocation(ir.InstanceInvocation node) {
    _handleMethodInvocation(node, node.receiver, node.arguments);
  }

  @override
  void visitInstanceGetterInvocation(ir.InstanceGetterInvocation node) {
    _handleMethodInvocation(
      node,
      node.receiver,
      node.arguments,
      isImplicitCall: true,
    );
  }

  @override
  void visitDynamicInvocation(ir.DynamicInvocation node) {
    _handleMethodInvocation(node, node.receiver, node.arguments);
  }

  @override
  void visitFunctionInvocation(ir.FunctionInvocation node) {
    _handleMethodInvocation(node, node.receiver, node.arguments);
  }

  @override
  void visitLocalFunctionInvocation(ir.LocalFunctionInvocation node) {
    Local local = _localsMap.getLocalVariable(node.variable);
    stack.add(
      localsHandler.readLocal(
        local,
        sourceInformation: _sourceInformationBuilder.buildGet(node),
      ),
    );
    HInstruction receiverInstruction = pop();
    Selector selector = _elementMap.getSelector(node);
    List<DartType> typeArguments = [];
    selector = _fillDynamicTypeArguments(
      selector,
      node.arguments,
      typeArguments,
    );
    _pushDynamicInvocation(
      node,
      _elementMap.getDartType(node.variable.type),
      _typeInferenceMap.receiverTypeOfInvocation(node, _abstractValueDomain),
      selector,
      [
        receiverInstruction,
        ..._visitArgumentsForDynamicTarget(
          selector,
          node.arguments,
          typeArguments,
        ),
      ],
      typeArguments,
      _sourceInformationBuilder.buildCall(node, node),
    );
  }

  void _handleEquals(
    ir.Expression node,
    ir.Expression left,
    HInstruction leftInstruction,
    HInstruction rightInstruction,
  ) {
    _pushDynamicInvocation(
      node,
      _getStaticType(left),
      _typeInferenceMap.receiverTypeOfInvocation(node, _abstractValueDomain),
      Selectors.equals,
      [leftInstruction, rightInstruction],
      const <DartType>[],
      _sourceInformationBuilder.buildCall(left, node),
    );
  }

  @override
  void visitEqualsNull(ir.EqualsNull node) {
    node.expression.accept(this);
    HInstruction receiverInstruction = pop();
    _handleEquals(
      node,
      node.expression,
      receiverInstruction,
      graph.addConstantNull(closedWorld),
    );
  }

  @override
  void visitEqualsCall(ir.EqualsCall node) {
    node.left.accept(this);
    HInstruction leftInstruction = pop();
    node.right.accept(this);
    HInstruction rightInstruction = pop();
    return _handleEquals(node, node.left, leftInstruction, rightInstruction);
  }

  HInterceptor _interceptorFor(
    HInstruction intercepted,
    SourceInformation? sourceInformation,
  ) {
    HInterceptor interceptor = HInterceptor(
      intercepted,
      _abstractValueDomain.nonNullType,
    )..sourceInformation = sourceInformation;
    add(interceptor);
    return interceptor;
  }

  static ir.Class _containingClass(ir.TreeNode? node) {
    while (node != null) {
      if (node is ir.Class) return node;
      node = node.parent;
    }
    throw ArgumentError.value(node, 'node', 'No containing class found.');
  }

  HInstruction _buildInvokeSuper(
    Selector selector,
    ClassEntity containingClass,
    MemberEntity target,
    List<HInstruction> arguments,
    List<DartType> typeArguments,
    SourceInformation? sourceInformation,
  ) {
    HInstruction receiver = localsHandler.readThis(
      sourceInformation: sourceInformation,
    );

    List<HInstruction> inputs = [];
    bool isIntercepted = closedWorld.interceptorData.isInterceptedSelector(
      selector,
    );
    if (isIntercepted) {
      inputs.add(_interceptorFor(receiver, sourceInformation));
    }
    inputs.add(receiver);
    inputs.addAll(arguments);

    late final AbstractValue typeMask;
    if (selector.isGetter && target.isGetter ||
        !selector.isGetter && target is FunctionEntity) {
      typeMask = _typeInferenceMap.getReturnTypeOf(target as FunctionEntity);
    } else {
      typeMask = _abstractValueDomain.dynamicType;
    }
    HInstruction instruction = HInvokeSuper(
      target,
      containingClass,
      selector,
      inputs,
      isIntercepted,
      typeMask,
      typeArguments,
      sourceInformation,
      isSetter: selector.isSetter || selector.isIndexSet,
    );
    // TODO(natebiggs): Pass typeMask below and make non-nullable.
    instruction.sideEffects = _inferredData.getSideEffectsOfSelector(
      selector,
      null,
    );
    push(instruction);
    return instruction;
  }

  @override
  void visitSuperPropertyGet(ir.SuperPropertyGet node) {
    final sourceInformation = _sourceInformationBuilder.buildGet(node);
    final target = getEffectiveSuperTarget(node.interfaceTarget);
    MemberEntity member = _elementMap.getMember(target);
    if (member is FieldEntity) {
      FieldAnalysisData fieldData = _fieldAnalysis.getFieldData(member);
      if (fieldData.isEffectivelyConstant) {
        final value = fieldData.constantValue!;
        stack.add(
          graph.addConstant(
            value,
            closedWorld,
            sourceInformation: sourceInformation,
          ),
        );
        return;
      }
    }
    _buildInvokeSuper(
      _elementMap.getSelector(node),
      _elementMap.getClass(_containingClass(node)),
      member,
      const <HInstruction>[],
      const <DartType>[],
      sourceInformation,
    );
  }

  @override
  void visitSuperMethodInvocation(ir.SuperMethodInvocation node) {
    final sourceInformation = _sourceInformationBuilder.buildCall(node, node);
    final superTarget = getEffectiveSuperTarget(node.interfaceTarget);
    MemberEntity member = _elementMap.getMember(superTarget);
    List<DartType> typeArguments = _getStaticTypeArguments(
      member as FunctionEntity,
      node.arguments,
    );

    MemberDefinition targetDefinition = _elementMap.getMemberDefinition(member);
    final target = targetDefinition.node as ir.Procedure;
    List<HInstruction> arguments = _visitArgumentsForStaticTarget(
      target.function,
      member.parameterStructure,
      node.arguments,
      typeArguments,
      sourceInformation,
    );
    _buildInvokeSuper(
      _elementMap.getSelector(node),
      _elementMap.getClass(_containingClass(node)),
      member,
      arguments,
      typeArguments,
      sourceInformation,
    );
  }

  void _checkTypeBound(
    HInstruction typeInstruction,
    DartType bound,
    String variableName,
    String methodName,
  ) {
    HInstruction boundInstruction = _typeBuilder.analyzeTypeArgument(
      localsHandler.substInContext(bound),
      sourceElement,
    );

    HInstruction variableNameInstruction = graph.addConstantString(
      variableName,
      closedWorld,
    );
    HInstruction methodNameInstruction = graph.addConstantString(
      methodName,
      closedWorld,
    );
    FunctionEntity element = _commonElements.checkTypeBound;
    List<HInstruction> inputs = [
      typeInstruction,
      boundInstruction,
      variableNameInstruction,
      methodNameInstruction,
    ];
    HInstruction checkBound = HInvokeStatic(
      element,
      inputs,
      typeInstruction.instructionType,
      const <DartType>[],
    );
    add(checkBound);
  }

  @override
  void visitConstructorInvocation(ir.ConstructorInvocation node) {
    final sourceInformation = _sourceInformationBuilder.buildNew(node);
    ir.Constructor target = node.target;
    if (node.isConst) {
      ConstantValue constant = _elementMap.getConstantValue(node)!;
      stack.add(
        graph.addConstant(
          constant,
          closedWorld,
          sourceInformation: sourceInformation,
        ),
      );
      return;
    }

    ConstructorEntity constructor = _elementMap.getConstructor(target);
    ClassEntity cls = constructor.enclosingClass;
    AbstractValue typeMask = _abstractValueDomain.createNonNullExact(cls);
    InterfaceType instanceType = _elementMap.createInterfaceType(
      target.enclosingClass,
      node.arguments.types,
    );
    instanceType = localsHandler.substInContext(instanceType) as InterfaceType;

    if (_nativeData.isJsInteropMember(constructor)) {
      List<HInstruction?> arguments = [];

      List<DartType> typeArguments = _getConstructorTypeArguments(
        constructor,
        node.arguments,
      );
      arguments.addAll(
        _visitArgumentsForNativeStaticTarget(target.function, node.arguments),
      );
      // TODO(johnniwinther): Remove this when type arguments are passed to
      // constructors like calling a generic method.
      _addTypeArguments(
        arguments,
        _getClassTypeArguments(cls, node.arguments),
        sourceInformation,
      );
      _addImplicitInstantiation(instanceType);
      _pushStaticNativeInvocation(
        constructor,
        arguments,
        typeMask,
        typeArguments,
        sourceInformation: sourceInformation,
      );
      _removeImplicitInstantiation(instanceType);
    } else {
      List<HInstruction> arguments = [];

      if (constructor.isGenerativeConstructor &&
          _nativeData.isNativeOrExtendsNative(constructor.enclosingClass)) {
        // Native class generative constructors take a pre-constructed object.
        arguments.add(graph.addConstantNull(closedWorld));
      }
      List<DartType> typeArguments = _getConstructorTypeArguments(
        constructor,
        node.arguments,
      );

      arguments.addAll(
        _visitArgumentsForStaticTarget(
          target.function,
          constructor.parameterStructure,
          node.arguments,
          typeArguments,
          sourceInformation,
        ),
      );
      // TODO(johnniwinther): Remove this when type arguments are passed to
      // constructors like calling a generic method.
      _addTypeArguments(
        arguments,
        _getClassTypeArguments(cls, node.arguments),
        sourceInformation,
      );
      _addImplicitInstantiation(instanceType);
      _pushStaticInvocation(
        constructor,
        arguments,
        typeMask,
        typeArguments,
        sourceInformation: sourceInformation,
        instanceType: instanceType,
      );
      _removeImplicitInstantiation(instanceType);
    }
  }

  @override
  void visitIsExpression(ir.IsExpression node) {
    node.operand.accept(this);
    HInstruction expression = pop();
    _pushIsTest(
      _widenCheckedTypeForOperand(node.type, node.operand),
      expression,
      _sourceInformationBuilder.buildIs(node),
    );
  }

  /// Returns a type that is equivalent to `checkedType`, but possibly simpler.
  /// For example, if operand has static type `Iterable<E>` and checkedType is
  /// `List<E>`, returns `List<dynamic>` since that is an easier test that does
  /// not reference any type variables.
  ir.DartType _widenCheckedTypeForOperand(
    ir.DartType checkedType,
    ir.Expression operand,
  ) {
    if (checkedType is ir.InterfaceType) {
      if (checkedType.typeArguments.isEmpty) return checkedType;
      final operandType = operand.getStaticType(
        _currentFrame!.staticTypeContext!,
      );
      final sufficiency = closedWorld.elementMap.typeEnvironment
          .computeTypeShapeCheckSufficiency(
            expressionStaticType: operandType,
            // Add `?` in case operand is nullable:
            checkTargetType: checkedType.withDeclaredNullability(
              ir.Nullability.nullable,
            ),
            subtypeCheckMode: ir.SubtypeCheckMode.withNullabilities,
          );

      // If `true` the caller only needs to check nullabillity and the actual
      // concrete class, no need to check [testedAgainstType] arguments.
      if (sufficiency == ir.TypeShapeCheckSufficiency.interfaceShape) {
        return ir.InterfaceType(
          checkedType.classNode,
          (operandType is ir.InterfaceType &&
                  operandType.nullability == ir.Nullability.nonNullable)
              ? ir.Nullability.nonNullable
              : checkedType.nullability,
          [
            for (final parameter in checkedType.classNode.typeParameters)
              parameter.defaultType,
          ],
        );
      }
    }
    return checkedType;
  }

  void _pushIsTest(
    ir.DartType type,
    HInstruction expression,
    SourceInformation? sourceInformation,
  ) {
    if (type is ir.InvalidType) {
      // TODO(sra): Make InvalidType carry a message.
      _generateTypeError('invalid type', sourceInformation);
      pop();
      stack.add(graph.addConstantBool(true, closedWorld));
      return;
    }

    DartType typeValue = localsHandler.substInContext(
      _elementMap.getDartType(type),
    );

    HInstruction rti = _typeBuilder.analyzeTypeArgument(
      typeValue,
      sourceElement,
    );
    AbstractValueWithPrecision checkedType = _abstractValueDomain
        .createFromStaticType(typeValue, nullable: false);

    push(
      HIsTest(
        typeValue,
        checkedType,
        rti,
        expression,
        _abstractValueDomain.boolType,
      )..sourceInformation = sourceInformation,
    );
  }

  @override
  void visitThrow(ir.Throw node) {
    _visitThrowExpression(node.expression);
    if (_isReachable) {
      final sourceInformation = _sourceInformationBuilder.buildThrow(node);
      _handleInTryStatement();
      push(
        HThrowExpression(
          pop(),
          _abstractValueDomain.emptyType,
          sourceInformation,
          withoutHelperFrame: closedWorld.annotationsData
              .throwWithoutHelperFrame(node),
        ),
      );
      _isReachable = false;
    }
  }

  void _visitThrowExpression(ir.Expression expression) {
    bool old = _inExpressionOfThrow;
    try {
      _inExpressionOfThrow = true;
      expression.accept(this);
    } finally {
      _inExpressionOfThrow = old;
    }
  }

  @override
  void visitYieldStatement(ir.YieldStatement node) {
    node.expression.accept(this);
    add(
      HYield(
        pop(),
        node.isYieldStar,
        _abstractValueDomain.emptyType,
        _sourceInformationBuilder.buildYield(node),
      ),
    );
  }

  @override
  void visitAwaitExpression(ir.AwaitExpression node) {
    node.operand.accept(this);
    HInstruction awaited = pop();
    // TODO(herhut): Improve this type.
    push(
      HAwait(awaited, _abstractValueDomain.dynamicType)
        ..sourceInformation = _sourceInformationBuilder.buildAwait(node),
    );
  }

  @override
  void visitRethrow(ir.Rethrow node) {
    HInstruction? exception = _rethrowableException;
    if (exception == null) {
      exception = graph.addConstantNull(closedWorld);
      reporter.internalError(
        _elementMap.getSpannable(targetElement, node),
        'rethrowableException should not be null.',
      );
    }
    _handleInTryStatement();
    final sourceInformation = _sourceInformationBuilder.buildThrow(node);
    _closeAndGotoExit(HThrow(exception, sourceInformation, isRethrow: true));
    // ir.Rethrow is an expression so we need to push a value - a constant with
    // no type.
    stack.add(graph.addConstantUnreachable(closedWorld));
  }

  @override
  void visitThisExpression(ir.ThisExpression node) {
    stack.add(
      localsHandler.readThis(
        sourceInformation: _sourceInformationBuilder.buildGet(node),
      ),
    );
  }

  @override
  void visitNot(ir.Not node) {
    node.operand.accept(this);
    push(
      HNot(popBoolified(), _abstractValueDomain.boolType)
        ..sourceInformation = _sourceInformationBuilder.buildUnary(node),
    );
  }

  @override
  void visitStringConcatenation(ir.StringConcatenation node) {
    KernelStringBuilder stringBuilder = KernelStringBuilder(this);
    node.accept(stringBuilder);
    stack.add(stringBuilder.result!);
  }

  @override
  void visitTryCatch(ir.TryCatch node) {
    TryCatchFinallyBuilder tryBuilder = TryCatchFinallyBuilder(
      this,
      _sourceInformationBuilder.buildTry(node),
    );
    node.body.accept(this);
    tryBuilder
      ..closeTryBody()
      ..buildCatch(node)
      ..cleanUp();
  }

  /// `try { ... } catch { ... } finally { ... }` statements are a little funny
  /// because a try can have one or both of {catch|finally}. The way this is
  /// encoded in kernel AST are two separate classes with no common superclass
  /// aside from Statement. If a statement has both `catch` and `finally`
  /// clauses then it is encoded in kernel as so that the TryCatch is the body
  /// statement of the TryFinally. To produce more efficient code rather than
  /// nested try statements, the visitors avoid one potential level of
  /// recursion.
  @override
  void visitTryFinally(ir.TryFinally node) {
    TryCatchFinallyBuilder tryBuilder = TryCatchFinallyBuilder(
      this,
      _sourceInformationBuilder.buildTry(node),
    );

    // We do these shenanigans to produce better looking code that doesn't
    // have nested try statements.
    final nodeBody = node.body;
    if (nodeBody is ir.TryCatch) {
      nodeBody.body.accept(this);
      tryBuilder
        ..closeTryBody()
        ..buildCatch(nodeBody);
    } else {
      node.body.accept(this);
      tryBuilder.closeTryBody();
    }

    tryBuilder
      ..buildFinallyBlock(() {
        node.finalizer.accept(this);
      })
      ..cleanUp();
  }

  @override
  void visitFileUriExpression(ir.FileUriExpression node) {
    node.expression.accept(this);
  }

  bool _tryInlineMethod(
    FunctionEntity function,
    Selector? selector,
    AbstractValue? mask,
    List<HInstruction> providedArguments,
    List<DartType>? typeArguments,
    ir.Node? currentNode,
    SourceInformation? sourceInformation, {
    InterfaceType? instanceType,
  }) {
    final inlined = _doTryInlineMethod(
      function,
      selector,
      mask,
      providedArguments,
      typeArguments,
      currentNode,
      sourceInformation,
      instanceType: instanceType,
    );
    if (inlined) {
      _metrics.countMethodInlined.add();
    } else {
      _metrics.countMethodNotInlined.add();
    }
    return inlined;
  }

  /// Try to inline [element] within the correct context of the builder. The
  /// insertion point is the state of the builder.
  bool _doTryInlineMethod(
    FunctionEntity function,
    Selector? selector,
    AbstractValue? mask,
    List<HInstruction> providedArguments,
    List<DartType>? typeArguments,
    ir.Node? currentNode,
    SourceInformation? sourceInformation, {
    InterfaceType? instanceType,
  }) {
    if (function.isExternal) {
      // Don't inline external methods; these should just fail at runtime.
      return false;
    }

    if (_nativeData.isJsInteropMember(function) &&
        !(function is ConstructorEntity && function.isFactoryConstructor)) {
      // We only inline factory JavaScript interop constructors.
      return false;
    }

    // Check if inlining is disabled for the current element (includes globally)
    // before making decisions on the basis of the callee so that cached callee
    // decisions are not a function of the call site's method.
    if (closedWorld.annotationsData.hasDisableInlining(_currentFrame!.member)) {
      return false;
    }

    bool insideLoop = loopDepth > 0 || graph.calledInLoop;

    // Bail out early if the inlining decision is in the cache and we can't
    // inline (no need to check the hard constraints).
    if (_inlineCache.markedAsNoInline(function)) return false;
    final cachedCanBeInlined = _inlineCache.canInline(
      function,
      insideLoop: insideLoop,
    );
    if (cachedCanBeInlined == false) return false;

    bool meetsHardConstraints() {
      assert(
        selector != null ||
            function.isStatic ||
            function.isTopLevel ||
            function is ConstructorEntity ||
            function is ConstructorBodyEntity,
        failedAt(function, "Missing selector for inlining of $function."),
      );
      if (selector != null) {
        if (!selector.applies(function)) return false;
        if (mask != null &&
            _abstractValueDomain
                .isTargetingMember(mask, function, selector.memberName)
                .isDefinitelyFalse) {
          return false;
        }
      }

      if (_nativeData.isJsInteropMember(function)) return false;

      // Don't inline operator== methods if the parameter can be null.
      if (function.name == '==') {
        if (providedArguments[1]
            .isNull(_abstractValueDomain)
            .isPotentiallyTrue) {
          return false;
        }
      }

      // Generative constructors of native classes should not be called directly
      // and have an extra argument that causes problems with inlining.
      if (function is ConstructorEntity &&
          function.isGenerativeConstructor &&
          _nativeData.isNativeOrExtendsNative(function.enclosingClass)) {
        return false;
      }

      // A generative constructor body is not seen by global analysis,
      // so we should not query for its type.
      if (function is! ConstructorBodyEntity) {
        if (globalInferenceResults.resultOfMember(function).throwsAlways) {
          // TODO(johnniwinther): It seems wrong to set `isReachable` to `false`
          // since we are _not_ going to inline [function]. This has
          // implications in switch cases where we might need to insert a
          // `break` that was skipped due to `isReachable` being `false`.
          _isReachable = false;
          return false;
        }
      }

      // Record getters are synthetic and have no bodies so we cannot inline
      // them at this point.
      if (function is JRecordGetter) return false;

      return true;
    }

    bool doesNotContainCode(InlineData inlineData) {
      // A function with size 1 does not contain any code.
      return inlineData.canBeInlined(maxInliningNodes: 1);
    }

    bool reductiveHeuristic(InlineData inlineData) {
      // The call is on a path which is executed rarely, so inline only if it
      // does not make the program larger.
      if (_isCalledOnce(function)) {
        return inlineData.canBeInlined();
      }
      if (inlineData.canBeInlinedReductive(
        argumentCount: providedArguments.length,
      )) {
        return true;
      }
      return doesNotContainCode(inlineData);
    }

    bool heuristicSayGoodToGo() {
      // Don't inline recursively,
      if (_inliningStack.any((entry) => entry.function == function)) {
        return false;
      }

      // Don't inline across deferred import to prevent leaking code. The only
      // exception is an empty function (which does not contain code).
      bool hasOnlyNonDeferredImportPaths = closedWorld.outputUnitData
          .hasOnlyNonDeferredImportPaths(_initialTargetElement, function);

      InlineData inlineData = _inlineDataCache.getInlineData(
        _elementMap,
        function,
      );

      if (!hasOnlyNonDeferredImportPaths) {
        return doesNotContainCode(inlineData);
      }

      // Do not inline code that is rarely executed unless it reduces size.
      if (_inExpressionOfThrow || graph.isLazyInitializer) {
        return reductiveHeuristic(inlineData);
      }

      if (cachedCanBeInlined == true) {
        // We may have forced the inlining of some methods. Therefore check
        // if we can inline this method regardless of size.
        String? reason;
        assert(
          (reason = inlineData.cannotBeInlinedReason(allowLoops: true)) == null,
          failedAt(function, "Cannot inline $function: $reason"),
        );
        return true;
      }

      int numParameters = function.parameterStructure.totalParameters;
      int? maxInliningNodes;
      if (insideLoop) {
        maxInliningNodes =
            InlineWeeder.inliningNodesInsideLoop +
            InlineWeeder.inliningNodesInsideLoopArgFactor * numParameters;
      } else {
        maxInliningNodes =
            InlineWeeder.inliningNodesOutsideLoop +
            InlineWeeder.inliningNodesOutsideLoopArgFactor * numParameters;
      }

      bool markedTryInline = _inlineCache.markedAsTryInline(function);
      bool calledOnce = _isCalledOnce(function);
      // If a method is called only once, and all the methods in the inlining
      // stack are called only once as well, we know we will save on output size
      // by inlining this method.
      if (markedTryInline || calledOnce) {
        maxInliningNodes = null;
      }
      bool allowLoops = false;
      if (markedTryInline) {
        allowLoops = true;
      }

      bool canInline = inlineData.canBeInlined(
        maxInliningNodes: maxInliningNodes,
        allowLoops: allowLoops,
      );
      if (markedTryInline) {
        if (canInline) {
          _inlineCache.markAsInlinable(function, insideLoop: true);
          _inlineCache.markAsInlinable(function, insideLoop: false);
        } else {
          _inlineCache.markAsNonInlinable(function, insideLoop: true);
          _inlineCache.markAsNonInlinable(function, insideLoop: false);
        }
      } else if (calledOnce) {
        // TODO(34203): We can't update the decision due to imprecision in the
        // calledOnce data, described in Issue 34203.
      } else {
        if (canInline) {
          _inlineCache.markAsInlinable(function, insideLoop: insideLoop);
        } else {
          if (_isFunctionCalledOnce(function)) {
            // TODO(34203): We can't update the decision due to imprecision in
            // the calledOnce data, described in Issue 34203.
          } else {
            _inlineCache.markAsNonInlinable(function, insideLoop: insideLoop);
          }
        }
      }
      return canInline;
    }

    void doInlining() {
      if (function is ConstructorEntity) {
        registry.registerStaticUse(
          StaticUse.constructorInlining(function, instanceType),
        );
      } else {
        assert(
          instanceType == null,
          "Unexpected instance type for $function: $instanceType",
        );
        registry.registerStaticUse(
          StaticUse.methodInlining(function, typeArguments),
        );
      }

      // Add an explicit null check on the receiver before doing the inlining.
      if (function.isInstanceMember &&
          function is! ConstructorBodyEntity &&
          (mask == null ||
              _abstractValueDomain.isNull(mask).isPotentiallyTrue)) {
        HNullCheck guard =
            HNullCheck(providedArguments[0], _abstractValueDomain.dynamicType)
              ..selector = selector
              ..sourceInformation = sourceInformation;
        add(guard);
        providedArguments[0] = guard;
      }
      List<HInstruction> compiledArguments = _completeCallArgumentsList(
        function,
        selector,
        providedArguments,
        currentNode,
      );
      _enterInlinedMethod(function, compiledArguments, instanceType);
      _inlinedFrom(function, sourceInformation, () {
        if (!_isReachable) {
          _emitReturn(
            graph.addConstantUnreachable(closedWorld),
            sourceInformation,
          );
        } else {
          _doInline(function);
        }
      });
      _leaveInlinedMethod();
    }

    if (meetsHardConstraints() && heuristicSayGoodToGo()) {
      doInlining();
      _infoReporter?.reportInlined(
        function,
        _inliningStack.isEmpty ? targetElement : _inliningStack.last.function,
      );
      return true;
    }

    return false;
  }

  /// Returns a complete argument list for a call of [function].
  List<HInstruction> _completeCallArgumentsList(
    FunctionEntity function,
    Selector? selector,
    List<HInstruction> providedArguments,
    ir.Node? currentNode,
  ) {
    bool isInstanceMember = function.isInstanceMember;
    // For static calls, [providedArguments] is complete, default arguments
    // have been included if necessary, see [makeStaticArgumentList].
    if (!isInstanceMember ||
        currentNode == null || // In erroneous code, currentNode can be null.
        _providedArgumentsKnownToBeComplete(currentNode) ||
        function is ConstructorBodyEntity ||
        selector!.isGetter) {
      // For these cases, the provided argument list is known to be complete.
      return providedArguments;
    } else {
      return _completeDynamicCallArgumentsList(
        selector,
        function,
        providedArguments,
      );
    }
  }

  /// Returns a complete argument list for a dynamic call of [function]. The
  /// initial argument list [providedArguments], created by
  /// [addDynamicSendArgumentsToList], does not include values for default
  /// arguments used in the call. The reason is that the target function (which
  /// defines the defaults) is not known.
  ///
  /// However, inlining can only be performed when the target function can be
  /// resolved statically. The defaults can therefore be included at this point.
  ///
  /// The [providedArguments] list contains first all positional arguments, then
  /// the provided named arguments (the named arguments that are defined in the
  /// [selector]) in a specific order (see [addDynamicSendArgumentsToList]).
  List<HInstruction> _completeDynamicCallArgumentsList(
    Selector selector,
    FunctionEntity function,
    List<HInstruction> providedArguments,
  ) {
    assert(selector.applies(function));
    CallStructure callStructure = selector.callStructure;
    ParameterStructure parameterStructure = function.parameterStructure;
    List<String> selectorArgumentNames =
        selector.callStructure.getOrderedNamedArguments();
    bool methodNeedsTypeArguments = _rtiNeed.methodNeedsTypeArguments(function);
    List<HInstruction> compiledArguments = [];

    // Copy receiver.
    compiledArguments.add(providedArguments[0]);

    /// Offset of positional arguments in [providedArguments].
    int positionalArgumentOffset = 1;

    /// Offset of named arguments in [providedArguments].
    int namedArgumentOffset = callStructure.positionalArgumentCount + 1;

    int positionalArgumentIndex = 0;
    int namedArgumentIndex = 0;

    _elementEnvironment.forEachParameter(function, (
      DartType type,
      String? name,
      ConstantValue? defaultValue,
    ) {
      if (positionalArgumentIndex < parameterStructure.positionalParameters) {
        if (positionalArgumentIndex < callStructure.positionalArgumentCount) {
          compiledArguments.add(
            providedArguments[positionalArgumentOffset +
                positionalArgumentIndex++],
          );
        } else {
          assert(
            defaultValue != null,
            failedAt(function, 'No constant computed for parameter $name'),
          );
          compiledArguments.add(graph.addConstant(defaultValue!, closedWorld));
        }
      } else {
        // Example:
        //     void foo(a, {b, d, c})
        //     foo(0, d = 1, b = 2)
        //
        // providedArguments = [0, 2, 1]
        // selectorArgumentNames = [b, d]
        // parameterStructure.namedParameters = [b, c, d]
        //
        // For each parameter name in the signature, if the argument name
        // matches we use the next provided argument, otherwise we get the
        // default.
        if (namedArgumentIndex < selectorArgumentNames.length &&
            name == selectorArgumentNames[namedArgumentIndex]) {
          // The named argument was provided in the function invocation.
          compiledArguments.add(
            providedArguments[namedArgumentOffset + namedArgumentIndex++],
          );
        } else {
          assert(
            defaultValue != null,
            failedAt(function, 'No constant computed for parameter $name'),
          );
          compiledArguments.add(graph.addConstant(defaultValue!, closedWorld));
        }
      }
    });
    if (methodNeedsTypeArguments) {
      if (callStructure.typeArgumentCount ==
          parameterStructure.typeParameters) {
        /// Offset of type arguments in [providedArguments].
        int typeArgumentOffset = callStructure.argumentCount + 1;
        // Pass explicit type arguments.
        for (
          int typeArgumentIndex = 0;
          typeArgumentIndex < callStructure.typeArgumentCount;
          typeArgumentIndex++
        ) {
          compiledArguments.add(
            providedArguments[typeArgumentOffset + typeArgumentIndex],
          );
        }
      } else {
        assert(callStructure.typeArgumentCount == 0);
        // Pass type variable bounds as type arguments.
        for (TypeVariableType typeVariable in _elementEnvironment
            .getFunctionTypeVariables(function)) {
          compiledArguments.add(
            _computeTypeArgumentDefaultValue(function, typeVariable),
          );
        }
      }
    }
    return compiledArguments;
  }

  HInstruction _computeTypeArgumentDefaultValue(
    FunctionEntity function,
    TypeVariableType typeVariable,
  ) {
    DartType bound = _elementEnvironment.getTypeVariableDefaultType(
      typeVariable.element,
    );
    return _typeBuilder.analyzeTypeArgument(bound, function);
  }

  /// This method is invoked before inlining the body of [function] into this
  /// [SsaGraphBuilder].
  void _enterInlinedMethod(
    FunctionEntity function,
    List<HInstruction> compiledArguments,
    InterfaceType? instanceType,
  ) {
    KernelInliningState state = KernelInliningState(
      function,
      _returnLocal,
      _returnType,
      stack,
      localsHandler,
      _inTryStatement,
      _isCalledOnce(function),
    );
    _inliningStack.add(state);

    // Setting up the state of the (AST) builder is performed even when the
    // inlined function is in IR, because the irInliner uses the [returnElement]
    // of the AST builder.
    _setupStateForInlining(function, compiledArguments, instanceType);
  }

  /// This method sets up the local state of the builder for inlining
  /// [function]. The arguments of the function are inserted into the
  /// [localsHandler].
  ///
  /// When inlining a function, `return` statements are not emitted as
  /// [HReturn] instructions. Instead, the value of a synthetic element is
  /// updated in the [localsHandler]. This function creates such an element and
  /// stores it in the [_returnLocal] field.
  void _setupStateForInlining(
    FunctionEntity function,
    List<HInstruction> compiledArguments,
    InterfaceType? instanceType,
  ) {
    localsHandler = LocalsHandler(
      this,
      function,
      function,
      instanceType ?? _elementMap.getMemberThisType(function),
      _nativeData,
      _interceptorData,
    );
    localsHandler.setupScope(function);

    CapturedScope scopeData = _closureDataLookup.getCapturedScope(function);
    bool forGenerativeConstructorBody = function is ConstructorBodyEntity;

    _returnLocal = SyntheticLocal("result", function, function);
    localsHandler.updateLocal(
      _returnLocal!,
      graph.addConstantNull(closedWorld),
    );

    _inTryStatement = false; // TODO(lry): why? Document.

    int argumentIndex = 0;
    if (function.isInstanceMember) {
      localsHandler.updateLocal(
        localsHandler.thisLocal!,
        compiledArguments[argumentIndex++],
      );
    }

    KernelToLocalsMap localsMap = _globalLocalsMap.getLocalsMap(function);
    forEachOrderedParameter(_elementMap, function, (
      ir.VariableDeclaration variable, {
      required bool isElided,
    }) {
      Local local = localsMap.getLocalVariable(variable);
      if (isElided) {
        localsHandler.updateLocal(local, _defaultValueForParameter(variable));
        return;
      }
      if (forGenerativeConstructorBody &&
          scopeData.isBoxedVariable(_localsMap, local)) {
        // The parameter will be a field in the box passed as the last
        // parameter. So no need to have it.
        return;
      }
      HInstruction argument = compiledArguments[argumentIndex++];
      localsHandler.updateLocal(local, argument);
    });

    bool hasTypeParameters = function.parameterStructure.typeParameters > 0;
    bool needsTypeArguments = _rtiNeed.methodNeedsTypeArguments(function);
    for (TypeVariableType typeVariable in _elementEnvironment
        .getFunctionTypeVariables(function)) {
      HInstruction argument;
      if (hasTypeParameters && needsTypeArguments) {
        argument = compiledArguments[argumentIndex++];
      } else {
        argument = _computeTypeArgumentDefaultValue(function, typeVariable);
      }
      localsHandler.updateLocal(
        localsHandler.getTypeVariableAsLocal(typeVariable),
        argument,
      );
    }

    if (forGenerativeConstructorBody && scopeData.requiresContextBox) {
      HInstruction box = compiledArguments[argumentIndex++];
      assert(box is HCreateBox);
      // TODO(sra): Make inlining of closures work. We should always call
      // enterScope, and pass in the inlined 'this' as well as the 'box'.
      localsHandler.enterScope(
        scopeData,
        null,
        inlinedBox: box,
        forGenerativeConstructorBody: forGenerativeConstructorBody,
      );
    }

    final enclosing = function.enclosingClass;
    if ((function is ConstructorEntity || function is ConstructorBodyEntity) &&
        _rtiNeed.classNeedsTypeArguments(enclosing!)) {
      InterfaceType thisType = _elementEnvironment.getThisType(enclosing);
      for (var (typeVariable as TypeVariableType) in thisType.typeArguments) {
        HInstruction argument = compiledArguments[argumentIndex++];
        localsHandler.updateLocal(
          localsHandler.getTypeVariableAsLocal(typeVariable),
          argument,
        );
      }
    }

    assert(
      argumentIndex == compiledArguments.length ||
          !_rtiNeed.methodNeedsTypeArguments(function) &&
              compiledArguments.length - argumentIndex ==
                  function.parameterStructure.typeParameters,
      failedAt(
        function,
        "Only $argumentIndex of ${compiledArguments.length} "
        "arguments have been read from: $compiledArguments passed to "
        "$function.",
      ),
    );

    _returnType = _elementEnvironment.getFunctionType(function).returnType;
    stack = <HInstruction>[];

    _insertCoverageCall(function);
  }

  void _leaveInlinedMethod() {
    HInstruction result = localsHandler.readLocal(_returnLocal!);
    KernelInliningState state = _inliningStack.removeLast();
    _restoreState(state);
    stack.add(result);
  }

  void _restoreState(KernelInliningState state) {
    localsHandler = state.oldLocalsHandler;
    _returnLocal = state.oldReturnLocal;
    _inTryStatement = state.inTryStatement;
    _returnType = state.oldReturnType;
    assert(stack.isEmpty);
    stack = state.oldStack;
  }

  bool _providedArgumentsKnownToBeComplete(ir.Node currentNode) {
    /* When inlining the iterator methods generated for a for-in loop, the
     * [currentNode] is the [ForIn] tree. The compiler-generated iterator
     * invocations are known to have fully specified argument lists, no default
     * arguments are used. See invocations of [pushInvokeDynamic] in
     * [visitForIn].
     */
    // TODO(redemption): Is this valid here?
    return currentNode is ir.ForInStatement;
  }

  void _emitReturn(HInstruction? value, SourceInformation? sourceInformation) {
    if (_inliningStack.isEmpty) {
      _closeAndGotoExit(HReturn(value, sourceInformation));
    } else {
      value ??= graph.addConstantNull(closedWorld);
      localsHandler.updateLocal(_returnLocal!, value);
    }
  }

  void _doInline(FunctionEntity function) {
    _visitInlinedFunction(function);
  }

  /// Run this builder on the body of the [function] to be inlined.
  void _visitInlinedFunction(FunctionEntity function) {
    _potentiallyCheckInlinedParameterTypes(function);

    MemberDefinition definition = _elementMap.getMemberDefinition(function);
    switch (definition.kind) {
      case MemberKind.constructor:
        _buildConstructor(
          function as ConstructorEntity,
          definition.node as ir.Constructor,
        );
        return;
      case MemberKind.constructorBody:
        final constructor = definition.node as ir.Constructor;
        constructor.function.body!.accept(this);
        return;
      case MemberKind.regular:
        ir.Node node = definition.node;
        if (node is ir.Constructor) {
          node.function.body!.accept(this);
          return;
        } else if (node is ir.Procedure) {
          node.function.body!.accept(this);
          return;
        }
        break;
      case MemberKind.closureCall:
        final node = definition.node as ir.LocalFunction;
        node.function.body!.accept(this);
        return;
      case MemberKind.closureField:
      case MemberKind.generatorBody:
      case MemberKind.recordGetter:
      case MemberKind.signature:
      case MemberKind.parameterStub:
    }
    failedAt(function, "Unexpected inlined function: $definition");
  }

  /// Generates type tests for the parameters of the inlined function.
  void _potentiallyCheckInlinedParameterTypes(FunctionEntity function) {
    // TODO(sra): Incorporate properties of call site to help determine which
    // type parameters and value parameters need to be checked.
    bool trusted = false;
    if (function.isStatic ||
        function.isTopLevel ||
        function is ConstructorEntity ||
        function is ConstructorBodyEntity) {
      // We inline static methods, top-level methods, constructors and
      // constructor bodies only from direct call sites.
      trusted = true;
    }

    if (!trusted) {
      _checkTypeVariableBounds(function);
    }

    KernelToLocalsMap localsMap = _globalLocalsMap.getLocalsMap(function);
    forEachOrderedParameter(_elementMap, function, (
      ir.VariableDeclaration variable, {
      required bool isElided,
    }) {
      Local parameter = localsMap.getLocalVariable(variable);
      HInstruction argument = localsHandler.readLocal(parameter);
      DartType type = localsMap.getLocalType(_elementMap, parameter);
      HInstruction checkedOrTrusted;
      if (trusted) {
        checkedOrTrusted = _typeBuilder.trustTypeOfParameter(
          function,
          argument,
          type,
        );
      } else {
        checkedOrTrusted = _typeBuilder.potentiallyCheckOrTrustTypeOfParameter(
          function,
          argument,
          type,
        );
      }
      checkedOrTrusted = _potentiallyAssertNotNull(
        function,
        variable,
        checkedOrTrusted,
        type,
      );
      localsHandler.updateLocal(parameter, checkedOrTrusted);
    });
  }

  bool get _allInlinedFunctionsCalledOnce {
    return _inliningStack.isEmpty || _inliningStack.last.allFunctionsCalledOnce;
  }

  bool _isFunctionCalledOnce(FunctionEntity element) {
    // ConstructorBodyElements are not in the type inference graph.
    if (element is ConstructorBodyEntity) {
      // If there are no subclasses with constructors that have this constructor
      // as a superconstructor, it is called once by the generative
      // constructor's factory.  A simplified version is to check this is a
      // constructor body for a leaf class.
      ClassEntity class_ = element.enclosingClass!;
      if (closedWorld.classHierarchy.isDirectlyInstantiated(class_)) {
        return !closedWorld.classHierarchy.isIndirectlyInstantiated(class_);
      }
      return false;
    }
    return globalInferenceResults.resultOfMember(element).isCalledOnce;
  }

  bool _isCalledOnce(FunctionEntity element) {
    return _allInlinedFunctionsCalledOnce && _isFunctionCalledOnce(element);
  }

  void _insertCoverageCall(MemberEntity element) {
    if (!options.experimentCallInstrumentation) return;
    if (element == _commonElements.traceHelper) return;
    // TODO(sigmund): create a better uuid for elements.
    HConstant idConstant = graph.addConstantInt(element.hashCode, closedWorld);
    String? n(Entity? e) => e == null ? '' : e.name;
    String name =
        "${n(element.library)}:${n(element.enclosingClass)}."
        "${n(element)}";
    HConstant nameConstant = graph.addConstantString(name, closedWorld);
    add(
      HInvokeStatic(
        _commonElements.traceHelper,
        [idConstant, nameConstant],
        _abstractValueDomain.dynamicType,
        const <DartType>[],
      ),
    );
  }
}

/// Data collected to create a constructor.
class ConstructorData {
  /// Inlined (super) constructors.
  final List<ir.Constructor> constructorChain = [];

  /// Initial values for all instance fields.
  final Map<FieldEntity, HInstruction> fieldValues = {};

  /// Classes for which type variables have been prepared.
  final Set<ClassEntity> includedClasses = {};
}

class KernelInliningState {
  final FunctionEntity function;
  final Local? oldReturnLocal;
  final DartType? oldReturnType;
  final List<HInstruction> oldStack;
  final LocalsHandler oldLocalsHandler;
  final bool inTryStatement;
  final bool allFunctionsCalledOnce;

  KernelInliningState(
    this.function,
    this.oldReturnLocal,
    this.oldReturnType,
    this.oldStack,
    this.oldLocalsHandler,
    this.inTryStatement,
    this.allFunctionsCalledOnce,
  );

  @override
  String toString() =>
      'KernelInliningState($function,'
      'allFunctionsCalledOnce=$allFunctionsCalledOnce)';
}

/// Class in charge of building try, catch and/or finally blocks. This handles
/// the instructions that need to be output and the dominator calculation of
/// this sequence of code.
class TryCatchFinallyBuilder {
  final KernelSsaGraphBuilder kernelBuilder;
  final SourceInformation? trySourceInformation;

  late final HBasicBlock enterBlock;
  late final HBasicBlock startTryBlock;
  HBasicBlock? endTryBlock;
  HBasicBlock? startCatchBlock;
  HBasicBlock? endCatchBlock;
  HBasicBlock? startFinallyBlock;
  HBasicBlock? endFinallyBlock;
  HBasicBlock? exitBlock;
  late final HTry tryInstruction;
  HLocalValue? exception;

  /// True if the code surrounding this try statement was also part of a
  /// try/catch/finally statement.
  late final bool previouslyInTryStatement;

  SubGraph? bodyGraph;
  SubGraph? catchGraph;
  SubGraph? finallyGraph;

  // The original set of locals that were defined before this try block.
  // The catch block and the finally block must not reuse the existing locals
  // handler. None of the variables that have been defined in the body-block
  // will be used, but for loops we will add (unnecessary) phis that will
  // reference the body variables. This makes it look as if the variables were
  // used in a non-dominated block.
  LocalsHandler? originalSavedLocals;

  TryCatchFinallyBuilder(this.kernelBuilder, this.trySourceInformation) {
    tryInstruction = HTry();
    originalSavedLocals = LocalsHandler.from(kernelBuilder.localsHandler);
    enterBlock = kernelBuilder.openNewBlock();
    kernelBuilder.close(tryInstruction);
    previouslyInTryStatement = kernelBuilder._inTryStatement;
    kernelBuilder._inTryStatement = true;

    startTryBlock = kernelBuilder.graph.addNewBlock();
    kernelBuilder.open(startTryBlock);
  }

  void _addExitTrySuccessor(HBasicBlock? successor) {
    if (successor == null) return;
    // Iterate over all blocks created inside this try/catch, and
    // attach successor information to blocks that end with
    // [HExitTry].
    for (int i = startTryBlock.id; i < successor.id; i++) {
      HBasicBlock block = kernelBuilder.graph.blocks[i];
      var last = block.last;
      if (last is HExitTry) {
        block.addSuccessor(successor);
      }
    }
  }

  void _addOptionalSuccessor(HBasicBlock block1, HBasicBlock? block2) {
    if (block2 != null) block1.addSuccessor(block2);
  }

  /// Helper function to set up basic block successors for try-catch-finally
  /// sequences.
  void _setBlockSuccessors() {
    // Setup all successors. The entry block that contains the [HTry]
    // has 1) the body, 2) the catch, 3) the finally, and 4) the exit
    // blocks as successors.
    final exit = exitBlock!;
    enterBlock.addSuccessor(startTryBlock);
    _addOptionalSuccessor(enterBlock, startCatchBlock);
    _addOptionalSuccessor(enterBlock, startFinallyBlock);
    enterBlock.addSuccessor(exit);

    // The body has either the catch or the finally block as successor.
    final endTry = endTryBlock;
    if (endTry != null) {
      assert(startCatchBlock != null || startFinallyBlock != null);
      endTry.addSuccessor(startCatchBlock ?? startFinallyBlock!);
      endTry.addSuccessor(exit);
    }

    // The catch block has either the finally or the exit block as
    // successor.
    endCatchBlock?.addSuccessor(startFinallyBlock ?? exit);

    // The finally block has the exit block as successor.
    endFinallyBlock?.addSuccessor(exit);

    // If a block inside try/catch aborts (eg with a return statement),
    // we explicitly mark this block a predecessor of the catch
    // block and the finally block.
    _addExitTrySuccessor(startCatchBlock);
    _addExitTrySuccessor(startFinallyBlock);
  }

  /// Build the finally{} clause of a try/{catch}/finally statement. Note this
  /// does not examine the body of the try clause, only the finally portion.
  void buildFinallyBlock(void Function() buildFinalizer) {
    kernelBuilder.localsHandler = LocalsHandler.from(originalSavedLocals!);
    startFinallyBlock = kernelBuilder.graph.addNewBlock();
    kernelBuilder.open(startFinallyBlock!);
    buildFinalizer();
    if (!kernelBuilder.isAborted()) {
      endFinallyBlock = kernelBuilder.close(HGoto());
    }
    tryInstruction.finallyBlock = startFinallyBlock;
    finallyGraph = SubGraph(startFinallyBlock!, kernelBuilder.lastOpenedBlock);
  }

  void closeTryBody() {
    // We use a [HExitTry] instead of a [HGoto] for the try block
    // because it will have multiple successors: the join block, and
    // the catch or finally block.
    if (!kernelBuilder.isAborted()) {
      endTryBlock = kernelBuilder.close(HExitTry());
    }
    bodyGraph = SubGraph(startTryBlock, kernelBuilder.lastOpenedBlock);
  }

  void buildCatch(ir.TryCatch tryCatch) {
    kernelBuilder.localsHandler = LocalsHandler.from(originalSavedLocals!);
    startCatchBlock = kernelBuilder.graph.addNewBlock();
    kernelBuilder.open(startCatchBlock!);
    // Note that the name of this local is irrelevant.
    SyntheticLocal local = kernelBuilder.localsHandler.createLocal('exception');
    exception = HLocalValue(
      local,
      kernelBuilder._abstractValueDomain.nonNullType,
    )..sourceInformation = trySourceInformation;
    kernelBuilder.add(exception!);
    final oldRethrowableException = kernelBuilder._rethrowableException;
    kernelBuilder._rethrowableException = exception;

    AbstractValue unwrappedType = kernelBuilder._typeInferenceMap
        .getReturnTypeOf(kernelBuilder._commonElements.exceptionUnwrapper);
    // Global type analysis does not currently understand that strong mode
    // `Object` is not nullable, so is imprecise in the return type of the
    // unwrapper, which leads to unnecessary checks for 'on Object'.
    unwrappedType = kernelBuilder._abstractValueDomain.excludeNull(
      unwrappedType,
    );
    kernelBuilder._pushStaticInvocation(
      kernelBuilder._commonElements.exceptionUnwrapper,
      [exception!],
      unwrappedType,
      const <DartType>[],
      sourceInformation: trySourceInformation,
    );
    final unwrappedException = kernelBuilder.pop() as HInvokeStatic;
    unwrappedException.sideEffects
      ..clearAllDependencies()
      ..clearAllSideEffects();
    unwrappedException.targetCanThrow = false;
    tryInstruction.exception = exception;
    int catchesIndex = 0;

    void pushCondition(ir.Catch catchBlock) {
      kernelBuilder._pushIsTest(
        catchBlock.guard,
        unwrappedException,
        kernelBuilder._sourceInformationBuilder.buildCatch(catchBlock),
      );
    }

    void visitThen() {
      ir.Catch catchBlock = tryCatch.catches[catchesIndex];
      catchesIndex++;
      if (catchBlock.exception != null) {
        Local exceptionVariable = kernelBuilder._localsMap.getLocalVariable(
          catchBlock.exception!,
        );
        kernelBuilder.localsHandler.updateLocal(
          exceptionVariable,
          unwrappedException,
          sourceInformation: kernelBuilder._sourceInformationBuilder.buildCatch(
            catchBlock,
          ),
        );
      }
      if (catchBlock.stackTrace != null) {
        kernelBuilder._pushStaticInvocation(
          kernelBuilder._commonElements.traceFromException,
          [exception!],
          kernelBuilder._typeInferenceMap.getReturnTypeOf(
            kernelBuilder._commonElements.traceFromException,
          ),
          const <DartType>[],
          sourceInformation: kernelBuilder._sourceInformationBuilder.buildCatch(
            catchBlock,
          ),
        );
        HInstruction traceInstruction = kernelBuilder.pop();
        Local traceVariable = kernelBuilder._localsMap.getLocalVariable(
          catchBlock.stackTrace!,
        );
        kernelBuilder.localsHandler.updateLocal(
          traceVariable,
          traceInstruction,
          sourceInformation: kernelBuilder._sourceInformationBuilder.buildCatch(
            catchBlock,
          ),
        );
      }
      catchBlock.body.accept(kernelBuilder);
    }

    void visitElse() {
      if (catchesIndex >= tryCatch.catches.length) {
        kernelBuilder._closeAndGotoExit(
          HThrow(exception!, exception!.sourceInformation, isRethrow: true),
        );
      } else {
        ir.Catch nextCatch = tryCatch.catches[catchesIndex];
        kernelBuilder._handleIf(
          visitCondition: () {
            pushCondition(nextCatch);
          },
          visitThen: visitThen,
          visitElse: visitElse,
          sourceInformation: kernelBuilder._sourceInformationBuilder.buildCatch(
            nextCatch,
          ),
        );
      }
    }

    ir.Catch firstBlock = tryCatch.catches[catchesIndex];
    kernelBuilder._handleIf(
      visitCondition: () {
        pushCondition(firstBlock);
      },
      visitThen: visitThen,
      visitElse: visitElse,
      sourceInformation: kernelBuilder._sourceInformationBuilder.buildCatch(
        firstBlock,
      ),
    );
    if (!kernelBuilder.isAborted()) {
      endCatchBlock = kernelBuilder.close(HGoto());
    }

    kernelBuilder._rethrowableException = oldRethrowableException;
    tryInstruction.catchBlock = startCatchBlock;
    catchGraph = SubGraph(startCatchBlock!, kernelBuilder.lastOpenedBlock);
  }

  void cleanUp() {
    exitBlock = kernelBuilder.graph.addNewBlock();
    _setBlockSuccessors();

    // Use the locals handler not altered by the catch and finally
    // blocks.
    kernelBuilder.localsHandler = originalSavedLocals!;
    kernelBuilder.open(exitBlock!);
    enterBlock.setBlockFlow(
      HTryBlockInformation(
        kernelBuilder.wrapStatementGraph(bodyGraph),
        exception,
        kernelBuilder.wrapStatementGraph(catchGraph),
        kernelBuilder.wrapStatementGraph(finallyGraph),
      ),
      exitBlock,
    );
    kernelBuilder._inTryStatement = previouslyInTryStatement;
  }
}

class KernelTypeBuilder extends TypeBuilder {
  final JsToElementMap _elementMap;

  KernelTypeBuilder(super.builder, this._elementMap);

  @override
  ClassTypeVariableAccess computeTypeVariableAccess(MemberEntity member) {
    return _elementMap.getClassTypeVariableAccessForMember(member);
  }
}

class _ErroneousInitializerVisitor extends ir.VisitorDefault<bool>
    with ir.VisitorDefaultValueMixin<bool> {
  _ErroneousInitializerVisitor();

  // TODO(30809): Use const constructor.
  static bool check(ir.Initializer initializer) =>
      initializer.accept(_ErroneousInitializerVisitor());

  @override
  bool defaultInitializer(ir.Node node) => false;

  @override
  bool visitInvalidInitializer(ir.InvalidInitializer node) => true;

  @override
  bool visitLocalInitializer(ir.LocalInitializer node) {
    return node.variable.initializer?.accept(this) ?? false;
  }

  // Expressions: Does the expression always throw?
  @override
  bool get defaultValue => false;

  @override
  bool visitThrow(ir.Throw node) => true;

  // TODO(sra): We might need to match other expressions that always throw but
  // in a subexpression.
}

/// Special [JumpHandler] implementation used to handle continue statements
/// targeting switch cases.
class KernelSwitchCaseJumpHandler extends SwitchCaseJumpHandler {
  KernelSwitchCaseJumpHandler(
    KernelSsaGraphBuilder builder,
    JumpTarget target,
    ir.SwitchStatement switchStatement,
    KernelToLocalsMap localsMap,
  ) : super(builder, target) {
    // The switch case indices must match those computed in
    // [KernelSsaBuilder.buildSwitchCaseConstants].
    // Switch indices are 1-based so we can bypass the synthetic loop when no
    // cases match simply by branching on the index (which defaults to null).
    // TODO
    int switchIndex = 1;
    for (ir.SwitchCase switchCase in switchStatement.cases) {
      final continueTarget = localsMap.getJumpTargetForSwitchCase(switchCase);
      if (continueTarget != null) {
        targetIndexMap[continueTarget] = switchIndex;
        assert(builder.jumpTargets[continueTarget] == null);
        builder.jumpTargets[continueTarget] = this;
      }
      switchIndex++;
    }
  }
}

class InlineData {
  bool isConstructor = false;
  bool codeAfterReturn = false;
  bool hasLoop = false;
  bool hasClosure = false;
  bool hasTry = false;
  bool hasAsyncAwait = false;
  bool hasThrow = false;
  bool hasLongString = false;
  bool hasExternalConstantConstructorCall = false;
  bool hasTypeArguments = false;
  bool hasArgumentDefaulting = false;
  bool hasCast = false;
  bool hasIf = false;
  bool hasLabel = false; // TODO(51652): Remove when inlining works with labels.
  List<int> argumentCounts = [];
  int regularNodeCount = 0;
  int callCount = 0;
  int reductiveNodeCount = 0;

  InlineData();

  bool canBeInlined({int? maxInliningNodes, bool allowLoops = false}) {
    return cannotBeInlinedReason(
          maxInliningNodes: maxInliningNodes,
          allowLoops: allowLoops,
        ) ==
        null;
  }

  String? cannotBeInlinedReason({
    int? maxInliningNodes,
    bool allowLoops = false,
  }) {
    if (hasLoop && !allowLoops) {
      return 'loop';
    } else if (hasTry) {
      return 'try';
    } else if (hasClosure) {
      return 'closure';
    } else if (codeAfterReturn) {
      return 'code after return';
    } else if (hasAsyncAwait) {
      return 'async/await';
    } else if (maxInliningNodes != null &&
        regularNodeCount - 1 > maxInliningNodes) {
      return 'too many nodes (${regularNodeCount - 1}>$maxInliningNodes)';
    }
    if (hasLabel) return 'has label';
    return null;
  }

  bool canBeInlinedReductive({required int argumentCount}) {
    return cannotBeInlinedReductiveReason(argumentCount: argumentCount) == null;
  }

  String? cannotBeInlinedReductiveReason({required int argumentCount}) {
    if (hasTry) {
      return 'try';
    } else if (hasClosure) {
      return 'closure';
    } else if (codeAfterReturn) {
      return 'code after return';
    } else if (hasAsyncAwait) {
      return 'async/await';
    } else if (callCount > 1) {
      return 'too many calls';
    } else if (hasThrow) {
      return 'throw';
    } else if (hasLongString) {
      return 'long string';
    } else if (hasExternalConstantConstructorCall) {
      return 'external const constructor';
    } else if (hasTypeArguments) {
      return 'type arguments';
    } else if (hasArgumentDefaulting) {
      return 'argument defaulting';
    } else if (hasCast) {
      return 'cast';
    } else if (hasIf) {
      return 'if';
    } else if (isConstructor) {
      return 'constructor';
    }
    if (hasLabel) return 'has label';
    for (int count in argumentCounts) {
      if (count > argumentCount) {
        return 'increasing arguments';
      }
    }
    // Node budget that covers one call and the passed-in arguments.
    // The +1 also allows a top-level zero-argument to be inlined if it
    // returns a constant.
    int maxInliningNodes = argumentCount + 1;
    if (reductiveNodeCount > maxInliningNodes) {
      return 'too many nodes ($reductiveNodeCount>$maxInliningNodes)';
    }

    return null;
  }

  @override
  String toString() {
    StringBuffer sb = StringBuffer();
    sb.write('InlineData(');
    String comma = '';
    if (isConstructor) {
      sb.write('isConstructor');
      comma = ',';
    }
    if (codeAfterReturn) {
      sb.write(comma);
      sb.write('codeAfterReturn');
      comma = ',';
    }
    if (hasLoop) {
      sb.write(comma);
      sb.write('hasLoop');
      comma = ',';
    }
    if (hasClosure) {
      sb.write(comma);
      sb.write('hasClosure');
      comma = ',';
    }
    if (hasTry) {
      sb.write(comma);
      sb.write('hasTry');
      comma = ',';
    }
    if (hasAsyncAwait) {
      sb.write(comma);
      sb.write('hasAsyncAwait');
      comma = ',';
    }
    if (hasThrow) {
      sb.write(comma);
      sb.write('hasThrow');
      comma = ',';
    }
    if (hasLongString) {
      sb.write(comma);
      sb.write('hasLongString');
      comma = ',';
    }
    if (hasExternalConstantConstructorCall) {
      sb.write(comma);
      sb.write('hasExternalConstantConstructorCall');
      comma = ',';
    }
    if (hasTypeArguments) {
      sb.write(comma);
      sb.write('hasTypeArguments');
      comma = ',';
    }
    if (hasArgumentDefaulting) {
      sb.write(comma);
      sb.write('hasArgumentDefaulting');
      comma = ',';
    }
    if (hasCast) {
      sb.write(comma);
      sb.write('hasCast');
      comma = ',';
    }
    if (hasIf) {
      sb.write(comma);
      sb.write('hasIf');
      comma = ',';
    }
    if (hasLabel) {
      sb.write(comma);
      sb.write('hasLabel');
      comma = ',';
    }
    if (argumentCounts.isNotEmpty) {
      sb.write(comma);
      sb.write('argumentCounts={${argumentCounts.join(',')}}');
      comma = ',';
    }
    sb.write(comma);
    sb.write('regularNodeCount=$regularNodeCount,');
    sb.write('callCount=$callCount,');
    sb.write('reductiveNodeCount=$reductiveNodeCount');
    sb.write(')');
    return sb.toString();
  }
}

class InlineDataCache {
  final bool enableUserAssertions;
  final bool omitImplicitCasts;

  InlineDataCache({
    this.enableUserAssertions = false,
    this.omitImplicitCasts = false,
  });

  final Map<FunctionEntity, InlineData> _cache = {};

  InlineData getInlineData(JsToElementMap elementMap, FunctionEntity function) {
    return _cache[function] ??= InlineWeeder.computeInlineData(
      elementMap,
      function,
      enableUserAssertions: enableUserAssertions,
      omitImplicitCasts: omitImplicitCasts,
    );
  }
}

class InlineWeeder extends ir.VisitorDefault<void> with ir.VisitorVoidMixin {
  // Invariant: *INSIDE_LOOP* > *OUTSIDE_LOOP*
  static const inliningNodesOutsideLoop = 15;
  static const inliningNodesOutsideLoopArgFactor = 3;
  static const inliningNodesInsideLoop = 34;
  static const inliningNodesInsideLoopArgFactor = 4;

  final bool enableUserAssertions;
  final bool omitImplicitCasts;

  final InlineData data = InlineData();
  bool seenReturn = false;

  /// Whether node-count is collector to determine if a function can be
  /// inlined.
  bool countRegularNode = true;

  /// Whether node-count is collected to determine if inlining a function is
  /// very likely to reduce code size.
  ///
  /// For the reductive analysis:
  /// We allow the body to be a single function call that does not have any more
  /// inputs than the inlinee.
  ///
  /// We allow the body to be the return of an 'eligible' constant. A constant
  /// is 'eligible' if it is not large (e.g. a long string).
  ///
  /// We skip 'e as{TypeError} T' when the checks are omitted.
  //
  // TODO(sra): Consider slightly expansive simple constructors where all we
  // gain is a 'new' keyword, e.g. `new X.Foo(a)` vs `X.Foo$(a)`.
  //
  // TODO(25231): Make larger string constants eligible by sharing references.
  bool countReductiveNode = true;

  // When handling a generative constructor factory, the super constructor calls
  // are 'inlined', so tend to reuse the same parameters. [discountParameters]
  // is true to avoid double-counting these parameters.
  bool discountParameters = false;

  InlineWeeder({
    this.enableUserAssertions = false,
    this.omitImplicitCasts = false,
  });

  static InlineData computeInlineData(
    JsToElementMap elementMap,
    FunctionEntity function, {
    bool enableUserAssertions = false,
    bool omitImplicitCasts = false,
  }) {
    InlineWeeder visitor = InlineWeeder(
      enableUserAssertions: enableUserAssertions,
      omitImplicitCasts: omitImplicitCasts,
    );
    final node = getFunctionNode(elementMap, function)!;
    if (function is ConstructorEntity) {
      visitor.data.isConstructor = true;
      MemberDefinition definition = elementMap.getMemberDefinition(function);
      ir.Node node = definition.node;
      if (node is ir.Constructor) {
        visitor.skipReductiveNodes(() {
          visitor.handleGenerativeConstructorFactory(node);
        });
        return visitor.data;
      }
    }
    node.accept(visitor);
    return visitor.data;
  }

  void skipRegularNodes(void Function() f) {
    bool oldCountRegularNode = countRegularNode;
    countRegularNode = false;
    f();
    countRegularNode = oldCountRegularNode;
  }

  void skipReductiveNodes(void Function() f) {
    bool oldCountReductiveNode = countReductiveNode;
    countReductiveNode = false;
    f();
    countReductiveNode = oldCountReductiveNode;
  }

  void registerRegularNode([int count = 1]) {
    if (countRegularNode) {
      data.regularNodeCount += count;
      if (seenReturn) {
        data.codeAfterReturn = true;
      }
    }
  }

  void registerReductiveNode() {
    if (countReductiveNode) {
      data.reductiveNodeCount++;
      if (seenReturn) {
        data.codeAfterReturn = true;
      }
    }
  }

  void unregisterReductiveNode() {
    if (countReductiveNode) {
      data.reductiveNodeCount--;
    }
  }

  void visit(ir.Node? node) => node?.accept(this);

  void visitList(List<ir.Node> nodes) {
    for (ir.Node node in nodes) {
      visit(node);
    }
  }

  @override
  void defaultNode(ir.Node node) {
    registerRegularNode();
    registerReductiveNode();
    node.visitChildren(this);
  }

  @override
  void visitConstantExpression(ir.ConstantExpression node) {
    registerRegularNode();
    registerReductiveNode();
    ir.Constant constant = node.constant;
    // Avoid copying long strings into call site.
    if (constant is ir.StringConstant && isLongString(constant.value)) {
      data.hasLongString = true;
    }
  }

  @override
  void visitReturnStatement(ir.ReturnStatement node) {
    registerRegularNode();
    node.visitChildren(this);
    seenReturn = true;
  }

  @override
  void visitThrow(ir.Throw node) {
    registerRegularNode();
    data.hasThrow = true;
    node.visitChildren(this);
  }

  void _handleLoop(ir.Node node) {
    // It's actually not difficult to inline a method with a loop, but our
    // measurements show that it's currently better to not inline a method that
    // contains a loop.
    data.hasLoop = true;
    node.visitChildren(this);
  }

  @override
  void visitForStatement(ir.ForStatement node) {
    _handleLoop(node);
  }

  @override
  void visitForInStatement(ir.ForInStatement node) {
    _handleLoop(node);
  }

  @override
  void visitWhileStatement(ir.WhileStatement node) {
    _handleLoop(node);
  }

  @override
  void visitDoStatement(ir.DoStatement node) {
    _handleLoop(node);
  }

  @override
  void visitTryCatch(ir.TryCatch node) {
    data.hasTry = true;
  }

  @override
  void visitTryFinally(ir.TryFinally node) {
    data.hasTry = true;
  }

  @override
  void visitFunctionExpression(ir.FunctionExpression node) {
    registerRegularNode();
    data.hasClosure = true;
  }

  @override
  void visitFunctionDeclaration(ir.FunctionDeclaration node) {
    registerRegularNode();
    data.hasClosure = true;
  }

  @override
  void visitFunctionNode(ir.FunctionNode node) {
    if (node.asyncMarker != ir.AsyncMarker.Sync) {
      data.hasAsyncAwait = true;
    }
    // TODO(sra): Cost of parameter checking?
    skipReductiveNodes(() {
      visitList(node.typeParameters);
      visitList(node.positionalParameters);
      visitList(node.namedParameters);
      visit(node.returnType);
    });
    visit(node.body);
  }

  @override
  void visitConditionalExpression(ir.ConditionalExpression node) {
    // Heuristic: In "parameter ? A : B" there is a high probability that
    // parameter is a constant. Assuming the parameter is constant, we can
    // compute a count that is bounded by the largest arm rather than the sum of
    // both arms.
    ir.Expression condition = node.condition;
    visit(condition);
    int commonPrefixCount = data.regularNodeCount;

    visit(node.then);
    int thenCount = data.regularNodeCount - commonPrefixCount;

    data.regularNodeCount = commonPrefixCount;
    visit(node.otherwise);
    int elseCount = data.regularNodeCount - commonPrefixCount;

    data.regularNodeCount = commonPrefixCount + thenCount + elseCount;
    if (condition is ir.VariableGet &&
        condition.variable.parent is ir.FunctionNode) {
      data.regularNodeCount =
          commonPrefixCount + (thenCount > elseCount ? thenCount : elseCount);
    }
    // This is last so that [tooDifficult] is always updated.
    registerRegularNode();
    registerReductiveNode();
    skipRegularNodes(() => visit(node.staticType));
  }

  @override
  void visitAssertInitializer(ir.AssertInitializer node) {
    if (!enableUserAssertions) return;
    node.visitChildren(this);
  }

  @override
  void visitAssertStatement(ir.AssertStatement node) {
    if (!enableUserAssertions) return;
    defaultNode(node);
  }

  void registerCall() {
    ++data.callCount;
  }

  @override
  void visitEmptyStatement(ir.EmptyStatement node) {
    registerRegularNode();
  }

  @override
  void visitExpressionStatement(ir.ExpressionStatement node) {
    registerRegularNode();
    node.visitChildren(this);
  }

  @override
  void visitLabeledStatement(ir.LabeledStatement node) {
    registerRegularNode();
    data.hasLabel = true;
    node.visitChildren(this);
  }

  @override
  void visitSwitchStatement(ir.SwitchStatement node) {
    registerRegularNode();
    registerReductiveNode();
    // Don't visit 'SwitchStatement.expressionType'.
    node.expression.accept(this);
    visitList(node.cases);
  }

  @override
  void visitBlock(ir.Block node) {
    registerRegularNode();
    node.visitChildren(this);
  }

  /// Returns `true` if [value] is considered a long string for which copying
  /// should be avoided.
  bool isLongString(String value) => value.length > 14;

  @override
  void visitStringLiteral(ir.StringLiteral node) {
    registerRegularNode();
    registerReductiveNode();
    // Avoid copying long strings into call site.
    if (isLongString(node.value)) {
      data.hasLongString = true;
    }
  }

  @override
  void visitInstanceGet(ir.InstanceGet node) {
    registerCall();
    registerRegularNode();
    registerReductiveNode();
    skipReductiveNodes(() => visit(node.name));
    visit(node.receiver);
  }

  @override
  void visitInstanceTearOff(ir.InstanceTearOff node) {
    registerCall();
    registerRegularNode();
    registerReductiveNode();
    skipReductiveNodes(() => visit(node.name));
    visit(node.receiver);
  }

  @override
  void visitDynamicGet(ir.DynamicGet node) {
    registerCall();
    registerRegularNode();
    registerReductiveNode();
    skipReductiveNodes(() => visit(node.name));
    visit(node.receiver);
  }

  @override
  void visitInstanceSet(ir.InstanceSet node) {
    registerCall();
    registerRegularNode();
    registerReductiveNode();
    skipReductiveNodes(() => visit(node.name));
    visit(node.receiver);
    visit(node.value);
  }

  @override
  void visitDynamicSet(ir.DynamicSet node) {
    registerCall();
    registerRegularNode();
    registerReductiveNode();
    skipReductiveNodes(() => visit(node.name));
    visit(node.receiver);
    visit(node.value);
  }

  @override
  void visitVariableGet(ir.VariableGet node) {
    if (discountParameters && node.variable.parent is ir.FunctionNode) return;
    registerRegularNode();
    registerReductiveNode();
    skipReductiveNodes(() => visit(node.promotedType));
  }

  @override
  void visitThisExpression(ir.ThisExpression node) {
    registerRegularNode();
    registerReductiveNode();
  }

  @override
  void visitStaticGet(ir.StaticGet node) {
    // Assume lazy-init static, loaded via a call: `$.$get$foo()`.
    registerCall();
    registerRegularNode();
    registerReductiveNode();
  }

  @override
  void visitConstructorInvocation(ir.ConstructorInvocation node) {
    registerRegularNode();
    registerReductiveNode();
    if (node.isConst) {
      // A const constructor call compiles to a constant pool reference.
      skipReductiveNodes(() => node.visitChildren(this));
    } else {
      registerCall();
      _processArguments(node.arguments, node.target.function);
    }
  }

  @override
  void visitStaticInvocation(ir.StaticInvocation node) {
    registerRegularNode();
    if (node.isConst) {
      data.hasExternalConstantConstructorCall = true;
      skipReductiveNodes(() => node.visitChildren(this));
    } else {
      registerCall();
      registerReductiveNode();
      _processArguments(node.arguments, node.target.function);
    }
  }

  @override
  void visitInstanceInvocation(ir.InstanceInvocation node) {
    registerRegularNode();
    registerReductiveNode();
    registerCall();
    visit(node.receiver);
    skipReductiveNodes(() => visit(node.name));
    _processArguments(node.arguments, null);
  }

  @override
  void visitInstanceGetterInvocation(ir.InstanceGetterInvocation node) {
    registerRegularNode();
    registerReductiveNode();
    registerCall();
    visit(node.receiver);
    skipReductiveNodes(() => visit(node.name));
    _processArguments(node.arguments, null);
  }

  @override
  void visitDynamicInvocation(ir.DynamicInvocation node) {
    registerRegularNode();
    registerReductiveNode();
    registerCall();
    visit(node.receiver);
    skipReductiveNodes(() => visit(node.name));
    _processArguments(node.arguments, null);
  }

  @override
  void visitFunctionInvocation(ir.FunctionInvocation node) {
    registerRegularNode();
    registerReductiveNode();
    registerCall();
    visit(node.receiver);
    skipReductiveNodes(() => visit(node.name));
    _processArguments(node.arguments, null);
  }

  @override
  void visitLocalFunctionInvocation(ir.LocalFunctionInvocation node) {
    registerRegularNode();
    registerReductiveNode();
    registerCall();
    _processArguments(node.arguments, null);
    // Account for the implicit access to the local variable:
    registerRegularNode();
    registerReductiveNode();
  }

  @override
  void visitEqualsNull(ir.EqualsNull node) {
    registerRegularNode();
    registerReductiveNode();
    visit(node.expression);
  }

  @override
  void visitEqualsCall(ir.EqualsCall node) {
    registerRegularNode();
    registerReductiveNode();
    registerCall();
    visit(node.left);
    visit(node.right);
  }

  void _processArguments(ir.Arguments arguments, ir.FunctionNode? target) {
    registerRegularNode();
    if (arguments.types.isNotEmpty) {
      data.hasTypeArguments = true;
      skipReductiveNodes(() => visitList(arguments.types));
    }
    int count = arguments.positional.length + arguments.named.length;
    data.argumentCounts.add(count);

    if (target != null) {
      // Disallow defaulted optional arguments since they will be passed
      // explicitly.
      if (target.positionalParameters.length + target.namedParameters.length >
          count) {
        data.hasArgumentDefaulting = true;
      }
    }

    visitList(arguments.positional);
    for (ir.NamedExpression expression in arguments.named) {
      registerRegularNode();
      expression.value.accept(this);
    }
  }

  @override
  void visitAsExpression(ir.AsExpression node) {
    registerRegularNode();
    visit(node.operand);
    skipReductiveNodes(() => visit(node.type));
    if (!(node.isTypeError && omitImplicitCasts)) {
      data.hasCast = true;
    }
  }

  @override
  void visitVariableDeclaration(ir.VariableDeclaration node) {
    registerRegularNode();
    skipReductiveNodes(() {
      visitList(node.annotations);
      visit(node.type);
    });
    visit(node.initializer);

    // A local variable is an alias for the initializer expression.
    if (node.initializer != null) {
      unregisterReductiveNode(); // discount one reference to the variable.
    }
  }

  @override
  void visitIfStatement(ir.IfStatement node) {
    registerRegularNode();
    node.visitChildren(this);
    data.hasIf = true;
  }

  void handleGenerativeConstructorFactory(ir.Constructor node) {
    // Generative constructors are compiled to a factory constructor which
    // contains inlined all the initializations up the inheritance chain and
    // then call each of the constructor bodies down the inheritance chain.
    ir.Constructor? constructor = node;

    Set<ir.Field> initializedFields = {};
    bool hasCallToSomeConstructorBody = false;

    inheritance_loop:
    while (constructor != null) {
      ir.Constructor? superConstructor;
      for (var initializer in constructor.initializers) {
        if (initializer is ir.RedirectingInitializer) {
          // Discount the size of the arguments by references that are
          // pass-through.
          // TODO(sra): Need to add size of defaulted arguments.
          var discountParametersOld = discountParameters;
          discountParameters = true;
          initializer.arguments.accept(this);
          discountParameters = discountParametersOld;
          constructor = initializer.target;
          continue inheritance_loop;
        } else if (initializer is ir.SuperInitializer) {
          superConstructor = initializer.target;
          // Discount the size of the arguments by references that are
          // pass-through.
          // TODO(sra): Need to add size of defaulted arguments.
          var discountParametersOld = discountParameters;
          discountParameters = true;
          initializer.arguments.accept(this);
          discountParameters = discountParametersOld;
        } else if (initializer is ir.FieldInitializer) {
          initializedFields.add(initializer.field);
          initializer.value.accept(this);
        } else if (initializer is ir.AssertInitializer) {
          if (enableUserAssertions) {
            initializer.accept(this);
          }
        } else {
          initializer.accept(this);
        }
      }

      _handleFields(constructor!.enclosingClass, initializedFields);

      // There will be a call to the constructor's body, which might be empty
      // and inlined away.
      var function = constructor.function;
      var body = function.body!;
      if (!isEmptyBody(body)) {
        // All of the parameters are passed to the body.
        int parameterCount =
            function.positionalParameters.length +
            function.namedParameters.length +
            function.typeParameters.length;

        hasCallToSomeConstructorBody = true;
        registerCall();
        // A body call looks like "t.Body$(arguments);", i.e. an expression
        // statement with an instance member call, but the receiver is not
        // counted in the arguments. I'm guessing about 6 nodes for this.
        registerRegularNode(
          6 + parameterCount * inliningNodesOutsideLoopArgFactor,
        );

        // We can't inline a generative constructor factory when one of the
        // bodies rewrites the environment to put locals or parameters into a
        // box. The box is created in the generative constructor factory since
        // the box may be shared between closures in the initializer list and
        // closures in the constructor body.
        var bodyVisitor = InlineWeederBodyClosure();
        body.accept(bodyVisitor);
        if (bodyVisitor.tooDifficult) {
          data.hasClosure = true;
        }
      }

      if (superConstructor != null) {
        // The class of the super-constructor may not be the supertype class. In
        // this case, we must go up the class hierarchy until we reach the class
        // containing the super-constructor.
        ir.Supertype supertype = constructor.enclosingClass.supertype!;
        while (supertype.classNode != superConstructor.enclosingClass) {
          _handleFields(supertype.classNode, initializedFields);
          supertype = supertype.classNode.supertype!;
        }
      }
      constructor = superConstructor;
    }

    // In addition to the initializer expressions and body calls, there is an
    // allocator call.
    if (hasCallToSomeConstructorBody) {
      // A temporary is required so we have
      //
      //     t=new ...;
      //     ...;
      //     use(t);
      //
      // I'm guessing it takes about 4 nodes to introduce the temporary and
      // assign it.
      registerRegularNode(4); // A temporary is required.
    }
    // The initial field values are passed to the allocator.
    registerRegularNode(
      initializedFields.length * inliningNodesOutsideLoopArgFactor,
    );
  }

  void _handleFields(ir.Class cls, Set<ir.Field> initializedFields) {
    for (ir.Field field in cls.fields) {
      if (!field.isInstanceMember) continue;
      final initializer = field.initializer;
      if (initializer == null ||
          initializer is ir.ConstantExpression &&
              initializer.constant is ir.PrimitiveConstant ||
          initializer is ir.BasicLiteral) {
        // Simple field initializers happen in the allocator, so do not
        // contribute to the size of the generative constructor factory.
        // TODO(sra): Use FieldInfo which tells us if the field is elided or
        // initialized in the allocator.
        continue;
      }
      if (!initializedFields.add(field)) continue;
      initializer.accept(this);
    }
    // If [cls] is a mixin application, include fields from mixed in class.
    if (cls.mixedInType != null) {
      _handleFields(cls.mixedInType!.classNode, initializedFields);
    }
  }

  bool isEmptyBody(ir.Statement body) {
    if (body is ir.EmptyStatement) return true;
    if (body is ir.Block) return body.statements.every(isEmptyBody);
    if (body is ir.AssertStatement && !enableUserAssertions) return true;
    return false;
  }
}

/// Visitor to detect environment-rewriting that prevents inlining
/// (e.g. closures).
class InlineWeederBodyClosure extends ir.VisitorDefault<void>
    with ir.VisitorVoidMixin {
  bool tooDifficult = false;

  InlineWeederBodyClosure();

  @override
  void defaultNode(ir.Node node) {
    if (tooDifficult) return;
    node.visitChildren(this);
  }

  @override
  void visitFunctionExpression(ir.FunctionExpression node) {
    tooDifficult = true;
  }

  @override
  void visitFunctionDeclaration(ir.FunctionDeclaration node) {
    tooDifficult = true;
  }

  @override
  void visitFunctionNode(ir.FunctionNode node) {
    assert(false);
    if (node.asyncMarker != ir.AsyncMarker.Sync) {
      tooDifficult = true;
      return;
    }
    node.visitChildren(this);
  }
}
