// 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.

import 'package:compiler/src/js_model/element_map.dart';

import '../closure.dart';
import '../common.dart';
import '../elements/entities.dart';
import '../elements/types.dart';
import '../inferrer/abstract_value_domain.dart';
import '../inferrer/types.dart';
import '../io/source_information.dart';
import '../js_backend/native_data.dart';
import '../js_backend/interceptor_data.dart';
import '../js_model/closure.dart' show JContextField, JClosureField;
import '../js_model/js_world.dart' show JClosedWorld;
import '../js_model/locals.dart' show GlobalLocalsMap, JLocal;

import 'builder.dart';
import 'nodes.dart';
import 'types.dart';

/// Keeps track of locals (including parameters and phis) when building. The
/// 'this' reference is treated as parameter and hence handled by this class,
/// too.
class LocalsHandler {
  /// The values of locals that can be directly accessed (without redirections
  /// to boxes or closure-fields).
  ///
  /// [directLocals] is iterated, so it is "insertion ordered" to make the
  /// iteration order a function only of insertions and not a function of
  /// e.g. Element hash codes.  I'd prefer to use a SortedMap but some elements
  /// don't have source locations for [Elements.compareByPosition].
  Map<Local, HInstruction> directLocals = {};
  Map<Local, FieldEntity> redirectionMapping = {};
  final KernelSsaGraphBuilder builder;

  MemberEntity? _scopeInfoMember;
  ScopeInfo? _scopeInfo;
  KernelToLocalsMap? _localsMap;

  Map<TypeVariableEntity, TypeVariableLocal> typeVariableLocals = {};
  final Entity executableContext;
  final MemberEntity memberContext;

  /// The type of the current instance. `null` if in a static context.
  ///
  /// This is the type of `this` is the current context, and is often the
  /// 'this type' of the enclosing class of a member.
  ///
  /// If the current instance is concrete, we can handle fixed type argument in
  /// case of inlining. For instance, checking `'foo'` against `String` instead
  /// of `T` in `main`:
  ///
  ///     class Foo<T> {
  ///       T field;
  ///       Foo(this.field);
  ///     }
  ///     main() {
  ///       Foo<String>('foo');
  ///     }
  ///
  final InterfaceType? instanceType;

  final NativeData _nativeData;

  final InterceptorData _interceptorData;

  LocalsHandler(
    this.builder,
    this.executableContext,
    this.memberContext,
    this.instanceType,
    this._nativeData,
    this._interceptorData,
  );

  JClosedWorld get _closedWorld => builder.closedWorld;

  AbstractValueDomain get _abstractValueDomain =>
      _closedWorld.abstractValueDomain;

  GlobalTypeInferenceResults get _globalInferenceResults =>
      builder.globalInferenceResults;

  GlobalLocalsMap get _globalLocalsMap =>
      _globalInferenceResults.globalLocalsMap;

  /// Substituted type variables occurring in [type] into the context of
  /// [contextClass].
  DartType substInContext(DartType type) {
    DartType newType = type;
    final iType = instanceType;
    if (iType != null) {
      final typeContext = DartTypes.getClassContext(newType);
      if (typeContext != null) {
        newType = _closedWorld.dartTypes.substByContext(
          newType,
          _closedWorld.dartTypes.asInstanceOf(
            _closedWorld.dartTypes.getThisType(iType.element),
            typeContext,
          )!,
        );
      }
      if (!iType.containsTypeVariables) {
        newType = _closedWorld.dartTypes.substByContext(newType, iType);
      }
    }
    return newType;
  }

  /// Creates a new [LocalsHandler] based on [other]. We only need to
  /// copy the [directLocals], since the other fields can be shared
  /// throughout the AST visit.
  LocalsHandler.from(LocalsHandler other)
    : directLocals = Map<Local, HInstruction>.from(other.directLocals),
      redirectionMapping = other.redirectionMapping,
      executableContext = other.executableContext,
      memberContext = other.memberContext,
      instanceType = other.instanceType,
      builder = other.builder,
      _scopeInfo = other._scopeInfo,
      _scopeInfoMember = other._scopeInfoMember,
      _localsMap = other._localsMap,
      _nativeData = other._nativeData,
      _interceptorData = other._interceptorData,
      activationVariables = other.activationVariables,
      cachedTypeOfThis = other.cachedTypeOfThis,
      cachedTypesOfCapturedVariables = other.cachedTypesOfCapturedVariables;

  /// Sets up the scope to use the scope and locals from [member].
  void setupScope(MemberEntity? member) {
    _scopeInfoMember = member;
    if (member != null) {
      _scopeInfo = _closedWorld.closureDataLookup.getScopeInfo(member);
      _localsMap = _globalLocalsMap.getLocalsMap(member);
    } else {
      _scopeInfo = null;
      _localsMap = null;
    }
  }

  /// Returns the member that currently defines the scope as setup in
  /// [setupScope].
  MemberEntity? get scopeMember => _scopeInfoMember;

  Local? get thisLocal => _scopeInfo?.thisLocal;

  /// Redirects accesses from element [from] to element [to]. The [to] element
  /// must be a boxed variable or a variable that is stored in a closure-field.
  void redirectElement(Local from, FieldEntity to) {
    assert(redirectionMapping[from] == null);
    redirectionMapping[from] = to;
    assert(isStoredInClosureField(from) || isBoxed(from));
  }

  HInstruction createBox(SourceInformation? sourceInformation) {
    HInstruction box = HCreateBox(_abstractValueDomain.nonNullType)
      ..sourceInformation = sourceInformation;
    builder.add(box);
    return box;
  }

  /// If the scope (function or loop) [node] has captured variables then this
  /// method creates a box and sets up the redirections.
  void enterScope(
    CapturedScope closureInfo,
    SourceInformation? sourceInformation, {
    bool forGenerativeConstructorBody = false,
    HInstruction? inlinedBox,
  }) {
    // See if any variable in the top-scope of the function is captured. If yes
    // we need to create a box-object.
    if (!closureInfo.requiresContextBox) return;
    HInstruction box;
    final contentBox = closureInfo.contextBox!;
    // The scope has captured variables.
    if (forGenerativeConstructorBody) {
      // The box is passed as a parameter to a generative constructor body.
      box =
          inlinedBox ??
          builder.addParameter(contentBox, _abstractValueDomain.nonNullType);
    } else {
      box = createBox(sourceInformation);
    }
    // Add the box to the known locals.
    directLocals[contentBox] = box;
    // Make sure that accesses to the boxed locals go into the box. We also
    // need to make sure that parameters are copied into the box if necessary.
    closureInfo.forEachBoxedVariable(_localsMap!, (Local from, FieldEntity to) {
      // The [from] can only be a parameter for function-scopes and not
      // loop scopes.
      bool isParameter = (from as JLocal).isRegularParameter;
      if (isParameter && !forGenerativeConstructorBody) {
        // Now that the redirection is set up, the update to the local will
        // write the parameter value into the box.
        // Store the captured parameter in the box. Get the current value
        // before we put the redirection in place.
        // We don't need to update the local for a generative
        // constructor body, because it receives a box that already
        // contains the updates as the last parameter.
        HInstruction instruction = readLocal(from);
        redirectElement(from, to);
        updateLocal(from, instruction);
      } else {
        redirectElement(from, to);
      }
    });
  }

  /// Replaces the current box with a new box and copies over the given list
  /// of elements from the old box into the new box.
  void updateCaptureBox(
    Local currentBox,
    List<Local> toBeCopiedElements,
    SourceInformation? sourceInformation,
  ) {
    // Create a new box and copy over the values from the old box into the
    // new one.
    HInstruction oldBox = readLocal(currentBox);
    HInstruction newBox = createBox(sourceInformation);
    for (Local boxedVariable in toBeCopiedElements) {
      // [readLocal] uses the [currentBox] to find its box. By replacing it
      // behind its back we can still get to the old values.
      updateLocal(currentBox, oldBox);
      HInstruction oldValue = readLocal(boxedVariable);
      updateLocal(currentBox, newBox);
      updateLocal(boxedVariable, oldValue);
    }
    updateLocal(currentBox, newBox);
  }

  /// Documentation wanted -- johnniwinther
  ///
  /// Invariant: [function] must be an implementation element.
  void startFunction(
    MemberEntity element,
    Map<Local, AbstractValue> parameters,
    Set<Local> elidedParameters,
    SourceInformation? sourceInformation, {
    required bool isGenerativeConstructorBody,
  }) {
    setupScope(element);

    CapturedScope scopeData = _closedWorld.closureDataLookup.getCapturedScope(
      element,
    );

    parameters.forEach((Local local, AbstractValue typeMask) {
      if (isGenerativeConstructorBody) {
        if (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 parameter = builder.addParameter(
        local,
        typeMask,
        isElided: elidedParameters.contains(local),
      );
      builder.parameters[local] = parameter;
      directLocals[local] = parameter;
    });
    builder.elidedParameters = elidedParameters;

    enterScope(
      scopeData,
      sourceInformation,
      forGenerativeConstructorBody: isGenerativeConstructorBody,
    );

    // When we remove the element model, we can just use the first check
    // (because the underlying elements won't all be *both* ScopeInfos and
    // ClosureRepresentationInfos).
    final scopeInfo = _scopeInfo;
    if (scopeInfo is ClosureRepresentationInfo && scopeInfo.isClosure) {
      // If the freeVariableMapping is not empty, then this function was a
      // nested closure that captures variables. Redirect the captured
      // variables to fields in the closure.
      scopeInfo.forEachFreeVariable(_localsMap!, (Local from, FieldEntity to) {
        redirectElement(from, to);
      });
      // Inside closure redirect references to itself to [:this:].
      HThis thisInstruction = HThis(
        scopeInfo.thisLocal as ThisLocal?,
        _abstractValueDomain.nonNullType,
      );
      builder.graph.thisInstruction = thisInstruction;
      builder.graph.entry.addAtEntry(thisInstruction);
      updateLocal(scopeInfo.getClosureEntity(_localsMap!)!, thisInstruction);
    } else if (element.isInstanceMember) {
      // Once closures have been mapped to classes their instance members might
      // not have any thisElement if the closure was created inside a static
      // context.
      final thisLocal = scopeInfo!.thisLocal as ThisLocal;
      HThis thisInstruction = HThis(thisLocal, getTypeOfThis());
      builder.graph.thisInstruction = thisInstruction;
      builder.graph.entry.addAtEntry(thisInstruction);
      directLocals[thisLocal] = thisInstruction;
    }

    // If this method is an intercepted method, add the extra
    // parameter to it, that is the actual receiver for intercepted
    // classes, or the same as [:this:] for non-intercepted classes.
    final cls = element.enclosingClass;

    // When the class extends a native class, the instance is pre-constructed
    // and passed to the generative constructor factory function as a parameter.
    // Instead of allocating and initializing the object, the constructor
    // 'upgrades' the native subclass object by initializing the Dart fields.
    bool isNativeUpgradeFactory =
        element is ConstructorEntity &&
        element.isGenerativeConstructor &&
        _nativeData.isNativeOrExtendsNative(cls);
    if (_interceptorData.isInterceptedMethod(element)) {
      SyntheticLocal parameter = createLocal('receiver');
      HParameterValue value = HParameterValue(parameter, getTypeOfThis());
      builder.graph.explicitReceiverParameter = value;
      builder.graph.entry.addAfter(directLocals[scopeInfo!.thisLocal], value);
      builder.lastAddedParameter ??= value;
      directLocals[scopeInfo.thisLocal!] = value;
    } else if (isNativeUpgradeFactory) {
      SyntheticLocal parameter = createLocal('receiver');
      // Unlike `this`, receiver is nullable since direct calls to generative
      // constructor call the constructor with `null`.
      HParameterValue value = HParameterValue(
        parameter,
        _closedWorld.abstractValueDomain.createNullableExact(cls!),
      );
      builder.graph.explicitReceiverParameter = value;
      builder.graph.entry.addAtEntry(value);
      builder.lastAddedParameter ??= value;
    }
  }

  /// Returns true if the local can be accessed directly. Boxed variables or
  /// captured variables that are stored in the closure-field return [:false:].
  bool isAccessedDirectly(Local local) {
    return !redirectionMapping.containsKey(local) &&
        !_scopeInfo!.localIsUsedInTryOrSync(_localsMap!, local);
  }

  bool isStoredInClosureField(Local local) {
    if (isAccessedDirectly(local)) return false;
    if (_scopeInfo is! ClosureRepresentationInfo) return false;
    final redirectTarget = redirectionMapping[local];
    if (redirectTarget == null) return false;
    return redirectTarget is JClosureField;
  }

  bool isBoxed(Local local) {
    if (isAccessedDirectly(local)) return false;
    if (isStoredInClosureField(local)) return false;
    return redirectionMapping.containsKey(local);
  }

  bool _isUsedInTryOrGenerator(Local local) {
    return _scopeInfo!.localIsUsedInTryOrSync(_localsMap!, local);
  }

  /// Returns an [HInstruction] for the given element. If the element is
  /// boxed or stored in a closure then the method generates code to retrieve
  /// the value.
  HInstruction readLocal(Local local, {SourceInformation? sourceInformation}) {
    if (isAccessedDirectly(local)) {
      HInstruction? value = directLocals[local];
      if (value == null) {
        if (local is TypeVariableLocal) {
          failedAt(
            currentElementSpannable,
            "Runtime type information not available for $local "
            "in ${directLocals.keys} for $executableContext.",
          );
        } else {
          failedAt(
            local,
            "Cannot find value $local in ${directLocals.keys} for "
            "$executableContext.",
          );
        }
      }
      if (sourceInformation != null) {
        value = HRef(value, sourceInformation);
        builder.add(value);
      }
      return value;
    } else if (isStoredInClosureField(local)) {
      final closureData = _scopeInfo as ClosureRepresentationInfo;
      final redirect = redirectionMapping[local]!;
      HInstruction receiver = readLocal(
        closureData.getClosureEntity(_localsMap!)!,
      );
      AbstractValue type =
          local is BoxLocal
              ? _abstractValueDomain.nonNullType
              : getTypeOfCapturedVariable(redirect);
      HInstruction fieldGet = HFieldGet(
        redirect,
        receiver,
        type,
        sourceInformation,
        isAssignable: redirect.isAssignable,
      );
      builder.add(fieldGet);
      return fieldGet;
    } else if (isBoxed(local)) {
      FieldEntity? redirect = redirectionMapping[local];
      // In the function that declares the captured variable the box is
      // accessed as direct local. Inside the nested closure the box is
      // accessed through a closure-field.
      // Calling [readLocal] makes sure we generate the correct code to get
      // the box.
      BoxLocal localBox = (redirect as JContextField).box;

      HInstruction box = readLocal(localBox);
      HInstruction lookup = HFieldGet(
        redirect,
        box,
        getTypeOfCapturedVariable(redirect),
        sourceInformation,
        isAssignable: redirect.isAssignable,
      );
      builder.add(lookup);
      return lookup;
    } else {
      assert(_isUsedInTryOrGenerator(local));
      HLocalValue localValue = getLocal(local);
      HInstruction instruction = HLocalGet(
        local,
        localValue,
        _abstractValueDomain.dynamicType,
        sourceInformation,
      );
      builder.add(instruction);
      return instruction;
    }
  }

  HInstruction readThis({SourceInformation? sourceInformation}) {
    return readLocal(
      _scopeInfo!.thisLocal!,
      sourceInformation: sourceInformation,
    );
  }

  HLocalValue getLocal(Local local, {SourceInformation? sourceInformation}) {
    // If the element is a parameter, we already have a
    // HParameterValue for it. We cannot create another one because
    // it could then have another name than the real parameter. And
    // the other one would not know it is just a copy of the real
    // parameter.
    if (builder.parameters.containsKey(local)) {
      return builder.parameters[local] as HLocalValue;
    }

    return activationVariables.putIfAbsent(local, () {
      HLocalValue localValue = HLocalValue(
        local,
        _abstractValueDomain.nonNullType,
      )..sourceInformation = sourceInformation;
      builder.graph.entry.addAtExit(localValue);
      return localValue;
    });
  }

  Local getTypeVariableAsLocal(TypeVariableType type) {
    return typeVariableLocals[type.element] ??= TypeVariableLocal(type.element);
  }

  /// Sets the [element] to [value]. If the element is boxed or stored in a
  /// closure then the method generates code to set the value.
  void updateLocal(
    Local local,
    HInstruction value, {
    SourceInformation? sourceInformation,
  }) {
    if (value is HRef) {
      HRef ref = value;
      value = ref.value;
    }
    assert(
      !isStoredInClosureField(local),
      "Local $local is stored in a closure field.",
    );
    if (isAccessedDirectly(local)) {
      directLocals[local] = value;
    } else if (isBoxed(local)) {
      FieldEntity redirect = redirectionMapping[local]!;
      BoxLocal localBox = (redirect as JContextField).box;

      // The box itself could be captured, or be local. A local variable that
      // is captured will be boxed, but the box itself will be a local.
      // Inside the closure the box is stored in a closure-field and cannot
      // be accessed directly.
      HInstruction box = readLocal(localBox);
      builder.add(
        HFieldSet(redirect, box, value)..sourceInformation = sourceInformation,
      );
    } else {
      assert(_isUsedInTryOrGenerator(local));
      HLocalValue localValue = getLocal(local);
      builder.add(
        HLocalSet(local, localValue, value, _abstractValueDomain.dynamicType)
          ..sourceInformation = sourceInformation,
      );
    }
  }

  /// This function, startLoop, must be called before visiting any children of
  /// the loop. In particular it needs to be called before executing the
  /// initializers.
  ///
  /// The [LocalsHandler] will make the boxes and updates at the right moment.
  /// The builder just needs to call [enterLoopBody] and [enterLoopUpdates]
  /// (for [ast.For] loops) at the correct places. For phi-handling
  /// [beginLoopHeader] and [endLoop] must also be called.
  ///
  /// The correct place for the box depends on the given loop. In most cases
  /// the box will be created when entering the loop-body: while, do-while, and
  /// for-in (assuming the call to [:next:] is inside the body) can always be
  /// constructed this way.
  ///
  /// Things are slightly more complicated for [ast.For] loops. If no declared
  /// loop variable is boxed then the loop-body approach works here too. If a
  /// loop-variable is boxed we need to introduce a new box for the
  /// loop-variable before we enter the initializer so that the initializer
  /// writes the values into the box. In any case we need to create the box
  /// before the condition since the condition could box the variable.
  /// Since the first box is created outside the actual loop we have a second
  /// location where a box is created: just before the updates. This is
  /// necessary since updates are considered to be part of the next iteration
  /// (and can again capture variables).
  ///
  /// For example the following Dart code prints 1 3 -- 3 4.
  ///
  ///     var fs = [];
  ///     for (var i = 0; i < 3; (f() { fs.add(f); print(i); i++; })()) {
  ///       i++;
  ///     }
  ///     print("--");
  ///     for (var i = 0; i < 2; i++) fs[i]();
  ///
  /// We solve this by emitting the following code (only for [ast.For] loops):
  ///
  ///     <Create box>    <== move the first box creation outside the loop.
  ///     <initializer>;
  ///     loop-entry:
  ///       if (!<condition>) goto loop-exit;
  ///     <body>
  ///     <update box>  // create a new box and copy the captured loop-variables.
  ///     <updates>
  ///     goto loop-entry;
  ///     loop-exit:
  void startLoop(
    CapturedLoopScope loopInfo,
    SourceInformation? sourceInformation,
  ) {
    if (loopInfo.hasBoxedLoopVariables) {
      // If there are boxed loop variables then we set up the box and
      // redirections already now. This way the initializer can write its
      // values into the box.
      // For other loops the box will be created when entering the body.
      enterScope(loopInfo, sourceInformation);
    }
  }

  /// Create phis at the loop entry for local variables (ready for the values
  /// from the back edge).  Populate the phis with the current values.
  void beginLoopHeader(HBasicBlock loopEntry) {
    // Create a copy because we modify the map while iterating over it.
    Map<Local, HInstruction> savedDirectLocals = Map<Local, HInstruction>.from(
      directLocals,
    );

    // Create phis for all elements in the definitions environment.
    savedDirectLocals.forEach((Local local, HInstruction instruction) {
      if (isAccessedDirectly(local)) {
        // We know 'this' cannot be modified.
        if (local != _scopeInfo!.thisLocal) {
          HPhi phi = HPhi.singleInput(
            local,
            instruction,
            _abstractValueDomain.dynamicType,
          );
          loopEntry.addPhi(phi);
          directLocals[local] = phi;
        } else {
          directLocals[local] = instruction;
        }
      }
    });
  }

  void enterLoopBody(
    CapturedLoopScope loopInfo,
    SourceInformation? sourceInformation,
  ) {
    // If there are no declared boxed loop variables then we did not create the
    // box before the initializer and we have to create the box now.
    if (!loopInfo.hasBoxedLoopVariables) {
      enterScope(loopInfo, sourceInformation);
    }
  }

  void enterLoopUpdates(
    CapturedLoopScope loopInfo,
    SourceInformation? sourceInformation,
  ) {
    // If there are declared boxed loop variables then the updates might have
    // access to the box and we must switch to a new box before executing the
    // updates.
    // In all other cases a new box will be created when entering the body of
    // the next iteration.
    if (loopInfo.hasBoxedLoopVariables) {
      updateCaptureBox(
        loopInfo.contextBox!,
        loopInfo.getBoxedLoopVariables(_localsMap!),
        sourceInformation,
      );
    }
  }

  /// Goes through the phis created in beginLoopHeader entry and adds the
  /// input from the back edge (from the current value of directLocals) to them.
  void endLoop(HBasicBlock loopEntry) {
    // If the loop has an aborting body, we don't update the loop
    // phis.
    if (loopEntry.predecessors.length == 1) return;
    loopEntry.forEachPhi((HPhi phi) {
      final element = phi.sourceElement;
      final postLoopDefinition = directLocals[element]!;
      phi.addInput(postLoopDefinition);
    });
  }

  /// Merge [otherLocals] into this locals handler, creating phi-nodes when
  /// there is a conflict.
  /// If a phi node is necessary, it will use this handler's instruction as the
  /// first input, and the otherLocals instruction as the second.
  void mergeWith(LocalsHandler otherLocals, HBasicBlock joinBlock) {
    // If an element is in one map but not the other we can safely
    // ignore it. It means that a variable was declared in the
    // block. Since variable declarations are scoped the declared
    // variable cannot be alive outside the block. Note: this is only
    // true for nodes where we do joins.
    Map<Local, HInstruction> joinedLocals = {};
    otherLocals.directLocals.forEach((Local local, HInstruction instruction) {
      // We know 'this' cannot be modified.
      if (local == _scopeInfo!.thisLocal) {
        assert(directLocals[local] == instruction);
        joinedLocals[local] = instruction;
      } else {
        final mine = directLocals[local];
        if (mine == null) return;
        if (identical(instruction, mine)) {
          joinedLocals[local] = instruction;
        } else {
          final phi = HPhi.manyInputs(local, <HInstruction>[
            mine,
            instruction,
          ], _abstractValueDomain.dynamicType);
          joinBlock.addPhi(phi);
          joinedLocals[local] = phi;
        }
      }
    });
    directLocals = joinedLocals;
  }

  /// When control flow merges, this method can be used to merge several
  /// localsHandlers into a new one using phis.  The new localsHandler is
  /// returned.  Unless it is also in the list, the current localsHandler is not
  /// used for its values, only for its declared variables. This is a way to
  /// exclude local values from the result when they are no longer in scope.
  LocalsHandler mergeMultiple(
    List<LocalsHandler> localsHandlers,
    HBasicBlock joinBlock,
  ) {
    assert(localsHandlers.isNotEmpty);
    if (localsHandlers.length == 1) return localsHandlers.single;
    Map<Local, HInstruction> joinedLocals = {};
    HInstruction? thisValue;
    directLocals.forEach((Local local, HInstruction instruction) {
      if (local != _scopeInfo!.thisLocal) {
        HPhi phi = HPhi.noInputs(local, _abstractValueDomain.dynamicType);
        joinedLocals[local] = phi;
        joinBlock.addPhi(phi);
      } else {
        // We know that "this" never changes, if it's there.
        // Save it for later. While merging, there is no phi for "this",
        // so we don't have to special case it in the merge loop.
        thisValue = instruction;
      }
    });
    for (LocalsHandler handler in localsHandlers) {
      handler.directLocals.forEach((Local local, HInstruction instruction) {
        final phi = joinedLocals[local] as HPhi?;
        if (phi != null) {
          phi.addInput(instruction);
        }
      });
    }
    if (thisValue != null) {
      // If there was a "this" for the scope, add it to the new locals.
      joinedLocals[_scopeInfo!.thisLocal!] = thisValue!;
    }

    // Remove locals that are not in all handlers.
    directLocals = {};
    joinedLocals.forEach((Local local, HInstruction instruction) {
      if (local != _scopeInfo!.thisLocal &&
          instruction.inputs.length != localsHandlers.length) {
        joinBlock.removePhi(instruction as HPhi);
      } else {
        directLocals[local] = instruction;
      }
    });
    return this;
  }

  AbstractValue? cachedTypeOfThis;

  AbstractValue getTypeOfThis() {
    AbstractValue? result = cachedTypeOfThis;
    if (result == null) {
      final local = _scopeInfo!.thisLocal as ThisLocal;
      ClassEntity cls = local.enclosingClass;
      if (_closedWorld.isUsedAsMixin(cls)) {
        // If the enclosing class is used as a mixin, [:this:] can be
        // of the class that mixins the enclosing class. These two
        // classes do not have a subclass relationship, so, for
        // simplicity, we mark the type as an interface type.
        result = _abstractValueDomain.createNonNullSubtype(cls);
      } else {
        result = _abstractValueDomain.createNonNullSubclass(cls);
      }
      cachedTypeOfThis = result;
    }
    return result;
  }

  Map<FieldEntity, AbstractValue> cachedTypesOfCapturedVariables = {};

  AbstractValue getTypeOfCapturedVariable(FieldEntity element) {
    return cachedTypesOfCapturedVariables.putIfAbsent(element, () {
      return AbstractValueFactory.inferredTypeForMember(
        element,
        _globalInferenceResults,
      );
    });
  }

  /// Variables stored in the current activation. These variables are
  /// being updated in try/catch blocks, and should be
  /// accessed indirectly through [HLocalGet] and [HLocalSet].
  Map<Local, HLocalValue> activationVariables = {};

  SyntheticLocal createLocal(String name) {
    return SyntheticLocal(name, executableContext, memberContext);
  }
}

/// A synthetic local variable only used with the SSA graph.
///
/// For instance used for holding return value of function or the exception of a
/// try-catch statement.
class SyntheticLocal extends Local {
  @override
  final String name;
  final Entity executableContext;
  final MemberEntity memberContext;

  // Avoid slow Object.hashCode.
  @override
  final int hashCode = _nextHashCode = (_nextHashCode + 1).toUnsigned(30);
  static int _nextHashCode = 0;

  SyntheticLocal(this.name, this.executableContext, this.memberContext);

  @override
  bool operator ==(other) => identical(this, other);

  @override
  String toString() => 'SyntheticLocal($name)';
}
