LCOV - code coverage report
Current view: top level - src/compiler - js-native-context-specialization.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1171 1214 96.5 %
Date: 2019-04-19 Functions: 63 69 91.3 %

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

Generated by: LCOV version 1.10