// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/compiler/js-native-context-specialization.h"

#include "src/accessors.h"
#include "src/api.h"
#include "src/code-factory.h"
#include "src/compilation-dependencies.h"
#include "src/compiler/access-builder.h"
#include "src/compiler/access-info.h"
#include "src/compiler/allocation-builder.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/js-operator.h"
#include "src/compiler/linkage.h"
#include "src/compiler/node-matchers.h"
#include "src/compiler/property-access-builder.h"
#include "src/compiler/type-cache.h"
#include "src/feedback-vector.h"
#include "src/field-index-inl.h"
#include "src/isolate-inl.h"
#include "src/vector-slot-pair.h"

namespace v8 {
namespace internal {
namespace compiler {

namespace {

bool HasNumberMaps(MapHandles const& maps) {
  for (auto map : maps) {
    if (map->instance_type() == HEAP_NUMBER_TYPE) return true;
  }
  return false;
}

bool HasOnlyJSArrayMaps(MapHandles const& maps) {
  for (auto map : maps) {
    if (!map->IsJSArrayMap()) return false;
  }
  return true;
}

}  // namespace

struct JSNativeContextSpecialization::ScriptContextTableLookupResult {
  Handle<Context> context;
  bool immutable;
  int index;
};

JSNativeContextSpecialization::JSNativeContextSpecialization(
    Editor* editor, JSGraph* jsgraph, Flags flags,
    Handle<Context> native_context, CompilationDependencies* dependencies,
    Zone* zone)
    : AdvancedReducer(editor),
      jsgraph_(jsgraph),
      flags_(flags),
      global_object_(native_context->global_object()),
      global_proxy_(JSGlobalProxy::cast(native_context->global_proxy())),
      native_context_(native_context),
      dependencies_(dependencies),
      zone_(zone),
      type_cache_(TypeCache::Get()) {}

Reduction JSNativeContextSpecialization::Reduce(Node* node) {
  switch (node->opcode()) {
    case IrOpcode::kJSAdd:
      return ReduceJSAdd(node);
    case IrOpcode::kJSGetSuperConstructor:
      return ReduceJSGetSuperConstructor(node);
    case IrOpcode::kJSInstanceOf:
      return ReduceJSInstanceOf(node);
    case IrOpcode::kJSHasInPrototypeChain:
      return ReduceJSHasInPrototypeChain(node);
    case IrOpcode::kJSOrdinaryHasInstance:
      return ReduceJSOrdinaryHasInstance(node);
    case IrOpcode::kJSLoadContext:
      return ReduceJSLoadContext(node);
    case IrOpcode::kJSLoadGlobal:
      return ReduceJSLoadGlobal(node);
    case IrOpcode::kJSStoreGlobal:
      return ReduceJSStoreGlobal(node);
    case IrOpcode::kJSLoadNamed:
      return ReduceJSLoadNamed(node);
    case IrOpcode::kJSStoreNamed:
      return ReduceJSStoreNamed(node);
    case IrOpcode::kJSLoadProperty:
      return ReduceJSLoadProperty(node);
    case IrOpcode::kJSStoreProperty:
      return ReduceJSStoreProperty(node);
    case IrOpcode::kJSStoreNamedOwn:
      return ReduceJSStoreNamedOwn(node);
    case IrOpcode::kJSStoreDataPropertyInLiteral:
      return ReduceJSStoreDataPropertyInLiteral(node);
    default:
      break;
  }
  return NoChange();
}

Reduction JSNativeContextSpecialization::ReduceJSAdd(Node* node) {
  // TODO(turbofan): This has to run together with the inlining and
  // native context specialization to be able to leverage the string
  // constant-folding for optimizing property access, but we should
  // nevertheless find a better home for this at some point.
  DCHECK_EQ(IrOpcode::kJSAdd, node->opcode());

  // Constant-fold string concatenation.
  HeapObjectBinopMatcher m(node);
  if (m.left().HasValue() && m.left().Value()->IsString() &&
      m.right().HasValue() && m.right().Value()->IsString()) {
    Handle<String> left = Handle<String>::cast(m.left().Value());
    Handle<String> right = Handle<String>::cast(m.right().Value());
    if (left->length() + right->length() <= String::kMaxLength) {
      Handle<String> result =
          factory()->NewConsString(left, right).ToHandleChecked();
      Node* value = jsgraph()->HeapConstant(result);
      ReplaceWithValue(node, value);
      return Replace(value);
    }
  }
  return NoChange();
}

Reduction JSNativeContextSpecialization::ReduceJSGetSuperConstructor(
    Node* node) {
  DCHECK_EQ(IrOpcode::kJSGetSuperConstructor, node->opcode());
  Node* constructor = NodeProperties::GetValueInput(node, 0);

  // Check if the input is a known JSFunction.
  HeapObjectMatcher m(constructor);
  if (!m.HasValue()) return NoChange();
  Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value());
  Handle<Map> function_map(function->map(), isolate());
  Handle<Object> function_prototype(function_map->prototype(), isolate());

  // We can constant-fold the super constructor access if the
  // {function}s map is stable, i.e. we can use a code dependency
  // to guard against [[Prototype]] changes of {function}.
  if (function_map->is_stable()) {
    Node* value = jsgraph()->Constant(function_prototype);
    dependencies()->AssumeMapStable(function_map);
    if (function_prototype->IsConstructor()) {
      ReplaceWithValue(node, value);
      return Replace(value);
    }
  }

  return NoChange();
}

Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) {
  DCHECK_EQ(IrOpcode::kJSInstanceOf, node->opcode());
  FeedbackParameter const& p = FeedbackParameterOf(node->op());
  Node* object = NodeProperties::GetValueInput(node, 0);
  Node* constructor = NodeProperties::GetValueInput(node, 1);
  Node* context = NodeProperties::GetContextInput(node);
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* frame_state = NodeProperties::GetFrameStateInput(node);
  Node* control = NodeProperties::GetControlInput(node);

  // Check if the right hand side is a known {receiver}, or
  // we have feedback from the InstanceOfIC.
  Handle<JSObject> receiver;
  HeapObjectMatcher m(constructor);
  if (m.HasValue() && m.Value()->IsJSObject()) {
    receiver = Handle<JSObject>::cast(m.Value());
  } else if (p.feedback().IsValid()) {
    InstanceOfICNexus nexus(p.feedback().vector(), p.feedback().slot());
    if (!nexus.GetConstructorFeedback().ToHandle(&receiver)) return NoChange();
  } else {
    return NoChange();
  }
  Handle<Map> receiver_map(receiver->map(), isolate());

  // Compute property access info for @@hasInstance on {receiver}.
  PropertyAccessInfo access_info;
  AccessInfoFactory access_info_factory(dependencies(), native_context(),
                                        graph()->zone());
  if (!access_info_factory.ComputePropertyAccessInfo(
          receiver_map, factory()->has_instance_symbol(), AccessMode::kLoad,
          &access_info)) {
    return NoChange();
  }

  PropertyAccessBuilder access_builder(jsgraph(), dependencies());

  if (access_info.IsNotFound()) {
    // If there's no @@hasInstance handler, the OrdinaryHasInstance operation
    // takes over, but that requires the {receiver} to be callable.
    if (receiver->IsCallable()) {
      // Determine actual holder and perform prototype chain checks.
      Handle<JSObject> holder;
      if (access_info.holder().ToHandle(&holder)) {
        access_builder.AssumePrototypesStable(
            native_context(), access_info.receiver_maps(), holder);
      }

      // Check that {constructor} is actually {receiver}.
      constructor = access_builder.BuildCheckValue(constructor, &effect,
                                                   control, receiver);

      // Monomorphic property access.
      access_builder.BuildCheckMaps(constructor, &effect, control,
                                    access_info.receiver_maps());

      // Lower to OrdinaryHasInstance(C, O).
      NodeProperties::ReplaceValueInput(node, constructor, 0);
      NodeProperties::ReplaceValueInput(node, object, 1);
      NodeProperties::ReplaceEffectInput(node, effect);
      NodeProperties::ChangeOp(node, javascript()->OrdinaryHasInstance());
      Reduction const reduction = ReduceJSOrdinaryHasInstance(node);
      return reduction.Changed() ? reduction : Changed(node);
    }
  } else if (access_info.IsDataConstant() ||
             access_info.IsDataConstantField()) {
    // Determine actual holder and perform prototype chain checks.
    Handle<JSObject> holder;
    if (access_info.holder().ToHandle(&holder)) {
      access_builder.AssumePrototypesStable(
          native_context(), access_info.receiver_maps(), holder);
    } else {
      holder = receiver;
    }

    Handle<Object> constant;
    if (access_info.IsDataConstant()) {
      DCHECK(!FLAG_track_constant_fields);
      constant = access_info.constant();
    } else {
      DCHECK(FLAG_track_constant_fields);
      DCHECK(access_info.IsDataConstantField());
      // The value must be callable therefore tagged.
      DCHECK(CanBeTaggedPointer(access_info.field_representation()));
      FieldIndex field_index = access_info.field_index();
      constant = JSObject::FastPropertyAt(holder, Representation::Tagged(),
                                          field_index);
    }
    DCHECK(constant->IsCallable());

    // Check that {constructor} is actually {receiver}.
    constructor =
        access_builder.BuildCheckValue(constructor, &effect, control, receiver);

    // Monomorphic property access.
    access_builder.BuildCheckMaps(constructor, &effect, control,
                                  access_info.receiver_maps());

    // Create a nested frame state inside the current method's most-recent frame
    // state that will ensure that deopts that happen after this point will not
    // fallback to the last Checkpoint--which would completely re-execute the
    // instanceof logic--but rather create an activation of a version of the
    // ToBoolean stub that finishes the remaining work of instanceof and returns
    // to the caller without duplicating side-effects upon a lazy deopt.
    Node* continuation_frame_state = CreateStubBuiltinContinuationFrameState(
        jsgraph(), Builtins::kToBooleanLazyDeoptContinuation, context, nullptr,
        0, frame_state, ContinuationFrameStateMode::LAZY);

    // Call the @@hasInstance handler.
    Node* target = jsgraph()->Constant(constant);
    node->InsertInput(graph()->zone(), 0, target);
    node->ReplaceInput(1, constructor);
    node->ReplaceInput(2, object);
    node->ReplaceInput(4, continuation_frame_state);
    node->ReplaceInput(5, effect);
    NodeProperties::ChangeOp(
        node, javascript()->Call(3, CallFrequency(), VectorSlotPair(),
                                 ConvertReceiverMode::kNotNullOrUndefined));

    // Rewire the value uses of {node} to ToBoolean conversion of the result.
    Node* value = graph()->NewNode(simplified()->ToBoolean(), node);
    for (Edge edge : node->use_edges()) {
      if (NodeProperties::IsValueEdge(edge) && edge.from() != value) {
        edge.UpdateTo(value);
        Revisit(edge.from());
      }
    }
    return Changed(node);
  }

  return NoChange();
}

JSNativeContextSpecialization::InferHasInPrototypeChainResult
JSNativeContextSpecialization::InferHasInPrototypeChain(
    Node* receiver, Node* effect, Handle<HeapObject> prototype) {
  ZoneHandleSet<Map> receiver_maps;
  NodeProperties::InferReceiverMapsResult result =
      NodeProperties::InferReceiverMaps(receiver, effect, &receiver_maps);
  if (result == NodeProperties::kNoReceiverMaps) return kMayBeInPrototypeChain;

  // Check if either all or none of the {receiver_maps} have the given
  // {prototype} in their prototype chain.
  bool all = true;
  bool none = true;
  for (size_t i = 0; i < receiver_maps.size(); ++i) {
    Handle<Map> receiver_map = receiver_maps[i];
    if (receiver_map->instance_type() <= LAST_SPECIAL_RECEIVER_TYPE) {
      return kMayBeInPrototypeChain;
    }
    if (result == NodeProperties::kUnreliableReceiverMaps) {
      // In case of an unreliable {result} we need to ensure that all
      // {receiver_maps} are stable, because otherwise we cannot trust
      // the {receiver_maps} information, since arbitrary side-effects
      // may have happened.
      if (!receiver_map->is_stable()) {
        return kMayBeInPrototypeChain;
      }
    }
    for (PrototypeIterator j(receiver_map);; j.Advance()) {
      if (j.IsAtEnd()) {
        all = false;
        break;
      }
      Handle<HeapObject> const current =
          PrototypeIterator::GetCurrent<HeapObject>(j);
      if (current.is_identical_to(prototype)) {
        none = false;
        break;
      }
      if (!current->map()->is_stable() ||
          current->map()->instance_type() <= LAST_SPECIAL_RECEIVER_TYPE) {
        return kMayBeInPrototypeChain;
      }
    }
  }
  DCHECK_IMPLIES(all, !none);
  DCHECK_IMPLIES(none, !all);

  if (all) return kIsInPrototypeChain;
  if (none) return kIsNotInPrototypeChain;
  return kMayBeInPrototypeChain;
}

Reduction JSNativeContextSpecialization::ReduceJSHasInPrototypeChain(
    Node* node) {
  DCHECK_EQ(IrOpcode::kJSHasInPrototypeChain, node->opcode());
  Node* value = NodeProperties::GetValueInput(node, 0);
  Node* prototype = NodeProperties::GetValueInput(node, 1);
  Node* effect = NodeProperties::GetEffectInput(node);

  // Check if we can constant-fold the prototype chain walk
  // for the given {value} and the {prototype}.
  HeapObjectMatcher m(prototype);
  if (m.HasValue()) {
    InferHasInPrototypeChainResult result =
        InferHasInPrototypeChain(value, effect, m.Value());
    if (result != kMayBeInPrototypeChain) {
      Node* value = jsgraph()->BooleanConstant(result == kIsInPrototypeChain);
      ReplaceWithValue(node, value);
      return Replace(value);
    }
  }

  return NoChange();
}

Reduction JSNativeContextSpecialization::ReduceJSOrdinaryHasInstance(
    Node* node) {
  DCHECK_EQ(IrOpcode::kJSOrdinaryHasInstance, node->opcode());
  Node* constructor = NodeProperties::GetValueInput(node, 0);
  Node* object = NodeProperties::GetValueInput(node, 1);

  // Check if the {constructor} is known at compile time.
  HeapObjectMatcher m(constructor);
  if (!m.HasValue()) return NoChange();

  // Check if the {constructor} is a JSBoundFunction.
  if (m.Value()->IsJSBoundFunction()) {
    // OrdinaryHasInstance on bound functions turns into a recursive
    // invocation of the instanceof operator again.
    // ES6 section 7.3.19 OrdinaryHasInstance (C, O) step 2.
    Handle<JSBoundFunction> function = Handle<JSBoundFunction>::cast(m.Value());
    Handle<JSReceiver> bound_target_function(function->bound_target_function());
    NodeProperties::ReplaceValueInput(node, object, 0);
    NodeProperties::ReplaceValueInput(
        node, jsgraph()->HeapConstant(bound_target_function), 1);
    NodeProperties::ChangeOp(node, javascript()->InstanceOf(VectorSlotPair()));
    Reduction const reduction = ReduceJSInstanceOf(node);
    return reduction.Changed() ? reduction : Changed(node);
  }

  // Check if the {constructor} is a JSFunction.
  if (m.Value()->IsJSFunction()) {
    // Check if the {function} is a constructor and has an instance "prototype".
    Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value());
    if (function->IsConstructor() && function->has_prototype_slot() &&
        function->has_instance_prototype() &&
        function->prototype()->IsJSReceiver()) {
      // Ensure that the {function} has a valid initial map, so we can
      // depend on that for the prototype constant-folding below.
      JSFunction::EnsureHasInitialMap(function);

      // Install a code dependency on the {function}s initial map.
      Handle<Map> initial_map(function->initial_map(), isolate());
      dependencies()->AssumeInitialMapCantChange(initial_map);
      Node* prototype =
          jsgraph()->Constant(handle(initial_map->prototype(), isolate()));

      // Lower the {node} to JSHasInPrototypeChain.
      NodeProperties::ReplaceValueInput(node, object, 0);
      NodeProperties::ReplaceValueInput(node, prototype, 1);
      NodeProperties::ChangeOp(node, javascript()->HasInPrototypeChain());
      Reduction const reduction = ReduceJSHasInPrototypeChain(node);
      return reduction.Changed() ? reduction : Changed(node);
    }
  }

  return NoChange();
}

Reduction JSNativeContextSpecialization::ReduceJSLoadContext(Node* node) {
  DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode());
  ContextAccess const& access = ContextAccessOf(node->op());
  // Specialize JSLoadContext(NATIVE_CONTEXT_INDEX) to the known native
  // context (if any), so we can constant-fold those fields, which is
  // safe, since the NATIVE_CONTEXT_INDEX slot is always immutable.
  if (access.index() == Context::NATIVE_CONTEXT_INDEX) {
    Node* value = jsgraph()->HeapConstant(native_context());
    ReplaceWithValue(node, value);
    return Replace(value);
  }
  return NoChange();
}

namespace {

FieldAccess ForPropertyCellValue(MachineRepresentation representation,
                                 Type* type, MaybeHandle<Map> map,
                                 Handle<Name> name) {
  WriteBarrierKind kind = kFullWriteBarrier;
  if (representation == MachineRepresentation::kTaggedSigned) {
    kind = kNoWriteBarrier;
  } else if (representation == MachineRepresentation::kTaggedPointer) {
    kind = kPointerWriteBarrier;
  }
  MachineType r = MachineType::TypeForRepresentation(representation);
  FieldAccess access = {
      kTaggedBase, PropertyCell::kValueOffset, name, map, type, r, kind};
  return access;
}

}  // namespace

Reduction JSNativeContextSpecialization::ReduceGlobalAccess(
    Node* node, Node* receiver, Node* value, Handle<Name> name,
    AccessMode access_mode, Node* index) {
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);

  // Lookup on the global object. We only deal with own data properties
  // of the global object here (represented as PropertyCell).
  LookupIterator it(global_object(), name, LookupIterator::OWN);
  it.TryLookupCachedProperty();
  if (it.state() != LookupIterator::DATA) return NoChange();
  if (!it.GetHolder<JSObject>()->IsJSGlobalObject()) return NoChange();
  Handle<PropertyCell> property_cell = it.GetPropertyCell();
  PropertyDetails property_details = property_cell->property_details();
  Handle<Object> property_cell_value(property_cell->value(), isolate());
  PropertyCellType property_cell_type = property_details.cell_type();

  // We have additional constraints for stores.
  if (access_mode == AccessMode::kStore) {
    if (property_details.IsReadOnly()) {
      // Don't even bother trying to lower stores to read-only data properties.
      return NoChange();
    } else if (property_cell_type == PropertyCellType::kUndefined) {
      // There's no fast-path for dealing with undefined property cells.
      return NoChange();
    } else if (property_cell_type == PropertyCellType::kConstantType) {
      // There's also no fast-path to store to a global cell which pretended
      // to be stable, but is no longer stable now.
      if (property_cell_value->IsHeapObject() &&
          !Handle<HeapObject>::cast(property_cell_value)->map()->is_stable()) {
        return NoChange();
      }
    }
  }

  // Ensure that {index} matches the specified {name} (if {index} is given).
  if (index != nullptr) {
    effect = BuildCheckEqualsName(name, index, effect, control);
  }

  // Check if we have a {receiver} to validate. If so, we need to check that
  // the {receiver} is actually the JSGlobalProxy for the native context that
  // we are specializing to.
  if (receiver != nullptr) {
    Node* check = graph()->NewNode(simplified()->ReferenceEqual(), receiver,
                                   jsgraph()->HeapConstant(global_proxy()));
    effect = graph()->NewNode(
        simplified()->CheckIf(DeoptimizeReason::kReceiverNotAGlobalProxy),
        check, effect, control);
  }

  if (access_mode == AccessMode::kLoad) {
    // Load from non-configurable, read-only data property on the global
    // object can be constant-folded, even without deoptimization support.
    if (!property_details.IsConfigurable() && property_details.IsReadOnly()) {
      value = jsgraph()->Constant(property_cell_value);
    } else {
      // Record a code dependency on the cell if we can benefit from the
      // additional feedback, or the global property is configurable (i.e.
      // can be deleted or reconfigured to an accessor property).
      if (property_details.cell_type() != PropertyCellType::kMutable ||
          property_details.IsConfigurable()) {
        dependencies()->AssumePropertyCell(property_cell);
      }

      // Load from constant/undefined global property can be constant-folded.
      if (property_details.cell_type() == PropertyCellType::kConstant ||
          property_details.cell_type() == PropertyCellType::kUndefined) {
        value = jsgraph()->Constant(property_cell_value);
      } else {
        // Load from constant type cell can benefit from type feedback.
        MaybeHandle<Map> map;
        Type* property_cell_value_type = Type::NonInternal();
        MachineRepresentation representation = MachineRepresentation::kTagged;
        if (property_details.cell_type() == PropertyCellType::kConstantType) {
          // Compute proper type based on the current value in the cell.
          if (property_cell_value->IsSmi()) {
            property_cell_value_type = Type::SignedSmall();
            representation = MachineRepresentation::kTaggedSigned;
          } else if (property_cell_value->IsNumber()) {
            property_cell_value_type = Type::Number();
            representation = MachineRepresentation::kTaggedPointer;
          } else {
            Handle<Map> property_cell_value_map(
                Handle<HeapObject>::cast(property_cell_value)->map(),
                isolate());
            property_cell_value_type = Type::For(property_cell_value_map);
            representation = MachineRepresentation::kTaggedPointer;

            // We can only use the property cell value map for map check
            // elimination if it's stable, i.e. the HeapObject wasn't
            // mutated without the cell state being updated.
            if (property_cell_value_map->is_stable()) {
              dependencies()->AssumeMapStable(property_cell_value_map);
              map = property_cell_value_map;
            }
          }
        }
        value = effect = graph()->NewNode(
            simplified()->LoadField(ForPropertyCellValue(
                representation, property_cell_value_type, map, name)),
            jsgraph()->HeapConstant(property_cell), effect, control);
      }
    }
  } else {
    DCHECK_EQ(AccessMode::kStore, access_mode);
    DCHECK(!property_details.IsReadOnly());
    switch (property_details.cell_type()) {
      case PropertyCellType::kUndefined: {
        UNREACHABLE();
        break;
      }
      case PropertyCellType::kConstant: {
        // Record a code dependency on the cell, and just deoptimize if the new
        // value doesn't match the previous value stored inside the cell.
        dependencies()->AssumePropertyCell(property_cell);
        Node* check =
            graph()->NewNode(simplified()->ReferenceEqual(), value,
                             jsgraph()->Constant(property_cell_value));
        effect = graph()->NewNode(
            simplified()->CheckIf(DeoptimizeReason::kValueMismatch), check,
            effect, control);
        break;
      }
      case PropertyCellType::kConstantType: {
        // Record a code dependency on the cell, and just deoptimize if the new
        // values' type doesn't match the type of the previous value in the
        // cell.
        dependencies()->AssumePropertyCell(property_cell);
        Type* property_cell_value_type;
        MachineRepresentation representation = MachineRepresentation::kTagged;
        if (property_cell_value->IsHeapObject()) {
          // We cannot do anything if the {property_cell_value}s map is no
          // longer stable.
          Handle<Map> property_cell_value_map(
              Handle<HeapObject>::cast(property_cell_value)->map(), isolate());
          DCHECK(property_cell_value_map->is_stable());
          dependencies()->AssumeMapStable(property_cell_value_map);

          // Check that the {value} is a HeapObject.
          value = effect = graph()->NewNode(simplified()->CheckHeapObject(),
                                            value, effect, control);

          // Check {value} map against the {property_cell} map.
          effect =
              graph()->NewNode(simplified()->CheckMaps(
                                   CheckMapsFlag::kNone,
                                   ZoneHandleSet<Map>(property_cell_value_map)),
                               value, effect, control);
          property_cell_value_type = Type::OtherInternal();
          representation = MachineRepresentation::kTaggedPointer;
        } else {
          // Check that the {value} is a Smi.
          value = effect = graph()->NewNode(
              simplified()->CheckSmi(VectorSlotPair()), value, effect, control);
          property_cell_value_type = Type::SignedSmall();
          representation = MachineRepresentation::kTaggedSigned;
        }
        effect = graph()->NewNode(simplified()->StoreField(ForPropertyCellValue(
                                      representation, property_cell_value_type,
                                      MaybeHandle<Map>(), name)),
                                  jsgraph()->HeapConstant(property_cell), value,
                                  effect, control);
        break;
      }
      case PropertyCellType::kMutable: {
        // Record a code dependency on the cell, and just deoptimize if the
        // property ever becomes read-only.
        dependencies()->AssumePropertyCell(property_cell);
        effect = graph()->NewNode(
            simplified()->StoreField(ForPropertyCellValue(
                MachineRepresentation::kTagged, Type::NonInternal(),
                MaybeHandle<Map>(), name)),
            jsgraph()->HeapConstant(property_cell), value, effect, control);
        break;
      }
    }
  }

  ReplaceWithValue(node, value, effect, control);
  return Replace(value);
}

Reduction JSNativeContextSpecialization::ReduceJSLoadGlobal(Node* node) {
  DCHECK_EQ(IrOpcode::kJSLoadGlobal, node->opcode());
  Handle<Name> name = LoadGlobalParametersOf(node->op()).name();
  Node* effect = NodeProperties::GetEffectInput(node);

  // Try to lookup the name on the script context table first (lexical scoping).
  ScriptContextTableLookupResult result;
  if (LookupInScriptContextTable(name, &result)) {
    if (result.context->is_the_hole(isolate(), result.index)) return NoChange();
    Node* context = jsgraph()->HeapConstant(result.context);
    Node* value = effect = graph()->NewNode(
        javascript()->LoadContext(0, result.index, result.immutable), context,
        effect);
    ReplaceWithValue(node, value, effect);
    return Replace(value);
  }

  // Lookup the {name} on the global object instead.
  return ReduceGlobalAccess(node, nullptr, nullptr, name, AccessMode::kLoad);
}

Reduction JSNativeContextSpecialization::ReduceJSStoreGlobal(Node* node) {
  DCHECK_EQ(IrOpcode::kJSStoreGlobal, node->opcode());
  Handle<Name> name = StoreGlobalParametersOf(node->op()).name();
  Node* value = NodeProperties::GetValueInput(node, 0);
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);

  // Try to lookup the name on the script context table first (lexical scoping).
  ScriptContextTableLookupResult result;
  if (LookupInScriptContextTable(name, &result)) {
    if (result.context->is_the_hole(isolate(), result.index)) return NoChange();
    if (result.immutable) return NoChange();
    Node* context = jsgraph()->HeapConstant(result.context);
    effect = graph()->NewNode(javascript()->StoreContext(0, result.index),
                              value, context, effect, control);
    ReplaceWithValue(node, value, effect, control);
    return Replace(value);
  }

  // Lookup the {name} on the global object instead.
  return ReduceGlobalAccess(node, nullptr, value, name, AccessMode::kStore);
}

Reduction JSNativeContextSpecialization::ReduceNamedAccess(
    Node* node, Node* value, MapHandles const& receiver_maps, Handle<Name> name,
    AccessMode access_mode, Node* index) {
  DCHECK(node->opcode() == IrOpcode::kJSLoadNamed ||
         node->opcode() == IrOpcode::kJSStoreNamed ||
         node->opcode() == IrOpcode::kJSLoadProperty ||
         node->opcode() == IrOpcode::kJSStoreProperty ||
         node->opcode() == IrOpcode::kJSStoreNamedOwn);
  Node* receiver = NodeProperties::GetValueInput(node, 0);
  Node* context = NodeProperties::GetContextInput(node);
  Node* frame_state = NodeProperties::GetFrameStateInput(node);
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);

  // Check if we have an access o.x or o.x=v where o is the current
  // native contexts' global proxy, and turn that into a direct access
  // to the current native contexts' global object instead.
  if (receiver_maps.size() == 1) {
    Handle<Map> receiver_map = receiver_maps.front();
    if (receiver_map->IsJSGlobalProxyMap()) {
      Object* maybe_constructor = receiver_map->GetConstructor();
      // Detached global proxies have |null| as their constructor.
      if (maybe_constructor->IsJSFunction() &&
          JSFunction::cast(maybe_constructor)->native_context() ==
              *native_context()) {
        return ReduceGlobalAccess(node, receiver, value, name, access_mode,
                                  index);
      }
    }
  }

  // Compute property access infos for the receiver maps.
  AccessInfoFactory access_info_factory(dependencies(), native_context(),
                                        graph()->zone());
  ZoneVector<PropertyAccessInfo> access_infos(zone());
  if (!access_info_factory.ComputePropertyAccessInfos(
          receiver_maps, name, access_mode, &access_infos)) {
    return NoChange();
  }

  // Nothing to do if we have no non-deprecated maps.
  if (access_infos.empty()) {
    return ReduceSoftDeoptimize(
        node, DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess);
  }

  // Ensure that {index} matches the specified {name} (if {index} is given).
  if (index != nullptr) {
    effect = BuildCheckEqualsName(name, index, effect, control);
  }

  // Collect call nodes to rewire exception edges.
  ZoneVector<Node*> if_exception_nodes(zone());
  ZoneVector<Node*>* if_exceptions = nullptr;
  Node* if_exception = nullptr;
  if (NodeProperties::IsExceptionalCall(node, &if_exception)) {
    if_exceptions = &if_exception_nodes;
  }

  PropertyAccessBuilder access_builder(jsgraph(), dependencies());

  // Check for the monomorphic cases.
  if (access_infos.size() == 1) {
    PropertyAccessInfo access_info = access_infos.front();
    // Try to build string check or number check if possible.
    // Otherwise build a map check.
    if (!access_builder.TryBuildStringCheck(access_info.receiver_maps(),
                                            &receiver, &effect, control) &&
        !access_builder.TryBuildNumberCheck(access_info.receiver_maps(),
                                            &receiver, &effect, control)) {
      if (HasNumberMaps(access_info.receiver_maps())) {
        // We need to also let Smi {receiver}s through in this case, so
        // we construct a diamond, guarded by the Sminess of the {receiver}
        // and if {receiver} is not a Smi just emit a sequence of map checks.
        Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver);
        Node* branch = graph()->NewNode(common()->Branch(), check, control);

        Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
        Node* etrue = effect;

        Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
        Node* efalse = effect;
        {
          access_builder.BuildCheckMaps(receiver, &efalse, if_false,
                                        access_info.receiver_maps());
        }

        control = graph()->NewNode(common()->Merge(2), if_true, if_false);
        effect =
            graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
      } else {
        receiver =
            access_builder.BuildCheckHeapObject(receiver, &effect, control);
        access_builder.BuildCheckMaps(receiver, &effect, control,
                                      access_info.receiver_maps());
      }
    }

    // Generate the actual property access.
    ValueEffectControl continuation = BuildPropertyAccess(
        receiver, value, context, frame_state, effect, control, name,
        if_exceptions, access_info, access_mode);
    value = continuation.value();
    effect = continuation.effect();
    control = continuation.control();
  } else {
    // The final states for every polymorphic branch. We join them with
    // Merge+Phi+EffectPhi at the bottom.
    ZoneVector<Node*> values(zone());
    ZoneVector<Node*> effects(zone());
    ZoneVector<Node*> controls(zone());

    // Check if {receiver} may be a number.
    bool receiverissmi_possible = false;
    for (PropertyAccessInfo const& access_info : access_infos) {
      if (HasNumberMaps(access_info.receiver_maps())) {
        receiverissmi_possible = true;
        break;
      }
    }

    // Ensure that {receiver} is a heap object.
    Node* receiverissmi_control = nullptr;
    Node* receiverissmi_effect = effect;
    if (receiverissmi_possible) {
      Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver);
      Node* branch = graph()->NewNode(common()->Branch(), check, control);
      control = graph()->NewNode(common()->IfFalse(), branch);
      receiverissmi_control = graph()->NewNode(common()->IfTrue(), branch);
      receiverissmi_effect = effect;
    } else {
      receiver =
          access_builder.BuildCheckHeapObject(receiver, &effect, control);
    }

    // Generate code for the various different property access patterns.
    Node* fallthrough_control = control;
    for (size_t j = 0; j < access_infos.size(); ++j) {
      PropertyAccessInfo const& access_info = access_infos[j];
      Node* this_value = value;
      Node* this_receiver = receiver;
      Node* this_effect = effect;
      Node* this_control = fallthrough_control;

      // Perform map check on {receiver}.
      MapHandles const& receiver_maps = access_info.receiver_maps();
      {
        // Whether to insert a dedicated MapGuard node into the
        // effect to be able to learn from the control flow.
        bool insert_map_guard = true;

        // Check maps for the {receiver}s.
        if (j == access_infos.size() - 1) {
          // Last map check on the fallthrough control path, do a
          // conditional eager deoptimization exit here.
          access_builder.BuildCheckMaps(receiver, &this_effect, this_control,
                                        receiver_maps);
          fallthrough_control = nullptr;

          // Don't insert a MapGuard in this case, as the CheckMaps
          // node already gives you all the information you need
          // along the effect chain.
          insert_map_guard = false;
        } else {
          // Explicitly branch on the {receiver_maps}.
          ZoneHandleSet<Map> maps;
          for (Handle<Map> map : receiver_maps) {
            maps.insert(map, graph()->zone());
          }
          Node* check = this_effect =
              graph()->NewNode(simplified()->CompareMaps(maps), receiver,
                               this_effect, this_control);
          Node* branch =
              graph()->NewNode(common()->Branch(), check, this_control);
          fallthrough_control = graph()->NewNode(common()->IfFalse(), branch);
          this_control = graph()->NewNode(common()->IfTrue(), branch);
        }

        // The Number case requires special treatment to also deal with Smis.
        if (HasNumberMaps(receiver_maps)) {
          // Join this check with the "receiver is smi" check above.
          DCHECK_NOT_NULL(receiverissmi_effect);
          DCHECK_NOT_NULL(receiverissmi_control);
          this_control = graph()->NewNode(common()->Merge(2), this_control,
                                          receiverissmi_control);
          this_effect = graph()->NewNode(common()->EffectPhi(2), this_effect,
                                         receiverissmi_effect, this_control);
          receiverissmi_effect = receiverissmi_control = nullptr;

          // The {receiver} can also be a Smi in this case, so
          // a MapGuard doesn't make sense for this at all.
          insert_map_guard = false;
        }

        // Introduce a MapGuard to learn from this on the effect chain.
        if (insert_map_guard) {
          ZoneHandleSet<Map> maps;
          for (auto receiver_map : receiver_maps) {
            maps.insert(receiver_map, graph()->zone());
          }
          this_effect = graph()->NewNode(simplified()->MapGuard(maps), receiver,
                                         this_effect, this_control);
        }
      }

      // Generate the actual property access.
      ValueEffectControl continuation = BuildPropertyAccess(
          this_receiver, this_value, context, frame_state, this_effect,
          this_control, name, if_exceptions, access_info, access_mode);
      values.push_back(continuation.value());
      effects.push_back(continuation.effect());
      controls.push_back(continuation.control());
    }

    DCHECK_NULL(fallthrough_control);

    // Generate the final merge point for all (polymorphic) branches.
    int const control_count = static_cast<int>(controls.size());
    if (control_count == 0) {
      value = effect = control = jsgraph()->Dead();
    } else if (control_count == 1) {
      value = values.front();
      effect = effects.front();
      control = controls.front();
    } else {
      control = graph()->NewNode(common()->Merge(control_count), control_count,
                                 &controls.front());
      values.push_back(control);
      value = graph()->NewNode(
          common()->Phi(MachineRepresentation::kTagged, control_count),
          control_count + 1, &values.front());
      effects.push_back(control);
      effect = graph()->NewNode(common()->EffectPhi(control_count),
                                control_count + 1, &effects.front());
    }
  }

  // Properly rewire IfException edges if {node} is inside a try-block.
  if (!if_exception_nodes.empty()) {
    DCHECK_NOT_NULL(if_exception);
    DCHECK_EQ(if_exceptions, &if_exception_nodes);
    int const if_exception_count = static_cast<int>(if_exceptions->size());
    Node* merge = graph()->NewNode(common()->Merge(if_exception_count),
                                   if_exception_count, &if_exceptions->front());
    if_exceptions->push_back(merge);
    Node* ephi =
        graph()->NewNode(common()->EffectPhi(if_exception_count),
                         if_exception_count + 1, &if_exceptions->front());
    Node* phi = graph()->NewNode(
        common()->Phi(MachineRepresentation::kTagged, if_exception_count),
        if_exception_count + 1, &if_exceptions->front());
    ReplaceWithValue(if_exception, phi, ephi, merge);
  }

  ReplaceWithValue(node, value, effect, control);
  return Replace(value);
}

Reduction JSNativeContextSpecialization::ReduceNamedAccessFromNexus(
    Node* node, Node* value, FeedbackNexus const& nexus, Handle<Name> name,
    AccessMode access_mode) {
  DCHECK(node->opcode() == IrOpcode::kJSLoadNamed ||
         node->opcode() == IrOpcode::kJSStoreNamed ||
         node->opcode() == IrOpcode::kJSStoreNamedOwn);
  Node* const receiver = NodeProperties::GetValueInput(node, 0);
  Node* const effect = NodeProperties::GetEffectInput(node);

  // Check if we are accessing the current native contexts' global proxy.
  HeapObjectMatcher m(receiver);
  if (m.HasValue() && m.Value().is_identical_to(global_proxy())) {
    // Optimize accesses to the current native contexts' global proxy.
    return ReduceGlobalAccess(node, nullptr, value, name, access_mode);
  }

  // Check if the {nexus} reports type feedback for the IC.
  if (nexus.IsUninitialized()) {
    if (flags() & kBailoutOnUninitialized) {
      return ReduceSoftDeoptimize(
          node,
          DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess);
    }
    return NoChange();
  }

  // Extract receiver maps from the IC using the {nexus}.
  MapHandles receiver_maps;
  if (!ExtractReceiverMaps(receiver, effect, nexus, &receiver_maps)) {
    return NoChange();
  } else if (receiver_maps.empty()) {
    if (flags() & kBailoutOnUninitialized) {
      return ReduceSoftDeoptimize(
          node,
          DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess);
    }
    return NoChange();
  }

  // Try to lower the named access based on the {receiver_maps}.
  return ReduceNamedAccess(node, value, receiver_maps, name, access_mode);
}

Reduction JSNativeContextSpecialization::ReduceJSLoadNamed(Node* node) {
  DCHECK_EQ(IrOpcode::kJSLoadNamed, node->opcode());
  NamedAccess const& p = NamedAccessOf(node->op());
  Node* const receiver = NodeProperties::GetValueInput(node, 0);
  Node* const value = jsgraph()->Dead();

  // Check if we have a constant receiver.
  HeapObjectMatcher m(receiver);
  if (m.HasValue()) {
    if (m.Value()->IsJSFunction() &&
        p.name().is_identical_to(factory()->prototype_string())) {
      // Optimize "prototype" property of functions.
      Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value());
      if (function->IsConstructor()) {
        // We need to add a code dependency on the initial map of the
        // {function} in order to be notified about changes to the
        // "prototype" of {function}.
        JSFunction::EnsureHasInitialMap(function);
        Handle<Map> initial_map(function->initial_map(), isolate());
        dependencies()->AssumeInitialMapCantChange(initial_map);
        Handle<Object> prototype(function->prototype(), isolate());
        Node* value = jsgraph()->Constant(prototype);
        ReplaceWithValue(node, value);
        return Replace(value);
      }
    } else if (m.Value()->IsString() &&
               p.name().is_identical_to(factory()->length_string())) {
      // Constant-fold "length" property on constant strings.
      Handle<String> string = Handle<String>::cast(m.Value());
      Node* value = jsgraph()->Constant(string->length());
      ReplaceWithValue(node, value);
      return Replace(value);
    }
  }

  // Extract receiver maps from the load IC using the LoadICNexus.
  if (!p.feedback().IsValid()) return NoChange();
  LoadICNexus nexus(p.feedback().vector(), p.feedback().slot());

  // Try to lower the named access based on the {receiver_maps}.
  return ReduceNamedAccessFromNexus(node, value, nexus, p.name(),
                                    AccessMode::kLoad);
}


Reduction JSNativeContextSpecialization::ReduceJSStoreNamed(Node* node) {
  DCHECK_EQ(IrOpcode::kJSStoreNamed, node->opcode());
  NamedAccess const& p = NamedAccessOf(node->op());
  Node* const value = NodeProperties::GetValueInput(node, 1);

  // Extract receiver maps from the store IC using the StoreICNexus.
  if (!p.feedback().IsValid()) return NoChange();
  StoreICNexus nexus(p.feedback().vector(), p.feedback().slot());

  // Try to lower the named access based on the {receiver_maps}.
  return ReduceNamedAccessFromNexus(node, value, nexus, p.name(),
                                    AccessMode::kStore);
}

Reduction JSNativeContextSpecialization::ReduceJSStoreNamedOwn(Node* node) {
  DCHECK_EQ(IrOpcode::kJSStoreNamedOwn, node->opcode());
  StoreNamedOwnParameters const& p = StoreNamedOwnParametersOf(node->op());
  Node* const value = NodeProperties::GetValueInput(node, 1);

  // Extract receiver maps from the IC using the StoreOwnICNexus.
  if (!p.feedback().IsValid()) return NoChange();
  StoreOwnICNexus nexus(p.feedback().vector(), p.feedback().slot());

  // Try to lower the creation of a named property based on the {receiver_maps}.
  return ReduceNamedAccessFromNexus(node, value, nexus, p.name(),
                                    AccessMode::kStoreInLiteral);
}

Reduction JSNativeContextSpecialization::ReduceElementAccess(
    Node* node, Node* index, Node* value, MapHandles const& receiver_maps,
    AccessMode access_mode, KeyedAccessLoadMode load_mode,
    KeyedAccessStoreMode store_mode) {
  DCHECK(node->opcode() == IrOpcode::kJSLoadProperty ||
         node->opcode() == IrOpcode::kJSStoreProperty);
  Node* receiver = NodeProperties::GetValueInput(node, 0);
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);
  Node* frame_state = NodeProperties::FindFrameStateBefore(node);

  // Check for keyed access to strings.
  if (HasOnlyStringMaps(receiver_maps)) {
    // Strings are immutable in JavaScript.
    if (access_mode == AccessMode::kStore) return NoChange();

    // Ensure that the {receiver} is actually a String.
    receiver = effect = graph()->NewNode(
        simplified()->CheckString(VectorSlotPair()), receiver, effect, control);

    // Determine the {receiver} length.
    Node* length = graph()->NewNode(simplified()->StringLength(), receiver);

    // Load the single character string from {receiver} or yield undefined
    // if the {index} is out of bounds (depending on the {load_mode}).
    value = BuildIndexedStringLoad(receiver, index, length, &effect, &control,
                                   load_mode);
  } else {
    // Retrieve the native context from the given {node}.
    // Compute element access infos for the receiver maps.
    AccessInfoFactory access_info_factory(dependencies(), native_context(),
                                          graph()->zone());
    ZoneVector<ElementAccessInfo> access_infos(zone());
    if (!access_info_factory.ComputeElementAccessInfos(
            receiver_maps, access_mode, &access_infos)) {
      return NoChange();
    }

    // Nothing to do if we have no non-deprecated maps.
    if (access_infos.empty()) {
      return ReduceSoftDeoptimize(
          node,
          DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess);
    }

    // For holey stores or growing stores, we need to check that the prototype
    // chain contains no setters for elements, and we need to guard those checks
    // via code dependencies on the relevant prototype maps.
    if (access_mode == AccessMode::kStore) {
      // TODO(turbofan): We could have a fast path here, that checks for the
      // common case of Array or Object prototype only and therefore avoids
      // the zone allocation of this vector.
      ZoneVector<Handle<Map>> prototype_maps(zone());
      for (ElementAccessInfo const& access_info : access_infos) {
        for (Handle<Map> receiver_map : access_info.receiver_maps()) {
          // If the {receiver_map} has a prototype and it's elements backing
          // store is either holey, or we have a potentially growing store,
          // then we need to check that all prototypes have stable maps with
          // fast elements (and we need to guard against changes to that below).
          if (IsHoleyOrDictionaryElementsKind(receiver_map->elements_kind()) ||
              IsGrowStoreMode(store_mode)) {
            // Make sure all prototypes are stable and have fast elements.
            for (Handle<Map> map = receiver_map;;) {
              Handle<Object> map_prototype(map->prototype(), isolate());
              if (map_prototype->IsNull(isolate())) break;
              if (!map_prototype->IsJSObject()) return NoChange();
              map = handle(Handle<JSObject>::cast(map_prototype)->map(),
                           isolate());
              if (!map->is_stable()) return NoChange();
              if (!IsFastElementsKind(map->elements_kind())) return NoChange();
              prototype_maps.push_back(map);
            }
          }
        }
      }

      // Install dependencies on the relevant prototype maps.
      for (Handle<Map> prototype_map : prototype_maps) {
        dependencies()->AssumeMapStable(prototype_map);
      }
    }

    // Ensure that {receiver} is a heap object.
    PropertyAccessBuilder access_builder(jsgraph(), dependencies());
    receiver = access_builder.BuildCheckHeapObject(receiver, &effect, control);

    // Check for the monomorphic case.
    if (access_infos.size() == 1) {
      ElementAccessInfo access_info = access_infos.front();

      // Perform possible elements kind transitions.
      for (auto transition : access_info.transitions()) {
        Handle<Map> const transition_source = transition.first;
        Handle<Map> const transition_target = transition.second;
        effect = graph()->NewNode(
            simplified()->TransitionElementsKind(ElementsTransition(
                IsSimpleMapChangeTransition(transition_source->elements_kind(),
                                            transition_target->elements_kind())
                    ? ElementsTransition::kFastTransition
                    : ElementsTransition::kSlowTransition,
                transition_source, transition_target)),
            receiver, effect, control);
      }

      // TODO(turbofan): The effect/control linearization will not find a
      // FrameState after the StoreField or Call that is generated for the
      // elements kind transition above. This is because those operators
      // don't have the kNoWrite flag on it, even though they are not
      // observable by JavaScript.
      effect = graph()->NewNode(common()->Checkpoint(), frame_state, effect,
                                control);

      // Perform map check on the {receiver}.
      access_builder.BuildCheckMaps(receiver, &effect, control,
                                    access_info.receiver_maps());

      // Access the actual element.
      ValueEffectControl continuation =
          BuildElementAccess(receiver, index, value, effect, control,
                             access_info, access_mode, load_mode, store_mode);
      value = continuation.value();
      effect = continuation.effect();
      control = continuation.control();
    } else {
      // The final states for every polymorphic branch. We join them with
      // Merge+Phi+EffectPhi at the bottom.
      ZoneVector<Node*> values(zone());
      ZoneVector<Node*> effects(zone());
      ZoneVector<Node*> controls(zone());

      // Generate code for the various different element access patterns.
      Node* fallthrough_control = control;
      for (size_t j = 0; j < access_infos.size(); ++j) {
        ElementAccessInfo const& access_info = access_infos[j];
        Node* this_receiver = receiver;
        Node* this_value = value;
        Node* this_index = index;
        Node* this_effect = effect;
        Node* this_control = fallthrough_control;

        // Perform possible elements kind transitions.
        for (auto transition : access_info.transitions()) {
          Handle<Map> const transition_source = transition.first;
          Handle<Map> const transition_target = transition.second;
          this_effect = graph()->NewNode(
              simplified()->TransitionElementsKind(
                  ElementsTransition(IsSimpleMapChangeTransition(
                                         transition_source->elements_kind(),
                                         transition_target->elements_kind())
                                         ? ElementsTransition::kFastTransition
                                         : ElementsTransition::kSlowTransition,
                                     transition_source, transition_target)),
              receiver, this_effect, this_control);
        }

        // Perform map check(s) on {receiver}.
        MapHandles const& receiver_maps = access_info.receiver_maps();
        if (j == access_infos.size() - 1) {
          // Last map check on the fallthrough control path, do a
          // conditional eager deoptimization exit here.
          access_builder.BuildCheckMaps(receiver, &this_effect, this_control,
                                        receiver_maps);
          fallthrough_control = nullptr;
        } else {
          // Explicitly branch on the {receiver_maps}.
          ZoneHandleSet<Map> maps;
          for (Handle<Map> map : receiver_maps) {
            maps.insert(map, graph()->zone());
          }
          Node* check = this_effect =
              graph()->NewNode(simplified()->CompareMaps(maps), receiver,
                               this_effect, fallthrough_control);
          Node* branch =
              graph()->NewNode(common()->Branch(), check, fallthrough_control);
          fallthrough_control = graph()->NewNode(common()->IfFalse(), branch);
          this_control = graph()->NewNode(common()->IfTrue(), branch);

          // Introduce a MapGuard to learn from this on the effect chain.
          this_effect = graph()->NewNode(simplified()->MapGuard(maps), receiver,
                                         this_effect, this_control);
        }

        // Access the actual element.
        ValueEffectControl continuation = BuildElementAccess(
            this_receiver, this_index, this_value, this_effect, this_control,
            access_info, access_mode, load_mode, store_mode);
        values.push_back(continuation.value());
        effects.push_back(continuation.effect());
        controls.push_back(continuation.control());
      }

      DCHECK_NULL(fallthrough_control);

      // Generate the final merge point for all (polymorphic) branches.
      int const control_count = static_cast<int>(controls.size());
      if (control_count == 0) {
        value = effect = control = jsgraph()->Dead();
      } else if (control_count == 1) {
        value = values.front();
        effect = effects.front();
        control = controls.front();
      } else {
        control = graph()->NewNode(common()->Merge(control_count),
                                   control_count, &controls.front());
        values.push_back(control);
        value = graph()->NewNode(
            common()->Phi(MachineRepresentation::kTagged, control_count),
            control_count + 1, &values.front());
        effects.push_back(control);
        effect = graph()->NewNode(common()->EffectPhi(control_count),
                                  control_count + 1, &effects.front());
      }
    }
  }

  ReplaceWithValue(node, value, effect, control);
  return Replace(value);
}

template <typename KeyedICNexus>
Reduction JSNativeContextSpecialization::ReduceKeyedAccess(
    Node* node, Node* index, Node* value, KeyedICNexus const& nexus,
    AccessMode access_mode, KeyedAccessLoadMode load_mode,
    KeyedAccessStoreMode store_mode) {
  DCHECK(node->opcode() == IrOpcode::kJSLoadProperty ||
         node->opcode() == IrOpcode::kJSStoreProperty);
  Node* receiver = NodeProperties::GetValueInput(node, 0);
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);

  // Optimize the case where we load from a constant {receiver}.
  if (access_mode == AccessMode::kLoad) {
    HeapObjectMatcher mreceiver(receiver);
    if (mreceiver.HasValue() && !mreceiver.Value()->IsTheHole(isolate()) &&
        !mreceiver.Value()->IsNullOrUndefined(isolate())) {
      // Check whether we're accessing a known element on the {receiver}
      // that is non-configurable, non-writable (i.e. the {receiver} was
      // frozen using Object.freeze).
      NumberMatcher mindex(index);
      if (mindex.IsInteger() && mindex.IsInRange(0.0, kMaxUInt32 - 1.0)) {
        LookupIterator it(isolate(), mreceiver.Value(),
                          static_cast<uint32_t>(mindex.Value()),
                          LookupIterator::OWN);
        if (it.state() == LookupIterator::DATA) {
          if (it.IsReadOnly() && !it.IsConfigurable()) {
            // We can safely constant-fold the {index} access to {receiver},
            // since the element is non-configurable, non-writable and thus
            // cannot change anymore.
            value = jsgraph()->Constant(it.GetDataValue());
            ReplaceWithValue(node, value, effect, control);
            return Replace(value);
          }

          // Check if the {receiver} is a known constant with a copy-on-write
          // backing store, and whether {index} is within the appropriate
          // bounds. In that case we can constant-fold the access and only
          // check that the {elements} didn't change. This is sufficient as
          // the backing store of a copy-on-write JSArray is defensively copied
          // whenever the length or the elements (might) change.
          //
          // What's interesting here is that we don't need to map check the
          // {receiver}, since JSArray's will always have their elements in
          // the backing store.
          if (mreceiver.Value()->IsJSArray()) {
            Handle<JSArray> array = Handle<JSArray>::cast(mreceiver.Value());
            if (array->elements()->IsCowArray()) {
              Node* elements = effect = graph()->NewNode(
                  simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
                  receiver, effect, control);
              Handle<FixedArray> array_elements(
                  FixedArray::cast(array->elements()), isolate());
              Node* check =
                  graph()->NewNode(simplified()->ReferenceEqual(), elements,
                                   jsgraph()->HeapConstant(array_elements));
              effect = graph()->NewNode(
                  simplified()->CheckIf(
                      DeoptimizeReason::kCowArrayElementsChanged),
                  check, effect, control);
              value = jsgraph()->Constant(it.GetDataValue());
              ReplaceWithValue(node, value, effect, control);
              return Replace(value);
            }
          }
        }
      }

      // For constant Strings we can eagerly strength-reduce the keyed
      // accesses using the known length, which doesn't change.
      if (mreceiver.Value()->IsString()) {
        Handle<String> string = Handle<String>::cast(mreceiver.Value());

        // We can only assume that the {index} is a valid array index if the IC
        // is in element access mode and not MEGAMORPHIC, otherwise there's no
        // guard for the bounds check below.
        if (nexus.ic_state() != MEGAMORPHIC && nexus.GetKeyType() == ELEMENT) {
          // Ensure that {index} is less than {receiver} length.
          Node* length = jsgraph()->Constant(string->length());

          // Load the single character string from {receiver} or yield undefined
          // if the {index} is out of bounds (depending on the {load_mode}).
          value = BuildIndexedStringLoad(receiver, index, length, &effect,
                                         &control, load_mode);
          ReplaceWithValue(node, value, effect, control);
          return Replace(value);
        }
      }
    }
  }

  // Check if the {nexus} reports type feedback for the IC.
  if (nexus.IsUninitialized()) {
    if (flags() & kBailoutOnUninitialized) {
      return ReduceSoftDeoptimize(
          node,
          DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess);
    }
    return NoChange();
  }

  // Extract receiver maps from the {nexus}.
  MapHandles receiver_maps;
  if (!ExtractReceiverMaps(receiver, effect, nexus, &receiver_maps)) {
    return NoChange();
  } else if (receiver_maps.empty()) {
    if (flags() & kBailoutOnUninitialized) {
      return ReduceSoftDeoptimize(
          node,
          DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess);
    }
    return NoChange();
  }

  // Optimize access for constant {index}.
  HeapObjectMatcher mindex(index);
  if (mindex.HasValue() && mindex.Value()->IsPrimitive()) {
    // Keyed access requires a ToPropertyKey on the {index} first before
    // looking up the property on the object (see ES6 section 12.3.2.1).
    // We can only do this for non-observable ToPropertyKey invocations,
    // so we limit the constant indices to primitives at this point.
    Handle<Name> name;
    if (Object::ToName(isolate(), mindex.Value()).ToHandle(&name)) {
      uint32_t array_index;
      if (name->AsArrayIndex(&array_index)) {
        // Use the constant array index.
        index = jsgraph()->Constant(static_cast<double>(array_index));
      } else {
        name = factory()->InternalizeName(name);
        return ReduceNamedAccess(node, value, receiver_maps, name, access_mode);
      }
    }
  }

  // Check if we have feedback for a named access.
  if (Name* name = nexus.FindFirstName()) {
    return ReduceNamedAccess(node, value, receiver_maps,
                             handle(name, isolate()), access_mode, index);
  } else if (nexus.GetKeyType() != ELEMENT) {
    // The KeyedLoad/StoreIC has seen non-element accesses, so we cannot assume
    // that the {index} is a valid array index, thus we just let the IC continue
    // to deal with this load/store.
    return NoChange();
  } else if (nexus.ic_state() == MEGAMORPHIC) {
    // The KeyedLoad/StoreIC uses the MEGAMORPHIC state to guard the assumption
    // that a numeric {index} is within the valid bounds for {receiver}, i.e.
    // it transitions to MEGAMORPHIC once it sees an out-of-bounds access. Thus
    // we cannot continue here if the IC state is MEGAMORPHIC.
    return NoChange();
  }

  // Try to lower the element access based on the {receiver_maps}.
  return ReduceElementAccess(node, index, value, receiver_maps, access_mode,
                             load_mode, store_mode);
}

Reduction JSNativeContextSpecialization::ReduceSoftDeoptimize(
    Node* node, DeoptimizeReason reason) {
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);
  Node* frame_state = NodeProperties::FindFrameStateBefore(node);
  Node* deoptimize = graph()->NewNode(
      common()->Deoptimize(DeoptimizeKind::kSoft, reason, VectorSlotPair()),
      frame_state, effect, control);
  // TODO(bmeurer): This should be on the AdvancedReducer somehow.
  NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
  Revisit(graph()->end());
  node->TrimInputCount(0);
  NodeProperties::ChangeOp(node, common()->Dead());
  return Changed(node);
}

Reduction JSNativeContextSpecialization::ReduceJSLoadProperty(Node* node) {
  DCHECK_EQ(IrOpcode::kJSLoadProperty, node->opcode());
  PropertyAccess const& p = PropertyAccessOf(node->op());
  Node* receiver = NodeProperties::GetValueInput(node, 0);
  Node* name = NodeProperties::GetValueInput(node, 1);
  Node* value = jsgraph()->Dead();
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);

  // We can optimize a property load if it's being used inside a for..in,
  // so for code like this:
  //
  //   for (name in receiver) {
  //     value = receiver[name];
  //     ...
  //   }
  //
  // If the for..in is in fast-mode, we know that the {receiver} has {name}
  // as own property, otherwise the enumeration wouldn't include it. The graph
  // constructed by the BytecodeGraphBuilder in this case looks like this:

  // receiver
  //  ^    ^
  //  |    |
  //  |    +-+
  //  |      |
  //  |   JSToObject
  //  |      ^
  //  |      |
  //  |      |
  //  |  JSForInNext
  //  |      ^
  //  |      |
  //  +----+ |
  //       | |
  //       | |
  //   JSLoadProperty

  // If the for..in has only seen maps with enum cache consisting of keys
  // and indices so far, we can turn the {JSLoadProperty} into a map check
  // on the {receiver} and then just load the field value dynamically via
  // the {LoadFieldByIndex} operator. The map check is only necessary when
  // TurboFan cannot prove that there is no observable side effect between
  // the {JSForInNext} and the {JSLoadProperty} node.
  //
  // Also note that it's safe to look through the {JSToObject}, since the
  // [[Get]] operation does an implicit ToObject anyway, and these operations
  // are not observable.
  if (name->opcode() == IrOpcode::kJSForInNext) {
    ForInMode const mode = ForInModeOf(name->op());
    if (mode == ForInMode::kUseEnumCacheKeysAndIndices) {
      Node* object = NodeProperties::GetValueInput(name, 0);
      Node* enumerator = NodeProperties::GetValueInput(name, 2);
      Node* index = NodeProperties::GetValueInput(name, 3);
      if (object->opcode() == IrOpcode::kJSToObject) {
        object = NodeProperties::GetValueInput(object, 0);
      }
      if (object == receiver) {
        // No need to repeat the map check if we can prove that there's no
        // observable side effect between {effect} and {name].
        if (!NodeProperties::NoObservableSideEffectBetween(effect, name)) {
          // Check that the {receiver} map is still valid.
          Node* receiver_map = effect =
              graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
                               receiver, effect, control);
          Node* check = graph()->NewNode(simplified()->ReferenceEqual(),
                                         receiver_map, enumerator);
          effect = graph()->NewNode(
              simplified()->CheckIf(DeoptimizeReason::kWrongMap), check, effect,
              control);
        }

        // Load the enum cache indices from the {cache_type}.
        Node* descriptor_array = effect = graph()->NewNode(
            simplified()->LoadField(AccessBuilder::ForMapDescriptors()),
            enumerator, effect, control);
        Node* enum_cache = effect =
            graph()->NewNode(simplified()->LoadField(
                                 AccessBuilder::ForDescriptorArrayEnumCache()),
                             descriptor_array, effect, control);
        Node* enum_indices = effect = graph()->NewNode(
            simplified()->LoadField(AccessBuilder::ForEnumCacheIndices()),
            enum_cache, effect, control);

        // Ensure that the {enum_indices} are valid.
        Node* check = graph()->NewNode(
            simplified()->BooleanNot(),
            graph()->NewNode(simplified()->ReferenceEqual(), enum_indices,
                             jsgraph()->EmptyFixedArrayConstant()));
        effect = graph()->NewNode(
            simplified()->CheckIf(DeoptimizeReason::kWrongEnumIndices), check,
            effect, control);

        // Determine the index from the {enum_indices}.
        index = effect = graph()->NewNode(
            simplified()->LoadElement(
                AccessBuilder::ForFixedArrayElement(PACKED_SMI_ELEMENTS)),
            enum_indices, index, effect, control);

        // Load the actual field value.
        Node* value = effect = graph()->NewNode(
            simplified()->LoadFieldByIndex(), receiver, index, effect, control);
        ReplaceWithValue(node, value, effect, control);
        return Replace(value);
      }
    }
  }

  // Extract receiver maps from the keyed load IC using the KeyedLoadICNexus.
  if (!p.feedback().IsValid()) return NoChange();
  KeyedLoadICNexus nexus(p.feedback().vector(), p.feedback().slot());

  // Extract the keyed access load mode from the keyed load IC.
  KeyedAccessLoadMode load_mode = nexus.GetKeyedAccessLoadMode();

  // Try to lower the keyed access based on the {nexus}.
  return ReduceKeyedAccess(node, name, value, nexus, AccessMode::kLoad,
                           load_mode, STANDARD_STORE);
}

Reduction JSNativeContextSpecialization::ReduceJSStoreProperty(Node* node) {
  DCHECK_EQ(IrOpcode::kJSStoreProperty, node->opcode());
  PropertyAccess const& p = PropertyAccessOf(node->op());
  Node* const index = NodeProperties::GetValueInput(node, 1);
  Node* const value = NodeProperties::GetValueInput(node, 2);

  // Extract receiver maps from the keyed store IC using the KeyedStoreICNexus.
  if (!p.feedback().IsValid()) return NoChange();
  KeyedStoreICNexus nexus(p.feedback().vector(), p.feedback().slot());

  // Extract the keyed access store mode from the keyed store IC.
  KeyedAccessStoreMode store_mode = nexus.GetKeyedAccessStoreMode();

  // Try to lower the keyed access based on the {nexus}.
  return ReduceKeyedAccess(node, index, value, nexus, AccessMode::kStore,
                           STANDARD_LOAD, store_mode);
}

Node* JSNativeContextSpecialization::InlinePropertyGetterCall(
    Node* receiver, Node* context, Node* frame_state, Node** effect,
    Node** control, ZoneVector<Node*>* if_exceptions,
    PropertyAccessInfo const& access_info) {
  Node* target = jsgraph()->Constant(access_info.constant());
  FrameStateInfo const& frame_info = OpParameter<FrameStateInfo>(frame_state);
  Handle<SharedFunctionInfo> shared_info =
      frame_info.shared_info().ToHandleChecked();
  // Introduce the call to the getter function.
  Node* value;
  if (access_info.constant()->IsJSFunction()) {
    value = *effect = *control = graph()->NewNode(
        jsgraph()->javascript()->Call(2, CallFrequency(), VectorSlotPair(),
                                      ConvertReceiverMode::kNotNullOrUndefined),
        target, receiver, context, frame_state, *effect, *control);
  } else {
    DCHECK(access_info.constant()->IsFunctionTemplateInfo());
    Handle<FunctionTemplateInfo> function_template_info(
        Handle<FunctionTemplateInfo>::cast(access_info.constant()));
    DCHECK(!function_template_info->call_code()->IsUndefined(isolate()));
    Node* holder =
        access_info.holder().is_null()
            ? receiver
            : jsgraph()->Constant(access_info.holder().ToHandleChecked());
    value = InlineApiCall(receiver, holder, frame_state, nullptr, effect,
                          control, shared_info, function_template_info);
  }
  // Remember to rewire the IfException edge if this is inside a try-block.
  if (if_exceptions != nullptr) {
    // Create the appropriate IfException/IfSuccess projections.
    Node* const if_exception =
        graph()->NewNode(common()->IfException(), *control, *effect);
    Node* const if_success = graph()->NewNode(common()->IfSuccess(), *control);
    if_exceptions->push_back(if_exception);
    *control = if_success;
  }
  return value;
}

void JSNativeContextSpecialization::InlinePropertySetterCall(
    Node* receiver, Node* value, Node* context, Node* frame_state,
    Node** effect, Node** control, ZoneVector<Node*>* if_exceptions,
    PropertyAccessInfo const& access_info) {
  Node* target = jsgraph()->Constant(access_info.constant());
  FrameStateInfo const& frame_info = OpParameter<FrameStateInfo>(frame_state);
  Handle<SharedFunctionInfo> shared_info =
      frame_info.shared_info().ToHandleChecked();
  // Introduce the call to the setter function.
  if (access_info.constant()->IsJSFunction()) {
    *effect = *control = graph()->NewNode(
        jsgraph()->javascript()->Call(3, CallFrequency(), VectorSlotPair(),
                                      ConvertReceiverMode::kNotNullOrUndefined),
        target, receiver, value, context, frame_state, *effect, *control);
  } else {
    DCHECK(access_info.constant()->IsFunctionTemplateInfo());
    Handle<FunctionTemplateInfo> function_template_info(
        Handle<FunctionTemplateInfo>::cast(access_info.constant()));
    DCHECK(!function_template_info->call_code()->IsUndefined(isolate()));
    Node* holder =
        access_info.holder().is_null()
            ? receiver
            : jsgraph()->Constant(access_info.holder().ToHandleChecked());
    InlineApiCall(receiver, holder, frame_state, value, effect, control,
                  shared_info, function_template_info);
  }
  // Remember to rewire the IfException edge if this is inside a try-block.
  if (if_exceptions != nullptr) {
    // Create the appropriate IfException/IfSuccess projections.
    Node* const if_exception =
        graph()->NewNode(common()->IfException(), *control, *effect);
    Node* const if_success = graph()->NewNode(common()->IfSuccess(), *control);
    if_exceptions->push_back(if_exception);
    *control = if_success;
  }
}

Node* JSNativeContextSpecialization::InlineApiCall(
    Node* receiver, Node* holder, Node* frame_state, Node* value, Node** effect,
    Node** control, Handle<SharedFunctionInfo> shared_info,
    Handle<FunctionTemplateInfo> function_template_info) {
  Handle<CallHandlerInfo> call_handler_info = handle(
      CallHandlerInfo::cast(function_template_info->call_code()), isolate());
  Handle<Object> call_data_object(call_handler_info->data(), isolate());

  // Only setters have a value.
  int const argc = value == nullptr ? 0 : 1;
  // The stub always expects the receiver as the first param on the stack.
  CallApiCallbackStub stub(isolate(), argc);
  CallInterfaceDescriptor call_interface_descriptor =
      stub.GetCallInterfaceDescriptor();
  CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
      isolate(), graph()->zone(), call_interface_descriptor,
      call_interface_descriptor.GetStackParameterCount() + argc +
          1 /* implicit receiver */,
      CallDescriptor::kNeedsFrameState, Operator::kNoProperties,
      MachineType::AnyTagged(), 1, Linkage::kNoContext);

  Node* data = jsgraph()->Constant(call_data_object);
  ApiFunction function(v8::ToCData<Address>(call_handler_info->callback()));
  Node* function_reference =
      graph()->NewNode(common()->ExternalConstant(ExternalReference(
          &function, ExternalReference::DIRECT_API_CALL, isolate())));
  Node* code = jsgraph()->HeapConstant(stub.GetCode());

  // Add CallApiCallbackStub's register argument as well.
  Node* context = jsgraph()->Constant(native_context());
  Node* inputs[10] = {code,    context, data, holder, function_reference,
                      receiver};
  int index = 6 + argc;
  inputs[index++] = frame_state;
  inputs[index++] = *effect;
  inputs[index++] = *control;
  // This needs to stay here because of the edge case described in
  // http://crbug.com/675648.
  if (value != nullptr) {
    inputs[6] = value;
  }

  return *effect = *control =
             graph()->NewNode(common()->Call(call_descriptor), index, inputs);
}

JSNativeContextSpecialization::ValueEffectControl
JSNativeContextSpecialization::BuildPropertyLoad(
    Node* receiver, Node* context, Node* frame_state, Node* effect,
    Node* control, Handle<Name> name, ZoneVector<Node*>* if_exceptions,
    PropertyAccessInfo const& access_info) {
  // Determine actual holder and perform prototype chain checks.
  Handle<JSObject> holder;
  PropertyAccessBuilder access_builder(jsgraph(), dependencies());
  if (access_info.holder().ToHandle(&holder)) {
    access_builder.AssumePrototypesStable(native_context(),
                                          access_info.receiver_maps(), holder);
  }

  // Generate the actual property access.
  Node* value;
  if (access_info.IsNotFound()) {
    value = jsgraph()->UndefinedConstant();
  } else if (access_info.IsDataConstant()) {
    DCHECK(!FLAG_track_constant_fields);
    value = jsgraph()->Constant(access_info.constant());
  } else if (access_info.IsAccessorConstant()) {
    value = InlinePropertyGetterCall(receiver, context, frame_state, &effect,
                                     &control, if_exceptions, access_info);
  } else if (access_info.IsModuleExport()) {
    Node* cell = jsgraph()->Constant(access_info.export_cell());
    value = effect =
        graph()->NewNode(simplified()->LoadField(AccessBuilder::ForCellValue()),
                         cell, effect, control);
  } else {
    DCHECK(access_info.IsDataField() || access_info.IsDataConstantField());
    value = access_builder.BuildLoadDataField(name, access_info, receiver,
                                              &effect, &control);
  }

  return ValueEffectControl(value, effect, control);
}

JSNativeContextSpecialization::ValueEffectControl
JSNativeContextSpecialization::BuildPropertyAccess(
    Node* receiver, Node* value, Node* context, Node* frame_state, Node* effect,
    Node* control, Handle<Name> name, ZoneVector<Node*>* if_exceptions,
    PropertyAccessInfo const& access_info, AccessMode access_mode) {
  switch (access_mode) {
    case AccessMode::kLoad:
      return BuildPropertyLoad(receiver, context, frame_state, effect, control,
                               name, if_exceptions, access_info);
    case AccessMode::kStore:
    case AccessMode::kStoreInLiteral:
      return BuildPropertyStore(receiver, value, context, frame_state, effect,
                                control, name, if_exceptions, access_info,
                                access_mode);
  }
  UNREACHABLE();
  return ValueEffectControl();
}

JSNativeContextSpecialization::ValueEffectControl
JSNativeContextSpecialization::BuildPropertyStore(
    Node* receiver, Node* value, Node* context, Node* frame_state, Node* effect,
    Node* control, Handle<Name> name, ZoneVector<Node*>* if_exceptions,
    PropertyAccessInfo const& access_info, AccessMode access_mode) {
  // Determine actual holder and perform prototype chain checks.
  Handle<JSObject> holder;
  PropertyAccessBuilder access_builder(jsgraph(), dependencies());
  if (access_info.holder().ToHandle(&holder)) {
    DCHECK_NE(AccessMode::kStoreInLiteral, access_mode);
    access_builder.AssumePrototypesStable(native_context(),
                                          access_info.receiver_maps(), holder);
  }

  DCHECK(!access_info.IsNotFound());

  // Generate the actual property access.
  if (access_info.IsDataConstant()) {
    DCHECK(!FLAG_track_constant_fields);
    Node* constant_value = jsgraph()->Constant(access_info.constant());
    Node* check =
        graph()->NewNode(simplified()->ReferenceEqual(), value, constant_value);
    effect =
        graph()->NewNode(simplified()->CheckIf(DeoptimizeReason::kWrongValue),
                         check, effect, control);
    value = constant_value;
  } else if (access_info.IsAccessorConstant()) {
    InlinePropertySetterCall(receiver, value, context, frame_state, &effect,
                             &control, if_exceptions, access_info);
  } else {
    DCHECK(access_info.IsDataField() || access_info.IsDataConstantField());
    FieldIndex const field_index = access_info.field_index();
    Type* const field_type = access_info.field_type();
    MachineRepresentation const field_representation =
        access_info.field_representation();
    Node* storage = receiver;
    if (!field_index.is_inobject()) {
      storage = effect = graph()->NewNode(
          simplified()->LoadField(AccessBuilder::ForJSObjectPropertiesOrHash()),
          storage, effect, control);
    }
    FieldAccess field_access = {
        kTaggedBase,
        field_index.offset(),
        name,
        MaybeHandle<Map>(),
        field_type,
        MachineType::TypeForRepresentation(field_representation),
        kFullWriteBarrier};
    bool store_to_constant_field = FLAG_track_constant_fields &&
                                   (access_mode == AccessMode::kStore) &&
                                   access_info.IsDataConstantField();

    DCHECK(access_mode == AccessMode::kStore ||
           access_mode == AccessMode::kStoreInLiteral);
    switch (field_representation) {
      case MachineRepresentation::kFloat64: {
        value = effect =
            graph()->NewNode(simplified()->CheckNumber(VectorSlotPair()), value,
                             effect, control);
        if (!field_index.is_inobject() || field_index.is_hidden_field() ||
            !FLAG_unbox_double_fields) {
          if (access_info.HasTransitionMap()) {
            // Allocate a MutableHeapNumber for the new property.
            AllocationBuilder a(jsgraph(), effect, control);
            a.Allocate(HeapNumber::kSize, NOT_TENURED, Type::OtherInternal());
            a.Store(AccessBuilder::ForMap(),
                    factory()->mutable_heap_number_map());
            a.Store(AccessBuilder::ForHeapNumberValue(), value);
            value = effect = a.Finish();

            field_access.type = Type::Any();
            field_access.machine_type = MachineType::TaggedPointer();
            field_access.write_barrier_kind = kPointerWriteBarrier;
          } else {
            // We just store directly to the MutableHeapNumber.
            FieldAccess const storage_access = {kTaggedBase,
                                                field_index.offset(),
                                                name,
                                                MaybeHandle<Map>(),
                                                Type::OtherInternal(),
                                                MachineType::TaggedPointer(),
                                                kPointerWriteBarrier};
            storage = effect =
                graph()->NewNode(simplified()->LoadField(storage_access),
                                 storage, effect, control);
            field_access.offset = HeapNumber::kValueOffset;
            field_access.name = MaybeHandle<Name>();
            field_access.machine_type = MachineType::Float64();
          }
        }
        if (store_to_constant_field) {
          DCHECK(!access_info.HasTransitionMap());
          // If the field is constant check that the value we are going
          // to store matches current value.
          Node* current_value = effect = graph()->NewNode(
              simplified()->LoadField(field_access), storage, effect, control);

          Node* check = graph()->NewNode(simplified()->NumberEqual(),
                                         current_value, value);
          effect = graph()->NewNode(
              simplified()->CheckIf(DeoptimizeReason::kWrongValue), check,
              effect, control);
          return ValueEffectControl(value, effect, control);
        }
        break;
      }
      case MachineRepresentation::kTaggedSigned:
      case MachineRepresentation::kTaggedPointer:
      case MachineRepresentation::kTagged:
        if (store_to_constant_field) {
          DCHECK(!access_info.HasTransitionMap());
          // If the field is constant check that the value we are going
          // to store matches current value.
          Node* current_value = effect = graph()->NewNode(
              simplified()->LoadField(field_access), storage, effect, control);

          Node* check = graph()->NewNode(simplified()->ReferenceEqual(),
                                         current_value, value);
          effect = graph()->NewNode(
              simplified()->CheckIf(DeoptimizeReason::kWrongValue), check,
              effect, control);
          return ValueEffectControl(value, effect, control);
        }

        if (field_representation == MachineRepresentation::kTaggedSigned) {
          value = effect = graph()->NewNode(
              simplified()->CheckSmi(VectorSlotPair()), value, effect, control);
          field_access.write_barrier_kind = kNoWriteBarrier;

        } else if (field_representation ==
                   MachineRepresentation::kTaggedPointer) {
          // Ensure that {value} is a HeapObject.
          value = access_builder.BuildCheckHeapObject(value, &effect, control);
          Handle<Map> field_map;
          if (access_info.field_map().ToHandle(&field_map)) {
            // Emit a map check for the value.
            effect = graph()->NewNode(
                simplified()->CheckMaps(CheckMapsFlag::kNone,
                                        ZoneHandleSet<Map>(field_map)),
                value, effect, control);
          }
          field_access.write_barrier_kind = kPointerWriteBarrier;

        } else {
          DCHECK_EQ(MachineRepresentation::kTagged, field_representation);
        }
        break;
      case MachineRepresentation::kNone:
      case MachineRepresentation::kBit:
      case MachineRepresentation::kWord8:
      case MachineRepresentation::kWord16:
      case MachineRepresentation::kWord32:
      case MachineRepresentation::kWord64:
      case MachineRepresentation::kFloat32:
      case MachineRepresentation::kSimd128:
        UNREACHABLE();
        break;
    }
    // Check if we need to perform a transitioning store.
    Handle<Map> transition_map;
    if (access_info.transition_map().ToHandle(&transition_map)) {
      // Check if we need to grow the properties backing store
      // with this transitioning store.
      Handle<Map> original_map(Map::cast(transition_map->GetBackPointer()),
                               isolate());
      if (original_map->UnusedPropertyFields() == 0) {
        DCHECK(!field_index.is_inobject());

        // Reallocate the properties {storage}.
        storage = effect = BuildExtendPropertiesBackingStore(
            original_map, storage, effect, control);

        // Perform the actual store.
        effect = graph()->NewNode(simplified()->StoreField(field_access),
                                  storage, value, effect, control);

        // Atomically switch to the new properties below.
        field_access = AccessBuilder::ForJSObjectPropertiesOrHash();
        value = storage;
        storage = receiver;
      }
      effect = graph()->NewNode(
          common()->BeginRegion(RegionObservability::kObservable), effect);
      effect = graph()->NewNode(
          simplified()->StoreField(AccessBuilder::ForMap()), receiver,
          jsgraph()->Constant(transition_map), effect, control);
      effect = graph()->NewNode(simplified()->StoreField(field_access), storage,
                                value, effect, control);
      effect = graph()->NewNode(common()->FinishRegion(),
                                jsgraph()->UndefinedConstant(), effect);
    } else {
      // Regular non-transitioning field store.
      effect = graph()->NewNode(simplified()->StoreField(field_access), storage,
                                value, effect, control);
    }
  }

  return ValueEffectControl(value, effect, control);
}

Reduction JSNativeContextSpecialization::ReduceJSStoreDataPropertyInLiteral(
    Node* node) {
  DCHECK_EQ(IrOpcode::kJSStoreDataPropertyInLiteral, node->opcode());

  FeedbackParameter const& p = FeedbackParameterOf(node->op());

  if (!p.feedback().IsValid()) return NoChange();

  StoreDataPropertyInLiteralICNexus nexus(p.feedback().vector(),
                                          p.feedback().slot());
  if (nexus.IsUninitialized()) {
    return NoChange();
  }

  if (nexus.ic_state() == MEGAMORPHIC) {
    return NoChange();
  }

  DCHECK_EQ(MONOMORPHIC, nexus.ic_state());

  Map* map = nexus.FindFirstMap();
  if (map == nullptr) {
    // Maps are weakly held in the type feedback vector, we may not have one.
    return NoChange();
  }

  Handle<Map> receiver_map(map, isolate());
  if (!Map::TryUpdate(receiver_map).ToHandle(&receiver_map)) return NoChange();

  Handle<Name> cached_name =
      handle(Name::cast(nexus.GetFeedbackExtra()), isolate());

  PropertyAccessInfo access_info;
  AccessInfoFactory access_info_factory(dependencies(), native_context(),
                                        graph()->zone());
  if (!access_info_factory.ComputePropertyAccessInfo(
          receiver_map, cached_name, AccessMode::kStoreInLiteral,
          &access_info)) {
    return NoChange();
  }

  Node* receiver = NodeProperties::GetValueInput(node, 0);
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);

  // Monomorphic property access.
  PropertyAccessBuilder access_builder(jsgraph(), dependencies());
  receiver = access_builder.BuildCheckHeapObject(receiver, &effect, control);
  access_builder.BuildCheckMaps(receiver, &effect, control,
                                access_info.receiver_maps());

  // Ensure that {name} matches the cached name.
  Node* name = NodeProperties::GetValueInput(node, 1);
  Node* check = graph()->NewNode(simplified()->ReferenceEqual(), name,
                                 jsgraph()->HeapConstant(cached_name));
  effect = graph()->NewNode(simplified()->CheckIf(DeoptimizeReason::kWrongName),
                            check, effect, control);

  Node* value = NodeProperties::GetValueInput(node, 2);
  Node* context = NodeProperties::GetContextInput(node);
  Node* frame_state_lazy = NodeProperties::GetFrameStateInput(node);

  // Generate the actual property access.
  ValueEffectControl continuation = BuildPropertyAccess(
      receiver, value, context, frame_state_lazy, effect, control, cached_name,
      nullptr, access_info, AccessMode::kStoreInLiteral);
  value = continuation.value();
  effect = continuation.effect();
  control = continuation.control();

  ReplaceWithValue(node, value, effect, control);
  return Replace(value);
}

namespace {

ExternalArrayType GetArrayTypeFromElementsKind(ElementsKind kind) {
  switch (kind) {
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
  case TYPE##_ELEMENTS:                                 \
    return kExternal##Type##Array;
    TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE
    default:
      break;
  }
  UNREACHABLE();
}

}  // namespace

JSNativeContextSpecialization::ValueEffectControl
JSNativeContextSpecialization::BuildElementAccess(
    Node* receiver, Node* index, Node* value, Node* effect, Node* control,
    ElementAccessInfo const& access_info, AccessMode access_mode,
    KeyedAccessLoadMode load_mode, KeyedAccessStoreMode store_mode) {
  DCHECK_NE(AccessMode::kStoreInLiteral, access_mode);

  // TODO(bmeurer): We currently specialize based on elements kind. We should
  // also be able to properly support strings and other JSObjects here.
  ElementsKind elements_kind = access_info.elements_kind();
  MapHandles const& receiver_maps = access_info.receiver_maps();

  if (IsFixedTypedArrayElementsKind(elements_kind)) {
    Node* buffer;
    Node* length;
    Node* base_pointer;
    Node* external_pointer;

    // Check if we can constant-fold information about the {receiver} (i.e.
    // for asm.js-like code patterns).
    HeapObjectMatcher m(receiver);
    if (m.HasValue() && m.Value()->IsJSTypedArray()) {
      Handle<JSTypedArray> typed_array = Handle<JSTypedArray>::cast(m.Value());

      // Determine the {receiver}s (known) length.
      length = jsgraph()->Constant(typed_array->length_value());

      // Check if the {receiver}s buffer was neutered.
      buffer = jsgraph()->HeapConstant(typed_array->GetBuffer());

      // Load the (known) base and external pointer for the {receiver}. The
      // {external_pointer} might be invalid if the {buffer} was neutered, so
      // we need to make sure that any access is properly guarded.
      base_pointer = jsgraph()->ZeroConstant();
      external_pointer = jsgraph()->PointerConstant(
          FixedTypedArrayBase::cast(typed_array->elements())
              ->external_pointer());
    } else {
      // Load the {receiver}s length.
      length = effect = graph()->NewNode(
          simplified()->LoadField(AccessBuilder::ForJSTypedArrayLength()),
          receiver, effect, control);

      // Load the buffer for the {receiver}.
      buffer = effect = graph()->NewNode(
          simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
          receiver, effect, control);

      // Load the elements for the {receiver}.
      Node* elements = effect = graph()->NewNode(
          simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
          receiver, effect, control);

      // Load the base and external pointer for the {receiver}s {elements}.
      base_pointer = effect = graph()->NewNode(
          simplified()->LoadField(
              AccessBuilder::ForFixedTypedArrayBaseBasePointer()),
          elements, effect, control);
      external_pointer = effect = graph()->NewNode(
          simplified()->LoadField(
              AccessBuilder::ForFixedTypedArrayBaseExternalPointer()),
          elements, effect, control);
    }

    // See if we can skip the neutering check.
    if (isolate()->IsArrayBufferNeuteringIntact()) {
      // Add a code dependency so we are deoptimized in case an ArrayBuffer
      // gets neutered.
      dependencies()->AssumePropertyCell(
          factory()->array_buffer_neutering_protector());
    } else {
      // Default to zero if the {receiver}s buffer was neutered.
      Node* check = effect = graph()->NewNode(
          simplified()->ArrayBufferWasNeutered(), buffer, effect, control);
      length = graph()->NewNode(
          common()->Select(MachineRepresentation::kTagged, BranchHint::kFalse),
          check, jsgraph()->ZeroConstant(), length);
    }

    if (load_mode == LOAD_IGNORE_OUT_OF_BOUNDS ||
        store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
      // Check that the {index} is a valid array index, we do the actual
      // bounds check below and just skip the store below if it's out of
      // bounds for the {receiver}.
      index = effect = graph()->NewNode(
          simplified()->CheckBounds(VectorSlotPair()), index,
          jsgraph()->Constant(Smi::kMaxValue), effect, control);
    } else {
      // Check that the {index} is in the valid range for the {receiver}.
      index = effect =
          graph()->NewNode(simplified()->CheckBounds(VectorSlotPair()), index,
                           length, effect, control);
    }

    // Access the actual element.
    ExternalArrayType external_array_type =
        GetArrayTypeFromElementsKind(elements_kind);
    switch (access_mode) {
      case AccessMode::kLoad: {
        // Check if we can return undefined for out-of-bounds loads.
        if (load_mode == LOAD_IGNORE_OUT_OF_BOUNDS) {
          Node* check =
              graph()->NewNode(simplified()->NumberLessThan(), index, length);
          Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
                                          check, control);

          Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
          Node* etrue = effect;
          Node* vtrue;
          {
            Node* masked_index = graph()->NewNode(
                simplified()->MaskIndexWithBound(), index, length);

            // Perform the actual load
            vtrue = etrue = graph()->NewNode(
                simplified()->LoadTypedElement(external_array_type), buffer,
                base_pointer, external_pointer, masked_index, etrue, if_true);
          }

          Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
          Node* efalse = effect;
          Node* vfalse;
          {
            // Materialize undefined for out-of-bounds loads.
            vfalse = jsgraph()->UndefinedConstant();
          }

          control = graph()->NewNode(common()->Merge(2), if_true, if_false);
          effect =
              graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
          value =
              graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
                               vtrue, vfalse, control);
        } else {
          Node* masked_index = graph()->NewNode(
              simplified()->MaskIndexWithBound(), index, length);

          // Perform the actual load.
          value = effect = graph()->NewNode(
              simplified()->LoadTypedElement(external_array_type), buffer,
              base_pointer, external_pointer, masked_index, effect, control);
        }
        break;
      }
      case AccessMode::kStoreInLiteral:
        UNREACHABLE();
        break;
      case AccessMode::kStore: {
        // Ensure that the {value} is actually a Number or an Oddball,
        // and truncate it to a Number appropriately.
        value = effect =
            graph()->NewNode(simplified()->SpeculativeToNumber(
                                 NumberOperationHint::kNumberOrOddball),
                             value, effect, control);

        // Introduce the appropriate truncation for {value}. Currently we
        // only need to do this for ClamedUint8Array {receiver}s, as the
        // other truncations are implicit in the StoreTypedElement, but we
        // might want to change that at some point.
        if (external_array_type == kExternalUint8ClampedArray) {
          value = graph()->NewNode(simplified()->NumberToUint8Clamped(), value);
        }

        // Check if we can skip the out-of-bounds store.
        if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
          Node* check =
              graph()->NewNode(simplified()->NumberLessThan(), index, length);
          Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
                                          check, control);

          Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
          Node* etrue = effect;
          {
            // Perform the actual store.
            etrue = graph()->NewNode(
                simplified()->StoreTypedElement(external_array_type), buffer,
                base_pointer, external_pointer, index, value, etrue, if_true);
          }

          Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
          Node* efalse = effect;
          {
            // Just ignore the out-of-bounds write.
          }

          control = graph()->NewNode(common()->Merge(2), if_true, if_false);
          effect =
              graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
        } else {
          // Perform the actual store
          effect = graph()->NewNode(
              simplified()->StoreTypedElement(external_array_type), buffer,
              base_pointer, external_pointer, index, value, effect, control);
        }
        break;
      }
    }
  } else {
    // Load the elements for the {receiver}.
    Node* elements = effect = graph()->NewNode(
        simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver,
        effect, control);

    // Don't try to store to a copy-on-write backing store.
    if (access_mode == AccessMode::kStore &&
        IsSmiOrObjectElementsKind(elements_kind) &&
        store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
      effect = graph()->NewNode(
          simplified()->CheckMaps(
              CheckMapsFlag::kNone,
              ZoneHandleSet<Map>(factory()->fixed_array_map())),
          elements, effect, control);
    }

    // Check if the {receiver} is a JSArray.
    bool receiver_is_jsarray = HasOnlyJSArrayMaps(receiver_maps);

    // Load the length of the {receiver}.
    Node* length = effect =
        receiver_is_jsarray
            ? graph()->NewNode(
                  simplified()->LoadField(
                      AccessBuilder::ForJSArrayLength(elements_kind)),
                  receiver, effect, control)
            : graph()->NewNode(
                  simplified()->LoadField(AccessBuilder::ForFixedArrayLength()),
                  elements, effect, control);

    // Check if we might need to grow the {elements} backing store.
    if (IsGrowStoreMode(store_mode)) {
      // For growing stores we validate the {index} below.
      DCHECK_EQ(AccessMode::kStore, access_mode);
    } else if (load_mode == LOAD_IGNORE_OUT_OF_BOUNDS &&
               CanTreatHoleAsUndefined(receiver_maps)) {
      // Check that the {index} is a valid array index, we do the actual
      // bounds check below and just skip the store below if it's out of
      // bounds for the {receiver}.
      index = effect = graph()->NewNode(
          simplified()->CheckBounds(VectorSlotPair()), index,
          jsgraph()->Constant(Smi::kMaxValue), effect, control);
    } else {
      // Check that the {index} is in the valid range for the {receiver}.
      index = effect =
          graph()->NewNode(simplified()->CheckBounds(VectorSlotPair()), index,
                           length, effect, control);
    }

    // Compute the element access.
    Type* element_type = Type::NonInternal();
    MachineType element_machine_type = MachineType::AnyTagged();
    if (IsDoubleElementsKind(elements_kind)) {
      element_type = Type::Number();
      element_machine_type = MachineType::Float64();
    } else if (IsSmiElementsKind(elements_kind)) {
      element_type = Type::SignedSmall();
      element_machine_type = MachineType::TaggedSigned();
    }
    ElementAccess element_access = {kTaggedBase, FixedArray::kHeaderSize,
                                    element_type, element_machine_type,
                                    kFullWriteBarrier};

    // Access the actual element.
    if (access_mode == AccessMode::kLoad) {
      // Compute the real element access type, which includes the hole in case
      // of holey backing stores.
      if (IsHoleyOrDictionaryElementsKind(elements_kind)) {
        element_access.type =
            Type::Union(element_type, Type::Hole(), graph()->zone());
      }
      if (elements_kind == HOLEY_ELEMENTS ||
          elements_kind == HOLEY_SMI_ELEMENTS) {
        element_access.machine_type = MachineType::AnyTagged();
      }

      // Check if we can return undefined for out-of-bounds loads.
      if (load_mode == LOAD_IGNORE_OUT_OF_BOUNDS &&
          CanTreatHoleAsUndefined(receiver_maps)) {
        Node* check =
            graph()->NewNode(simplified()->NumberLessThan(), index, length);
        Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
                                        check, control);

        Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
        Node* etrue = effect;
        Node* vtrue;
        {
          Node* masked_index = graph()->NewNode(
              simplified()->MaskIndexWithBound(), index, length);

          // Perform the actual load
          vtrue = etrue =
              graph()->NewNode(simplified()->LoadElement(element_access),
                               elements, masked_index, etrue, if_true);

          // Handle loading from holey backing stores correctly, by either
          // mapping the hole to undefined if possible, or deoptimizing
          // otherwise.
          if (elements_kind == HOLEY_ELEMENTS ||
              elements_kind == HOLEY_SMI_ELEMENTS) {
            // Turn the hole into undefined.
            vtrue = graph()->NewNode(
                simplified()->ConvertTaggedHoleToUndefined(), vtrue);
          } else if (elements_kind == HOLEY_DOUBLE_ELEMENTS) {
            // Return the signaling NaN hole directly if all uses are
            // truncating.
            vtrue = etrue =
                graph()->NewNode(simplified()->CheckFloat64Hole(
                                     CheckFloat64HoleMode::kAllowReturnHole),
                                 vtrue, etrue, if_true);
          }
        }

        Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
        Node* efalse = effect;
        Node* vfalse;
        {
          // Materialize undefined for out-of-bounds loads.
          vfalse = jsgraph()->UndefinedConstant();
        }

        control = graph()->NewNode(common()->Merge(2), if_true, if_false);
        effect =
            graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
        value =
            graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
                             vtrue, vfalse, control);
      } else {
        Node* masked_index =
            graph()->NewNode(simplified()->MaskIndexWithBound(), index, length);

        // Perform the actual load.
        value = effect =
            graph()->NewNode(simplified()->LoadElement(element_access),
                             elements, masked_index, effect, control);

        // Handle loading from holey backing stores correctly, by either mapping
        // the hole to undefined if possible, or deoptimizing otherwise.
        if (elements_kind == HOLEY_ELEMENTS ||
            elements_kind == HOLEY_SMI_ELEMENTS) {
          // Check if we are allowed to turn the hole into undefined.
          if (CanTreatHoleAsUndefined(receiver_maps)) {
            // Turn the hole into undefined.
            value = graph()->NewNode(
                simplified()->ConvertTaggedHoleToUndefined(), value);
          } else {
            // Bailout if we see the hole.
            value = effect = graph()->NewNode(
                simplified()->CheckNotTaggedHole(), value, effect, control);
          }
        } else if (elements_kind == HOLEY_DOUBLE_ELEMENTS) {
          // Perform the hole check on the result.
          CheckFloat64HoleMode mode = CheckFloat64HoleMode::kNeverReturnHole;
          // Check if we are allowed to return the hole directly.
          if (CanTreatHoleAsUndefined(receiver_maps)) {
            // Return the signaling NaN hole directly if all uses are
            // truncating.
            mode = CheckFloat64HoleMode::kAllowReturnHole;
          }
          value = effect = graph()->NewNode(
              simplified()->CheckFloat64Hole(mode), value, effect, control);
        }
      }
    } else {
      DCHECK_EQ(AccessMode::kStore, access_mode);
      if (IsSmiElementsKind(elements_kind)) {
        value = effect = graph()->NewNode(
            simplified()->CheckSmi(VectorSlotPair()), value, effect, control);
      } else if (IsDoubleElementsKind(elements_kind)) {
        value = effect =
            graph()->NewNode(simplified()->CheckNumber(VectorSlotPair()), value,
                             effect, control);
        // Make sure we do not store signalling NaNs into double arrays.
        value = graph()->NewNode(simplified()->NumberSilenceNaN(), value);
      }

      // Ensure that copy-on-write backing store is writable.
      if (IsSmiOrObjectElementsKind(elements_kind) &&
          store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
        elements = effect =
            graph()->NewNode(simplified()->EnsureWritableFastElements(),
                             receiver, elements, effect, control);
      } else if (IsGrowStoreMode(store_mode)) {
        // Determine the length of the {elements} backing store.
        Node* elements_length = effect = graph()->NewNode(
            simplified()->LoadField(AccessBuilder::ForFixedArrayLength()),
            elements, effect, control);

        // Validate the {index} depending on holeyness:
        //
        // For HOLEY_*_ELEMENTS the {index} must not exceed the {elements}
        // backing store capacity plus the maximum allowed gap, as otherwise
        // the (potential) backing store growth would normalize and thus
        // the elements kind of the {receiver} would change to slow mode.
        //
        // For PACKED_*_ELEMENTS the {index} must be within the range
        // [0,length+1[ to be valid. In case {index} equals {length},
        // the {receiver} will be extended, but kept packed.
        Node* limit =
            IsHoleyElementsKind(elements_kind)
                ? graph()->NewNode(simplified()->NumberAdd(), elements_length,
                                   jsgraph()->Constant(JSObject::kMaxGap))
                : graph()->NewNode(simplified()->NumberAdd(), length,
                                   jsgraph()->OneConstant());
        index = effect =
            graph()->NewNode(simplified()->CheckBounds(VectorSlotPair()), index,
                             limit, effect, control);

        // Grow {elements} backing store if necessary.
        GrowFastElementsMode mode =
            IsDoubleElementsKind(elements_kind)
                ? GrowFastElementsMode::kDoubleElements
                : GrowFastElementsMode::kSmiOrObjectElements;
        elements = effect = graph()->NewNode(
            simplified()->MaybeGrowFastElements(mode, VectorSlotPair()),
            receiver, elements, index, elements_length, effect, control);

        // Also update the "length" property if {receiver} is a JSArray.
        if (receiver_is_jsarray) {
          Node* check =
              graph()->NewNode(simplified()->NumberLessThan(), index, length);
          Node* branch = graph()->NewNode(common()->Branch(), check, control);

          Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
          Node* etrue = effect;
          {
            // We don't need to do anything, the {index} is within
            // the valid bounds for the JSArray {receiver}.
          }

          Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
          Node* efalse = effect;
          {
            // Update the JSArray::length field. Since this is observable,
            // there must be no other check after this.
            Node* new_length = graph()->NewNode(
                simplified()->NumberAdd(), index, jsgraph()->OneConstant());
            efalse = graph()->NewNode(
                simplified()->StoreField(
                    AccessBuilder::ForJSArrayLength(elements_kind)),
                receiver, new_length, efalse, if_false);
          }

          control = graph()->NewNode(common()->Merge(2), if_true, if_false);
          effect =
              graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
        }
      }

      // Perform the actual element access.
      effect = graph()->NewNode(simplified()->StoreElement(element_access),
                                elements, index, value, effect, control);
    }
  }

  return ValueEffectControl(value, effect, control);
}

Node* JSNativeContextSpecialization::BuildIndexedStringLoad(
    Node* receiver, Node* index, Node* length, Node** effect, Node** control,
    KeyedAccessLoadMode load_mode) {
  if (load_mode == LOAD_IGNORE_OUT_OF_BOUNDS &&
      isolate()->IsNoElementsProtectorIntact()) {
    // Add a code dependency on the "no elements" protector.
    dependencies()->AssumePropertyCell(factory()->no_elements_protector());

    // Ensure that the {index} is a valid String length.
    index = *effect = graph()->NewNode(
        simplified()->CheckBounds(VectorSlotPair()), index,
        jsgraph()->Constant(String::kMaxLength), *effect, *control);

    // Load the single character string from {receiver} or yield
    // undefined if the {index} is not within the valid bounds.
    Node* check =
        graph()->NewNode(simplified()->NumberLessThan(), index, length);
    Node* branch =
        graph()->NewNode(common()->Branch(BranchHint::kTrue), check, *control);

    Node* masked_index =
        graph()->NewNode(simplified()->MaskIndexWithBound(), index, length);

    Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    Node* vtrue = graph()->NewNode(simplified()->StringCharAt(), receiver,
                                   masked_index, if_true);

    Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    Node* vfalse = jsgraph()->UndefinedConstant();

    *control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    return graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
                            vtrue, vfalse, *control);
  } else {
    // Ensure that {index} is less than {receiver} length.
    index = *effect =
        graph()->NewNode(simplified()->CheckBounds(VectorSlotPair()), index,
                         length, *effect, *control);

    Node* masked_index =
        graph()->NewNode(simplified()->MaskIndexWithBound(), index, length);

    // Return the character from the {receiver} as single character string.
    return graph()->NewNode(simplified()->StringCharAt(), receiver,
                            masked_index, *control);
  }
}

Node* JSNativeContextSpecialization::BuildExtendPropertiesBackingStore(
    Handle<Map> map, Node* properties, Node* effect, Node* control) {
  // TODO(bmeurer/jkummerow): Property deletions can undo map transitions
  // while keeping the backing store around, meaning that even though the
  // map might believe that objects have no unused property fields, there
  // might actually be some. It would be nice to not create a new backing
  // store in that case (i.e. when properties->length() >= new_length).
  // However, introducing branches and Phi nodes here would make it more
  // difficult for escape analysis to get rid of the backing stores used
  // for intermediate states of chains of property additions. That makes
  // it unclear what the best approach is here.
  DCHECK_EQ(0, map->UnusedPropertyFields());
  // Compute the length of the old {properties} and the new properties.
  int length = map->NextFreePropertyIndex() - map->GetInObjectProperties();
  int new_length = length + JSObject::kFieldsAdded;
  // Collect the field values from the {properties}.
  ZoneVector<Node*> values(zone());
  values.reserve(new_length);
  for (int i = 0; i < length; ++i) {
    Node* value = effect = graph()->NewNode(
        simplified()->LoadField(AccessBuilder::ForFixedArraySlot(i)),
        properties, effect, control);
    values.push_back(value);
  }
  // Initialize the new fields to undefined.
  for (int i = 0; i < JSObject::kFieldsAdded; ++i) {
    values.push_back(jsgraph()->UndefinedConstant());
  }

  // Compute new length and hash.
  Node* hash;
  if (length == 0) {
    hash = graph()->NewNode(
        common()->Select(MachineRepresentation::kTaggedSigned),
        graph()->NewNode(simplified()->ObjectIsSmi(), properties), properties,
        jsgraph()->SmiConstant(PropertyArray::kNoHashSentinel));
    hash = effect = graph()->NewNode(common()->TypeGuard(Type::SignedSmall()),
                                     hash, effect, control);
    hash =
        graph()->NewNode(simplified()->NumberShiftLeft(), hash,
                         jsgraph()->Constant(PropertyArray::HashField::kShift));
  } else {
    hash = effect = graph()->NewNode(
        simplified()->LoadField(AccessBuilder::ForPropertyArrayLengthAndHash()),
        properties, effect, control);
    hash =
        graph()->NewNode(simplified()->NumberBitwiseAnd(), hash,
                         jsgraph()->Constant(PropertyArray::HashField::kMask));
  }
  Node* new_length_and_hash = graph()->NewNode(
      simplified()->NumberBitwiseOr(), jsgraph()->Constant(new_length), hash);

  // Allocate and initialize the new properties.
  AllocationBuilder a(jsgraph(), effect, control);
  a.Allocate(PropertyArray::SizeFor(new_length), NOT_TENURED,
             Type::OtherInternal());
  a.Store(AccessBuilder::ForMap(), jsgraph()->PropertyArrayMapConstant());
  a.Store(AccessBuilder::ForPropertyArrayLengthAndHash(), new_length_and_hash);
  for (int i = 0; i < new_length; ++i) {
    a.Store(AccessBuilder::ForFixedArraySlot(i), values[i]);
  }
  return a.Finish();
}

Node* JSNativeContextSpecialization::BuildCheckEqualsName(Handle<Name> name,
                                                          Node* value,
                                                          Node* effect,
                                                          Node* control) {
  DCHECK(name->IsUniqueName());
  Operator const* const op =
      name->IsSymbol() ? simplified()->CheckEqualsSymbol()
                       : simplified()->CheckEqualsInternalizedString();
  return graph()->NewNode(op, jsgraph()->HeapConstant(name), value, effect,
                          control);
}

bool JSNativeContextSpecialization::CanTreatHoleAsUndefined(
    MapHandles const& receiver_maps) {
  // Check if all {receiver_maps} either have one of the initial Array.prototype
  // or Object.prototype objects as their prototype (in any of the current
  // native contexts, as the global Array protector works isolate-wide).
  for (Handle<Map> receiver_map : receiver_maps) {
    DisallowHeapAllocation no_gc;
    Object* const receiver_prototype = receiver_map->prototype();
    if (!isolate()->IsInAnyContext(receiver_prototype,
                                   Context::INITIAL_ARRAY_PROTOTYPE_INDEX) &&
        !isolate()->IsInAnyContext(receiver_prototype,
                                   Context::INITIAL_OBJECT_PROTOTYPE_INDEX)) {
      return false;
    }
  }

  // Check if the array prototype chain is intact.
  if (!isolate()->IsNoElementsProtectorIntact()) return false;

  // Install code dependency on the array protector cell.
  dependencies()->AssumePropertyCell(factory()->no_elements_protector());
  return true;
}

bool JSNativeContextSpecialization::ExtractReceiverMaps(
    Node* receiver, Node* effect, FeedbackNexus const& nexus,
    MapHandles* receiver_maps) {
  DCHECK_EQ(0, receiver_maps->size());
  // See if we can infer a concrete type for the {receiver}.
  if (InferReceiverMaps(receiver, effect, receiver_maps)) {
    // We can assume that the {receiver} still has the inferred {receiver_maps}.
    return true;
  }
  // Try to extract some maps from the {nexus}.
  if (nexus.ExtractMaps(receiver_maps) != 0) {
    // Try to filter impossible candidates based on inferred root map.
    Handle<Map> receiver_map;
    if (InferReceiverRootMap(receiver).ToHandle(&receiver_map)) {
      DCHECK(!receiver_map->is_abandoned_prototype_map());
      receiver_maps->erase(
          std::remove_if(receiver_maps->begin(), receiver_maps->end(),
                         [receiver_map](const Handle<Map>& map) {
                           return map->is_abandoned_prototype_map() ||
                                  map->FindRootMap() != *receiver_map;
                         }),
          receiver_maps->end());
    }
    return true;
  }
  return false;
}

bool JSNativeContextSpecialization::InferReceiverMaps(
    Node* receiver, Node* effect, MapHandles* receiver_maps) {
  ZoneHandleSet<Map> maps;
  NodeProperties::InferReceiverMapsResult result =
      NodeProperties::InferReceiverMaps(receiver, effect, &maps);
  if (result == NodeProperties::kReliableReceiverMaps) {
    for (size_t i = 0; i < maps.size(); ++i) {
      receiver_maps->push_back(maps[i]);
    }
    return true;
  } else if (result == NodeProperties::kUnreliableReceiverMaps) {
    // For untrusted receiver maps, we can still use the information
    // if the maps are stable.
    for (size_t i = 0; i < maps.size(); ++i) {
      if (!maps[i]->is_stable()) return false;
    }
    for (size_t i = 0; i < maps.size(); ++i) {
      receiver_maps->push_back(maps[i]);
    }
    return true;
  }
  return false;
}

MaybeHandle<Map> JSNativeContextSpecialization::InferReceiverRootMap(
    Node* receiver) {
  HeapObjectMatcher m(receiver);
  if (m.HasValue()) {
    return handle(m.Value()->map()->FindRootMap(), isolate());
  } else if (m.IsJSCreate()) {
    HeapObjectMatcher mtarget(m.InputAt(0));
    HeapObjectMatcher mnewtarget(m.InputAt(1));
    if (mtarget.HasValue() && mnewtarget.HasValue()) {
      Handle<JSFunction> constructor =
          Handle<JSFunction>::cast(mtarget.Value());
      if (constructor->has_initial_map()) {
        Handle<Map> initial_map(constructor->initial_map(), isolate());
        if (initial_map->constructor_or_backpointer() == *mnewtarget.Value()) {
          DCHECK_EQ(*initial_map, initial_map->FindRootMap());
          return initial_map;
        }
      }
    }
  }
  return MaybeHandle<Map>();
}

bool JSNativeContextSpecialization::LookupInScriptContextTable(
    Handle<Name> name, ScriptContextTableLookupResult* result) {
  if (!name->IsString()) return false;
  Handle<ScriptContextTable> script_context_table(
      global_object()->native_context()->script_context_table(), isolate());
  ScriptContextTable::LookupResult lookup_result;
  if (!ScriptContextTable::Lookup(script_context_table,
                                  Handle<String>::cast(name), &lookup_result)) {
    return false;
  }
  Handle<Context> script_context = ScriptContextTable::GetContext(
      script_context_table, lookup_result.context_index);
  result->context = script_context;
  result->immutable = lookup_result.mode == CONST;
  result->index = lookup_result.slot_index;
  return true;
}

Graph* JSNativeContextSpecialization::graph() const {
  return jsgraph()->graph();
}

Isolate* JSNativeContextSpecialization::isolate() const {
  return jsgraph()->isolate();
}

Factory* JSNativeContextSpecialization::factory() const {
  return isolate()->factory();
}

CommonOperatorBuilder* JSNativeContextSpecialization::common() const {
  return jsgraph()->common();
}

JSOperatorBuilder* JSNativeContextSpecialization::javascript() const {
  return jsgraph()->javascript();
}

SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const {
  return jsgraph()->simplified();
}

}  // namespace compiler
}  // namespace internal
}  // namespace v8
