LCOV - code coverage report
Current view: top level - src/compiler - js-native-context-specialization.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1142 1168 97.8 %
Date: 2019-02-19 Functions: 59 65 90.8 %

          Line data    Source code
       1             : // Copyright 2015 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/compiler/js-native-context-specialization.h"
       6             : 
       7             : #include "src/accessors.h"
       8             : #include "src/api-inl.h"
       9             : #include "src/code-factory.h"
      10             : #include "src/compiler/access-builder.h"
      11             : #include "src/compiler/access-info.h"
      12             : #include "src/compiler/allocation-builder.h"
      13             : #include "src/compiler/compilation-dependencies.h"
      14             : #include "src/compiler/js-graph.h"
      15             : #include "src/compiler/js-operator.h"
      16             : #include "src/compiler/linkage.h"
      17             : #include "src/compiler/node-matchers.h"
      18             : #include "src/compiler/property-access-builder.h"
      19             : #include "src/compiler/type-cache.h"
      20             : #include "src/dtoa.h"
      21             : #include "src/feedback-vector.h"
      22             : #include "src/field-index-inl.h"
      23             : #include "src/isolate-inl.h"
      24             : #include "src/objects/heap-number.h"
      25             : #include "src/objects/js-array-buffer-inl.h"
      26             : #include "src/objects/js-array-inl.h"
      27             : #include "src/objects/templates.h"
      28             : #include "src/string-constants.h"
      29             : #include "src/vector-slot-pair.h"
      30             : 
      31             : namespace v8 {
      32             : namespace internal {
      33             : namespace compiler {
      34             : 
      35             : // This is needed for gc_mole which will compile this file without the full set
      36             : // of GN defined macros.
      37             : #ifndef V8_TYPED_ARRAY_MAX_SIZE_IN_HEAP
      38             : #define V8_TYPED_ARRAY_MAX_SIZE_IN_HEAP 64
      39             : #endif
      40             : 
      41             : namespace {
      42             : 
      43      135826 : bool HasNumberMaps(JSHeapBroker* broker, MapHandles const& maps) {
      44      414524 :   for (auto map : maps) {
      45             :     MapRef map_ref(broker, map);
      46      143049 :     if (map_ref.IsHeapNumberMap()) return true;
      47             :   }
      48             :   return false;
      49             : }
      50             : 
      51       15968 : bool HasOnlyJSArrayMaps(JSHeapBroker* broker, MapHandles const& maps) {
      52       47632 :   for (auto map : maps) {
      53             :     MapRef map_ref(broker, map);
      54       17421 :     if (!map_ref.IsJSArrayMap()) return false;
      55             :   }
      56             :   return true;
      57             : }
      58             : 
      59             : }  // namespace
      60             : 
      61      456725 : JSNativeContextSpecialization::JSNativeContextSpecialization(
      62      913456 :     Editor* editor, JSGraph* jsgraph, JSHeapBroker* broker, Flags flags,
      63             :     Handle<Context> native_context, CompilationDependencies* dependencies,
      64             :     Zone* zone, Zone* shared_zone)
      65             :     : AdvancedReducer(editor),
      66             :       jsgraph_(jsgraph),
      67             :       broker_(broker),
      68             :       flags_(flags),
      69             :       global_object_(native_context->global_object(), jsgraph->isolate()),
      70      913461 :       global_proxy_(JSGlobalProxy::cast(native_context->global_proxy()),
      71             :                     jsgraph->isolate()),
      72             :       dependencies_(dependencies),
      73             :       zone_(zone),
      74             :       shared_zone_(shared_zone),
      75     2740373 :       type_cache_(TypeCache::Get()) {}
      76             : 
      77    35775684 : Reduction JSNativeContextSpecialization::Reduce(Node* node) {
      78    35775684 :   switch (node->opcode()) {
      79             :     case IrOpcode::kJSAdd:
      80       90356 :       return ReduceJSAdd(node);
      81             :     case IrOpcode::kJSAsyncFunctionEnter:
      82        1203 :       return ReduceJSAsyncFunctionEnter(node);
      83             :     case IrOpcode::kJSAsyncFunctionReject:
      84        1157 :       return ReduceJSAsyncFunctionReject(node);
      85             :     case IrOpcode::kJSAsyncFunctionResolve:
      86        1065 :       return ReduceJSAsyncFunctionResolve(node);
      87             :     case IrOpcode::kJSGetSuperConstructor:
      88        2880 :       return ReduceJSGetSuperConstructor(node);
      89             :     case IrOpcode::kJSInstanceOf:
      90        3788 :       return ReduceJSInstanceOf(node);
      91             :     case IrOpcode::kJSHasInPrototypeChain:
      92         982 :       return ReduceJSHasInPrototypeChain(node);
      93             :     case IrOpcode::kJSOrdinaryHasInstance:
      94        1148 :       return ReduceJSOrdinaryHasInstance(node);
      95             :     case IrOpcode::kJSPromiseResolve:
      96         171 :       return ReduceJSPromiseResolve(node);
      97             :     case IrOpcode::kJSResolvePromise:
      98         997 :       return ReduceJSResolvePromise(node);
      99             :     case IrOpcode::kJSLoadContext:
     100      533389 :       return ReduceJSLoadContext(node);
     101             :     case IrOpcode::kJSLoadGlobal:
     102     1026094 :       return ReduceJSLoadGlobal(node);
     103             :     case IrOpcode::kJSStoreGlobal:
     104      216149 :       return ReduceJSStoreGlobal(node);
     105             :     case IrOpcode::kJSLoadNamed:
     106      528282 :       return ReduceJSLoadNamed(node);
     107             :     case IrOpcode::kJSStoreNamed:
     108       99962 :       return ReduceJSStoreNamed(node);
     109             :     case IrOpcode::kJSLoadProperty:
     110       44154 :       return ReduceJSLoadProperty(node);
     111             :     case IrOpcode::kJSStoreProperty:
     112       11615 :       return ReduceJSStoreProperty(node);
     113             :     case IrOpcode::kJSStoreNamedOwn:
     114       35304 :       return ReduceJSStoreNamedOwn(node);
     115             :     case IrOpcode::kJSStoreDataPropertyInLiteral:
     116         539 :       return ReduceJSStoreDataPropertyInLiteral(node);
     117             :     case IrOpcode::kJSStoreInArrayLiteral:
     118       43797 :       return ReduceJSStoreInArrayLiteral(node);
     119             :     case IrOpcode::kJSToObject:
     120        2003 :       return ReduceJSToObject(node);
     121             :     case IrOpcode::kJSToString:
     122        2712 :       return ReduceJSToString(node);
     123             :     default:
     124             :       break;
     125             :   }
     126             :   return NoChange();
     127             : }
     128             : 
     129             : // static
     130      180714 : base::Optional<size_t> JSNativeContextSpecialization::GetMaxStringLength(
     131      180714 :     JSHeapBroker* broker, Node* node) {
     132      180714 :   if (node->opcode() == IrOpcode::kDelayedStringConstant) {
     133        3761 :     return StringConstantBaseOf(node->op())->GetMaxStringConstantLength();
     134             :   }
     135             : 
     136             :   HeapObjectMatcher matcher(node);
     137      220299 :   if (matcher.HasValue() && matcher.Ref(broker).IsString()) {
     138       42917 :     StringRef input = matcher.Ref(broker).AsString();
     139       42917 :     return input.length();
     140             :   }
     141             : 
     142             :   NumberMatcher number_matcher(node);
     143      134036 :   if (number_matcher.HasValue()) {
     144             :     return kBase10MaximalLength + 1;
     145             :   }
     146             : 
     147             :   // We don't support objects with possibly monkey-patched prototype.toString
     148             :   // as it might have side-effects, so we shouldn't attempt lowering them.
     149             :   return base::nullopt;
     150             : }
     151             : 
     152        3355 : Reduction JSNativeContextSpecialization::ReduceJSToString(Node* node) {
     153             :   DCHECK_EQ(IrOpcode::kJSToString, node->opcode());
     154             :   Node* const input = node->InputAt(0);
     155             :   Reduction reduction;
     156             : 
     157             :   HeapObjectMatcher matcher(input);
     158        3346 :   if (matcher.HasValue() && matcher.Ref(broker()).IsString()) {
     159             :     reduction = Changed(input);  // JSToString(x:string) => x
     160         638 :     ReplaceWithValue(node, reduction.replacement());
     161         629 :     return reduction;
     162             :   }
     163             : 
     164             :   // TODO(turbofan): This optimization is weaker than what we used to have
     165             :   // in js-typed-lowering for OrderedNumbers. We don't have types here though,
     166             :   // so alternative approach should be designed if this causes performance
     167             :   // regressions and the stronger optimization should be re-implemented.
     168             :   NumberMatcher number_matcher(input);
     169        2083 :   if (number_matcher.HasValue()) {
     170             :     const StringConstantBase* base =
     171             :         new (shared_zone()) NumberToStringConstant(number_matcher.Value());
     172             :     reduction =
     173           9 :         Replace(graph()->NewNode(common()->DelayedStringConstant(base)));
     174             :     ReplaceWithValue(node, reduction.replacement());
     175           9 :     return reduction;
     176             :   }
     177             : 
     178             :   return NoChange();
     179             : }
     180             : 
     181             : const StringConstantBase*
     182       30283 : JSNativeContextSpecialization::CreateDelayedStringConstant(Node* node) {
     183       10034 :   if (node->opcode() == IrOpcode::kDelayedStringConstant) {
     184        3111 :     return StringConstantBaseOf(node->op());
     185             :   } else {
     186             :     NumberMatcher number_matcher(node);
     187        6923 :     if (number_matcher.HasValue()) {
     188         260 :       return new (shared_zone()) NumberToStringConstant(number_matcher.Value());
     189             :     } else {
     190             :       HeapObjectMatcher matcher(node);
     191       13326 :       if (matcher.HasValue() && matcher.Ref(broker()).IsString()) {
     192        6663 :         StringRef s = matcher.Ref(broker()).AsString();
     193             :         return new (shared_zone())
     194       13326 :             StringLiteral(s.object(), static_cast<size_t>(s.length()));
     195             :       } else {
     196           0 :         UNREACHABLE();
     197             :       }
     198             :     }
     199             :   }
     200             : }
     201             : 
     202             : namespace {
     203        7710 : bool IsStringConstant(JSHeapBroker* broker, Node* node) {
     204        7710 :   if (node->opcode() == IrOpcode::kDelayedStringConstant) {
     205             :     return true;
     206             :   }
     207             : 
     208             :   HeapObjectMatcher matcher(node);
     209        6529 :   return matcher.HasValue() && matcher.Ref(broker).IsString();
     210             : }
     211             : }
     212             : 
     213        1203 : Reduction JSNativeContextSpecialization::ReduceJSAsyncFunctionEnter(
     214        2160 :     Node* node) {
     215             :   DCHECK_EQ(IrOpcode::kJSAsyncFunctionEnter, node->opcode());
     216        1203 :   Node* closure = NodeProperties::GetValueInput(node, 0);
     217        1203 :   Node* receiver = NodeProperties::GetValueInput(node, 1);
     218        1203 :   Node* context = NodeProperties::GetContextInput(node);
     219        2283 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
     220        1203 :   Node* effect = NodeProperties::GetEffectInput(node);
     221        1203 :   Node* control = NodeProperties::GetControlInput(node);
     222        1203 :   if (!isolate()->IsPromiseHookProtectorIntact()) return NoChange();
     223             : 
     224             :   // Install a code dependency on the promise hook protector cell.
     225             :   dependencies()->DependOnProtector(
     226        1080 :       PropertyCellRef(broker(), factory()->promise_hook_protector()));
     227             : 
     228             :   // Create the promise for the async function.
     229             :   Node* promise = effect =
     230        1080 :       graph()->NewNode(javascript()->CreatePromise(), context, effect);
     231             : 
     232             :   // Create the JSAsyncFunctionObject based on the SharedFunctionInfo
     233             :   // extracted from the top-most frame in {frame_state}.
     234             :   Handle<SharedFunctionInfo> shared =
     235        1080 :       FrameStateInfoOf(frame_state->op()).shared_info().ToHandleChecked();
     236             :   DCHECK(shared->is_compiled());
     237        1080 :   int register_count = shared->internal_formal_parameter_count() +
     238        2160 :                        shared->GetBytecodeArray()->register_count();
     239             :   Node* value = effect =
     240             :       graph()->NewNode(javascript()->CreateAsyncFunctionObject(register_count),
     241        1080 :                        closure, receiver, promise, context, effect, control);
     242        1080 :   ReplaceWithValue(node, value, effect, control);
     243             :   return Replace(value);
     244             : }
     245             : 
     246        1157 : Reduction JSNativeContextSpecialization::ReduceJSAsyncFunctionReject(
     247        4148 :     Node* node) {
     248             :   DCHECK_EQ(IrOpcode::kJSAsyncFunctionReject, node->opcode());
     249        1157 :   Node* async_function_object = NodeProperties::GetValueInput(node, 0);
     250        1157 :   Node* reason = NodeProperties::GetValueInput(node, 1);
     251        1157 :   Node* context = NodeProperties::GetContextInput(node);
     252        1157 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
     253        1157 :   Node* effect = NodeProperties::GetEffectInput(node);
     254        1157 :   Node* control = NodeProperties::GetControlInput(node);
     255        1157 :   if (!isolate()->IsPromiseHookProtectorIntact()) return NoChange();
     256             : 
     257             :   // Install a code dependency on the promise hook protector cell.
     258             :   dependencies()->DependOnProtector(
     259        1037 :       PropertyCellRef(broker(), factory()->promise_hook_protector()));
     260             : 
     261             :   // Load the promise from the {async_function_object}.
     262             :   Node* promise = effect = graph()->NewNode(
     263             :       simplified()->LoadField(AccessBuilder::ForJSAsyncFunctionObjectPromise()),
     264        3111 :       async_function_object, effect, control);
     265             : 
     266             :   // Create a nested frame state inside the current method's most-recent
     267             :   // {frame_state} that will ensure that lazy deoptimizations at this
     268             :   // point will still return the {promise} instead of the result of the
     269             :   // JSRejectPromise operation (which yields undefined).
     270        1037 :   Node* parameters[] = {promise};
     271             :   frame_state = CreateStubBuiltinContinuationFrameState(
     272             :       jsgraph(), Builtins::kAsyncFunctionLazyDeoptContinuation, context,
     273             :       parameters, arraysize(parameters), frame_state,
     274        1037 :       ContinuationFrameStateMode::LAZY);
     275             : 
     276             :   // Disable the additional debug event for the rejection since a
     277             :   // debug event already happend for the exception that got us here.
     278        1037 :   Node* debug_event = jsgraph()->FalseConstant();
     279             :   effect = graph()->NewNode(javascript()->RejectPromise(), promise, reason,
     280        1037 :                             debug_event, context, frame_state, effect, control);
     281        1037 :   ReplaceWithValue(node, promise, effect, control);
     282             :   return Replace(promise);
     283             : }
     284             : 
     285        1065 : Reduction JSNativeContextSpecialization::ReduceJSAsyncFunctionResolve(
     286        2862 :     Node* node) {
     287             :   DCHECK_EQ(IrOpcode::kJSAsyncFunctionResolve, node->opcode());
     288        1065 :   Node* async_function_object = NodeProperties::GetValueInput(node, 0);
     289        1065 :   Node* value = NodeProperties::GetValueInput(node, 1);
     290        1065 :   Node* context = NodeProperties::GetContextInput(node);
     291        1065 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
     292        1065 :   Node* effect = NodeProperties::GetEffectInput(node);
     293        1065 :   Node* control = NodeProperties::GetControlInput(node);
     294        1065 :   if (!isolate()->IsPromiseHookProtectorIntact()) return NoChange();
     295             : 
     296             :   // Install a code dependency on the promise hook protector cell.
     297             :   dependencies()->DependOnProtector(
     298         954 :       PropertyCellRef(broker(), factory()->promise_hook_protector()));
     299             : 
     300             :   // Load the promise from the {async_function_object}.
     301             :   Node* promise = effect = graph()->NewNode(
     302             :       simplified()->LoadField(AccessBuilder::ForJSAsyncFunctionObjectPromise()),
     303        2862 :       async_function_object, effect, control);
     304             : 
     305             :   // Create a nested frame state inside the current method's most-recent
     306             :   // {frame_state} that will ensure that lazy deoptimizations at this
     307             :   // point will still return the {promise} instead of the result of the
     308             :   // JSResolvePromise operation (which yields undefined).
     309         954 :   Node* parameters[] = {promise};
     310             :   frame_state = CreateStubBuiltinContinuationFrameState(
     311             :       jsgraph(), Builtins::kAsyncFunctionLazyDeoptContinuation, context,
     312             :       parameters, arraysize(parameters), frame_state,
     313         954 :       ContinuationFrameStateMode::LAZY);
     314             : 
     315             :   effect = graph()->NewNode(javascript()->ResolvePromise(), promise, value,
     316         954 :                             context, frame_state, effect, control);
     317         954 :   ReplaceWithValue(node, promise, effect, control);
     318             :   return Replace(promise);
     319             : }
     320             : 
     321      283795 : Reduction JSNativeContextSpecialization::ReduceJSAdd(Node* node) {
     322             :   // TODO(turbofan): This has to run together with the inlining and
     323             :   // native context specialization to be able to leverage the string
     324             :   // constant-folding for optimizing property access, but we should
     325             :   // nevertheless find a better home for this at some point.
     326             :   DCHECK_EQ(IrOpcode::kJSAdd, node->opcode());
     327             : 
     328             :   Node* const lhs = node->InputAt(0);
     329             :   Node* const rhs = node->InputAt(1);
     330             : 
     331       90356 :   base::Optional<size_t> lhs_len = GetMaxStringLength(broker(), lhs);
     332       90356 :   base::Optional<size_t> rhs_len = GetMaxStringLength(broker(), rhs);
     333       90356 :   if (!lhs_len || !rhs_len) {
     334             :     return NoChange();
     335             :   }
     336             : 
     337             :   // Fold into DelayedStringConstant if at least one of the parameters is a
     338             :   // string constant and the addition won't throw due to too long result.
     339       19041 :   if (*lhs_len + *rhs_len <= String::kMaxLength &&
     340        7710 :       (IsStringConstant(broker(), lhs) || IsStringConstant(broker(), rhs))) {
     341        5017 :     const StringConstantBase* left = CreateDelayedStringConstant(lhs);
     342        5017 :     const StringConstantBase* right = CreateDelayedStringConstant(rhs);
     343             :     const StringConstantBase* cons =
     344             :         new (shared_zone()) StringCons(left, right);
     345             : 
     346        5017 :     Node* reduced = graph()->NewNode(common()->DelayedStringConstant(cons));
     347        5017 :     ReplaceWithValue(node, reduced);
     348             :     return Replace(reduced);
     349             :   }
     350             : 
     351             :   return NoChange();
     352             : }
     353             : 
     354        2880 : Reduction JSNativeContextSpecialization::ReduceJSGetSuperConstructor(
     355        8463 :     Node* node) {
     356             :   DCHECK_EQ(IrOpcode::kJSGetSuperConstructor, node->opcode());
     357        2880 :   Node* constructor = NodeProperties::GetValueInput(node, 0);
     358             : 
     359             :   // Check if the input is a known JSFunction.
     360             :   HeapObjectMatcher m(constructor);
     361        2880 :   if (!m.HasValue()) return NoChange();
     362        2855 :   JSFunctionRef function = m.Ref(broker()).AsJSFunction();
     363        2855 :   MapRef function_map = function.map();
     364             :   // TODO(neis): Remove SerializePrototype call once brokerization is complete.
     365        2855 :   function_map.SerializePrototype();
     366        2855 :   ObjectRef function_prototype = function_map.prototype();
     367             : 
     368             :   // We can constant-fold the super constructor access if the
     369             :   // {function}s map is stable, i.e. we can use a code dependency
     370             :   // to guard against [[Prototype]] changes of {function}.
     371        8565 :   if (function_map.is_stable() && function_prototype.IsHeapObject() &&
     372        8507 :       function_prototype.AsHeapObject().map().is_constructor()) {
     373        2804 :     dependencies()->DependOnStableMap(function_map);
     374        2804 :     Node* value = jsgraph()->Constant(function_prototype);
     375        2804 :     ReplaceWithValue(node, value);
     376             :     return Replace(value);
     377             :   }
     378             : 
     379             :   return NoChange();
     380             : }
     381             : 
     382       12089 : Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) {
     383             :   DCHECK_EQ(IrOpcode::kJSInstanceOf, node->opcode());
     384        3795 :   FeedbackParameter const& p = FeedbackParameterOf(node->op());
     385        3795 :   Node* object = NodeProperties::GetValueInput(node, 0);
     386        3795 :   Node* constructor = NodeProperties::GetValueInput(node, 1);
     387        3795 :   Node* context = NodeProperties::GetContextInput(node);
     388        3795 :   Node* effect = NodeProperties::GetEffectInput(node);
     389        3795 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
     390        3795 :   Node* control = NodeProperties::GetControlInput(node);
     391             : 
     392             :   // Check if the right hand side is a known {receiver}, or
     393             :   // we have feedback from the InstanceOfIC.
     394             :   Handle<JSObject> receiver;
     395             :   HeapObjectMatcher m(constructor);
     396        5909 :   if (m.HasValue() && m.Value()->IsJSObject()) {
     397        1047 :     receiver = Handle<JSObject>::cast(m.Value());
     398        2748 :   } else if (p.feedback().IsValid()) {
     399        2748 :     FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot());
     400        5496 :     if (!nexus.GetConstructorFeedback().ToHandle(&receiver)) return NoChange();
     401             :   } else {
     402             :     return NoChange();
     403             :   }
     404             :   Handle<Map> receiver_map(receiver->map(), isolate());
     405             : 
     406             :   // Compute property access info for @@hasInstance on the constructor.
     407        1080 :   PropertyAccessInfo access_info;
     408             :   AccessInfoFactory access_info_factory(
     409        3240 :       broker(), dependencies(), native_context().object(), graph()->zone());
     410        1080 :   if (!access_info_factory.ComputePropertyAccessInfo(
     411             :           receiver_map, factory()->has_instance_symbol(), AccessMode::kLoad,
     412        1080 :           &access_info)) {
     413             :     return NoChange();
     414             :   }
     415             :   DCHECK_EQ(access_info.receiver_maps().size(), 1);
     416             :   DCHECK_EQ(access_info.receiver_maps()[0].address(), receiver_map.address());
     417             : 
     418             :   PropertyAccessBuilder access_builder(jsgraph(), broker(), dependencies());
     419             : 
     420        1064 :   if (access_info.IsNotFound()) {
     421             :     // If there's no @@hasInstance handler, the OrdinaryHasInstance operation
     422             :     // takes over, but that requires the constructor to be callable.
     423          14 :     if (!receiver_map->is_callable()) return NoChange();
     424             : 
     425             :     // Determine actual holder and perform prototype chain checks.
     426             :     Handle<JSObject> holder;
     427          14 :     if (access_info.holder().ToHandle(&holder)) {
     428             :       dependencies()->DependOnStablePrototypeChains(
     429           0 :           broker(), access_info.receiver_maps(), JSObjectRef(broker(), holder));
     430             :     }
     431             : 
     432             :     // Monomorphic property access.
     433             :     constructor =
     434          14 :         access_builder.BuildCheckHeapObject(constructor, &effect, control);
     435             :     access_builder.BuildCheckMaps(constructor, &effect, control,
     436          14 :                                   access_info.receiver_maps());
     437             : 
     438             :     // Lower to OrdinaryHasInstance(C, O).
     439          14 :     NodeProperties::ReplaceValueInput(node, constructor, 0);
     440          14 :     NodeProperties::ReplaceValueInput(node, object, 1);
     441          14 :     NodeProperties::ReplaceEffectInput(node, effect);
     442          14 :     NodeProperties::ChangeOp(node, javascript()->OrdinaryHasInstance());
     443          14 :     Reduction const reduction = ReduceJSOrdinaryHasInstance(node);
     444          14 :     return reduction.Changed() ? reduction : Changed(node);
     445             :   }
     446             : 
     447        1050 :   if (access_info.IsDataConstant() || access_info.IsDataConstantField()) {
     448             :     // Determine actual holder.
     449             :     Handle<JSObject> holder;
     450             :     bool found_on_proto = access_info.holder().ToHandle(&holder);
     451        1036 :     if (!found_on_proto) holder = receiver;
     452             : 
     453             :     Handle<Object> constant;
     454        1036 :     if (access_info.IsDataConstant()) {
     455             :       DCHECK(!FLAG_track_constant_fields);
     456             :       constant = access_info.constant();
     457             :     } else {
     458             :       DCHECK(FLAG_track_constant_fields);
     459             :       DCHECK(access_info.IsDataConstantField());
     460        1036 :       FieldIndex field_index = access_info.field_index();
     461             :       constant = JSObject::FastPropertyAt(holder, Representation::Tagged(),
     462        1036 :                                           field_index);
     463        2072 :       if (!constant->IsCallable()) {
     464           1 :         return NoChange();
     465             :       }
     466             : 
     467             :       // Install dependency on constness. Unfortunately, access_info does not
     468             :       // track descriptor index, so we have to search for it.
     469             :       MapRef holder_map(broker(), handle(holder->map(), isolate()));
     470             :       Handle<DescriptorArray> descriptors(
     471        3105 :           holder_map.object()->instance_descriptors(), isolate());
     472             :       int descriptor_index = descriptors->Search(
     473        3105 :           *(factory()->has_instance_symbol()), *(holder_map.object()));
     474        1035 :       CHECK_NE(descriptor_index, DescriptorArray::kNotFound);
     475        1035 :       holder_map.SerializeOwnDescriptors();
     476        1035 :       if (dependencies()->DependOnFieldConstness(
     477        1035 :               holder_map, descriptor_index) != PropertyConstness::kConst) {
     478             :         return NoChange();
     479             :       }
     480             :     }
     481             : 
     482        1035 :     if (found_on_proto) {
     483             :       dependencies()->DependOnStablePrototypeChains(
     484        1005 :           broker(), access_info.receiver_maps(), JSObjectRef(broker(), holder));
     485             :     }
     486             : 
     487             :     DCHECK(constant->IsCallable());
     488             : 
     489             :     // Check that {constructor} is actually {receiver}.
     490             :     constructor =
     491        1035 :         access_builder.BuildCheckValue(constructor, &effect, control, receiver);
     492             : 
     493             :     // Monomorphic property access.
     494             :     access_builder.BuildCheckMaps(constructor, &effect, control,
     495        1035 :                                   access_info.receiver_maps());
     496             : 
     497             :     // Create a nested frame state inside the current method's most-recent frame
     498             :     // state that will ensure that deopts that happen after this point will not
     499             :     // fallback to the last Checkpoint--which would completely re-execute the
     500             :     // instanceof logic--but rather create an activation of a version of the
     501             :     // ToBoolean stub that finishes the remaining work of instanceof and returns
     502             :     // to the caller without duplicating side-effects upon a lazy deopt.
     503             :     Node* continuation_frame_state = CreateStubBuiltinContinuationFrameState(
     504             :         jsgraph(), Builtins::kToBooleanLazyDeoptContinuation, context, nullptr,
     505        1035 :         0, frame_state, ContinuationFrameStateMode::LAZY);
     506             : 
     507             :     // Call the @@hasInstance handler.
     508        1035 :     Node* target = jsgraph()->Constant(constant);
     509        1035 :     node->InsertInput(graph()->zone(), 0, target);
     510        1035 :     node->ReplaceInput(1, constructor);
     511        1035 :     node->ReplaceInput(2, object);
     512        1035 :     node->ReplaceInput(4, continuation_frame_state);
     513        1035 :     node->ReplaceInput(5, effect);
     514             :     NodeProperties::ChangeOp(
     515             :         node, javascript()->Call(3, CallFrequency(), VectorSlotPair(),
     516        2070 :                                  ConvertReceiverMode::kNotNullOrUndefined));
     517             : 
     518             :     // Rewire the value uses of {node} to ToBoolean conversion of the result.
     519        1035 :     Node* value = graph()->NewNode(simplified()->ToBoolean(), node);
     520       12494 :     for (Edge edge : node->use_edges()) {
     521        7292 :       if (NodeProperties::IsValueEdge(edge) && edge.from() != value) {
     522        1045 :         edge.UpdateTo(value);
     523        2090 :         Revisit(edge.from());
     524             :       }
     525             :     }
     526             :     return Changed(node);
     527             :   }
     528             : 
     529             :   return NoChange();
     530             : }
     531             : 
     532             : JSNativeContextSpecialization::InferHasInPrototypeChainResult
     533        1823 : JSNativeContextSpecialization::InferHasInPrototypeChain(
     534        1823 :     Node* receiver, Node* effect, Handle<HeapObject> prototype) {
     535             :   ZoneHandleSet<Map> receiver_maps;
     536             :   NodeProperties::InferReceiverMapsResult result =
     537             :       NodeProperties::InferReceiverMaps(broker(), receiver, effect,
     538        1823 :                                         &receiver_maps);
     539        1823 :   if (result == NodeProperties::kNoReceiverMaps) return kMayBeInPrototypeChain;
     540             : 
     541             :   // Check if either all or none of the {receiver_maps} have the given
     542             :   // {prototype} in their prototype chain.
     543             :   bool all = true;
     544             :   bool none = true;
     545         402 :   for (size_t i = 0; i < receiver_maps.size(); ++i) {
     546             :     Handle<Map> receiver_map = receiver_maps[i];
     547         332 :     if (receiver_map->instance_type() <= LAST_SPECIAL_RECEIVER_TYPE) {
     548             :       return kMayBeInPrototypeChain;
     549             :     }
     550          42 :     if (result == NodeProperties::kUnreliableReceiverMaps) {
     551             :       // In case of an unreliable {result} we need to ensure that all
     552             :       // {receiver_maps} are stable, because otherwise we cannot trust
     553             :       // the {receiver_maps} information, since arbitrary side-effects
     554             :       // may have happened.
     555          21 :       if (!receiver_map->is_stable()) {
     556             :         return kMayBeInPrototypeChain;
     557             :       }
     558             :     }
     559          56 :     for (PrototypeIterator j(isolate(), receiver_map);; j.Advance()) {
     560          56 :       if (j.IsAtEnd()) {
     561             :         all = false;
     562             :         break;
     563             :       }
     564             :       Handle<HeapObject> const current =
     565             :           PrototypeIterator::GetCurrent<HeapObject>(j);
     566          49 :       if (current.is_identical_to(prototype)) {
     567             :         none = false;
     568             :         break;
     569             :       }
     570          35 :       if (!current->map()->is_stable() ||
     571             :           current->map()->instance_type() <= LAST_SPECIAL_RECEIVER_TYPE) {
     572             :         return kMayBeInPrototypeChain;
     573             :       }
     574          14 :     }
     575             :   }
     576             :   DCHECK_IMPLIES(all, !none);
     577             : 
     578          35 :   if (all) return kIsInPrototypeChain;
     579           7 :   if (none) return kIsNotInPrototypeChain;
     580           0 :   return kMayBeInPrototypeChain;
     581             : }
     582             : 
     583        1823 : Reduction JSNativeContextSpecialization::ReduceJSHasInPrototypeChain(
     584          35 :     Node* node) {
     585             :   DCHECK_EQ(IrOpcode::kJSHasInPrototypeChain, node->opcode());
     586        1823 :   Node* value = NodeProperties::GetValueInput(node, 0);
     587        1823 :   Node* prototype = NodeProperties::GetValueInput(node, 1);
     588        1823 :   Node* effect = NodeProperties::GetEffectInput(node);
     589             : 
     590             :   // Check if we can constant-fold the prototype chain walk
     591             :   // for the given {value} and the {prototype}.
     592             :   HeapObjectMatcher m(prototype);
     593        1823 :   if (m.HasValue()) {
     594             :     InferHasInPrototypeChainResult result =
     595        1823 :         InferHasInPrototypeChain(value, effect, m.Value());
     596        1823 :     if (result != kMayBeInPrototypeChain) {
     597          70 :       Node* value = jsgraph()->BooleanConstant(result == kIsInPrototypeChain);
     598          35 :       ReplaceWithValue(node, value);
     599             :       return Replace(value);
     600             :     }
     601             :   }
     602             : 
     603             :   return NoChange();
     604             : }
     605             : 
     606        1162 : Reduction JSNativeContextSpecialization::ReduceJSOrdinaryHasInstance(
     607        2816 :     Node* node) {
     608             :   DCHECK_EQ(IrOpcode::kJSOrdinaryHasInstance, node->opcode());
     609        1162 :   Node* constructor = NodeProperties::GetValueInput(node, 0);
     610        1162 :   Node* object = NodeProperties::GetValueInput(node, 1);
     611             : 
     612             :   // Check if the {constructor} is known at compile time.
     613             :   HeapObjectMatcher m(constructor);
     614        1162 :   if (!m.HasValue()) return NoChange();
     615             : 
     616             :   // Check if the {constructor} is a JSBoundFunction.
     617        2296 :   if (m.Value()->IsJSBoundFunction()) {
     618             :     // OrdinaryHasInstance on bound functions turns into a recursive
     619             :     // invocation of the instanceof operator again.
     620             :     // ES6 section 7.3.19 OrdinaryHasInstance (C, O) step 2.
     621           7 :     Handle<JSBoundFunction> function = Handle<JSBoundFunction>::cast(m.Value());
     622             :     Handle<JSReceiver> bound_target_function(function->bound_target_function(),
     623          14 :                                              isolate());
     624           7 :     NodeProperties::ReplaceValueInput(node, object, 0);
     625             :     NodeProperties::ReplaceValueInput(
     626           7 :         node, jsgraph()->HeapConstant(bound_target_function), 1);
     627          14 :     NodeProperties::ChangeOp(node, javascript()->InstanceOf(VectorSlotPair()));
     628           7 :     Reduction const reduction = ReduceJSInstanceOf(node);
     629           7 :     return reduction.Changed() ? reduction : Changed(node);
     630             :   }
     631             : 
     632             :   // Optimize if we currently know the "prototype" property.
     633        2282 :   if (m.Value()->IsJSFunction()) {
     634        1127 :     JSFunctionRef function = m.Ref(broker()).AsJSFunction();
     635             :     // TODO(neis): This is a temporary hack needed because the copy reducer
     636             :     // runs only after this pass.
     637        1127 :     function.Serialize();
     638             :     // TODO(neis): Remove the has_prototype_slot condition once the broker is
     639             :     // always enabled.
     640        2098 :     if (!function.map().has_prototype_slot() || !function.has_prototype() ||
     641         971 :         function.PrototypeRequiresRuntimeLookup()) {
     642             :       return NoChange();
     643             :     }
     644         841 :     ObjectRef prototype = dependencies()->DependOnPrototypeProperty(function);
     645         841 :     Node* prototype_constant = jsgraph()->Constant(prototype);
     646             : 
     647             :     // Lower the {node} to JSHasInPrototypeChain.
     648         841 :     NodeProperties::ReplaceValueInput(node, object, 0);
     649         841 :     NodeProperties::ReplaceValueInput(node, prototype_constant, 1);
     650         841 :     NodeProperties::ChangeOp(node, javascript()->HasInPrototypeChain());
     651         841 :     Reduction const reduction = ReduceJSHasInPrototypeChain(node);
     652         841 :     return reduction.Changed() ? reduction : Changed(node);
     653             :   }
     654             : 
     655             :   return NoChange();
     656             : }
     657             : 
     658             : // ES section #sec-promise-resolve
     659         642 : Reduction JSNativeContextSpecialization::ReduceJSPromiseResolve(Node* node) {
     660             :   DCHECK_EQ(IrOpcode::kJSPromiseResolve, node->opcode());
     661         171 :   Node* constructor = NodeProperties::GetValueInput(node, 0);
     662         171 :   Node* value = NodeProperties::GetValueInput(node, 1);
     663         171 :   Node* context = NodeProperties::GetContextInput(node);
     664         171 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
     665         171 :   Node* effect = NodeProperties::GetEffectInput(node);
     666         171 :   Node* control = NodeProperties::GetControlInput(node);
     667             : 
     668         171 :   if (!isolate()->IsPromiseHookProtectorIntact()) {
     669             :     return NoChange();
     670             :   }
     671             : 
     672             :   // Check if the {constructor} is the %Promise% function.
     673             :   HeapObjectMatcher m(constructor);
     674         489 :   if (!m.HasValue() ||
     675         652 :       !m.Ref(broker()).equals(broker()->native_context().promise_function())) {
     676             :     return NoChange();
     677             :   }
     678             : 
     679             :   // Check if we know something about the {value}.
     680             :   ZoneHandleSet<Map> value_maps;
     681             :   NodeProperties::InferReceiverMapsResult result =
     682          79 :       NodeProperties::InferReceiverMaps(broker(), value, effect, &value_maps);
     683          79 :   if (result == NodeProperties::kNoReceiverMaps) return NoChange();
     684             :   DCHECK_NE(0, value_maps.size());
     685             : 
     686             :   // Check that the {value} cannot be a JSPromise.
     687          66 :   for (Handle<Map> const value_map : value_maps) {
     688          33 :     if (value_map->IsJSPromiseMap()) return NoChange();
     689             :   }
     690             : 
     691             :   // Install a code dependency on the promise hook protector cell.
     692             :   dependencies()->DependOnProtector(
     693          33 :       PropertyCellRef(broker(), factory()->promise_hook_protector()));
     694             : 
     695             :   // Create a %Promise% instance and resolve it with {value}.
     696             :   Node* promise = effect =
     697          33 :       graph()->NewNode(javascript()->CreatePromise(), context, effect);
     698             :   effect = graph()->NewNode(javascript()->ResolvePromise(), promise, value,
     699          33 :                             context, frame_state, effect, control);
     700          33 :   ReplaceWithValue(node, promise, effect, control);
     701             :   return Replace(promise);
     702             : }
     703             : 
     704             : // ES section #sec-promise-resolve-functions
     705        2760 : Reduction JSNativeContextSpecialization::ReduceJSResolvePromise(Node* node) {
     706             :   DCHECK_EQ(IrOpcode::kJSResolvePromise, node->opcode());
     707         997 :   Node* promise = NodeProperties::GetValueInput(node, 0);
     708         997 :   Node* resolution = NodeProperties::GetValueInput(node, 1);
     709         997 :   Node* context = NodeProperties::GetContextInput(node);
     710         997 :   Node* effect = NodeProperties::GetEffectInput(node);
     711         997 :   Node* control = NodeProperties::GetControlInput(node);
     712             : 
     713             :   // Check if we know something about the {resolution}.
     714             :   ZoneHandleSet<Map> resolution_maps;
     715             :   NodeProperties::InferReceiverMapsResult result =
     716             :       NodeProperties::InferReceiverMaps(broker(), resolution, effect,
     717         997 :                                         &resolution_maps);
     718         997 :   if (result == NodeProperties::kNoReceiverMaps) return NoChange();
     719             :   DCHECK_NE(0, resolution_maps.size());
     720             : 
     721             :   // When the {resolution_maps} information is unreliable, we can
     722             :   // still optimize if all individual {resolution_maps} are stable.
     723         672 :   if (result == NodeProperties::kUnreliableReceiverMaps) {
     724        1330 :     for (Handle<Map> resolution_map : resolution_maps) {
     725         665 :       if (!resolution_map->is_stable()) return NoChange();
     726             :     }
     727             :   }
     728             : 
     729             :   // Compute property access info for "then" on {resolution}.
     730         672 :   PropertyAccessInfo access_info;
     731             :   AccessInfoFactory access_info_factory(
     732        2016 :       broker(), dependencies(), native_context().object(), graph()->zone());
     733         672 :   if (!access_info_factory.ComputePropertyAccessInfo(
     734             :           MapHandles(resolution_maps.begin(), resolution_maps.end()),
     735        1344 :           factory()->then_string(), AccessMode::kLoad, &access_info)) {
     736             :     return NoChange();
     737             :   }
     738             : 
     739             :   // We can further optimize the case where {resolution}
     740             :   // definitely doesn't have a "then" property.
     741          27 :   if (!access_info.IsNotFound()) return NoChange();
     742             :   PropertyAccessBuilder access_builder(jsgraph(), broker(), dependencies());
     743             : 
     744             :   // Add proper dependencies on the {resolution}s [[Prototype]]s.
     745             :   Handle<JSObject> holder;
     746          27 :   if (access_info.holder().ToHandle(&holder)) {
     747             :     dependencies()->DependOnStablePrototypeChains(
     748          27 :         broker(), access_info.receiver_maps(), JSObjectRef(broker(), holder));
     749             :   }
     750             : 
     751             :   // Add stability dependencies on the {resolution_maps}.
     752          27 :   if (result == NodeProperties::kUnreliableReceiverMaps) {
     753          40 :     for (Handle<Map> resolution_map : resolution_maps) {
     754          20 :       dependencies()->DependOnStableMap(MapRef(broker(), resolution_map));
     755             :     }
     756             :   }
     757             : 
     758             :   // Simply fulfill the {promise} with the {resolution}.
     759             :   Node* value = effect =
     760             :       graph()->NewNode(javascript()->FulfillPromise(), promise, resolution,
     761          27 :                        context, effect, control);
     762          27 :   ReplaceWithValue(node, value, effect, control);
     763             :   return Replace(value);
     764             : }
     765             : 
     766      533561 : Reduction JSNativeContextSpecialization::ReduceJSLoadContext(Node* node) {
     767             :   DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode());
     768      533389 :   ContextAccess const& access = ContextAccessOf(node->op());
     769             :   // Specialize JSLoadContext(NATIVE_CONTEXT_INDEX) to the known native
     770             :   // context (if any), so we can constant-fold those fields, which is
     771             :   // safe, since the NATIVE_CONTEXT_INDEX slot is always immutable.
     772      533389 :   if (access.index() == Context::NATIVE_CONTEXT_INDEX) {
     773         344 :     Node* value = jsgraph()->Constant(native_context());
     774         172 :     ReplaceWithValue(node, value);
     775             :     return Replace(value);
     776             :   }
     777             :   return NoChange();
     778             : }
     779             : 
     780             : namespace {
     781             : 
     782             : FieldAccess ForPropertyCellValue(MachineRepresentation representation,
     783             :                                  Type type, MaybeHandle<Map> map,
     784             :                                  Handle<Name> name) {
     785             :   WriteBarrierKind kind = kFullWriteBarrier;
     786       39398 :   if (representation == MachineRepresentation::kTaggedSigned) {
     787             :     kind = kNoWriteBarrier;
     788        9526 :   } else if (representation == MachineRepresentation::kTaggedPointer) {
     789             :     kind = kPointerWriteBarrier;
     790             :   }
     791       41508 :   MachineType r = MachineType::TypeForRepresentation(representation);
     792             :   FieldAccess access = {
     793             :       kTaggedBase, PropertyCell::kValueOffset, name, map, type, r, kind};
     794             :   return access;
     795             : }
     796             : 
     797             : }  // namespace
     798             : 
     799         234 : Reduction JSNativeContextSpecialization::ReduceGlobalAccess(
     800             :     Node* node, Node* receiver, Node* value, Handle<Name> name,
     801             :     AccessMode access_mode, Node* index) {
     802             :   // Lookup on the global object. We only deal with own data properties
     803             :   // of the global object here (represented as PropertyCell).
     804         234 :   LookupIterator it(isolate(), global_object(), name, LookupIterator::OWN);
     805         234 :   it.TryLookupCachedProperty();
     806         234 :   if (it.state() != LookupIterator::DATA) return NoChange();
     807         424 :   if (!it.GetHolder<JSObject>()->IsJSGlobalObject()) return NoChange();
     808         212 :   Handle<PropertyCell> property_cell = it.GetPropertyCell();
     809             :   return ReduceGlobalAccess(node, receiver, value, name, access_mode, index,
     810         212 :                             property_cell);
     811             : }
     812             : 
     813      191187 : Reduction JSNativeContextSpecialization::ReduceGlobalAccess(
     814             :     Node* node, Node* receiver, Node* value, Handle<Name> name,
     815      559999 :     AccessMode access_mode, Node* index, Handle<PropertyCell> property_cell) {
     816      191187 :   Node* effect = NodeProperties::GetEffectInput(node);
     817      191187 :   Node* control = NodeProperties::GetControlInput(node);
     818             : 
     819             :   Handle<Object> property_cell_value(property_cell->value(), isolate());
     820      191187 :   if (property_cell_value.is_identical_to(factory()->the_hole_value())) {
     821             :     // The property cell is no longer valid.
     822             :     return NoChange();
     823             :   }
     824             : 
     825      191159 :   PropertyDetails property_details = property_cell->property_details();
     826             :   PropertyCellType property_cell_type = property_details.cell_type();
     827             :   DCHECK_EQ(kData, property_details.kind());
     828             : 
     829             :   // We have additional constraints for stores.
     830      191159 :   if (access_mode == AccessMode::kStore) {
     831       16125 :     if (property_details.IsReadOnly()) {
     832             :       // Don't even bother trying to lower stores to read-only data properties.
     833             :       return NoChange();
     834       16125 :     } else if (property_cell_type == PropertyCellType::kUndefined) {
     835             :       // There's no fast-path for dealing with undefined property cells.
     836             :       return NoChange();
     837       16125 :     } else if (property_cell_type == PropertyCellType::kConstantType) {
     838             :       // There's also no fast-path to store to a global cell which pretended
     839             :       // to be stable, but is no longer stable now.
     840       42056 :       if (property_cell_value->IsHeapObject() &&
     841       14942 :           !Handle<HeapObject>::cast(property_cell_value)->map()->is_stable()) {
     842             :         return NoChange();
     843             :       }
     844             :     }
     845             :   }
     846             : 
     847             :   // Ensure that {index} matches the specified {name} (if {index} is given).
     848      191159 :   if (index != nullptr) {
     849           8 :     effect = BuildCheckEqualsName(name, index, effect, control);
     850             :   }
     851             : 
     852             :   // Check if we have a {receiver} to validate. If so, we need to check that
     853             :   // the {receiver} is actually the JSGlobalProxy for the native context that
     854             :   // we are specializing to.
     855      191159 :   if (receiver != nullptr) {
     856             :     Node* check = graph()->NewNode(simplified()->ReferenceEqual(), receiver,
     857         558 :                                    jsgraph()->HeapConstant(global_proxy()));
     858             :     effect = graph()->NewNode(
     859             :         simplified()->CheckIf(DeoptimizeReason::kReceiverNotAGlobalProxy),
     860         558 :         check, effect, control);
     861             :   }
     862             : 
     863      191159 :   if (access_mode == AccessMode::kLoad) {
     864             :     // Load from non-configurable, read-only data property on the global
     865             :     // object can be constant-folded, even without deoptimization support.
     866      284617 :     if (!property_details.IsConfigurable() && property_details.IsReadOnly()) {
     867        4077 :       value = jsgraph()->Constant(property_cell_value);
     868             :     } else {
     869             :       // Record a code dependency on the cell if we can benefit from the
     870             :       // additional feedback, or the global property is configurable (i.e.
     871             :       // can be deleted or reconfigured to an accessor property).
     872      170957 :       if (property_details.cell_type() != PropertyCellType::kMutable ||
     873             :           property_details.IsConfigurable()) {
     874             :         dependencies()->DependOnGlobalProperty(
     875      166214 :             PropertyCellRef(broker(), property_cell));
     876             :       }
     877             : 
     878             :       // Load from constant/undefined global property can be constant-folded.
     879      170957 :       if (property_details.cell_type() == PropertyCellType::kConstant ||
     880             :           property_details.cell_type() == PropertyCellType::kUndefined) {
     881      145393 :         value = jsgraph()->Constant(property_cell_value);
     882      145393 :         CHECK(
     883             :             !property_cell_value.is_identical_to(factory()->the_hole_value()));
     884             :       } else {
     885             :         // Load from constant type cell can benefit from type feedback.
     886             :         MaybeHandle<Map> map;
     887             :         Type property_cell_value_type = Type::NonInternal();
     888             :         MachineRepresentation representation = MachineRepresentation::kTagged;
     889       25564 :         if (property_details.cell_type() == PropertyCellType::kConstantType) {
     890             :           // Compute proper type based on the current value in the cell.
     891       37592 :           if (property_cell_value->IsSmi()) {
     892             :             property_cell_value_type = Type::SignedSmall();
     893             :             representation = MachineRepresentation::kTaggedSigned;
     894        4408 :           } else if (property_cell_value->IsNumber()) {
     895             :             property_cell_value_type = Type::Number();
     896             :             representation = MachineRepresentation::kTaggedPointer;
     897             :           } else {
     898             :             MapRef property_cell_value_map(
     899             :                 broker(), handle(HeapObject::cast(*property_cell_value)->map(),
     900             :                                  isolate()));
     901        1436 :             property_cell_value_type = Type::For(property_cell_value_map);
     902             :             representation = MachineRepresentation::kTaggedPointer;
     903             : 
     904             :             // We can only use the property cell value map for map check
     905             :             // elimination if it's stable, i.e. the HeapObject wasn't
     906             :             // mutated without the cell state being updated.
     907        1436 :             if (property_cell_value_map.is_stable()) {
     908        1432 :               dependencies()->DependOnStableMap(property_cell_value_map);
     909        1432 :               map = property_cell_value_map.object();
     910             :             }
     911             :           }
     912             :         }
     913             :         value = effect = graph()->NewNode(
     914             :             simplified()->LoadField(ForPropertyCellValue(
     915             :                 representation, property_cell_value_type, map, name)),
     916       76692 :             jsgraph()->HeapConstant(property_cell), effect, control);
     917             :       }
     918             :     }
     919             :   } else {
     920             :     DCHECK_EQ(AccessMode::kStore, access_mode);
     921             :     DCHECK(!property_details.IsReadOnly());
     922       16125 :     switch (property_details.cell_type()) {
     923             :       case PropertyCellType::kUndefined: {
     924           0 :         UNREACHABLE();
     925             :         break;
     926             :       }
     927             :       case PropertyCellType::kConstant: {
     928             :         // Record a code dependency on the cell, and just deoptimize if the new
     929             :         // value doesn't match the previous value stored inside the cell.
     930             :         dependencies()->DependOnGlobalProperty(
     931         181 :             PropertyCellRef(broker(), property_cell));
     932             :         Node* check =
     933             :             graph()->NewNode(simplified()->ReferenceEqual(), value,
     934         362 :                              jsgraph()->Constant(property_cell_value));
     935             :         effect = graph()->NewNode(
     936             :             simplified()->CheckIf(DeoptimizeReason::kValueMismatch), check,
     937         543 :             effect, control);
     938         181 :         break;
     939             :       }
     940             :       case PropertyCellType::kConstantType: {
     941             :         // Record a code dependency on the cell, and just deoptimize if the new
     942             :         // values' type doesn't match the type of the previous value in the
     943             :         // cell.
     944             :         dependencies()->DependOnGlobalProperty(
     945       13834 :             PropertyCellRef(broker(), property_cell));
     946             :         Type property_cell_value_type;
     947             :         MachineRepresentation representation = MachineRepresentation::kTagged;
     948       27668 :         if (property_cell_value->IsHeapObject()) {
     949             :           // We cannot do anything if the {property_cell_value}s map is no
     950             :           // longer stable.
     951             :           Handle<Map> property_cell_value_map(
     952        1108 :               Handle<HeapObject>::cast(property_cell_value)->map(), isolate());
     953             :           DCHECK(property_cell_value_map->is_stable());
     954             :           dependencies()->DependOnStableMap(
     955         554 :               MapRef(broker(), property_cell_value_map));
     956             : 
     957             :           // Check that the {value} is a HeapObject.
     958             :           value = effect = graph()->NewNode(simplified()->CheckHeapObject(),
     959         554 :                                             value, effect, control);
     960             : 
     961             :           // Check {value} map against the {property_cell} map.
     962             :           effect =
     963             :               graph()->NewNode(simplified()->CheckMaps(
     964             :                                    CheckMapsFlag::kNone,
     965             :                                    ZoneHandleSet<Map>(property_cell_value_map)),
     966        1662 :                                value, effect, control);
     967             :           property_cell_value_type = Type::OtherInternal();
     968             :           representation = MachineRepresentation::kTaggedPointer;
     969             :         } else {
     970             :           // Check that the {value} is a Smi.
     971             :           value = effect = graph()->NewNode(
     972       39840 :               simplified()->CheckSmi(VectorSlotPair()), value, effect, control);
     973             :           property_cell_value_type = Type::SignedSmall();
     974             :           representation = MachineRepresentation::kTaggedSigned;
     975             :         }
     976             :         effect = graph()->NewNode(simplified()->StoreField(ForPropertyCellValue(
     977             :                                       representation, property_cell_value_type,
     978             :                                       MaybeHandle<Map>(), name)),
     979             :                                   jsgraph()->HeapConstant(property_cell), value,
     980       41502 :                                   effect, control);
     981             :         break;
     982             :       }
     983             :       case PropertyCellType::kMutable: {
     984             :         // Record a code dependency on the cell, and just deoptimize if the
     985             :         // property ever becomes read-only.
     986             :         dependencies()->DependOnGlobalProperty(
     987        2110 :             PropertyCellRef(broker(), property_cell));
     988             :         effect = graph()->NewNode(
     989             :             simplified()->StoreField(ForPropertyCellValue(
     990             :                 MachineRepresentation::kTagged, Type::NonInternal(),
     991             :                 MaybeHandle<Map>(), name)),
     992        6330 :             jsgraph()->HeapConstant(property_cell), value, effect, control);
     993        2110 :         break;
     994             :       }
     995             :     }
     996             :   }
     997             : 
     998      191159 :   ReplaceWithValue(node, value, effect, control);
     999             :   return Replace(value);
    1000             : }
    1001             : 
    1002     2052578 : Reduction JSNativeContextSpecialization::ReduceJSLoadGlobal(Node* node) {
    1003             :   DCHECK_EQ(IrOpcode::kJSLoadGlobal, node->opcode());
    1004     1026094 :   Node* effect = NodeProperties::GetEffectInput(node);
    1005             : 
    1006     1026094 :   LoadGlobalParameters const& p = LoadGlobalParametersOf(node->op());
    1007     1026094 :   if (!p.feedback().IsValid()) return NoChange();
    1008     1026094 :   FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot());
    1009             : 
    1010             :   DCHECK(nexus.kind() == FeedbackSlotKind::kLoadGlobalInsideTypeof ||
    1011             :          nexus.kind() == FeedbackSlotKind::kLoadGlobalNotInsideTypeof);
    1012     1201145 :   if (nexus.ic_state() != MONOMORPHIC || nexus.GetFeedback()->IsCleared()) {
    1013             :     return NoChange();
    1014             :   }
    1015      349992 :   Handle<Object> feedback(nexus.GetFeedback()->GetHeapObjectOrSmi(), isolate());
    1016             : 
    1017      349992 :   if (feedback->IsSmi()) {
    1018             :     // The wanted name belongs to a script-scope variable and the feedback tells
    1019             :     // us where to find its value.
    1020             : 
    1021         130 :     int number = feedback->Number();
    1022             :     int const script_context_index =
    1023         260 :         FeedbackNexus::ContextIndexBits::decode(number);
    1024         130 :     int const context_slot_index = FeedbackNexus::SlotIndexBits::decode(number);
    1025             :     bool const immutable = FeedbackNexus::ImmutabilityBit::decode(number);
    1026             :     Handle<Context> context = ScriptContextTable::GetContext(
    1027         260 :         isolate(), native_context().script_context_table().object(),
    1028         260 :         script_context_index);
    1029             : 
    1030             :     {
    1031             :       ObjectRef contents(broker(),
    1032         260 :                          handle(context->get(context_slot_index), isolate()));
    1033         130 :       CHECK(!contents.equals(ObjectRef(broker(), factory()->the_hole_value())));
    1034             :     }
    1035             : 
    1036         130 :     Node* context_constant = jsgraph()->Constant(context);
    1037             :     Node* value = effect = graph()->NewNode(
    1038             :         javascript()->LoadContext(0, context_slot_index, immutable),
    1039         260 :         context_constant, effect);
    1040         130 :     ReplaceWithValue(node, value, effect);
    1041             :     return Replace(value);
    1042             :   }
    1043             : 
    1044      349732 :   CHECK(feedback->IsPropertyCell());
    1045             :   // The wanted name belongs (or did belong) to a property on the global object
    1046             :   // and the feedback is the cell holding its value.
    1047      174866 :   return ReduceGlobalAccess(node, nullptr, nullptr, p.name(), AccessMode::kLoad,
    1048      349732 :                             nullptr, Handle<PropertyCell>::cast(feedback));
    1049             : }
    1050             : 
    1051      432325 : Reduction JSNativeContextSpecialization::ReduceJSStoreGlobal(Node* node) {
    1052             :   DCHECK_EQ(IrOpcode::kJSStoreGlobal, node->opcode());
    1053      216149 :   Node* value = NodeProperties::GetValueInput(node, 0);
    1054      216149 :   Node* effect = NodeProperties::GetEffectInput(node);
    1055      216149 :   Node* control = NodeProperties::GetControlInput(node);
    1056             : 
    1057      216149 :   StoreGlobalParameters const& p = StoreGlobalParametersOf(node->op());
    1058      216149 :   if (!p.feedback().IsValid()) return NoChange();
    1059      216149 :   FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot());
    1060             : 
    1061             :   DCHECK(nexus.kind() == FeedbackSlotKind::kStoreGlobalSloppy ||
    1062             :          nexus.kind() == FeedbackSlotKind::kStoreGlobalStrict);
    1063      232334 :   if (nexus.ic_state() != MONOMORPHIC || nexus.GetFeedback()->IsCleared()) {
    1064             :     return NoChange();
    1065             :   }
    1066       32236 :   Handle<Object> feedback(nexus.GetFeedback()->GetHeapObjectOrSmi(), isolate());
    1067             : 
    1068       32236 :   if (feedback->IsSmi()) {
    1069             :     // The wanted name belongs to a script-scope variable and the feedback tells
    1070             :     // us where to find its value.
    1071             : 
    1072             :     int const script_context_index =
    1073          18 :         FeedbackNexus::ContextIndexBits::decode(feedback->Number());
    1074             :     int const context_slot_index =
    1075          18 :         FeedbackNexus::SlotIndexBits::decode(feedback->Number());
    1076             :     bool const immutable =
    1077          18 :         FeedbackNexus::ImmutabilityBit::decode(feedback->Number());
    1078             :     Handle<Context> context = ScriptContextTable::GetContext(
    1079          18 :         isolate(), native_context().script_context_table().object(),
    1080          18 :         script_context_index);
    1081             : 
    1082           9 :     if (immutable) return NoChange();
    1083             : 
    1084             :     {
    1085             :       ObjectRef contents(broker(),
    1086          18 :                          handle(context->get(context_slot_index), isolate()));
    1087           9 :       CHECK(!contents.equals(ObjectRef(broker(), factory()->the_hole_value())));
    1088             :     }
    1089             : 
    1090           9 :     Node* context_constant = jsgraph()->Constant(context);
    1091             :     effect = graph()->NewNode(javascript()->StoreContext(0, context_slot_index),
    1092          18 :                               value, context_constant, effect, control);
    1093           9 :     ReplaceWithValue(node, value, effect, control);
    1094             :     return Replace(value);
    1095             :   }
    1096             : 
    1097       32218 :   CHECK(feedback->IsPropertyCell());
    1098             :   // The wanted name belongs (or did belong) to a property on the global object
    1099             :   // and the feedback is the cell holding its value.
    1100       16109 :   return ReduceGlobalAccess(node, nullptr, value, p.name(), AccessMode::kStore,
    1101       32218 :                             nullptr, Handle<PropertyCell>::cast(feedback));
    1102             : }
    1103             : 
    1104      141922 : Reduction JSNativeContextSpecialization::ReduceNamedAccess(
    1105      141922 :     Node* node, Node* value, MapHandles const& receiver_maps, Handle<Name> name,
    1106      679821 :     AccessMode access_mode, Node* index) {
    1107             :   DCHECK(node->opcode() == IrOpcode::kJSLoadNamed ||
    1108             :          node->opcode() == IrOpcode::kJSStoreNamed ||
    1109             :          node->opcode() == IrOpcode::kJSLoadProperty ||
    1110             :          node->opcode() == IrOpcode::kJSStoreProperty ||
    1111             :          node->opcode() == IrOpcode::kJSStoreNamedOwn);
    1112      141922 :   Node* receiver = NodeProperties::GetValueInput(node, 0);
    1113      141922 :   Node* context = NodeProperties::GetContextInput(node);
    1114      141922 :   Node* frame_state = NodeProperties::GetFrameStateInput(node);
    1115      141922 :   Node* effect = NodeProperties::GetEffectInput(node);
    1116      141922 :   Node* control = NodeProperties::GetControlInput(node);
    1117             : 
    1118             :   // Check if we have an access o.x or o.x=v where o is the current
    1119             :   // native contexts' global proxy, and turn that into a direct access
    1120             :   // to the current native contexts' global object instead.
    1121      141922 :   if (receiver_maps.size() == 1) {
    1122      126149 :     Handle<Map> receiver_map = receiver_maps.front();
    1123      126149 :     if (receiver_map->IsJSGlobalProxyMap()) {
    1124         207 :       Object maybe_constructor = receiver_map->GetConstructor();
    1125             :       // Detached global proxies have |null| as their constructor.
    1126         621 :       if (maybe_constructor->IsJSFunction() &&
    1127         414 :           JSFunction::cast(maybe_constructor)->native_context() ==
    1128         621 :               *native_context().object()) {
    1129             :         return ReduceGlobalAccess(node, receiver, value, name, access_mode,
    1130         207 :                                   index);
    1131             :       }
    1132             :     }
    1133             :   }
    1134             : 
    1135             :   // Compute property access infos for the receiver maps.
    1136             :   AccessInfoFactory access_info_factory(
    1137      425145 :       broker(), dependencies(), native_context().object(), graph()->zone());
    1138             :   ZoneVector<PropertyAccessInfo> access_infos(zone());
    1139      141715 :   if (!access_info_factory.ComputePropertyAccessInfos(
    1140      141715 :           receiver_maps, name, access_mode, &access_infos)) {
    1141             :     return NoChange();
    1142             :   }
    1143             : 
    1144             :   // Nothing to do if we have no non-deprecated maps.
    1145      127610 :   if (access_infos.empty()) {
    1146             :     return ReduceSoftDeoptimize(
    1147           0 :         node, DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess);
    1148             :   }
    1149             : 
    1150             :   // Ensure that {index} matches the specified {name} (if {index} is given).
    1151      127610 :   if (index != nullptr) {
    1152          92 :     effect = BuildCheckEqualsName(name, index, effect, control);
    1153             :   }
    1154             : 
    1155             :   // Collect call nodes to rewire exception edges.
    1156             :   ZoneVector<Node*> if_exception_nodes(zone());
    1157             :   ZoneVector<Node*>* if_exceptions = nullptr;
    1158      127610 :   Node* if_exception = nullptr;
    1159      127610 :   if (NodeProperties::IsExceptionalCall(node, &if_exception)) {
    1160             :     if_exceptions = &if_exception_nodes;
    1161             :   }
    1162             : 
    1163             :   PropertyAccessBuilder access_builder(jsgraph(), broker(), dependencies());
    1164             : 
    1165             :   // Check for the monomorphic cases.
    1166      255220 :   if (access_infos.size() == 1) {
    1167      122265 :     PropertyAccessInfo access_info = access_infos.front();
    1168             :     // Try to build string check or number check if possible.
    1169             :     // Otherwise build a map check.
    1170      122265 :     if (!access_builder.TryBuildStringCheck(access_info.receiver_maps(),
    1171      237134 :                                             &receiver, &effect, control) &&
    1172             :         !access_builder.TryBuildNumberCheck(access_info.receiver_maps(),
    1173      114869 :                                             &receiver, &effect, control)) {
    1174      113579 :       if (HasNumberMaps(broker(), access_info.receiver_maps())) {
    1175             :         // We need to also let Smi {receiver}s through in this case, so
    1176             :         // we construct a diamond, guarded by the Sminess of the {receiver}
    1177             :         // and if {receiver} is not a Smi just emit a sequence of map checks.
    1178          14 :         Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver);
    1179          14 :         Node* branch = graph()->NewNode(common()->Branch(), check, control);
    1180             : 
    1181           7 :         Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    1182           7 :         Node* etrue = effect;
    1183             : 
    1184           7 :         Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    1185           7 :         Node* efalse = effect;
    1186             :         {
    1187             :           access_builder.BuildCheckMaps(receiver, &efalse, if_false,
    1188           7 :                                         access_info.receiver_maps());
    1189             :         }
    1190             : 
    1191          14 :         control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    1192             :         effect =
    1193          21 :             graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
    1194             :       } else {
    1195             :         receiver =
    1196      113572 :             access_builder.BuildCheckHeapObject(receiver, &effect, control);
    1197             :         access_builder.BuildCheckMaps(receiver, &effect, control,
    1198      113572 :                                       access_info.receiver_maps());
    1199             :       }
    1200             :     }
    1201             : 
    1202             :     // Generate the actual property access.
    1203             :     ValueEffectControl continuation = BuildPropertyAccess(
    1204             :         receiver, value, context, frame_state, effect, control, name,
    1205      122265 :         if_exceptions, access_info, access_mode);
    1206      122265 :     value = continuation.value();
    1207      122265 :     effect = continuation.effect();
    1208      122265 :     control = continuation.control();
    1209             :   } else {
    1210             :     // The final states for every polymorphic branch. We join them with
    1211             :     // Merge+Phi+EffectPhi at the bottom.
    1212             :     ZoneVector<Node*> values(zone());
    1213             :     ZoneVector<Node*> effects(zone());
    1214             :     ZoneVector<Node*> controls(zone());
    1215             : 
    1216             :     // Check if {receiver} may be a number.
    1217             :     bool receiverissmi_possible = false;
    1218       21677 :     for (PropertyAccessInfo const& access_info : access_infos) {
    1219       22144 :       if (HasNumberMaps(broker(), access_info.receiver_maps())) {
    1220             :         receiverissmi_possible = true;
    1221             :         break;
    1222             :       }
    1223             :     }
    1224             : 
    1225             :     // Ensure that {receiver} is a heap object.
    1226             :     Node* receiverissmi_control = nullptr;
    1227        5345 :     Node* receiverissmi_effect = effect;
    1228        5345 :     if (receiverissmi_possible) {
    1229         170 :       Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver);
    1230         170 :       Node* branch = graph()->NewNode(common()->Branch(), check, control);
    1231         170 :       control = graph()->NewNode(common()->IfFalse(), branch);
    1232          85 :       receiverissmi_control = graph()->NewNode(common()->IfTrue(), branch);
    1233          85 :       receiverissmi_effect = effect;
    1234             :     } else {
    1235             :       receiver =
    1236        5260 :           access_builder.BuildCheckHeapObject(receiver, &effect, control);
    1237             :     }
    1238             : 
    1239             :     // Generate code for the various different property access patterns.
    1240        5345 :     Node* fallthrough_control = control;
    1241       33040 :     for (size_t j = 0; j < access_infos.size(); ++j) {
    1242             :       PropertyAccessInfo const& access_info = access_infos[j];
    1243             :       Node* this_value = value;
    1244       11175 :       Node* this_receiver = receiver;
    1245       11175 :       Node* this_effect = effect;
    1246             :       Node* this_control = fallthrough_control;
    1247             : 
    1248             :       // Perform map check on {receiver}.
    1249       11175 :       MapHandles const& receiver_maps = access_info.receiver_maps();
    1250             :       {
    1251             :         // Whether to insert a dedicated MapGuard node into the
    1252             :         // effect to be able to learn from the control flow.
    1253             :         bool insert_map_guard = true;
    1254             : 
    1255             :         // Check maps for the {receiver}s.
    1256       11175 :         if (j == access_infos.size() - 1) {
    1257             :           // Last map check on the fallthrough control path, do a
    1258             :           // conditional eager deoptimization exit here.
    1259             :           access_builder.BuildCheckMaps(receiver, &this_effect, this_control,
    1260        5345 :                                         receiver_maps);
    1261             :           fallthrough_control = nullptr;
    1262             : 
    1263             :           // Don't insert a MapGuard in this case, as the CheckMaps
    1264             :           // node already gives you all the information you need
    1265             :           // along the effect chain.
    1266             :           insert_map_guard = false;
    1267             :         } else {
    1268             :           // Explicitly branch on the {receiver_maps}.
    1269             :           ZoneHandleSet<Map> maps;
    1270       17611 :           for (Handle<Map> map : receiver_maps) {
    1271        5951 :             maps.insert(map, graph()->zone());
    1272             :           }
    1273             :           Node* check = this_effect =
    1274             :               graph()->NewNode(simplified()->CompareMaps(maps), receiver,
    1275       17490 :                                this_effect, this_control);
    1276             :           Node* branch =
    1277        5830 :               graph()->NewNode(common()->Branch(), check, this_control);
    1278        5830 :           fallthrough_control = graph()->NewNode(common()->IfFalse(), branch);
    1279        5830 :           this_control = graph()->NewNode(common()->IfTrue(), branch);
    1280             :         }
    1281             : 
    1282             :         // The Number case requires special treatment to also deal with Smis.
    1283       11175 :         if (HasNumberMaps(broker(), receiver_maps)) {
    1284             :           // Join this check with the "receiver is smi" check above.
    1285             :           DCHECK_NOT_NULL(receiverissmi_effect);
    1286             :           DCHECK_NOT_NULL(receiverissmi_control);
    1287             :           this_control = graph()->NewNode(common()->Merge(2), this_control,
    1288          85 :                                           receiverissmi_control);
    1289             :           this_effect = graph()->NewNode(common()->EffectPhi(2), this_effect,
    1290         255 :                                          receiverissmi_effect, this_control);
    1291             :           receiverissmi_effect = receiverissmi_control = nullptr;
    1292             : 
    1293             :           // The {receiver} can also be a Smi in this case, so
    1294             :           // a MapGuard doesn't make sense for this at all.
    1295             :           insert_map_guard = false;
    1296             :         }
    1297             : 
    1298             :         // Introduce a MapGuard to learn from this on the effect chain.
    1299       11175 :         if (insert_map_guard) {
    1300             :           ZoneHandleSet<Map> maps;
    1301       17398 :           for (auto receiver_map : receiver_maps) {
    1302        5880 :             maps.insert(receiver_map, graph()->zone());
    1303             :           }
    1304             :           this_effect = graph()->NewNode(simplified()->MapGuard(maps), receiver,
    1305       17277 :                                          this_effect, this_control);
    1306             :         }
    1307             : 
    1308             :         // If all {receiver_maps} are Strings we also need to rename the
    1309             :         // {receiver} here to make sure that TurboFan knows that along this
    1310             :         // path the {this_receiver} is a String. This is because we want
    1311             :         // strict checking of types, for example for StringLength operators.
    1312       11175 :         if (HasOnlyStringMaps(receiver_maps)) {
    1313             :           this_receiver = this_effect =
    1314             :               graph()->NewNode(common()->TypeGuard(Type::String()), receiver,
    1315         300 :                                this_effect, this_control);
    1316             :         }
    1317             :       }
    1318             : 
    1319             :       // Generate the actual property access.
    1320             :       ValueEffectControl continuation = BuildPropertyAccess(
    1321             :           this_receiver, this_value, context, frame_state, this_effect,
    1322       11175 :           this_control, name, if_exceptions, access_info, access_mode);
    1323       22350 :       values.push_back(continuation.value());
    1324       22350 :       effects.push_back(continuation.effect());
    1325       22350 :       controls.push_back(continuation.control());
    1326             :     }
    1327             : 
    1328             :     DCHECK_NULL(fallthrough_control);
    1329             : 
    1330             :     // Generate the final merge point for all (polymorphic) branches.
    1331       10690 :     int const control_count = static_cast<int>(controls.size());
    1332        5345 :     if (control_count == 0) {
    1333           0 :       value = effect = control = jsgraph()->Dead();
    1334        5345 :     } else if (control_count == 1) {
    1335           0 :       value = values.front();
    1336           0 :       effect = effects.front();
    1337           0 :       control = controls.front();
    1338             :     } else {
    1339             :       control = graph()->NewNode(common()->Merge(control_count), control_count,
    1340       10690 :                                  &controls.front());
    1341        5345 :       values.push_back(control);
    1342             :       value = graph()->NewNode(
    1343             :           common()->Phi(MachineRepresentation::kTagged, control_count),
    1344       16035 :           control_count + 1, &values.front());
    1345        5345 :       effects.push_back(control);
    1346             :       effect = graph()->NewNode(common()->EffectPhi(control_count),
    1347       10690 :                                 control_count + 1, &effects.front());
    1348             :     }
    1349             :   }
    1350             : 
    1351             :   // Properly rewire IfException edges if {node} is inside a try-block.
    1352      127610 :   if (!if_exception_nodes.empty()) {
    1353             :     DCHECK_NOT_NULL(if_exception);
    1354             :     DCHECK_EQ(if_exceptions, &if_exception_nodes);
    1355         178 :     int const if_exception_count = static_cast<int>(if_exceptions->size());
    1356             :     Node* merge = graph()->NewNode(common()->Merge(if_exception_count),
    1357         178 :                                    if_exception_count, &if_exceptions->front());
    1358          89 :     if_exceptions->push_back(merge);
    1359             :     Node* ephi =
    1360             :         graph()->NewNode(common()->EffectPhi(if_exception_count),
    1361         267 :                          if_exception_count + 1, &if_exceptions->front());
    1362             :     Node* phi = graph()->NewNode(
    1363             :         common()->Phi(MachineRepresentation::kTagged, if_exception_count),
    1364         178 :         if_exception_count + 1, &if_exceptions->front());
    1365      127699 :     ReplaceWithValue(if_exception, phi, ephi, merge);
    1366             :   }
    1367             : 
    1368      127610 :   ReplaceWithValue(node, value, effect, control);
    1369             :   return Replace(value);
    1370             : }
    1371             : 
    1372      464342 : Reduction JSNativeContextSpecialization::ReduceNamedAccessFromNexus(
    1373             :     Node* node, Node* value, FeedbackNexus const& nexus, Handle<Name> name,
    1374             :     AccessMode access_mode) {
    1375             :   DCHECK(node->opcode() == IrOpcode::kJSLoadNamed ||
    1376             :          node->opcode() == IrOpcode::kJSStoreNamed ||
    1377             :          node->opcode() == IrOpcode::kJSStoreNamedOwn);
    1378      464342 :   Node* const receiver = NodeProperties::GetValueInput(node, 0);
    1379      464343 :   Node* const effect = NodeProperties::GetEffectInput(node);
    1380             : 
    1381             :   // Check if we are accessing the current native contexts' global proxy.
    1382             :   HeapObjectMatcher m(receiver);
    1383      526548 :   if (m.HasValue() && m.Value().is_identical_to(global_proxy())) {
    1384             :     // Optimize accesses to the current native contexts' global proxy.
    1385          27 :     return ReduceGlobalAccess(node, nullptr, value, name, access_mode);
    1386             :   }
    1387             : 
    1388             :   // Extract receiver maps from the IC using the {nexus}.
    1389             :   MapHandles receiver_maps;
    1390      464316 :   if (!ExtractReceiverMaps(receiver, effect, nexus, &receiver_maps)) {
    1391             :     return NoChange();
    1392      458112 :   } else if (receiver_maps.empty()) {
    1393             :     return ReduceSoftDeoptimize(
    1394      316972 :         node, DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess);
    1395             :   }
    1396             :   DCHECK(!nexus.IsUninitialized());
    1397             : 
    1398             :   // Try to lower the named access based on the {receiver_maps}.
    1399      141140 :   return ReduceNamedAccess(node, value, receiver_maps, name, access_mode);
    1400             : }
    1401             : 
    1402     1015045 : Reduction JSNativeContextSpecialization::ReduceJSLoadNamed(Node* node) {
    1403             :   DCHECK_EQ(IrOpcode::kJSLoadNamed, node->opcode());
    1404      528281 :   NamedAccess const& p = NamedAccessOf(node->op());
    1405      528282 :   Node* const receiver = NodeProperties::GetValueInput(node, 0);
    1406             : 
    1407             :   // Check if we have a constant receiver.
    1408             :   HeapObjectMatcher m(receiver);
    1409      528282 :   if (m.HasValue()) {
    1410       64340 :     ObjectRef object = m.Ref(broker());
    1411             :     NameRef name(broker(), p.name());
    1412      193020 :     if (object.IsJSFunction() &&
    1413       74678 :         name.equals(ObjectRef(broker(), factory()->prototype_string()))) {
    1414             :       // Optimize "prototype" property of functions.
    1415         543 :       JSFunctionRef function = object.AsJSFunction();
    1416             :       // TODO(neis): This is a temporary hack needed because the copy reducer
    1417             :       // runs only after this pass.
    1418         543 :       function.Serialize();
    1419             :       // TODO(neis): Remove the has_prototype_slot condition once the broker is
    1420             :       // always enabled.
    1421        1085 :       if (!function.map().has_prototype_slot() || !function.has_prototype() ||
    1422         542 :           function.PrototypeRequiresRuntimeLookup()) {
    1423             :         return NoChange();
    1424             :       }
    1425         535 :       ObjectRef prototype = dependencies()->DependOnPrototypeProperty(function);
    1426         535 :       Node* value = jsgraph()->Constant(prototype);
    1427         790 :       ReplaceWithValue(node, value);
    1428             :       return Replace(value);
    1429      191391 :     } else if (object.IsString() &&
    1430       70875 :                name.equals(ObjectRef(broker(), factory()->length_string()))) {
    1431             :       // Constant-fold "length" property on constant strings.
    1432         510 :       Node* value = jsgraph()->Constant(object.AsString().length());
    1433             :       ReplaceWithValue(node, value);
    1434             :       return Replace(value);
    1435             :     }
    1436             :   }
    1437             : 
    1438             :   // Extract receiver maps from the load IC using the FeedbackNexus.
    1439      527484 :   if (!p.feedback().IsValid()) return NoChange();
    1440      348051 :   FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot());
    1441             : 
    1442             :   // Try to lower the named access based on the {receiver_maps}.
    1443             :   return ReduceNamedAccessFromNexus(node, jsgraph()->Dead(), nexus, p.name(),
    1444      348051 :                                     AccessMode::kLoad);
    1445             : }
    1446             : 
    1447             : 
    1448       99962 : Reduction JSNativeContextSpecialization::ReduceJSStoreNamed(Node* node) {
    1449             :   DCHECK_EQ(IrOpcode::kJSStoreNamed, node->opcode());
    1450       99962 :   NamedAccess const& p = NamedAccessOf(node->op());
    1451       99962 :   Node* const value = NodeProperties::GetValueInput(node, 1);
    1452             : 
    1453             :   // Extract receiver maps from the store IC using the FeedbackNexus.
    1454       99962 :   if (!p.feedback().IsValid()) return NoChange();
    1455       80988 :   FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot());
    1456             : 
    1457             :   // Try to lower the named access based on the {receiver_maps}.
    1458             :   return ReduceNamedAccessFromNexus(node, value, nexus, p.name(),
    1459       80988 :                                     AccessMode::kStore);
    1460             : }
    1461             : 
    1462       35304 : Reduction JSNativeContextSpecialization::ReduceJSStoreNamedOwn(Node* node) {
    1463             :   DCHECK_EQ(IrOpcode::kJSStoreNamedOwn, node->opcode());
    1464       35304 :   StoreNamedOwnParameters const& p = StoreNamedOwnParametersOf(node->op());
    1465       35304 :   Node* const value = NodeProperties::GetValueInput(node, 1);
    1466             : 
    1467             :   // Extract receiver maps from the IC using the FeedbackNexus.
    1468       35304 :   if (!p.feedback().IsValid()) return NoChange();
    1469       35304 :   FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot());
    1470             : 
    1471             :   // Try to lower the creation of a named property based on the {receiver_maps}.
    1472             :   return ReduceNamedAccessFromNexus(node, value, nexus, p.name(),
    1473       35304 :                                     AccessMode::kStoreInLiteral);
    1474             : }
    1475             : 
    1476       23384 : Reduction JSNativeContextSpecialization::ReduceElementAccess(
    1477             :     Node* node, Node* index, Node* value, MapHandles const& receiver_maps,
    1478             :     AccessMode access_mode, KeyedAccessLoadMode load_mode,
    1479       81395 :     KeyedAccessStoreMode store_mode) {
    1480             :   DCHECK(node->opcode() == IrOpcode::kJSLoadProperty ||
    1481             :          node->opcode() == IrOpcode::kJSStoreProperty ||
    1482             :          node->opcode() == IrOpcode::kJSStoreInArrayLiteral);
    1483       23384 :   Node* receiver = NodeProperties::GetValueInput(node, 0);
    1484       23384 :   Node* effect = NodeProperties::GetEffectInput(node);
    1485       23384 :   Node* control = NodeProperties::GetControlInput(node);
    1486       23384 :   Node* frame_state = NodeProperties::FindFrameStateBefore(node);
    1487             : 
    1488             :   // Check for keyed access to strings.
    1489       23384 :   if (HasOnlyStringMaps(receiver_maps)) {
    1490             :     // Strings are immutable in JavaScript.
    1491         362 :     if (access_mode == AccessMode::kStore) return NoChange();
    1492             : 
    1493             :     // Ensure that the {receiver} is actually a String.
    1494             :     receiver = effect = graph()->NewNode(
    1495        1086 :         simplified()->CheckString(VectorSlotPair()), receiver, effect, control);
    1496             : 
    1497             :     // Determine the {receiver} length.
    1498         362 :     Node* length = graph()->NewNode(simplified()->StringLength(), receiver);
    1499             : 
    1500             :     // Load the single character string from {receiver} or yield undefined
    1501             :     // if the {index} is out of bounds (depending on the {load_mode}).
    1502             :     value = BuildIndexedStringLoad(receiver, index, length, &effect, &control,
    1503         362 :                                    load_mode);
    1504             :   } else {
    1505             :     // Compute element access infos for the receiver maps.
    1506             :     AccessInfoFactory access_info_factory(
    1507       69066 :         broker(), dependencies(), native_context().object(), graph()->zone());
    1508             :     ZoneVector<ElementAccessInfo> access_infos(zone());
    1509       23022 :     if (!access_info_factory.ComputeElementAccessInfos(
    1510       23022 :             receiver_maps, access_mode, &access_infos)) {
    1511             :       return NoChange();
    1512             :     }
    1513             : 
    1514             :     // Nothing to do if we have no non-deprecated maps.
    1515       21992 :     if (access_infos.empty()) {
    1516             :       return ReduceSoftDeoptimize(
    1517             :           node,
    1518           0 :           DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess);
    1519             :     }
    1520             : 
    1521             :     // For holey stores or growing stores, we need to check that the prototype
    1522             :     // chain contains no setters for elements, and we need to guard those checks
    1523             :     // via code dependencies on the relevant prototype maps.
    1524       21992 :     if (access_mode == AccessMode::kStore) {
    1525             :       // TODO(turbofan): We could have a fast path here, that checks for the
    1526             :       // common case of Array or Object prototype only and therefore avoids
    1527             :       // the zone allocation of this vector.
    1528             :       ZoneVector<Handle<Map>> prototype_maps(zone());
    1529       16043 :       for (ElementAccessInfo const& access_info : access_infos) {
    1530       16625 :         for (Handle<Map> receiver_map : access_info.receiver_maps()) {
    1531             :           // If the {receiver_map} has a prototype and its elements backing
    1532             :           // store is either holey, or we have a potentially growing store,
    1533             :           // then we need to check that all prototypes have stable maps with
    1534             :           // fast elements (and we need to guard against changes to that below).
    1535        9392 :           if (IsHoleyOrDictionaryElementsKind(receiver_map->elements_kind()) ||
    1536             :               IsGrowStoreMode(store_mode)) {
    1537             :             // Make sure all prototypes are stable and have fast elements.
    1538        1963 :             for (Handle<Map> map = receiver_map;;) {
    1539             :               Handle<Object> map_prototype(map->prototype(), isolate());
    1540       11560 :               if (map_prototype->IsNull(isolate())) break;
    1541        7648 :               if (!map_prototype->IsJSObject()) return NoChange();
    1542        7648 :               map = handle(Handle<JSObject>::cast(map_prototype)->map(),
    1543        3824 :                            isolate());
    1544        3824 :               if (!map->is_stable()) return NoChange();
    1545        3817 :               if (!IsFastElementsKind(map->elements_kind())) return NoChange();
    1546        3817 :               prototype_maps.push_back(map);
    1547        3817 :             }
    1548             :           }
    1549             :         }
    1550             :       }
    1551             : 
    1552             :       // Install dependencies on the relevant prototype maps.
    1553       14302 :       for (Handle<Map> prototype_map : prototype_maps) {
    1554        3810 :         dependencies()->DependOnStableMap(MapRef(broker(), prototype_map));
    1555             :       }
    1556             :     }
    1557             : 
    1558             :     // Ensure that {receiver} is a heap object.
    1559             :     PropertyAccessBuilder access_builder(jsgraph(), broker(), dependencies());
    1560       21985 :     receiver = access_builder.BuildCheckHeapObject(receiver, &effect, control);
    1561             : 
    1562             :     // Check for the monomorphic case.
    1563       43970 :     if (access_infos.size() == 1) {
    1564       21492 :       ElementAccessInfo access_info = access_infos.front();
    1565             : 
    1566             :       // Perform possible elements kind transitions.
    1567       21492 :       Handle<Map> const transition_target = access_info.receiver_maps().front();
    1568       43449 :       for (auto transition_source : access_info.transition_sources()) {
    1569             :         DCHECK_EQ(access_info.receiver_maps().size(), 1);
    1570             :         effect = graph()->NewNode(
    1571             :             simplified()->TransitionElementsKind(ElementsTransition(
    1572             :                 IsSimpleMapChangeTransition(transition_source->elements_kind(),
    1573             :                                             transition_target->elements_kind())
    1574             :                     ? ElementsTransition::kFastTransition
    1575             :                     : ElementsTransition::kSlowTransition,
    1576             :                 transition_source, transition_target)),
    1577        1860 :             receiver, effect, control);
    1578             :       }
    1579             : 
    1580             :       // TODO(turbofan): The effect/control linearization will not find a
    1581             :       // FrameState after the StoreField or Call that is generated for the
    1582             :       // elements kind transition above. This is because those operators
    1583             :       // don't have the kNoWrite flag on it, even though they are not
    1584             :       // observable by JavaScript.
    1585             :       effect = graph()->NewNode(common()->Checkpoint(), frame_state, effect,
    1586       64476 :                                 control);
    1587             : 
    1588             :       // Perform map check on the {receiver}.
    1589             :       access_builder.BuildCheckMaps(receiver, &effect, control,
    1590       21492 :                                     access_info.receiver_maps());
    1591             : 
    1592             :       // Access the actual element.
    1593             :       ValueEffectControl continuation =
    1594             :           BuildElementAccess(receiver, index, value, effect, control,
    1595       21492 :                              access_info, access_mode, load_mode, store_mode);
    1596       21492 :       value = continuation.value();
    1597       21492 :       effect = continuation.effect();
    1598       21492 :       control = continuation.control();
    1599             :     } else {
    1600             :       // The final states for every polymorphic branch. We join them with
    1601             :       // Merge+Phi+EffectPhi at the bottom.
    1602             :       ZoneVector<Node*> values(zone());
    1603             :       ZoneVector<Node*> effects(zone());
    1604             :       ZoneVector<Node*> controls(zone());
    1605             : 
    1606             :       // Generate code for the various different element access patterns.
    1607         493 :       Node* fallthrough_control = control;
    1608        3336 :       for (size_t j = 0; j < access_infos.size(); ++j) {
    1609             :         ElementAccessInfo const& access_info = access_infos[j];
    1610             :         Node* this_receiver = receiver;
    1611             :         Node* this_value = value;
    1612             :         Node* this_index = index;
    1613        1175 :         Node* this_effect = effect;
    1614             :         Node* this_control = fallthrough_control;
    1615             : 
    1616             :         // Perform possible elements kind transitions.
    1617             :         Handle<Map> const transition_target =
    1618        1175 :             access_info.receiver_maps().front();
    1619        2430 :         for (auto transition_source : access_info.transition_sources()) {
    1620             :           DCHECK_EQ(access_info.receiver_maps().size(), 1);
    1621             :           this_effect = graph()->NewNode(
    1622             :               simplified()->TransitionElementsKind(
    1623             :                   ElementsTransition(IsSimpleMapChangeTransition(
    1624             :                                          transition_source->elements_kind(),
    1625             :                                          transition_target->elements_kind())
    1626             :                                          ? ElementsTransition::kFastTransition
    1627             :                                          : ElementsTransition::kSlowTransition,
    1628             :                                      transition_source, transition_target)),
    1629         320 :               receiver, this_effect, this_control);
    1630             :         }
    1631             : 
    1632             :         // Perform map check(s) on {receiver}.
    1633        1175 :         MapHandles const& receiver_maps = access_info.receiver_maps();
    1634        2350 :         if (j == access_infos.size() - 1) {
    1635             :           // Last map check on the fallthrough control path, do a
    1636             :           // conditional eager deoptimization exit here.
    1637             :           access_builder.BuildCheckMaps(receiver, &this_effect, this_control,
    1638         493 :                                         receiver_maps);
    1639             :           fallthrough_control = nullptr;
    1640             :         } else {
    1641             :           // Explicitly branch on the {receiver_maps}.
    1642             :           ZoneHandleSet<Map> maps;
    1643        2046 :           for (Handle<Map> map : receiver_maps) {
    1644         682 :             maps.insert(map, graph()->zone());
    1645             :           }
    1646             :           Node* check = this_effect =
    1647             :               graph()->NewNode(simplified()->CompareMaps(maps), receiver,
    1648        2046 :                                this_effect, fallthrough_control);
    1649             :           Node* branch =
    1650         682 :               graph()->NewNode(common()->Branch(), check, fallthrough_control);
    1651         682 :           fallthrough_control = graph()->NewNode(common()->IfFalse(), branch);
    1652         682 :           this_control = graph()->NewNode(common()->IfTrue(), branch);
    1653             : 
    1654             :           // Introduce a MapGuard to learn from this on the effect chain.
    1655             :           this_effect = graph()->NewNode(simplified()->MapGuard(maps), receiver,
    1656        2046 :                                          this_effect, this_control);
    1657             :         }
    1658             : 
    1659             :         // Access the actual element.
    1660             :         ValueEffectControl continuation = BuildElementAccess(
    1661             :             this_receiver, this_index, this_value, this_effect, this_control,
    1662        1175 :             access_info, access_mode, load_mode, store_mode);
    1663        2350 :         values.push_back(continuation.value());
    1664        2350 :         effects.push_back(continuation.effect());
    1665        2350 :         controls.push_back(continuation.control());
    1666             :       }
    1667             : 
    1668             :       DCHECK_NULL(fallthrough_control);
    1669             : 
    1670             :       // Generate the final merge point for all (polymorphic) branches.
    1671         986 :       int const control_count = static_cast<int>(controls.size());
    1672         493 :       if (control_count == 0) {
    1673           0 :         value = effect = control = jsgraph()->Dead();
    1674         493 :       } else if (control_count == 1) {
    1675           0 :         value = values.front();
    1676           0 :         effect = effects.front();
    1677           0 :         control = controls.front();
    1678             :       } else {
    1679             :         control = graph()->NewNode(common()->Merge(control_count),
    1680         986 :                                    control_count, &controls.front());
    1681         493 :         values.push_back(control);
    1682             :         value = graph()->NewNode(
    1683             :             common()->Phi(MachineRepresentation::kTagged, control_count),
    1684        1479 :             control_count + 1, &values.front());
    1685         493 :         effects.push_back(control);
    1686             :         effect = graph()->NewNode(common()->EffectPhi(control_count),
    1687         986 :                                   control_count + 1, &effects.front());
    1688             :       }
    1689             :     }
    1690             :   }
    1691             : 
    1692       22347 :   ReplaceWithValue(node, value, effect, control);
    1693             :   return Replace(value);
    1694             : }
    1695             : 
    1696        5265 : Reduction JSNativeContextSpecialization::ReduceKeyedLoadFromHeapConstant(
    1697             :     Node* node, Node* index, FeedbackNexus const& nexus,
    1698        5682 :     KeyedAccessLoadMode load_mode) {
    1699             :   DCHECK_EQ(node->opcode(), IrOpcode::kJSLoadProperty);
    1700        5265 :   Node* receiver = NodeProperties::GetValueInput(node, 0);
    1701        5265 :   Node* effect = NodeProperties::GetEffectInput(node);
    1702        5265 :   Node* control = NodeProperties::GetControlInput(node);
    1703             : 
    1704             :   HeapObjectMatcher mreceiver(receiver);
    1705        5265 :   HeapObjectRef receiver_ref = mreceiver.Ref(broker()).AsHeapObject();
    1706       15791 :   if (receiver_ref.map().oddball_type() == OddballType::kHole ||
    1707       15686 :       receiver_ref.map().oddball_type() == OddballType::kNull ||
    1708       10421 :       receiver_ref.map().oddball_type() == OddballType::kUndefined) {
    1709             :     return NoChange();
    1710             :   }
    1711             : 
    1712             :   // Check whether we're accessing a known element on the {receiver}
    1713             :   // that is non-configurable, non-writable (e.g. the {receiver} was
    1714             :   // frozen using Object.freeze).
    1715             :   NumberMatcher mindex(index);
    1716        6612 :   if (mindex.IsInteger() && mindex.IsInRange(0.0, kMaxUInt32 - 1.0)) {
    1717             :     LookupIterator it(isolate(), receiver_ref.object(),
    1718             :                       static_cast<uint32_t>(mindex.Value()),
    1719        3018 :                       LookupIterator::OWN);
    1720        1509 :     if (it.state() == LookupIterator::DATA) {
    1721        1355 :       if (it.IsReadOnly() && !it.IsConfigurable()) {
    1722             :         // We can safely constant-fold the {index} access to {receiver},
    1723             :         // since the element is non-configurable, non-writable and thus
    1724             :         // cannot change anymore.
    1725          48 :         Node* value = jsgraph()->Constant(it.GetDataValue());
    1726         333 :         ReplaceWithValue(node, value, effect, control);
    1727         108 :         return Replace(value);
    1728             :       }
    1729             : 
    1730             :       // Check if the {receiver} is a known constant with a copy-on-write
    1731             :       // backing store, and whether {index} is within the appropriate
    1732             :       // bounds. In that case we can constant-fold the access and only
    1733             :       // check that the {elements} didn't change. This is sufficient as
    1734             :       // the backing store of a copy-on-write JSArray is defensively
    1735             :       // copied whenever the length or the elements (might) change.
    1736             :       //
    1737             :       // What's interesting here is that we don't need to map check the
    1738             :       // {receiver}, since JSArray's will always have their elements in
    1739             :       // the backing store.
    1740        1307 :       if (receiver_ref.IsJSArray()) {
    1741         878 :         Handle<JSArray> array = receiver_ref.AsJSArray().object();
    1742         878 :         if (array->elements()->IsCowArray()) {
    1743             :           Node* elements = effect = graph()->NewNode(
    1744             :               simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
    1745         252 :               receiver, effect, control);
    1746         168 :           Handle<FixedArray> array_elements(FixedArray::cast(array->elements()),
    1747         168 :                                             isolate());
    1748             :           Node* check =
    1749             :               graph()->NewNode(simplified()->ReferenceEqual(), elements,
    1750         252 :                                jsgraph()->HeapConstant(array_elements));
    1751             :           effect = graph()->NewNode(
    1752             :               simplified()->CheckIf(DeoptimizeReason::kCowArrayElementsChanged),
    1753         252 :               check, effect, control);
    1754         168 :           Node* value = jsgraph()->Constant(it.GetDataValue());
    1755          84 :           ReplaceWithValue(node, value, effect, control);
    1756             :           return Replace(value);
    1757             :         }
    1758             :       }
    1759             :     }
    1760             :   }
    1761             : 
    1762             :   // For constant Strings we can eagerly strength-reduce the keyed
    1763             :   // accesses using the known length, which doesn't change.
    1764        4984 :   if (receiver_ref.IsString()) {
    1765             :     // We can only assume that the {index} is a valid array index if the
    1766             :     // IC is in element access mode and not MEGAMORPHIC, otherwise there's
    1767             :     // no guard for the bounds check below.
    1768         248 :     if (nexus.ic_state() != MEGAMORPHIC && nexus.GetKeyType() == ELEMENT) {
    1769             :       // Ensure that {index} is less than {receiver} length.
    1770         450 :       Node* length = jsgraph()->Constant(receiver_ref.AsString().length());
    1771             : 
    1772             :       // Load the single character string from {receiver} or yield
    1773             :       // undefined if the {index} is out of bounds (depending on the
    1774             :       // {load_mode}).
    1775             :       Node* value = BuildIndexedStringLoad(receiver, index, length, &effect,
    1776         225 :                                            &control, load_mode);
    1777         225 :       ReplaceWithValue(node, value, effect, control);
    1778             :       return Replace(value);
    1779             :     }
    1780             :   }
    1781             : 
    1782             :   return NoChange();
    1783             : }
    1784             : 
    1785       55460 : Reduction JSNativeContextSpecialization::ReduceKeyedAccess(
    1786             :     Node* node, Node* index, Node* value, FeedbackNexus const& nexus,
    1787             :     AccessMode access_mode, KeyedAccessLoadMode load_mode,
    1788         528 :     KeyedAccessStoreMode store_mode) {
    1789             :   DCHECK(node->opcode() == IrOpcode::kJSLoadProperty ||
    1790             :          node->opcode() == IrOpcode::kJSStoreProperty);
    1791       99305 :   Node* receiver = NodeProperties::GetValueInput(node, 0);
    1792       55460 :   Node* effect = NodeProperties::GetEffectInput(node);
    1793             : 
    1794       99305 :   if (access_mode == AccessMode::kLoad &&
    1795             :       receiver->opcode() == IrOpcode::kHeapConstant) {
    1796             :     Reduction reduction =
    1797        5265 :         ReduceKeyedLoadFromHeapConstant(node, index, nexus, load_mode);
    1798        5265 :     if (reduction.Changed()) return reduction;
    1799             :   }
    1800             : 
    1801             :   // Extract receiver maps from the {nexus}.
    1802             :   MapHandles receiver_maps;
    1803       55127 :   if (!ExtractReceiverMaps(receiver, effect, nexus, &receiver_maps)) {
    1804             :     return NoChange();
    1805       50234 :   } else if (receiver_maps.empty()) {
    1806             :     return ReduceSoftDeoptimize(
    1807       28735 :         node, DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess);
    1808             :   }
    1809             :   DCHECK(!nexus.IsUninitialized());
    1810             : 
    1811             :   // Optimize access for constant {index}.
    1812             :   HeapObjectMatcher mindex(index);
    1813       21499 :   if (mindex.HasValue()) {
    1814         528 :     ObjectRef name = mindex.Ref(broker());
    1815         528 :     if (name.IsSymbol()) {
    1816             :       return ReduceNamedAccess(node, value, receiver_maps,
    1817         249 :                                name.AsName().object(), access_mode);
    1818             :     }
    1819         279 :     if (name.IsInternalizedString()) {
    1820         279 :       uint32_t array_index = name.AsInternalizedString().array_index();
    1821         279 :       if (array_index != InternalizedStringRef::kNotAnArrayIndex) {
    1822           0 :         index = jsgraph()->Constant(static_cast<double>(array_index));
    1823             :       } else {
    1824             :         return ReduceNamedAccess(node, value, receiver_maps,
    1825         279 :                                  name.AsName().object(), access_mode);
    1826             :       }
    1827             :     }
    1828             :   }
    1829             : 
    1830             :   // Check if we have feedback for a named access.
    1831       20971 :   Name name = nexus.GetName();
    1832       20971 :   if (!name.is_null()) {
    1833             :     return ReduceNamedAccess(node, value, receiver_maps,
    1834         254 :                              handle(name, isolate()), access_mode, index);
    1835       20717 :   } else if (nexus.GetKeyType() != ELEMENT) {
    1836             :     // The KeyedLoad/StoreIC has seen non-element accesses, so we cannot assume
    1837             :     // that the {index} is a valid array index, thus we just let the IC continue
    1838             :     // to deal with this load/store.
    1839             :     return NoChange();
    1840       20682 :   } else if (nexus.ic_state() == MEGAMORPHIC) {
    1841             :     // The KeyedLoad/StoreIC uses the MEGAMORPHIC state to guard the assumption
    1842             :     // that a numeric {index} is within the valid bounds for {receiver}, i.e.
    1843             :     // it transitions to MEGAMORPHIC once it sees an out-of-bounds access. Thus
    1844             :     // we cannot continue here if the IC state is MEGAMORPHIC.
    1845             :     return NoChange();
    1846             :   }
    1847             : 
    1848             :   // Try to lower the element access based on the {receiver_maps}.
    1849             :   return ReduceElementAccess(node, index, value, receiver_maps, access_mode,
    1850       20513 :                              load_mode, store_mode);
    1851             : }
    1852             : 
    1853      386633 : Reduction JSNativeContextSpecialization::ReduceSoftDeoptimize(
    1854             :     Node* node, DeoptimizeReason reason) {
    1855      386633 :   if (flags() & kBailoutOnUninitialized) {
    1856         186 :     Node* effect = NodeProperties::GetEffectInput(node);
    1857         186 :     Node* control = NodeProperties::GetControlInput(node);
    1858         186 :     Node* frame_state = NodeProperties::FindFrameStateBefore(node);
    1859             :     Node* deoptimize = graph()->NewNode(
    1860             :         common()->Deoptimize(DeoptimizeKind::kSoft, reason, VectorSlotPair()),
    1861         558 :         frame_state, effect, control);
    1862             :     // TODO(bmeurer): This should be on the AdvancedReducer somehow.
    1863         186 :     NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
    1864         186 :     Revisit(graph()->end());
    1865         186 :     node->TrimInputCount(0);
    1866         186 :     NodeProperties::ChangeOp(node, common()->Dead());
    1867             :     return Changed(node);
    1868             :   }
    1869             :   return NoChange();
    1870             : }
    1871             : 
    1872        1276 : Reduction JSNativeContextSpecialization::ReduceJSLoadPropertyWithEnumeratedKey(
    1873         309 :     Node* node) {
    1874             :   // We can optimize a property load if it's being used inside a for..in:
    1875             :   //   for (name in receiver) {
    1876             :   //     value = receiver[name];
    1877             :   //     ...
    1878             :   //   }
    1879             :   //
    1880             :   // If the for..in is in fast-mode, we know that the {receiver} has {name}
    1881             :   // as own property, otherwise the enumeration wouldn't include it. The graph
    1882             :   // constructed by the BytecodeGraphBuilder in this case looks like this:
    1883             : 
    1884             :   // receiver
    1885             :   //  ^    ^
    1886             :   //  |    |
    1887             :   //  |    +-+
    1888             :   //  |      |
    1889             :   //  |   JSToObject
    1890             :   //  |      ^
    1891             :   //  |      |
    1892             :   //  |      |
    1893             :   //  |  JSForInNext
    1894             :   //  |      ^
    1895             :   //  |      |
    1896             :   //  +----+ |
    1897             :   //       | |
    1898             :   //       | |
    1899             :   //   JSLoadProperty
    1900             : 
    1901             :   // If the for..in has only seen maps with enum cache consisting of keys
    1902             :   // and indices so far, we can turn the {JSLoadProperty} into a map check
    1903             :   // on the {receiver} and then just load the field value dynamically via
    1904             :   // the {LoadFieldByIndex} operator. The map check is only necessary when
    1905             :   // TurboFan cannot prove that there is no observable side effect between
    1906             :   // the {JSForInNext} and the {JSLoadProperty} node.
    1907             :   //
    1908             :   // Also note that it's safe to look through the {JSToObject}, since the
    1909             :   // [[Get]] operation does an implicit ToObject anyway, and these operations
    1910             :   // are not observable.
    1911             : 
    1912             :   DCHECK_EQ(IrOpcode::kJSLoadProperty, node->opcode());
    1913        1276 :   Node* receiver = NodeProperties::GetValueInput(node, 0);
    1914        2552 :   Node* name = NodeProperties::GetValueInput(node, 1);
    1915             :   DCHECK_EQ(IrOpcode::kJSForInNext, name->opcode());
    1916        1276 :   Node* effect = NodeProperties::GetEffectInput(node);
    1917        1276 :   Node* control = NodeProperties::GetControlInput(node);
    1918             : 
    1919        1276 :   if (ForInModeOf(name->op()) != ForInMode::kUseEnumCacheKeysAndIndices) {
    1920             :     return NoChange();
    1921             :   }
    1922             : 
    1923        1362 :   Node* object = NodeProperties::GetValueInput(name, 0);
    1924         681 :   Node* enumerator = NodeProperties::GetValueInput(name, 2);
    1925         681 :   Node* index = NodeProperties::GetValueInput(name, 3);
    1926         681 :   if (object->opcode() == IrOpcode::kJSToObject) {
    1927         611 :     object = NodeProperties::GetValueInput(object, 0);
    1928             :   }
    1929         681 :   if (object != receiver) return NoChange();
    1930             : 
    1931             :   // No need to repeat the map check if we can prove that there's no
    1932             :   // observable side effect between {effect} and {name].
    1933         309 :   if (!NodeProperties::NoObservableSideEffectBetween(effect, name)) {
    1934             :     // Check that the {receiver} map is still valid.
    1935             :     Node* receiver_map = effect =
    1936             :         graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
    1937         723 :                          receiver, effect, control);
    1938             :     Node* check = graph()->NewNode(simplified()->ReferenceEqual(), receiver_map,
    1939         241 :                                    enumerator);
    1940             :     effect =
    1941             :         graph()->NewNode(simplified()->CheckIf(DeoptimizeReason::kWrongMap),
    1942         723 :                          check, effect, control);
    1943             :   }
    1944             : 
    1945             :   // Load the enum cache indices from the {cache_type}.
    1946             :   Node* descriptor_array = effect = graph()->NewNode(
    1947             :       simplified()->LoadField(AccessBuilder::ForMapDescriptors()), enumerator,
    1948         927 :       effect, control);
    1949             :   Node* enum_cache = effect = graph()->NewNode(
    1950             :       simplified()->LoadField(AccessBuilder::ForDescriptorArrayEnumCache()),
    1951         927 :       descriptor_array, effect, control);
    1952             :   Node* enum_indices = effect = graph()->NewNode(
    1953             :       simplified()->LoadField(AccessBuilder::ForEnumCacheIndices()), enum_cache,
    1954         927 :       effect, control);
    1955             : 
    1956             :   // Ensure that the {enum_indices} are valid.
    1957             :   Node* check = graph()->NewNode(
    1958             :       simplified()->BooleanNot(),
    1959             :       graph()->NewNode(simplified()->ReferenceEqual(), enum_indices,
    1960         927 :                        jsgraph()->EmptyFixedArrayConstant()));
    1961             :   effect = graph()->NewNode(
    1962             :       simplified()->CheckIf(DeoptimizeReason::kWrongEnumIndices), check, effect,
    1963         927 :       control);
    1964             : 
    1965             :   // Determine the index from the {enum_indices}.
    1966             :   index = effect = graph()->NewNode(
    1967             :       simplified()->LoadElement(
    1968             :           AccessBuilder::ForFixedArrayElement(PACKED_SMI_ELEMENTS)),
    1969         927 :       enum_indices, index, effect, control);
    1970             : 
    1971             :   // Load the actual field value.
    1972             :   Node* value = effect = graph()->NewNode(simplified()->LoadFieldByIndex(),
    1973         309 :                                           receiver, index, effect, control);
    1974         309 :   ReplaceWithValue(node, value, effect, control);
    1975             :   return Replace(value);
    1976             : }
    1977             : 
    1978       87999 : Reduction JSNativeContextSpecialization::ReduceJSLoadProperty(Node* node) {
    1979             :   DCHECK_EQ(IrOpcode::kJSLoadProperty, node->opcode());
    1980       44154 :   PropertyAccess const& p = PropertyAccessOf(node->op());
    1981       44154 :   Node* name = NodeProperties::GetValueInput(node, 1);
    1982             : 
    1983       44154 :   if (name->opcode() == IrOpcode::kJSForInNext) {
    1984        1276 :     Reduction reduction = ReduceJSLoadPropertyWithEnumeratedKey(node);
    1985        1276 :     if (reduction.Changed()) return reduction;
    1986             :   }
    1987             : 
    1988             :   // Extract receiver maps from the keyed load IC using the FeedbackNexus.
    1989       43845 :   if (!p.feedback().IsValid()) return NoChange();
    1990       43845 :   FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot());
    1991             : 
    1992             :   // Extract the keyed access load mode from the keyed load IC.
    1993       43845 :   KeyedAccessLoadMode load_mode = nexus.GetKeyedAccessLoadMode();
    1994             : 
    1995             :   // Try to lower the keyed access based on the {nexus}.
    1996       43845 :   Node* value = jsgraph()->Dead();
    1997             :   return ReduceKeyedAccess(node, name, value, nexus, AccessMode::kLoad,
    1998       43845 :                            load_mode, STANDARD_STORE);
    1999             : }
    2000             : 
    2001       11615 : Reduction JSNativeContextSpecialization::ReduceJSStoreProperty(Node* node) {
    2002             :   DCHECK_EQ(IrOpcode::kJSStoreProperty, node->opcode());
    2003       11615 :   PropertyAccess const& p = PropertyAccessOf(node->op());
    2004       11615 :   Node* const index = NodeProperties::GetValueInput(node, 1);
    2005       11615 :   Node* const value = NodeProperties::GetValueInput(node, 2);
    2006             : 
    2007             :   // Extract receiver maps from the keyed store IC using the FeedbackNexus.
    2008       11615 :   if (!p.feedback().IsValid()) return NoChange();
    2009       11615 :   FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot());
    2010             : 
    2011             :   // Extract the keyed access store mode from the keyed store IC.
    2012       11615 :   KeyedAccessStoreMode store_mode = nexus.GetKeyedAccessStoreMode();
    2013             : 
    2014             :   // Try to lower the keyed access based on the {nexus}.
    2015             :   return ReduceKeyedAccess(node, index, value, nexus, AccessMode::kStore,
    2016       11615 :                            STANDARD_LOAD, store_mode);
    2017             : }
    2018             : 
    2019        1939 : Node* JSNativeContextSpecialization::InlinePropertyGetterCall(
    2020        1939 :     Node* receiver, Node* context, Node* frame_state, Node** effect,
    2021             :     Node** control, ZoneVector<Node*>* if_exceptions,
    2022        3814 :     PropertyAccessInfo const& access_info) {
    2023        1939 :   Node* target = jsgraph()->Constant(access_info.constant());
    2024        1939 :   FrameStateInfo const& frame_info = FrameStateInfoOf(frame_state->op());
    2025             :   Handle<SharedFunctionInfo> shared_info =
    2026        1939 :       frame_info.shared_info().ToHandleChecked();
    2027             :   // Introduce the call to the getter function.
    2028             :   Node* value;
    2029        3878 :   if (access_info.constant()->IsJSFunction()) {
    2030             :     value = *effect = *control = graph()->NewNode(
    2031             :         jsgraph()->javascript()->Call(2, CallFrequency(), VectorSlotPair(),
    2032             :                                       ConvertReceiverMode::kNotNullOrUndefined),
    2033        5625 :         target, receiver, context, frame_state, *effect, *control);
    2034             :   } else {
    2035             :     DCHECK(access_info.constant()->IsFunctionTemplateInfo());
    2036             :     Handle<FunctionTemplateInfo> function_template_info(
    2037          64 :         Handle<FunctionTemplateInfo>::cast(access_info.constant()));
    2038             :     DCHECK(!function_template_info->call_code()->IsUndefined(isolate()));
    2039             :     Node* holder =
    2040             :         access_info.holder().is_null()
    2041             :             ? receiver
    2042          64 :             : jsgraph()->Constant(access_info.holder().ToHandleChecked());
    2043             :     value = InlineApiCall(receiver, holder, frame_state, nullptr, effect,
    2044          64 :                           control, shared_info, function_template_info);
    2045             :   }
    2046             :   // Remember to rewire the IfException edge if this is inside a try-block.
    2047        1939 :   if (if_exceptions != nullptr) {
    2048             :     // Create the appropriate IfException/IfSuccess projections.
    2049             :     Node* const if_exception =
    2050         174 :         graph()->NewNode(common()->IfException(), *control, *effect);
    2051         116 :     Node* const if_success = graph()->NewNode(common()->IfSuccess(), *control);
    2052          58 :     if_exceptions->push_back(if_exception);
    2053          58 :     *control = if_success;
    2054             :   }
    2055        1939 :   return value;
    2056             : }
    2057             : 
    2058         851 : void JSNativeContextSpecialization::InlinePropertySetterCall(
    2059         851 :     Node* receiver, Node* value, Node* context, Node* frame_state,
    2060             :     Node** effect, Node** control, ZoneVector<Node*>* if_exceptions,
    2061        1638 :     PropertyAccessInfo const& access_info) {
    2062         851 :   Node* target = jsgraph()->Constant(access_info.constant());
    2063         851 :   FrameStateInfo const& frame_info = FrameStateInfoOf(frame_state->op());
    2064             :   Handle<SharedFunctionInfo> shared_info =
    2065         851 :       frame_info.shared_info().ToHandleChecked();
    2066             :   // Introduce the call to the setter function.
    2067        1702 :   if (access_info.constant()->IsJSFunction()) {
    2068             :     *effect = *control = graph()->NewNode(
    2069             :         jsgraph()->javascript()->Call(3, CallFrequency(), VectorSlotPair(),
    2070             :                                       ConvertReceiverMode::kNotNullOrUndefined),
    2071        2361 :         target, receiver, value, context, frame_state, *effect, *control);
    2072             :   } else {
    2073             :     DCHECK(access_info.constant()->IsFunctionTemplateInfo());
    2074             :     Handle<FunctionTemplateInfo> function_template_info(
    2075          64 :         Handle<FunctionTemplateInfo>::cast(access_info.constant()));
    2076             :     DCHECK(!function_template_info->call_code()->IsUndefined(isolate()));
    2077             :     Node* holder =
    2078             :         access_info.holder().is_null()
    2079             :             ? receiver
    2080          64 :             : jsgraph()->Constant(access_info.holder().ToHandleChecked());
    2081             :     InlineApiCall(receiver, holder, frame_state, value, effect, control,
    2082          64 :                   shared_info, function_template_info);
    2083             :   }
    2084             :   // Remember to rewire the IfException edge if this is inside a try-block.
    2085         851 :   if (if_exceptions != nullptr) {
    2086             :     // Create the appropriate IfException/IfSuccess projections.
    2087             :     Node* const if_exception =
    2088          93 :         graph()->NewNode(common()->IfException(), *control, *effect);
    2089          62 :     Node* const if_success = graph()->NewNode(common()->IfSuccess(), *control);
    2090          31 :     if_exceptions->push_back(if_exception);
    2091          31 :     *control = if_success;
    2092             :   }
    2093         851 : }
    2094             : 
    2095         128 : Node* JSNativeContextSpecialization::InlineApiCall(
    2096             :     Node* receiver, Node* holder, Node* frame_state, Node* value, Node** effect,
    2097             :     Node** control, Handle<SharedFunctionInfo> shared_info,
    2098         512 :     Handle<FunctionTemplateInfo> function_template_info) {
    2099             :   Handle<CallHandlerInfo> call_handler_info = handle(
    2100             :       CallHandlerInfo::cast(function_template_info->call_code()), isolate());
    2101             :   Handle<Object> call_data_object(call_handler_info->data(), isolate());
    2102             : 
    2103             :   // Only setters have a value.
    2104         128 :   int const argc = value == nullptr ? 0 : 1;
    2105             :   // The stub always expects the receiver as the first param on the stack.
    2106         128 :   Callable call_api_callback = CodeFactory::CallApiCallback(isolate());
    2107             :   CallInterfaceDescriptor call_interface_descriptor =
    2108             :       call_api_callback.descriptor();
    2109             :   auto call_descriptor = Linkage::GetStubCallDescriptor(
    2110             :       graph()->zone(), call_interface_descriptor,
    2111         128 :       call_interface_descriptor.GetStackParameterCount() + argc +
    2112             :           1 /* implicit receiver */,
    2113         256 :       CallDescriptor::kNeedsFrameState);
    2114             : 
    2115         128 :   Node* data = jsgraph()->Constant(call_data_object);
    2116         128 :   ApiFunction function(v8::ToCData<Address>(call_handler_info->callback()));
    2117             :   Node* function_reference =
    2118             :       graph()->NewNode(common()->ExternalConstant(ExternalReference::Create(
    2119         384 :           &function, ExternalReference::DIRECT_API_CALL)));
    2120         128 :   Node* code = jsgraph()->HeapConstant(call_api_callback.code());
    2121             : 
    2122             :   // Add CallApiCallbackStub's register argument as well.
    2123         256 :   Node* context = jsgraph()->Constant(native_context());
    2124             :   Node* inputs[11] = {
    2125         256 :       code,    function_reference, jsgraph()->Constant(argc), data, holder,
    2126         256 :       receiver};
    2127         128 :   int index = 6 + argc;
    2128         128 :   inputs[index++] = context;
    2129         128 :   inputs[index++] = frame_state;
    2130         128 :   inputs[index++] = *effect;
    2131         128 :   inputs[index++] = *control;
    2132             :   // This needs to stay here because of the edge case described in
    2133             :   // http://crbug.com/675648.
    2134         128 :   if (value != nullptr) {
    2135          64 :     inputs[6] = value;
    2136             :   }
    2137             : 
    2138             :   return *effect = *control =
    2139         256 :              graph()->NewNode(common()->Call(call_descriptor), index, inputs);
    2140             : }
    2141             : 
    2142             : JSNativeContextSpecialization::ValueEffectControl
    2143      105808 : JSNativeContextSpecialization::BuildPropertyLoad(
    2144             :     Node* receiver, Node* context, Node* frame_state, Node* effect,
    2145             :     Node* control, Handle<Name> name, ZoneVector<Node*>* if_exceptions,
    2146      171846 :     PropertyAccessInfo const& access_info) {
    2147             :   // Determine actual holder and perform prototype chain checks.
    2148             :   Handle<JSObject> holder;
    2149             :   PropertyAccessBuilder access_builder(jsgraph(), broker(), dependencies());
    2150      105808 :   if (access_info.holder().ToHandle(&holder)) {
    2151             :     dependencies()->DependOnStablePrototypeChains(
    2152       62760 :         broker(), access_info.receiver_maps(), JSObjectRef(broker(), holder));
    2153             :   }
    2154             : 
    2155             :   // Generate the actual property access.
    2156             :   Node* value;
    2157      105808 :   if (access_info.IsNotFound()) {
    2158        3271 :     value = jsgraph()->UndefinedConstant();
    2159      102537 :   } else if (access_info.IsDataConstant()) {
    2160             :     DCHECK(!FLAG_track_constant_fields);
    2161           0 :     value = jsgraph()->Constant(access_info.constant());
    2162      102537 :   } else if (access_info.IsAccessorConstant()) {
    2163             :     value = InlinePropertyGetterCall(receiver, context, frame_state, &effect,
    2164        1939 :                                      &control, if_exceptions, access_info);
    2165      100598 :   } else if (access_info.IsModuleExport()) {
    2166          14 :     Node* cell = jsgraph()->Constant(access_info.export_cell());
    2167             :     value = effect =
    2168             :         graph()->NewNode(simplified()->LoadField(AccessBuilder::ForCellValue()),
    2169          21 :                          cell, effect, control);
    2170      100591 :   } else if (access_info.IsStringLength()) {
    2171        1969 :     value = graph()->NewNode(simplified()->StringLength(), receiver);
    2172             :   } else {
    2173             :     DCHECK(access_info.IsDataField() || access_info.IsDataConstantField());
    2174             :     value = access_builder.BuildLoadDataField(name, access_info, receiver,
    2175       98622 :                                               &effect, &control);
    2176             :   }
    2177             : 
    2178      211616 :   return ValueEffectControl(value, effect, control);
    2179             : }
    2180             : 
    2181             : JSNativeContextSpecialization::ValueEffectControl
    2182      133536 : JSNativeContextSpecialization::BuildPropertyAccess(
    2183             :     Node* receiver, Node* value, Node* context, Node* frame_state, Node* effect,
    2184             :     Node* control, Handle<Name> name, ZoneVector<Node*>* if_exceptions,
    2185             :     PropertyAccessInfo const& access_info, AccessMode access_mode) {
    2186      133536 :   switch (access_mode) {
    2187             :     case AccessMode::kLoad:
    2188             :       return BuildPropertyLoad(receiver, context, frame_state, effect, control,
    2189      105808 :                                name, if_exceptions, access_info);
    2190             :     case AccessMode::kStore:
    2191             :     case AccessMode::kStoreInLiteral:
    2192             :       return BuildPropertyStore(receiver, value, context, frame_state, effect,
    2193             :                                 control, name, if_exceptions, access_info,
    2194       27728 :                                 access_mode);
    2195             :   }
    2196           0 :   UNREACHABLE();
    2197             :   return ValueEffectControl();
    2198             : }
    2199             : 
    2200             : JSNativeContextSpecialization::ValueEffectControl
    2201       27728 : JSNativeContextSpecialization::BuildPropertyStore(
    2202             :     Node* receiver, Node* value, Node* context, Node* frame_state, Node* effect,
    2203             :     Node* control, Handle<Name> name, ZoneVector<Node*>* if_exceptions,
    2204      144482 :     PropertyAccessInfo const& access_info, AccessMode access_mode) {
    2205             :   // Determine actual holder and perform prototype chain checks.
    2206             :   Handle<JSObject> holder;
    2207             :   PropertyAccessBuilder access_builder(jsgraph(), broker(), dependencies());
    2208       27728 :   if (access_info.holder().ToHandle(&holder)) {
    2209             :     DCHECK_NE(AccessMode::kStoreInLiteral, access_mode);
    2210             :     dependencies()->DependOnStablePrototypeChains(
    2211       44048 :         broker(), access_info.receiver_maps(), JSObjectRef(broker(), holder));
    2212             :   }
    2213             : 
    2214             :   DCHECK(!access_info.IsNotFound());
    2215             : 
    2216             :   // Generate the actual property access.
    2217       27728 :   if (access_info.IsDataConstant()) {
    2218             :     DCHECK(!FLAG_track_constant_fields);
    2219           0 :     Node* constant_value = jsgraph()->Constant(access_info.constant());
    2220             :     Node* check =
    2221           0 :         graph()->NewNode(simplified()->ReferenceEqual(), value, constant_value);
    2222             :     effect =
    2223             :         graph()->NewNode(simplified()->CheckIf(DeoptimizeReason::kWrongValue),
    2224           0 :                          check, effect, control);
    2225             :     value = constant_value;
    2226       27728 :   } else if (access_info.IsAccessorConstant()) {
    2227             :     InlinePropertySetterCall(receiver, value, context, frame_state, &effect,
    2228         851 :                              &control, if_exceptions, access_info);
    2229             :   } else {
    2230             :     DCHECK(access_info.IsDataField() || access_info.IsDataConstantField());
    2231             :     FieldIndex const field_index = access_info.field_index();
    2232             :     Type const field_type = access_info.field_type();
    2233             :     MachineRepresentation const field_representation =
    2234       26877 :         access_info.field_representation();
    2235             :     Node* storage = receiver;
    2236       26877 :     if (!field_index.is_inobject()) {
    2237             :       storage = effect = graph()->NewNode(
    2238             :           simplified()->LoadField(AccessBuilder::ForJSObjectPropertiesOrHash()),
    2239       20043 :           storage, effect, control);
    2240             :     }
    2241             :     FieldAccess field_access = {
    2242             :         kTaggedBase,
    2243             :         field_index.offset(),
    2244             :         name,
    2245             :         MaybeHandle<Map>(),
    2246             :         field_type,
    2247             :         MachineType::TypeForRepresentation(field_representation),
    2248       26877 :         kFullWriteBarrier};
    2249             :     bool store_to_constant_field = FLAG_track_constant_fields &&
    2250       51886 :                                    (access_mode == AccessMode::kStore) &&
    2251             :                                    access_info.IsDataConstantField();
    2252             : 
    2253             :     DCHECK(access_mode == AccessMode::kStore ||
    2254             :            access_mode == AccessMode::kStoreInLiteral);
    2255       26877 :     switch (field_representation) {
    2256             :       case MachineRepresentation::kFloat64: {
    2257             :         value = effect =
    2258             :             graph()->NewNode(simplified()->CheckNumber(VectorSlotPair()), value,
    2259         909 :                              effect, control);
    2260         514 :         if (!field_index.is_inobject() || field_index.is_hidden_field() ||
    2261             :             !FLAG_unbox_double_fields) {
    2262          92 :           if (access_info.HasTransitionMap()) {
    2263             :             // Allocate a MutableHeapNumber for the new property.
    2264          52 :             AllocationBuilder a(jsgraph(), effect, control);
    2265          52 :             a.Allocate(HeapNumber::kSize, NOT_TENURED, Type::OtherInternal());
    2266             :             a.Store(AccessBuilder::ForMap(),
    2267          52 :                     factory()->mutable_heap_number_map());
    2268          52 :             a.Store(AccessBuilder::ForHeapNumberValue(), value);
    2269          52 :             value = effect = a.Finish();
    2270             : 
    2271          52 :             field_access.type = Type::Any();
    2272          52 :             field_access.machine_type = MachineType::TaggedPointer();
    2273          52 :             field_access.write_barrier_kind = kPointerWriteBarrier;
    2274             :           } else {
    2275             :             // We just store directly to the MutableHeapNumber.
    2276             :             FieldAccess const storage_access = {kTaggedBase,
    2277             :                                                 field_index.offset(),
    2278             :                                                 name,
    2279             :                                                 MaybeHandle<Map>(),
    2280             :                                                 Type::OtherInternal(),
    2281             :                                                 MachineType::TaggedPointer(),
    2282             :                                                 kPointerWriteBarrier};
    2283             :             storage = effect =
    2284             :                 graph()->NewNode(simplified()->LoadField(storage_access),
    2285         120 :                                  storage, effect, control);
    2286          40 :             field_access.offset = HeapNumber::kValueOffset;
    2287          40 :             field_access.name = MaybeHandle<Name>();
    2288          40 :             field_access.machine_type = MachineType::Float64();
    2289             :           }
    2290             :         }
    2291         303 :         if (store_to_constant_field) {
    2292             :           DCHECK(!access_info.HasTransitionMap());
    2293             :           // If the field is constant check that the value we are going
    2294             :           // to store matches current value.
    2295             :           Node* current_value = effect = graph()->NewNode(
    2296         117 :               simplified()->LoadField(field_access), storage, effect, control);
    2297             : 
    2298             :           Node* check = graph()->NewNode(simplified()->NumberEqual(),
    2299          39 :                                          current_value, value);
    2300             :           effect = graph()->NewNode(
    2301             :               simplified()->CheckIf(DeoptimizeReason::kWrongValue), check,
    2302         117 :               effect, control);
    2303         213 :           return ValueEffectControl(value, effect, control);
    2304             :         }
    2305             :         break;
    2306             :       }
    2307             :       case MachineRepresentation::kTaggedSigned:
    2308             :       case MachineRepresentation::kTaggedPointer:
    2309             :       case MachineRepresentation::kTagged:
    2310       26574 :         if (store_to_constant_field) {
    2311             :           DCHECK(!access_info.HasTransitionMap());
    2312             :           // If the field is constant check that the value we are going
    2313             :           // to store matches current value.
    2314             :           Node* current_value = effect = graph()->NewNode(
    2315         405 :               simplified()->LoadField(field_access), storage, effect, control);
    2316             : 
    2317             :           Node* check = graph()->NewNode(simplified()->ReferenceEqual(),
    2318         135 :                                          current_value, value);
    2319             :           effect = graph()->NewNode(
    2320             :               simplified()->CheckIf(DeoptimizeReason::kWrongValue), check,
    2321         405 :               effect, control);
    2322         135 :           return ValueEffectControl(value, effect, control);
    2323             :         }
    2324             : 
    2325       26439 :         if (field_representation == MachineRepresentation::kTaggedSigned) {
    2326             :           value = effect = graph()->NewNode(
    2327       59922 :               simplified()->CheckSmi(VectorSlotPair()), value, effect, control);
    2328       19974 :           field_access.write_barrier_kind = kNoWriteBarrier;
    2329             : 
    2330        6465 :         } else if (field_representation ==
    2331             :                    MachineRepresentation::kTaggedPointer) {
    2332             :           // Ensure that {value} is a HeapObject.
    2333        3309 :           value = access_builder.BuildCheckHeapObject(value, &effect, control);
    2334             :           Handle<Map> field_map;
    2335        3309 :           if (access_info.field_map().ToHandle(&field_map)) {
    2336             :             // Emit a map check for the value.
    2337             :             effect = graph()->NewNode(
    2338             :                 simplified()->CheckMaps(CheckMapsFlag::kNone,
    2339             :                                         ZoneHandleSet<Map>(field_map)),
    2340         492 :                 value, effect, control);
    2341             :           }
    2342        3309 :           field_access.write_barrier_kind = kPointerWriteBarrier;
    2343             : 
    2344             :         } else {
    2345             :           DCHECK_EQ(MachineRepresentation::kTagged, field_representation);
    2346             :         }
    2347             :         break;
    2348             :       case MachineRepresentation::kNone:
    2349             :       case MachineRepresentation::kBit:
    2350             :       case MachineRepresentation::kWord8:
    2351             :       case MachineRepresentation::kWord16:
    2352             :       case MachineRepresentation::kWord32:
    2353             :       case MachineRepresentation::kWord64:
    2354             :       case MachineRepresentation::kFloat32:
    2355             :       case MachineRepresentation::kSimd128:
    2356           0 :         UNREACHABLE();
    2357             :         break;
    2358             :     }
    2359             :     // Check if we need to perform a transitioning store.
    2360             :     Handle<Map> transition_map;
    2361       26703 :     if (access_info.transition_map().ToHandle(&transition_map)) {
    2362             :       // Check if we need to grow the properties backing store
    2363             :       // with this transitioning store.
    2364             :       Handle<Map> original_map(Map::cast(transition_map->GetBackPointer()),
    2365       43480 :                                isolate());
    2366       21740 :       if (original_map->UnusedPropertyFields() == 0) {
    2367             :         DCHECK(!field_index.is_inobject());
    2368             : 
    2369             :         // Reallocate the properties {storage}.
    2370             :         storage = effect = BuildExtendPropertiesBackingStore(
    2371        4594 :             MapRef(broker(), original_map), storage, effect, control);
    2372             : 
    2373             :         // Perform the actual store.
    2374             :         effect = graph()->NewNode(simplified()->StoreField(field_access),
    2375        6891 :                                   storage, value, effect, control);
    2376             : 
    2377             :         // Atomically switch to the new properties below.
    2378        2297 :         field_access = AccessBuilder::ForJSObjectPropertiesOrHash();
    2379             :         value = storage;
    2380             :         storage = receiver;
    2381             :       }
    2382             :       effect = graph()->NewNode(
    2383       65220 :           common()->BeginRegion(RegionObservability::kObservable), effect);
    2384             :       effect = graph()->NewNode(
    2385             :           simplified()->StoreField(AccessBuilder::ForMap()), receiver,
    2386       86960 :           jsgraph()->Constant(transition_map), effect, control);
    2387             :       effect = graph()->NewNode(simplified()->StoreField(field_access), storage,
    2388       65220 :                                 value, effect, control);
    2389             :       effect = graph()->NewNode(common()->FinishRegion(),
    2390       65220 :                                 jsgraph()->UndefinedConstant(), effect);
    2391             :     } else {
    2392             :       // Regular non-transitioning field store.
    2393             :       effect = graph()->NewNode(simplified()->StoreField(field_access), storage,
    2394       14889 :                                 value, effect, control);
    2395             :     }
    2396             :   }
    2397             : 
    2398       27554 :   return ValueEffectControl(value, effect, control);
    2399             : }
    2400             : 
    2401         539 : Reduction JSNativeContextSpecialization::ReduceJSStoreDataPropertyInLiteral(
    2402         858 :     Node* node) {
    2403             :   DCHECK_EQ(IrOpcode::kJSStoreDataPropertyInLiteral, node->opcode());
    2404             : 
    2405         539 :   FeedbackParameter const& p = FeedbackParameterOf(node->op());
    2406             : 
    2407         539 :   if (!p.feedback().IsValid()) return NoChange();
    2408             : 
    2409         539 :   FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot());
    2410         539 :   if (nexus.IsUninitialized()) {
    2411             :     return NoChange();
    2412             :   }
    2413             : 
    2414         143 :   if (nexus.ic_state() == MEGAMORPHIC) {
    2415             :     return NoChange();
    2416             :   }
    2417             : 
    2418             :   DCHECK_EQ(MONOMORPHIC, nexus.ic_state());
    2419             : 
    2420         127 :   Map map = nexus.GetFirstMap();
    2421         127 :   if (map.is_null()) {
    2422             :     // Maps are weakly held in the type feedback vector, we may not have one.
    2423             :     return NoChange();
    2424             :   }
    2425             : 
    2426             :   Handle<Map> receiver_map(map, isolate());
    2427         254 :   if (!Map::TryUpdate(isolate(), receiver_map).ToHandle(&receiver_map))
    2428             :     return NoChange();
    2429             : 
    2430             :   Handle<Name> cached_name(
    2431         254 :       Name::cast(nexus.GetFeedbackExtra()->GetHeapObjectAssumeStrong()),
    2432         254 :       isolate());
    2433             : 
    2434         127 :   PropertyAccessInfo access_info;
    2435             :   AccessInfoFactory access_info_factory(
    2436         381 :       broker(), dependencies(), native_context().object(), graph()->zone());
    2437         127 :   if (!access_info_factory.ComputePropertyAccessInfo(
    2438             :           receiver_map, cached_name, AccessMode::kStoreInLiteral,
    2439         127 :           &access_info)) {
    2440             :     return NoChange();
    2441             :   }
    2442             : 
    2443          96 :   Node* receiver = NodeProperties::GetValueInput(node, 0);
    2444          96 :   Node* effect = NodeProperties::GetEffectInput(node);
    2445          96 :   Node* control = NodeProperties::GetControlInput(node);
    2446             : 
    2447             :   // Monomorphic property access.
    2448             :   PropertyAccessBuilder access_builder(jsgraph(), broker(), dependencies());
    2449          96 :   receiver = access_builder.BuildCheckHeapObject(receiver, &effect, control);
    2450             :   access_builder.BuildCheckMaps(receiver, &effect, control,
    2451          96 :                                 access_info.receiver_maps());
    2452             : 
    2453             :   // Ensure that {name} matches the cached name.
    2454          96 :   Node* name = NodeProperties::GetValueInput(node, 1);
    2455             :   Node* check = graph()->NewNode(simplified()->ReferenceEqual(), name,
    2456         288 :                                  jsgraph()->HeapConstant(cached_name));
    2457             :   effect = graph()->NewNode(simplified()->CheckIf(DeoptimizeReason::kWrongName),
    2458         288 :                             check, effect, control);
    2459             : 
    2460          96 :   Node* value = NodeProperties::GetValueInput(node, 2);
    2461          96 :   Node* context = NodeProperties::GetContextInput(node);
    2462          96 :   Node* frame_state_lazy = NodeProperties::GetFrameStateInput(node);
    2463             : 
    2464             :   // Generate the actual property access.
    2465             :   ValueEffectControl continuation = BuildPropertyAccess(
    2466             :       receiver, value, context, frame_state_lazy, effect, control, cached_name,
    2467          96 :       nullptr, access_info, AccessMode::kStoreInLiteral);
    2468          96 :   value = continuation.value();
    2469          96 :   effect = continuation.effect();
    2470          96 :   control = continuation.control();
    2471             : 
    2472          96 :   ReplaceWithValue(node, value, effect, control);
    2473             :   return Replace(value);
    2474             : }
    2475             : 
    2476       43797 : Reduction JSNativeContextSpecialization::ReduceJSStoreInArrayLiteral(
    2477       43797 :     Node* node) {
    2478             :   DCHECK_EQ(IrOpcode::kJSStoreInArrayLiteral, node->opcode());
    2479       43797 :   FeedbackParameter const& p = FeedbackParameterOf(node->op());
    2480       43797 :   Node* const receiver = NodeProperties::GetValueInput(node, 0);
    2481       43797 :   Node* const index = NodeProperties::GetValueInput(node, 1);
    2482       43797 :   Node* const value = NodeProperties::GetValueInput(node, 2);
    2483       43797 :   Node* const effect = NodeProperties::GetEffectInput(node);
    2484             : 
    2485             :   // Extract receiver maps from the keyed store IC using the FeedbackNexus.
    2486       43797 :   if (!p.feedback().IsValid()) return NoChange();
    2487       43797 :   FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot());
    2488             : 
    2489             :   // Extract the keyed access store mode from the keyed store IC.
    2490       43797 :   KeyedAccessStoreMode store_mode = nexus.GetKeyedAccessStoreMode();
    2491             : 
    2492             :   // Extract receiver maps from the {nexus}.
    2493             :   MapHandles receiver_maps;
    2494       43797 :   if (!ExtractReceiverMaps(receiver, effect, nexus, &receiver_maps)) {
    2495             :     return NoChange();
    2496       43797 :   } else if (receiver_maps.empty()) {
    2497             :     return ReduceSoftDeoptimize(
    2498       40926 :         node, DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess);
    2499             :   }
    2500             :   DCHECK(!nexus.IsUninitialized());
    2501             :   DCHECK_EQ(ELEMENT, nexus.GetKeyType());
    2502             : 
    2503        2871 :   if (nexus.ic_state() == MEGAMORPHIC) return NoChange();
    2504             : 
    2505             :   // Try to lower the element access based on the {receiver_maps}.
    2506             :   return ReduceElementAccess(node, index, value, receiver_maps,
    2507             :                              AccessMode::kStoreInLiteral, STANDARD_LOAD,
    2508        2871 :                              store_mode);
    2509             : }
    2510             : 
    2511        4006 : Reduction JSNativeContextSpecialization::ReduceJSToObject(Node* node) {
    2512             :   DCHECK_EQ(IrOpcode::kJSToObject, node->opcode());
    2513        2003 :   Node* receiver = NodeProperties::GetValueInput(node, 0);
    2514        2003 :   Node* effect = NodeProperties::GetEffectInput(node);
    2515             : 
    2516             :   ZoneHandleSet<Map> receiver_maps;
    2517             :   NodeProperties::InferReceiverMapsResult result =
    2518             :       NodeProperties::InferReceiverMaps(broker(), receiver, effect,
    2519        2003 :                                         &receiver_maps);
    2520        2003 :   if (result == NodeProperties::kNoReceiverMaps) return NoChange();
    2521             : 
    2522         265 :   for (size_t i = 0; i < receiver_maps.size(); ++i) {
    2523         142 :     if (!receiver_maps[i]->IsJSReceiverMap()) return NoChange();
    2524             :   }
    2525             : 
    2526          59 :   ReplaceWithValue(node, receiver, effect);
    2527             :   return Replace(receiver);
    2528             : }
    2529             : 
    2530             : namespace {
    2531             : 
    2532        6699 : ExternalArrayType GetArrayTypeFromElementsKind(ElementsKind kind) {
    2533        6699 :   switch (kind) {
    2534             : #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
    2535             :   case TYPE##_ELEMENTS:                           \
    2536             :     return kExternal##Type##Array;
    2537         525 :     TYPED_ARRAYS(TYPED_ARRAY_CASE)
    2538             : #undef TYPED_ARRAY_CASE
    2539             :     default:
    2540             :       break;
    2541             :   }
    2542           0 :   UNREACHABLE();
    2543             : }
    2544             : 
    2545        6699 : base::Optional<JSTypedArrayRef> GetTypedArrayConstant(JSHeapBroker* broker,
    2546             :                                                       Node* receiver) {
    2547             :   HeapObjectMatcher m(receiver);
    2548        6699 :   if (!m.HasValue()) return base::nullopt;
    2549        2008 :   ObjectRef object = m.Ref(broker);
    2550        2008 :   if (!object.IsJSTypedArray()) return base::nullopt;
    2551        2008 :   JSTypedArrayRef typed_array = object.AsJSTypedArray();
    2552        2008 :   if (typed_array.is_on_heap()) return base::nullopt;
    2553             :   return typed_array;
    2554             : }
    2555             : 
    2556             : }  // namespace
    2557             : 
    2558             : JSNativeContextSpecialization::ValueEffectControl
    2559       22667 : JSNativeContextSpecialization::BuildElementAccess(
    2560             :     Node* receiver, Node* index, Node* value, Node* effect, Node* control,
    2561       22667 :     ElementAccessInfo const& access_info, AccessMode access_mode,
    2562       44003 :     KeyedAccessLoadMode load_mode, KeyedAccessStoreMode store_mode) {
    2563             : 
    2564             :   // TODO(bmeurer): We currently specialize based on elements kind. We should
    2565             :   // also be able to properly support strings and other JSObjects here.
    2566             :   ElementsKind elements_kind = access_info.elements_kind();
    2567       22667 :   MapHandles const& receiver_maps = access_info.receiver_maps();
    2568             : 
    2569       22667 :   if (IsFixedTypedArrayElementsKind(elements_kind)) {
    2570             :     Node* buffer;
    2571             :     Node* length;
    2572             :     Node* base_pointer;
    2573             :     Node* external_pointer;
    2574             : 
    2575             :     // Check if we can constant-fold information about the {receiver} (i.e.
    2576             :     // for asm.js-like code patterns).
    2577             :     base::Optional<JSTypedArrayRef> typed_array =
    2578        6699 :         GetTypedArrayConstant(broker(), receiver);
    2579        6699 :     if (typed_array.has_value()) {
    2580        1267 :       typed_array->Serialize();
    2581        2534 :       buffer = jsgraph()->Constant(typed_array->buffer());
    2582             :       length =
    2583        2534 :           jsgraph()->Constant(static_cast<double>(typed_array->length_value()));
    2584             : 
    2585             :       // Load the (known) base and external pointer for the {receiver}. The
    2586             :       // {external_pointer} might be invalid if the {buffer} was detached, so
    2587             :       // we need to make sure that any access is properly guarded.
    2588        1267 :       base_pointer = jsgraph()->ZeroConstant();
    2589             :       external_pointer =
    2590        2534 :           jsgraph()->PointerConstant(typed_array->elements_external_pointer());
    2591             :     } else {
    2592             :       // Load the {receiver}s length.
    2593             :       length = effect = graph()->NewNode(
    2594             :           simplified()->LoadField(AccessBuilder::ForJSTypedArrayLength()),
    2595       16296 :           receiver, effect, control);
    2596             : 
    2597             :       // Load the buffer for the {receiver}.
    2598             :       buffer = effect = graph()->NewNode(
    2599             :           simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
    2600       16296 :           receiver, effect, control);
    2601             : 
    2602             :       // Load the elements for the {receiver}.
    2603             :       Node* elements = effect = graph()->NewNode(
    2604             :           simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
    2605       16296 :           receiver, effect, control);
    2606             : 
    2607             :       // Load the base pointer for the {receiver}. This will always be Smi
    2608             :       // zero unless we allow on-heap TypedArrays, which is only the case
    2609             :       // for Chrome. Node and Electron both set this limit to 0. Setting
    2610             :       // the base to Smi zero here allows the EffectControlLinearizer to
    2611             :       // optimize away the tricky part of the access later.
    2612             :       if (V8_TYPED_ARRAY_MAX_SIZE_IN_HEAP == 0) {
    2613             :         base_pointer = jsgraph()->ZeroConstant();
    2614             :       } else {
    2615             :         base_pointer = effect = graph()->NewNode(
    2616             :             simplified()->LoadField(
    2617             :                 AccessBuilder::ForFixedTypedArrayBaseBasePointer()),
    2618       16296 :             elements, effect, control);
    2619             :       }
    2620             : 
    2621             :       // Load the external pointer for the {receiver}s {elements}.
    2622             :       external_pointer = effect = graph()->NewNode(
    2623             :           simplified()->LoadField(
    2624             :               AccessBuilder::ForFixedTypedArrayBaseExternalPointer()),
    2625       16296 :           elements, effect, control);
    2626             :     }
    2627             : 
    2628             :     // See if we can skip the detaching check.
    2629        6699 :     if (isolate()->IsArrayBufferDetachingIntact()) {
    2630             :       // Add a code dependency so we are deoptimized in case an ArrayBuffer
    2631             :       // gets detached.
    2632             :       dependencies()->DependOnProtector(PropertyCellRef(
    2633        6449 :           broker(), factory()->array_buffer_detaching_protector()));
    2634             :     } else {
    2635             :       // Deopt if the {buffer} was detached.
    2636             :       // Note: A detached buffer leads to megamorphic feedback.
    2637             :       Node* buffer_bit_field = effect = graph()->NewNode(
    2638             :           simplified()->LoadField(AccessBuilder::ForJSArrayBufferBitField()),
    2639         750 :           buffer, effect, control);
    2640             :       Node* check = graph()->NewNode(
    2641             :           simplified()->NumberEqual(),
    2642             :           graph()->NewNode(
    2643             :               simplified()->NumberBitwiseAnd(), buffer_bit_field,
    2644             :               jsgraph()->Constant(JSArrayBuffer::WasDetachedBit::kMask)),
    2645        1000 :           jsgraph()->ZeroConstant());
    2646             :       effect = graph()->NewNode(
    2647             :           simplified()->CheckIf(DeoptimizeReason::kArrayBufferWasDetached),
    2648         750 :           check, effect, control);
    2649             :     }
    2650             : 
    2651       13398 :     if (load_mode == LOAD_IGNORE_OUT_OF_BOUNDS ||
    2652        6699 :         store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
    2653             :       // Only check that the {index} is in SignedSmall range. We do the actual
    2654             :       // bounds check below and just skip the property access if it's out of
    2655             :       // bounds for the {receiver}.
    2656             :       index = effect = graph()->NewNode(
    2657        1404 :           simplified()->CheckSmi(VectorSlotPair()), index, effect, control);
    2658             : 
    2659             :       // Cast the {index} to Unsigned32 range, so that the bounds checks
    2660             :       // below are performed on unsigned values, which means that all the
    2661             :       // Negative32 values are treated as out-of-bounds.
    2662         468 :       index = graph()->NewNode(simplified()->NumberToUint32(), index);
    2663             :     } else {
    2664             :       // Check that the {index} is in the valid range for the {receiver}.
    2665             :       index = effect =
    2666             :           graph()->NewNode(simplified()->CheckBounds(VectorSlotPair()), index,
    2667       18693 :                            length, effect, control);
    2668             :     }
    2669             : 
    2670             :     // Access the actual element.
    2671             :     ExternalArrayType external_array_type =
    2672        6699 :         GetArrayTypeFromElementsKind(elements_kind);
    2673        6699 :     switch (access_mode) {
    2674             :       case AccessMode::kLoad: {
    2675             :         // Check if we can return undefined for out-of-bounds loads.
    2676        3510 :         if (load_mode == LOAD_IGNORE_OUT_OF_BOUNDS) {
    2677             :           Node* check =
    2678         298 :               graph()->NewNode(simplified()->NumberLessThan(), index, length);
    2679             :           Node* branch = graph()->NewNode(
    2680             :               common()->Branch(BranchHint::kTrue,
    2681             :                                IsSafetyCheck::kCriticalSafetyCheck),
    2682         298 :               check, control);
    2683             : 
    2684         298 :           Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    2685             :           Node* etrue = effect;
    2686             :           Node* vtrue;
    2687             :           {
    2688             :             // Perform the actual load
    2689             :             vtrue = etrue = graph()->NewNode(
    2690             :                 simplified()->LoadTypedElement(external_array_type), buffer,
    2691         298 :                 base_pointer, external_pointer, index, etrue, if_true);
    2692             :           }
    2693             : 
    2694         298 :           Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    2695             :           Node* efalse = effect;
    2696             :           Node* vfalse;
    2697             :           {
    2698             :             // Materialize undefined for out-of-bounds loads.
    2699         298 :             vfalse = jsgraph()->UndefinedConstant();
    2700             :           }
    2701             : 
    2702         298 :           control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    2703             :           effect =
    2704         298 :               graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
    2705             :           value =
    2706             :               graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    2707         298 :                                vtrue, vfalse, control);
    2708             :         } else {
    2709             :           // Perform the actual load.
    2710             :           value = effect = graph()->NewNode(
    2711             :               simplified()->LoadTypedElement(external_array_type), buffer,
    2712        3212 :               base_pointer, external_pointer, index, effect, control);
    2713             :         }
    2714             :         break;
    2715             :       }
    2716             :       case AccessMode::kStoreInLiteral:
    2717           0 :         UNREACHABLE();
    2718             :         break;
    2719             :       case AccessMode::kStore: {
    2720             :         // Ensure that the {value} is actually a Number or an Oddball,
    2721             :         // and truncate it to a Number appropriately.
    2722             :         value = effect = graph()->NewNode(
    2723             :             simplified()->SpeculativeToNumber(
    2724             :                 NumberOperationHint::kNumberOrOddball, VectorSlotPair()),
    2725        9567 :             value, effect, control);
    2726             : 
    2727             :         // Introduce the appropriate truncation for {value}. Currently we
    2728             :         // only need to do this for ClamedUint8Array {receiver}s, as the
    2729             :         // other truncations are implicit in the StoreTypedElement, but we
    2730             :         // might want to change that at some point.
    2731        3189 :         if (external_array_type == kExternalUint8ClampedArray) {
    2732         471 :           value = graph()->NewNode(simplified()->NumberToUint8Clamped(), value);
    2733             :         }
    2734             : 
    2735             :         // Check if we can skip the out-of-bounds store.
    2736        3189 :         if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
    2737             :           Node* check =
    2738         170 :               graph()->NewNode(simplified()->NumberLessThan(), index, length);
    2739             :           Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
    2740         170 :                                           check, control);
    2741             : 
    2742         170 :           Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    2743             :           Node* etrue = effect;
    2744             :           {
    2745             :             // Perform the actual store.
    2746             :             etrue = graph()->NewNode(
    2747             :                 simplified()->StoreTypedElement(external_array_type), buffer,
    2748         170 :                 base_pointer, external_pointer, index, value, etrue, if_true);
    2749             :           }
    2750             : 
    2751         170 :           Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    2752             :           Node* efalse = effect;
    2753             :           {
    2754             :             // Just ignore the out-of-bounds write.
    2755             :           }
    2756             : 
    2757         170 :           control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    2758             :           effect =
    2759         170 :               graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
    2760             :         } else {
    2761             :           // Perform the actual store
    2762             :           effect = graph()->NewNode(
    2763             :               simplified()->StoreTypedElement(external_array_type), buffer,
    2764        3019 :               base_pointer, external_pointer, index, value, effect, control);
    2765             :         }
    2766             :         break;
    2767             :       }
    2768             :     }
    2769             :   } else {
    2770             :     // Load the elements for the {receiver}.
    2771             :     Node* elements = effect = graph()->NewNode(
    2772             :         simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver,
    2773       47904 :         effect, control);
    2774             : 
    2775             :     // Don't try to store to a copy-on-write backing store (unless supported by
    2776             :     // the store mode).
    2777       18316 :     if (access_mode == AccessMode::kStore &&
    2778       17426 :         IsSmiOrObjectElementsKind(elements_kind) &&
    2779             :         !IsCOWHandlingStoreMode(store_mode)) {
    2780             :       effect = graph()->NewNode(
    2781             :           simplified()->CheckMaps(
    2782             :               CheckMapsFlag::kNone,
    2783             :               ZoneHandleSet<Map>(factory()->fixed_array_map())),
    2784        2946 :           elements, effect, control);
    2785             :     }
    2786             : 
    2787             :     // Check if the {receiver} is a JSArray.
    2788       15968 :     bool receiver_is_jsarray = HasOnlyJSArrayMaps(broker(), receiver_maps);
    2789             : 
    2790             :     // Load the length of the {receiver}.
    2791             :     Node* length = effect =
    2792             :         receiver_is_jsarray
    2793             :             ? graph()->NewNode(
    2794             :                   simplified()->LoadField(
    2795       14243 :                       AccessBuilder::ForJSArrayLength(elements_kind)),
    2796       58697 :                   receiver, effect, control)
    2797             :             : graph()->NewNode(
    2798             :                   simplified()->LoadField(AccessBuilder::ForFixedArrayLength()),
    2799       37111 :                   elements, effect, control);
    2800             : 
    2801             :     // Check if we might need to grow the {elements} backing store.
    2802       15968 :     if (IsGrowStoreMode(store_mode)) {
    2803             :       // For growing stores we validate the {index} below.
    2804             :       DCHECK(access_mode == AccessMode::kStore ||
    2805             :              access_mode == AccessMode::kStoreInLiteral);
    2806       15390 :     } else if (load_mode == LOAD_IGNORE_OUT_OF_BOUNDS &&
    2807         366 :                CanTreatHoleAsUndefined(receiver_maps)) {
    2808             :       // Check that the {index} is a valid array index, we do the actual
    2809             :       // bounds check below and just skip the store below if it's out of
    2810             :       // bounds for the {receiver}.
    2811             :       index = effect = graph()->NewNode(
    2812             :           simplified()->CheckBounds(VectorSlotPair()), index,
    2813        1053 :           jsgraph()->Constant(Smi::kMaxValue), effect, control);
    2814             :     } else {
    2815             :       // Check that the {index} is in the valid range for the {receiver}.
    2816             :       index = effect =
    2817             :           graph()->NewNode(simplified()->CheckBounds(VectorSlotPair()), index,
    2818       44019 :                            length, effect, control);
    2819             :     }
    2820             : 
    2821             :     // Compute the element access.
    2822             :     Type element_type = Type::NonInternal();
    2823             :     MachineType element_machine_type = MachineType::AnyTagged();
    2824       15968 :     if (IsDoubleElementsKind(elements_kind)) {
    2825             :       element_type = Type::Number();
    2826             :       element_machine_type = MachineType::Float64();
    2827       14127 :     } else if (IsSmiElementsKind(elements_kind)) {
    2828             :       element_type = Type::SignedSmall();
    2829             :       element_machine_type = MachineType::TaggedSigned();
    2830             :     }
    2831             :     ElementAccess element_access = {
    2832             :         kTaggedBase,       FixedArray::kHeaderSize,
    2833             :         element_type,      element_machine_type,
    2834             :         kFullWriteBarrier, LoadSensitivity::kCritical};
    2835             : 
    2836             :     // Access the actual element.
    2837       15968 :     if (access_mode == AccessMode::kLoad) {
    2838             :       // Compute the real element access type, which includes the hole in case
    2839             :       // of holey backing stores.
    2840       10756 :       if (IsHoleyElementsKind(elements_kind)) {
    2841             :         element_access.type =
    2842        2807 :             Type::Union(element_type, Type::Hole(), graph()->zone());
    2843             :       }
    2844       10756 :       if (elements_kind == HOLEY_ELEMENTS ||
    2845             :           elements_kind == HOLEY_SMI_ELEMENTS) {
    2846        2219 :         element_access.machine_type = MachineType::AnyTagged();
    2847             :       }
    2848             : 
    2849             :       // Check if we can return undefined for out-of-bounds loads.
    2850       11122 :       if (load_mode == LOAD_IGNORE_OUT_OF_BOUNDS &&
    2851         366 :           CanTreatHoleAsUndefined(receiver_maps)) {
    2852             :         Node* check =
    2853         351 :             graph()->NewNode(simplified()->NumberLessThan(), index, length);
    2854             :         Node* branch = graph()->NewNode(
    2855             :             common()->Branch(BranchHint::kTrue,
    2856             :                              IsSafetyCheck::kCriticalSafetyCheck),
    2857         351 :             check, control);
    2858             : 
    2859         351 :         Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    2860             :         Node* etrue = effect;
    2861             :         Node* vtrue;
    2862             :         {
    2863             :           // Perform the actual load
    2864             :           vtrue = etrue =
    2865             :               graph()->NewNode(simplified()->LoadElement(element_access),
    2866         351 :                                elements, index, etrue, if_true);
    2867             : 
    2868             :           // Handle loading from holey backing stores correctly, by either
    2869             :           // mapping the hole to undefined if possible, or deoptimizing
    2870             :           // otherwise.
    2871         351 :           if (elements_kind == HOLEY_ELEMENTS ||
    2872             :               elements_kind == HOLEY_SMI_ELEMENTS) {
    2873             :             // Turn the hole into undefined.
    2874             :             vtrue = graph()->NewNode(
    2875          86 :                 simplified()->ConvertTaggedHoleToUndefined(), vtrue);
    2876         265 :           } else if (elements_kind == HOLEY_DOUBLE_ELEMENTS) {
    2877             :             // Return the signaling NaN hole directly if all uses are
    2878             :             // truncating.
    2879             :             vtrue = etrue = graph()->NewNode(
    2880             :                 simplified()->CheckFloat64Hole(
    2881             :                     CheckFloat64HoleMode::kAllowReturnHole, VectorSlotPair()),
    2882          45 :                 vtrue, etrue, if_true);
    2883             :           }
    2884             :         }
    2885             : 
    2886         351 :         Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    2887             :         Node* efalse = effect;
    2888             :         Node* vfalse;
    2889             :         {
    2890             :           // Materialize undefined for out-of-bounds loads.
    2891         351 :           vfalse = jsgraph()->UndefinedConstant();
    2892             :         }
    2893             : 
    2894         351 :         control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    2895             :         effect =
    2896         351 :             graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
    2897             :         value =
    2898             :             graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    2899         351 :                              vtrue, vfalse, control);
    2900             :       } else {
    2901             :         // Perform the actual load.
    2902             :         value = effect =
    2903             :             graph()->NewNode(simplified()->LoadElement(element_access),
    2904       10405 :                              elements, index, effect, control);
    2905             : 
    2906             :         // Handle loading from holey backing stores correctly, by either mapping
    2907             :         // the hole to undefined if possible, or deoptimizing otherwise.
    2908       10405 :         if (elements_kind == HOLEY_ELEMENTS ||
    2909             :             elements_kind == HOLEY_SMI_ELEMENTS) {
    2910             :           // Check if we are allowed to turn the hole into undefined.
    2911        2133 :           if (CanTreatHoleAsUndefined(receiver_maps)) {
    2912             :             // Turn the hole into undefined.
    2913             :             value = graph()->NewNode(
    2914        1883 :                 simplified()->ConvertTaggedHoleToUndefined(), value);
    2915             :           } else {
    2916             :             // Bailout if we see the hole.
    2917             :             value = effect = graph()->NewNode(
    2918         250 :                 simplified()->CheckNotTaggedHole(), value, effect, control);
    2919             :           }
    2920        8272 :         } else if (elements_kind == HOLEY_DOUBLE_ELEMENTS) {
    2921             :           // Perform the hole check on the result.
    2922             :           CheckFloat64HoleMode mode = CheckFloat64HoleMode::kNeverReturnHole;
    2923             :           // Check if we are allowed to return the hole directly.
    2924         573 :           if (CanTreatHoleAsUndefined(receiver_maps)) {
    2925             :             // Return the signaling NaN hole directly if all uses are
    2926             :             // truncating.
    2927             :             mode = CheckFloat64HoleMode::kAllowReturnHole;
    2928             :           }
    2929             :           value = effect = graph()->NewNode(
    2930             :               simplified()->CheckFloat64Hole(mode, VectorSlotPair()), value,
    2931        1719 :               effect, control);
    2932             :         }
    2933             :       }
    2934             :     } else {
    2935             :       DCHECK(access_mode == AccessMode::kStore ||
    2936             :              access_mode == AccessMode::kStoreInLiteral);
    2937        5212 :       if (IsSmiElementsKind(elements_kind)) {
    2938             :         value = effect = graph()->NewNode(
    2939        4734 :             simplified()->CheckSmi(VectorSlotPair()), value, effect, control);
    2940        3634 :       } else if (IsDoubleElementsKind(elements_kind)) {
    2941             :         value = effect =
    2942             :             graph()->NewNode(simplified()->CheckNumber(VectorSlotPair()), value,
    2943        3186 :                              effect, control);
    2944             :         // Make sure we do not store signalling NaNs into double arrays.
    2945        1062 :         value = graph()->NewNode(simplified()->NumberSilenceNaN(), value);
    2946             :       }
    2947             : 
    2948             :       // Ensure that copy-on-write backing store is writable.
    2949        5212 :       if (IsSmiOrObjectElementsKind(elements_kind) &&
    2950             :           store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
    2951             :         elements = effect =
    2952             :             graph()->NewNode(simplified()->EnsureWritableFastElements(),
    2953         168 :                              receiver, elements, effect, control);
    2954        5044 :       } else if (IsGrowStoreMode(store_mode)) {
    2955             :         // Determine the length of the {elements} backing store.
    2956             :         Node* elements_length = effect = graph()->NewNode(
    2957             :             simplified()->LoadField(AccessBuilder::ForFixedArrayLength()),
    2958        2832 :             elements, effect, control);
    2959             : 
    2960             :         // Validate the {index} depending on holeyness:
    2961             :         //
    2962             :         // For HOLEY_*_ELEMENTS the {index} must not exceed the {elements}
    2963             :         // backing store capacity plus the maximum allowed gap, as otherwise
    2964             :         // the (potential) backing store growth would normalize and thus
    2965             :         // the elements kind of the {receiver} would change to slow mode.
    2966             :         //
    2967             :         // For PACKED_*_ELEMENTS the {index} must be within the range
    2968             :         // [0,length+1[ to be valid. In case {index} equals {length},
    2969             :         // the {receiver} will be extended, but kept packed.
    2970             :         Node* limit =
    2971             :             IsHoleyElementsKind(elements_kind)
    2972             :                 ? graph()->NewNode(simplified()->NumberAdd(), elements_length,
    2973         400 :                                    jsgraph()->Constant(JSObject::kMaxGap))
    2974             :                 : graph()->NewNode(simplified()->NumberAdd(), length,
    2975        2432 :                                    jsgraph()->OneConstant());
    2976             :         index = effect =
    2977             :             graph()->NewNode(simplified()->CheckBounds(VectorSlotPair()), index,
    2978        2832 :                              limit, effect, control);
    2979             : 
    2980             :         // Grow {elements} backing store if necessary.
    2981             :         GrowFastElementsMode mode =
    2982             :             IsDoubleElementsKind(elements_kind)
    2983             :                 ? GrowFastElementsMode::kDoubleElements
    2984         944 :                 : GrowFastElementsMode::kSmiOrObjectElements;
    2985             :         elements = effect = graph()->NewNode(
    2986             :             simplified()->MaybeGrowFastElements(mode, VectorSlotPair()),
    2987        2832 :             receiver, elements, index, elements_length, effect, control);
    2988             : 
    2989             :         // If we didn't grow {elements}, it might still be COW, in which case we
    2990             :         // copy it now.
    2991         944 :         if (IsSmiOrObjectElementsKind(elements_kind) &&
    2992             :             store_mode == STORE_AND_GROW_NO_TRANSITION_HANDLE_COW) {
    2993             :           elements = effect =
    2994             :               graph()->NewNode(simplified()->EnsureWritableFastElements(),
    2995         799 :                                receiver, elements, effect, control);
    2996             :         }
    2997             : 
    2998             :         // Also update the "length" property if {receiver} is a JSArray.
    2999         944 :         if (receiver_is_jsarray) {
    3000             :           Node* check =
    3001         926 :               graph()->NewNode(simplified()->NumberLessThan(), index, length);
    3002         926 :           Node* branch = graph()->NewNode(common()->Branch(), check, control);
    3003             : 
    3004         926 :           Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    3005             :           Node* etrue = effect;
    3006             :           {
    3007             :             // We don't need to do anything, the {index} is within
    3008             :             // the valid bounds for the JSArray {receiver}.
    3009             :           }
    3010             : 
    3011         926 :           Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    3012             :           Node* efalse = effect;
    3013             :           {
    3014             :             // Update the JSArray::length field. Since this is observable,
    3015             :             // there must be no other check after this.
    3016             :             Node* new_length = graph()->NewNode(
    3017        1852 :                 simplified()->NumberAdd(), index, jsgraph()->OneConstant());
    3018             :             efalse = graph()->NewNode(
    3019             :                 simplified()->StoreField(
    3020         926 :                     AccessBuilder::ForJSArrayLength(elements_kind)),
    3021        2778 :                 receiver, new_length, efalse, if_false);
    3022             :           }
    3023             : 
    3024         926 :           control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    3025             :           effect =
    3026         926 :               graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
    3027             :         }
    3028             :       }
    3029             : 
    3030             :       // Perform the actual element access.
    3031             :       effect = graph()->NewNode(simplified()->StoreElement(element_access),
    3032        5212 :                                 elements, index, value, effect, control);
    3033             :     }
    3034             :   }
    3035             : 
    3036       22667 :   return ValueEffectControl(value, effect, control);
    3037             : }
    3038             : 
    3039         587 : Node* JSNativeContextSpecialization::BuildIndexedStringLoad(
    3040             :     Node* receiver, Node* index, Node* length, Node** effect, Node** control,
    3041         192 :     KeyedAccessLoadMode load_mode) {
    3042         635 :   if (load_mode == LOAD_IGNORE_OUT_OF_BOUNDS &&
    3043          48 :       isolate()->IsNoElementsProtectorIntact()) {
    3044             :     dependencies()->DependOnProtector(
    3045          48 :         PropertyCellRef(broker(), factory()->no_elements_protector()));
    3046             : 
    3047             :     // Ensure that the {index} is a valid String length.
    3048             :     index = *effect = graph()->NewNode(
    3049             :         simplified()->CheckBounds(VectorSlotPair()), index,
    3050         192 :         jsgraph()->Constant(String::kMaxLength), *effect, *control);
    3051             : 
    3052             :     // Load the single character string from {receiver} or yield
    3053             :     // undefined if the {index} is not within the valid bounds.
    3054             :     Node* check =
    3055          48 :         graph()->NewNode(simplified()->NumberLessThan(), index, length);
    3056             :     Node* branch =
    3057             :         graph()->NewNode(common()->Branch(BranchHint::kTrue,
    3058             :                                           IsSafetyCheck::kCriticalSafetyCheck),
    3059          96 :                          check, *control);
    3060             : 
    3061          48 :     Node* masked_index = graph()->NewNode(simplified()->PoisonIndex(), index);
    3062             : 
    3063          48 :     Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
    3064             :     Node* etrue;
    3065             :     Node* vtrue = etrue =
    3066             :         graph()->NewNode(simplified()->StringCharCodeAt(), receiver,
    3067          96 :                          masked_index, *effect, if_true);
    3068          48 :     vtrue = graph()->NewNode(simplified()->StringFromSingleCharCode(), vtrue);
    3069             : 
    3070          48 :     Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
    3071          48 :     Node* vfalse = jsgraph()->UndefinedConstant();
    3072             : 
    3073          96 :     *control = graph()->NewNode(common()->Merge(2), if_true, if_false);
    3074             :     *effect =
    3075         144 :         graph()->NewNode(common()->EffectPhi(2), etrue, *effect, *control);
    3076             :     return graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
    3077         144 :                             vtrue, vfalse, *control);
    3078             :   } else {
    3079             :     // Ensure that {index} is less than {receiver} length.
    3080             :     index = *effect =
    3081             :         graph()->NewNode(simplified()->CheckBounds(VectorSlotPair()), index,
    3082        1617 :                          length, *effect, *control);
    3083             : 
    3084         539 :     Node* masked_index = graph()->NewNode(simplified()->PoisonIndex(), index);
    3085             : 
    3086             :     // Return the character from the {receiver} as single character string.
    3087             :     Node* value = *effect =
    3088             :         graph()->NewNode(simplified()->StringCharCodeAt(), receiver,
    3089        1617 :                          masked_index, *effect, *control);
    3090         539 :     value = graph()->NewNode(simplified()->StringFromSingleCharCode(), value);
    3091         539 :     return value;
    3092             :   }
    3093             : }
    3094             : 
    3095        2297 : Node* JSNativeContextSpecialization::BuildExtendPropertiesBackingStore(
    3096       18612 :     const MapRef& map, Node* properties, Node* effect, Node* control) {
    3097             :   // TODO(bmeurer/jkummerow): Property deletions can undo map transitions
    3098             :   // while keeping the backing store around, meaning that even though the
    3099             :   // map might believe that objects have no unused property fields, there
    3100             :   // might actually be some. It would be nice to not create a new backing
    3101             :   // store in that case (i.e. when properties->length() >= new_length).
    3102             :   // However, introducing branches and Phi nodes here would make it more
    3103             :   // difficult for escape analysis to get rid of the backing stores used
    3104             :   // for intermediate states of chains of property additions. That makes
    3105             :   // it unclear what the best approach is here.
    3106             :   DCHECK_EQ(0, map.UnusedPropertyFields());
    3107             :   // Compute the length of the old {properties} and the new properties.
    3108        2297 :   int length = map.NextFreePropertyIndex() - map.GetInObjectProperties();
    3109        2297 :   int new_length = length + JSObject::kFieldsAdded;
    3110             :   // Collect the field values from the {properties}.
    3111             :   ZoneVector<Node*> values(zone());
    3112        2297 :   values.reserve(new_length);
    3113      785720 :   for (int i = 0; i < length; ++i) {
    3114             :     Node* value = effect = graph()->NewNode(
    3115      783423 :         simplified()->LoadField(AccessBuilder::ForFixedArraySlot(i)),
    3116     2350269 :         properties, effect, control);
    3117      783423 :     values.push_back(value);
    3118             :   }
    3119             :   // Initialize the new fields to undefined.
    3120        6891 :   for (int i = 0; i < JSObject::kFieldsAdded; ++i) {
    3121       13782 :     values.push_back(jsgraph()->UndefinedConstant());
    3122             :   }
    3123             : 
    3124             :   // Compute new length and hash.
    3125             :   Node* hash;
    3126        2297 :   if (length == 0) {
    3127             :     hash = graph()->NewNode(
    3128             :         common()->Select(MachineRepresentation::kTaggedSigned),
    3129             :         graph()->NewNode(simplified()->ObjectIsSmi(), properties), properties,
    3130         472 :         jsgraph()->SmiConstant(PropertyArray::kNoHashSentinel));
    3131             :     hash = effect = graph()->NewNode(common()->TypeGuard(Type::SignedSmall()),
    3132         236 :                                      hash, effect, control);
    3133             :     hash =
    3134             :         graph()->NewNode(simplified()->NumberShiftLeft(), hash,
    3135         472 :                          jsgraph()->Constant(PropertyArray::HashField::kShift));
    3136             :   } else {
    3137             :     hash = effect = graph()->NewNode(
    3138             :         simplified()->LoadField(AccessBuilder::ForPropertyArrayLengthAndHash()),
    3139        6183 :         properties, effect, control);
    3140             :     hash =
    3141             :         graph()->NewNode(simplified()->NumberBitwiseAnd(), hash,
    3142        4122 :                          jsgraph()->Constant(PropertyArray::HashField::kMask));
    3143             :   }
    3144             :   Node* new_length_and_hash = graph()->NewNode(
    3145        6891 :       simplified()->NumberBitwiseOr(), jsgraph()->Constant(new_length), hash);
    3146             :   // TDOO(jarin): Fix the typer to infer tighter bound for NumberBitwiseOr.
    3147             :   new_length_and_hash = effect =
    3148             :       graph()->NewNode(common()->TypeGuard(Type::SignedSmall()),
    3149        2297 :                        new_length_and_hash, effect, control);
    3150             : 
    3151             :   // Allocate and initialize the new properties.
    3152             :   AllocationBuilder a(jsgraph(), effect, control);
    3153             :   a.Allocate(PropertyArray::SizeFor(new_length), NOT_TENURED,
    3154        2297 :              Type::OtherInternal());
    3155        2297 :   a.Store(AccessBuilder::ForMap(), jsgraph()->PropertyArrayMapConstant());
    3156        2297 :   a.Store(AccessBuilder::ForPropertyArrayLengthAndHash(), new_length_and_hash);
    3157      792611 :   for (int i = 0; i < new_length; ++i) {
    3158     1580628 :     a.Store(AccessBuilder::ForFixedArraySlot(i), values[i]);
    3159             :   }
    3160        2297 :   return a.Finish();
    3161             : }
    3162             : 
    3163         100 : Node* JSNativeContextSpecialization::BuildCheckEqualsName(Handle<Name> name,
    3164             :                                                           Node* value,
    3165             :                                                           Node* effect,
    3166         100 :                                                           Node* control) {
    3167             :   DCHECK(name->IsUniqueName());
    3168             :   Operator const* const op =
    3169         200 :       name->IsSymbol() ? simplified()->CheckEqualsSymbol()
    3170         200 :                        : simplified()->CheckEqualsInternalizedString();
    3171             :   return graph()->NewNode(op, jsgraph()->HeapConstant(name), value, effect,
    3172         200 :                           control);
    3173             : }
    3174             : 
    3175        3438 : bool JSNativeContextSpecialization::CanTreatHoleAsUndefined(
    3176       14494 :     MapHandles const& receiver_maps) {
    3177             :   // Check if all {receiver_maps} have one of the initial Array.prototype
    3178             :   // or Object.prototype objects as their prototype (in any of the current
    3179             :   // native contexts, as the global Array protector works isolate-wide).
    3180       10782 :   for (Handle<Map> map : receiver_maps) {
    3181             :     MapRef receiver_map(broker(), map);
    3182             :     // TODO(neis): Remove SerializePrototype call once brokerization is
    3183             :     // complete.
    3184        4264 :     receiver_map.SerializePrototype();
    3185        4264 :     ObjectRef receiver_prototype = receiver_map.prototype();
    3186       12792 :     if (!receiver_prototype.IsJSObject() ||
    3187       17056 :         !broker()->IsArrayOrObjectPrototype(receiver_prototype.AsJSObject())) {
    3188         358 :       return false;
    3189             :     }
    3190             :   }
    3191             : 
    3192             :   // Check if the array prototype chain is intact.
    3193        3080 :   if (!isolate()->IsNoElementsProtectorIntact()) return false;
    3194             : 
    3195             :   dependencies()->DependOnProtector(
    3196        2983 :       PropertyCellRef(broker(), factory()->no_elements_protector()));
    3197        2983 :   return true;
    3198             : }
    3199             : 
    3200             : namespace {
    3201      165698 : void TryUpdateThenDropDeprecated(Isolate* isolate, MapHandles* maps) {
    3202      517946 :   for (auto it = maps->begin(); it != maps->end();) {
    3203      373100 :     if (Map::TryUpdate(isolate, *it).ToHandle(&*it)) {
    3204             :       DCHECK(!(*it)->is_deprecated());
    3205             :       ++it;
    3206             :     } else {
    3207           0 :       it = maps->erase(it);
    3208             :     }
    3209             :   }
    3210      165698 : }
    3211             : }  // namespace
    3212             : 
    3213      563240 : bool JSNativeContextSpecialization::ExtractReceiverMaps(
    3214      176795 :     Node* receiver, Node* effect, FeedbackNexus const& nexus,
    3215             :     MapHandles* receiver_maps) {
    3216             :   DCHECK(receiver_maps->empty());
    3217      563240 :   if (nexus.IsUninitialized()) return true;
    3218             : 
    3219             :   // See if we can infer a concrete type for the {receiver}. Solely relying on
    3220             :   // the inference is not safe for keyed stores, because we would potentially
    3221             :   // miss out on transitions that need to be performed.
    3222             :   {
    3223             :     FeedbackSlotKind kind = nexus.kind();
    3224             :     bool use_inference =
    3225      176795 :         !IsKeyedStoreICKind(kind) && !IsStoreInArrayLiteralICKind(kind);
    3226      176795 :     if (use_inference && InferReceiverMaps(receiver, effect, receiver_maps)) {
    3227       75617 :       TryUpdateThenDropDeprecated(isolate(), receiver_maps);
    3228       75617 :       return true;
    3229             :     }
    3230             :   }
    3231             : 
    3232             :   // Try to extract some maps from the {nexus}.
    3233      101178 :   if (nexus.ExtractMaps(receiver_maps) != 0) {
    3234             :     // Try to filter impossible candidates based on inferred root map.
    3235             :     Handle<Map> receiver_map;
    3236      180162 :     if (InferReceiverRootMap(receiver).ToHandle(&receiver_map)) {
    3237             :       DCHECK(!receiver_map->is_abandoned_prototype_map());
    3238             :       Isolate* isolate = this->isolate();
    3239             :       receiver_maps->erase(
    3240             :           std::remove_if(receiver_maps->begin(), receiver_maps->end(),
    3241        5819 :                          [receiver_map, isolate](const Handle<Map>& map) {
    3242       17443 :                            return map->is_abandoned_prototype_map() ||
    3243       17429 :                                   map->FindRootMap(isolate) != *receiver_map;
    3244        5819 :                          }),
    3245       11426 :           receiver_maps->end());
    3246             :     }
    3247       90081 :     TryUpdateThenDropDeprecated(isolate(), receiver_maps);
    3248             :     return true;
    3249             :   }
    3250             : 
    3251             :   return false;
    3252             : }
    3253             : 
    3254      167350 : bool JSNativeContextSpecialization::InferReceiverMaps(
    3255      233152 :     Node* receiver, Node* effect, MapHandles* receiver_maps) {
    3256             :   ZoneHandleSet<Map> maps;
    3257             :   NodeProperties::InferReceiverMapsResult result =
    3258      167350 :       NodeProperties::InferReceiverMaps(broker(), receiver, effect, &maps);
    3259      167350 :   if (result == NodeProperties::kReliableReceiverMaps) {
    3260       59263 :     for (size_t i = 0; i < maps.size(); ++i) {
    3261       40746 :       receiver_maps->push_back(maps[i]);
    3262             :     }
    3263             :     return true;
    3264      148833 :   } else if (result == NodeProperties::kUnreliableReceiverMaps) {
    3265             :     // For untrusted receiver maps, we can still use the information
    3266             :     // if the maps are stable.
    3267      180899 :     for (size_t i = 0; i < maps.size(); ++i) {
    3268             :       MapRef map(broker(), maps[i]);
    3269       65802 :       if (!map.is_stable()) return false;
    3270             :     }
    3271      172144 :     for (size_t i = 0; i < maps.size(); ++i) {
    3272      115044 :       receiver_maps->push_back(maps[i]);
    3273             :     }
    3274             :     return true;
    3275             :   }
    3276             :   return false;
    3277             : }
    3278             : 
    3279       90081 : MaybeHandle<Map> JSNativeContextSpecialization::InferReceiverRootMap(
    3280             :     Node* receiver) {
    3281             :   HeapObjectMatcher m(receiver);
    3282       90081 :   if (m.HasValue()) {
    3283       11070 :     return handle(m.Value()->map()->FindRootMap(isolate()), isolate());
    3284       84546 :   } else if (m.IsJSCreate()) {
    3285             :     HeapObjectMatcher mtarget(m.InputAt(0));
    3286             :     HeapObjectMatcher mnewtarget(m.InputAt(1));
    3287        8249 :     if (mtarget.HasValue() && mnewtarget.HasValue()) {
    3288             :       Handle<JSFunction> constructor =
    3289         186 :           Handle<JSFunction>::cast(mtarget.Value());
    3290         186 :       if (constructor->has_initial_map()) {
    3291         372 :         Handle<Map> initial_map(constructor->initial_map(), isolate());
    3292         186 :         if (initial_map->constructor_or_backpointer() == *mnewtarget.Value()) {
    3293             :           DCHECK_EQ(*initial_map, initial_map->FindRootMap(isolate()));
    3294         178 :           return initial_map;
    3295             :         }
    3296             :       }
    3297             :     }
    3298             :   }
    3299       84368 :   return MaybeHandle<Map>();
    3300             : }
    3301             : 
    3302     1386520 : Graph* JSNativeContextSpecialization::graph() const {
    3303     1386706 :   return jsgraph()->graph();
    3304             : }
    3305             : 
    3306      980125 : Isolate* JSNativeContextSpecialization::isolate() const {
    3307      980125 :   return jsgraph()->isolate();
    3308             : }
    3309             : 
    3310           0 : Factory* JSNativeContextSpecialization::factory() const {
    3311           0 :   return isolate()->factory();
    3312             : }
    3313             : 
    3314      121298 : CommonOperatorBuilder* JSNativeContextSpecialization::common() const {
    3315      121298 :   return jsgraph()->common();
    3316             : }
    3317             : 
    3318        6280 : JSOperatorBuilder* JSNativeContextSpecialization::javascript() const {
    3319        6280 :   return jsgraph()->javascript();
    3320             : }
    3321             : 
    3322     1074282 : SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const {
    3323     1075264 :   return jsgraph()->simplified();
    3324             : }
    3325             : 
    3326             : #undef V8_TYPED_ARRAY_MAX_SIZE_IN_HEAP
    3327             : 
    3328             : }  // namespace compiler
    3329             : }  // namespace internal
    3330      178779 : }  // namespace v8

Generated by: LCOV version 1.10