LCOV - code coverage report
Current view: top level - src - lookup.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 377 408 92.4 %
Date: 2017-10-20 Functions: 44 48 91.7 %

          Line data    Source code
       1             : // Copyright 2014 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/lookup.h"
       6             : 
       7             : #include "src/bootstrapper.h"
       8             : #include "src/deoptimizer.h"
       9             : #include "src/elements.h"
      10             : #include "src/field-type.h"
      11             : #include "src/isolate-inl.h"
      12             : 
      13             : namespace v8 {
      14             : namespace internal {
      15             : 
      16             : // static
      17        3816 : LookupIterator LookupIterator::PropertyOrElement(
      18             :     Isolate* isolate, Handle<Object> receiver, Handle<Object> key,
      19             :     bool* success, Handle<JSReceiver> holder, Configuration configuration) {
      20        3816 :   uint32_t index = 0;
      21        3816 :   if (key->ToArrayIndex(&index)) {
      22        2100 :     *success = true;
      23        2100 :     return LookupIterator(isolate, receiver, index, holder, configuration);
      24             :   }
      25             : 
      26             :   Handle<Name> name;
      27        3432 :   *success = Object::ToName(isolate, key).ToHandle(&name);
      28        1716 :   if (!*success) {
      29             :     DCHECK(isolate->has_pending_exception());
      30             :     // Return an unusable dummy.
      31          10 :     return LookupIterator(receiver, isolate->factory()->empty_string());
      32             :   }
      33             : 
      34        1706 :   if (name->AsArrayIndex(&index)) {
      35           0 :     LookupIterator it(isolate, receiver, index, holder, configuration);
      36             :     // Here we try to avoid having to rebuild the string later
      37             :     // by storing it on the indexed LookupIterator.
      38           0 :     it.name_ = name;
      39           0 :     return it;
      40             :   }
      41             : 
      42        1706 :   return LookupIterator(receiver, name, holder, configuration);
      43             : }
      44             : 
      45             : // static
      46    70376587 : LookupIterator LookupIterator::PropertyOrElement(Isolate* isolate,
      47             :                                                  Handle<Object> receiver,
      48             :                                                  Handle<Object> key,
      49             :                                                  bool* success,
      50             :                                                  Configuration configuration) {
      51             :   // TODO(mslekova): come up with better way to avoid duplication
      52    70376587 :   uint32_t index = 0;
      53    70376588 :   if (key->ToArrayIndex(&index)) {
      54    26396852 :     *success = true;
      55    26396852 :     return LookupIterator(isolate, receiver, index, configuration);
      56             :   }
      57             : 
      58             :   Handle<Name> name;
      59    87959471 :   *success = Object::ToName(isolate, key).ToHandle(&name);
      60    43979735 :   if (!*success) {
      61             :     DCHECK(isolate->has_pending_exception());
      62             :     // Return an unusable dummy.
      63          33 :     return LookupIterator(receiver, isolate->factory()->empty_string());
      64             :   }
      65             : 
      66    43979702 :   if (name->AsArrayIndex(&index)) {
      67      317996 :     LookupIterator it(isolate, receiver, index, configuration);
      68             :     // Here we try to avoid having to rebuild the string later
      69             :     // by storing it on the indexed LookupIterator.
      70      317996 :     it.name_ = name;
      71      317996 :     return it;
      72             :   }
      73             : 
      74    43661706 :   return LookupIterator(receiver, name, configuration);
      75             : }
      76             : 
      77             : // static
      78     4304546 : LookupIterator LookupIterator::ForTransitionHandler(
      79             :     Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
      80             :     Handle<Object> value, MaybeHandle<Object> handler,
      81             :     Handle<Map> transition_map) {
      82     4304546 :   if (handler.is_null()) return LookupIterator(receiver, name);
      83             : 
      84        3084 :   PropertyDetails details = PropertyDetails::Empty();
      85             :   bool has_property;
      86        3084 :   if (transition_map->is_dictionary_map()) {
      87             :     details = PropertyDetails(kData, NONE, PropertyCellType::kNoCell);
      88             :     has_property = false;
      89             :   } else {
      90        3084 :     details = transition_map->GetLastDescriptorDetails();
      91             :     has_property = true;
      92             :   }
      93             :   LookupIterator it(isolate, receiver, name, transition_map, details,
      94        3084 :                     has_property);
      95             : 
      96        3084 :   if (!transition_map->is_dictionary_map()) {
      97             :     PropertyConstness new_constness = kConst;
      98             :     if (FLAG_track_constant_fields) {
      99             :       if (it.constness() == kConst) {
     100             :         DCHECK_EQ(kData, it.property_details_.kind());
     101             :         // Check that current value matches new value otherwise we should make
     102             :         // the property mutable.
     103             :         if (!it.IsConstFieldValueEqualTo(*value)) new_constness = kMutable;
     104             :       }
     105             :     } else {
     106             :       new_constness = kMutable;
     107             :     }
     108             : 
     109             :     int descriptor_number = transition_map->LastAdded();
     110             :     Handle<Map> new_map = Map::PrepareForDataProperty(
     111        3084 :         transition_map, descriptor_number, new_constness, value);
     112             :     // Reload information; this is no-op if nothing changed.
     113             :     it.property_details_ =
     114        3084 :         new_map->instance_descriptors()->GetDetails(descriptor_number);
     115        3084 :     it.transition_ = new_map;
     116             :   }
     117        3084 :   return it;
     118             : }
     119             : 
     120        3084 : LookupIterator::LookupIterator(Isolate* isolate, Handle<Object> receiver,
     121             :                                Handle<Name> name, Handle<Map> transition_map,
     122             :                                PropertyDetails details, bool has_property)
     123             :     : configuration_(DEFAULT),
     124             :       state_(TRANSITION),
     125             :       has_property_(has_property),
     126             :       interceptor_state_(InterceptorState::kUninitialized),
     127             :       property_details_(details),
     128             :       isolate_(isolate),
     129             :       name_(name),
     130             :       transition_(transition_map),
     131             :       receiver_(receiver),
     132             :       initial_holder_(GetRoot(isolate, receiver)),
     133             :       index_(kMaxUInt32),
     134        9252 :       number_(static_cast<uint32_t>(DescriptorArray::kNotFound)) {
     135        3084 :   holder_ = initial_holder_;
     136        3084 : }
     137             : 
     138             : template <bool is_element>
     139   311922834 : void LookupIterator::Start() {
     140             :   DisallowHeapAllocation no_gc;
     141             : 
     142   311922834 :   has_property_ = false;
     143   311922834 :   state_ = NOT_FOUND;
     144   311922834 :   holder_ = initial_holder_;
     145             : 
     146             :   JSReceiver* holder = *holder_;
     147             :   Map* map = holder->map();
     148             : 
     149   311922834 :   state_ = LookupInHolder<is_element>(map, holder);
     150   623845601 :   if (IsFound()) return;
     151             : 
     152   179131044 :   NextInternal<is_element>(map, holder);
     153             : }
     154             : 
     155             : template void LookupIterator::Start<true>();
     156             : template void LookupIterator::Start<false>();
     157             : 
     158    20181269 : void LookupIterator::Next() {
     159             :   DCHECK_NE(JSPROXY, state_);
     160             :   DCHECK_NE(TRANSITION, state_);
     161             :   DisallowHeapAllocation no_gc;
     162     6988776 :   has_property_ = false;
     163             : 
     164             :   JSReceiver* holder = *holder_;
     165             :   Map* map = holder->map();
     166             : 
     167     6988776 :   if (map->IsSpecialReceiverMap()) {
     168             :     state_ = IsElement() ? LookupInSpecialHolder<true>(map, holder)
     169     6767140 :                          : LookupInSpecialHolder<false>(map, holder);
     170    13755916 :     if (IsFound()) return;
     171             :   }
     172             : 
     173      115434 :   IsElement() ? NextInternal<true>(map, holder)
     174    12735272 :               : NextInternal<false>(map, holder);
     175             : }
     176             : 
     177             : template <bool is_element>
     178   185556407 : void LookupIterator::NextInternal(Map* map, JSReceiver* holder) {
     179   204752924 :   do {
     180             :     JSReceiver* maybe_holder = NextHolder(map);
     181   370409570 :     if (maybe_holder == nullptr) {
     182   165656648 :       if (interceptor_state_ == InterceptorState::kSkipNonMasking) {
     183           0 :         RestartLookupForNonMaskingInterceptors<is_element>();
     184           0 :         return;
     185             :       }
     186   165656498 :       state_ = NOT_FOUND;
     187   262296775 :       if (holder != *holder_) holder_ = handle(holder, isolate_);
     188             :       return;
     189             :     }
     190             :     holder = maybe_holder;
     191             :     map = holder->map();
     192   204752922 :     state_ = LookupInHolder<is_element>(map, holder);
     193             :   } while (!IsFound());
     194             : 
     195    39799522 :   holder_ = handle(holder, isolate_);
     196             : }
     197             : 
     198             : template <bool is_element>
     199     4703202 : void LookupIterator::RestartInternal(InterceptorState interceptor_state) {
     200     4703202 :   interceptor_state_ = interceptor_state;
     201     4703202 :   property_details_ = PropertyDetails::Empty();
     202     4703202 :   number_ = static_cast<uint32_t>(DescriptorArray::kNotFound);
     203     4703202 :   Start<is_element>();
     204     4703202 : }
     205             : 
     206             : template void LookupIterator::RestartInternal<true>(InterceptorState);
     207             : template void LookupIterator::RestartInternal<false>(InterceptorState);
     208             : 
     209             : // static
     210      165137 : Handle<JSReceiver> LookupIterator::GetRootForNonJSReceiver(
     211             :     Isolate* isolate, Handle<Object> receiver, uint32_t index) {
     212             :   // Strings are the only objects with properties (only elements) directly on
     213             :   // the wrapper. Hence we can skip generating the wrapper for all other cases.
     214      185182 :   if (index != kMaxUInt32 && receiver->IsString() &&
     215        4503 :       index < static_cast<uint32_t>(String::cast(*receiver)->length())) {
     216             :     // TODO(verwaest): Speed this up. Perhaps use a cached wrapper on the native
     217             :     // context, ensuring that we don't leak it into JS?
     218        1212 :     Handle<JSFunction> constructor = isolate->string_function();
     219        1212 :     Handle<JSObject> result = isolate->factory()->NewJSObject(constructor);
     220        1212 :     Handle<JSValue>::cast(result)->set_value(*receiver);
     221        1212 :     return result;
     222             :   }
     223             :   auto root =
     224      163925 :       handle(receiver->GetPrototypeChainRootMap(isolate)->prototype(), isolate);
     225      163925 :   if (root->IsNull(isolate)) {
     226             :     unsigned int magic = 0xbbbbbbbb;
     227           0 :     isolate->PushStackTraceAndDie(magic, *receiver, nullptr, magic);
     228             :   }
     229             :   return Handle<JSReceiver>::cast(root);
     230             : }
     231             : 
     232             : 
     233           0 : Handle<Map> LookupIterator::GetReceiverMap() const {
     234           0 :   if (receiver_->IsNumber()) return factory()->heap_number_map();
     235           0 :   return handle(Handle<HeapObject>::cast(receiver_)->map(), isolate_);
     236             : }
     237             : 
     238     5814652 : bool LookupIterator::HasAccess() const {
     239             :   DCHECK_EQ(ACCESS_CHECK, state_);
     240             :   return isolate_->MayAccess(handle(isolate_->context()),
     241    11629304 :                              GetHolder<JSObject>());
     242             : }
     243             : 
     244             : template <bool is_element>
     245    10528352 : void LookupIterator::ReloadPropertyInformation() {
     246    10528352 :   state_ = BEFORE_PROPERTY;
     247    10528352 :   interceptor_state_ = InterceptorState::kUninitialized;
     248    10528352 :   state_ = LookupInHolder<is_element>(holder_->map(), *holder_);
     249             :   DCHECK(IsFound() || !holder_->HasFastProperties());
     250    10528353 : }
     251             : 
     252     3615441 : void LookupIterator::InternalUpdateProtector() {
     253     3615441 :   if (isolate_->bootstrapper()->IsActive()) return;
     254             : 
     255      215759 :   if (*name_ == heap()->constructor_string()) {
     256      195044 :     if (!isolate_->IsArraySpeciesLookupChainIntact()) return;
     257             :     // Setting the constructor property could change an instance's @@species
     258      184741 :     if (holder_->IsJSArray()) {
     259             :       isolate_->CountUsage(
     260          60 :           v8::Isolate::UseCounterFeature::kArrayInstanceConstructorModified);
     261          60 :       isolate_->InvalidateArraySpeciesProtector();
     262      184681 :     } else if (holder_->map()->is_prototype_map()) {
     263             :       DisallowHeapAllocation no_gc;
     264             :       // Setting the constructor of Array.prototype of any realm also needs
     265             :       // to invalidate the species protector
     266       82695 :       if (isolate_->IsInAnyContext(*holder_,
     267       82695 :                                    Context::INITIAL_ARRAY_PROTOTYPE_INDEX)) {
     268             :         isolate_->CountUsage(v8::Isolate::UseCounterFeature::
     269           0 :                                  kArrayPrototypeConstructorModified);
     270           0 :         isolate_->InvalidateArraySpeciesProtector();
     271             :       }
     272             :     }
     273       20715 :   } else if (*name_ == heap()->species_symbol()) {
     274        4429 :     if (!isolate_->IsArraySpeciesLookupChainIntact()) return;
     275             :     // Setting the Symbol.species property of any Array constructor invalidates
     276             :     // the species protector
     277        4334 :     if (isolate_->IsInAnyContext(*holder_, Context::ARRAY_FUNCTION_INDEX)) {
     278             :       isolate_->CountUsage(
     279          21 :           v8::Isolate::UseCounterFeature::kArraySpeciesModified);
     280          21 :       isolate_->InvalidateArraySpeciesProtector();
     281             :     }
     282       16286 :   } else if (*name_ == heap()->is_concat_spreadable_symbol()) {
     283         990 :     if (!isolate_->IsIsConcatSpreadableLookupChainIntact()) return;
     284          58 :     isolate_->InvalidateIsConcatSpreadableProtector();
     285       15296 :   } else if (*name_ == heap()->iterator_symbol()) {
     286       15296 :     if (!isolate_->IsArrayIteratorLookupChainIntact()) return;
     287       12726 :     if (holder_->IsJSArray()) {
     288          46 :       isolate_->InvalidateArrayIteratorProtector();
     289             :     }
     290             :   }
     291             : }
     292             : 
     293    19483639 : void LookupIterator::PrepareForDataProperty(Handle<Object> value) {
     294             :   DCHECK(state_ == DATA || state_ == ACCESSOR);
     295             :   DCHECK(HolderIsReceiverOrHiddenPrototype());
     296             : 
     297             :   Handle<JSObject> holder = GetHolder<JSObject>();
     298             : 
     299     8957445 :   if (IsElement()) {
     300             :     ElementsKind kind = holder->GetElementsKind();
     301      880061 :     ElementsKind to = value->OptimalElementsKind();
     302      880061 :     if (IsHoleyOrDictionaryElementsKind(kind)) to = GetHoleyElementsKind(to);
     303             :     to = GetMoreGeneralElementsKind(kind, to);
     304             : 
     305      880061 :     if (kind != to) {
     306       17563 :       JSObject::TransitionElementsKind(holder, to);
     307             :     }
     308             : 
     309             :     // Copy the backing store if it is copy-on-write.
     310      880061 :     if (IsSmiOrObjectElementsKind(to)) {
     311      104465 :       JSObject::EnsureWritableFastElements(holder);
     312             :     }
     313     8945786 :     return;
     314             :   }
     315             : 
     316     8077384 :   if (holder->IsJSGlobalObject()) {
     317             :     Handle<GlobalDictionary> dictionary(
     318             :         JSGlobalObject::cast(*holder)->global_dictionary());
     319             :     Handle<PropertyCell> cell(dictionary->CellAt(dictionary_entry()));
     320     2296692 :     property_details_ = cell->property_details();
     321             :     PropertyCell::PrepareForValue(dictionary, dictionary_entry(), value,
     322     2296692 :                                   property_details_);
     323             :     return;
     324             :   }
     325     5780692 :   if (!holder->HasFastProperties()) return;
     326             : 
     327             :   PropertyConstness new_constness = kConst;
     328             :   if (FLAG_track_constant_fields) {
     329             :     if (constness() == kConst) {
     330             :       DCHECK_EQ(kData, property_details_.kind());
     331             :       // Check that current value matches new value otherwise we should make
     332             :       // the property mutable.
     333             :       if (!IsConstFieldValueEqualTo(*value)) new_constness = kMutable;
     334             :     }
     335             :   } else {
     336             :     new_constness = kMutable;
     337             :   }
     338             : 
     339     5652787 :   Handle<Map> old_map(holder->map(), isolate_);
     340             :   Handle<Map> new_map = Map::PrepareForDataProperty(
     341     5652787 :       old_map, descriptor_number(), new_constness, value);
     342             : 
     343     5652787 :   if (old_map.is_identical_to(new_map)) {
     344             :     // Update the property details if the representation was None.
     345    11280500 :     if (constness() != new_constness || representation().IsNone()) {
     346             :       property_details_ =
     347      280023 :           new_map->instance_descriptors()->GetDetails(descriptor_number());
     348             :     }
     349             :     return;
     350             :   }
     351             : 
     352       11659 :   JSObject::MigrateToMap(holder, new_map);
     353       11659 :   ReloadPropertyInformation<false>();
     354             : }
     355             : 
     356             : 
     357       36624 : void LookupIterator::ReconfigureDataProperty(Handle<Object> value,
     358      103223 :                                              PropertyAttributes attributes) {
     359             :   DCHECK(state_ == DATA || state_ == ACCESSOR);
     360             :   DCHECK(HolderIsReceiverOrHiddenPrototype());
     361             :   Handle<JSObject> holder = GetHolder<JSObject>();
     362       36624 :   if (IsElement()) {
     363             :     DCHECK(!holder->HasFixedTypedArrayElements());
     364             :     DCHECK(attributes != NONE || !holder->HasFastElements());
     365             :     Handle<FixedArrayBase> elements(holder->elements());
     366       21434 :     holder->GetElementsAccessor()->Reconfigure(holder, elements, number_, value,
     367       21434 :                                                attributes);
     368       21434 :     ReloadPropertyInformation<true>();
     369       15190 :   } else if (holder->HasFastProperties()) {
     370       13600 :     Handle<Map> old_map(holder->map(), isolate_);
     371             :     Handle<Map> new_map = Map::ReconfigureExistingProperty(
     372       13600 :         old_map, descriptor_number(), i::kData, attributes);
     373             :     // Force mutable to avoid changing constant value by reconfiguring
     374             :     // kData -> kAccessor -> kData.
     375             :     new_map = Map::PrepareForDataProperty(new_map, descriptor_number(),
     376       13600 :                                           kMutable, value);
     377       13600 :     JSObject::MigrateToMap(holder, new_map);
     378       13600 :     ReloadPropertyInformation<false>();
     379             :   }
     380             : 
     381       51814 :   if (!IsElement() && !holder->HasFastProperties()) {
     382             :     PropertyDetails details(kData, attributes, PropertyCellType::kMutable);
     383        1590 :     if (holder->IsJSGlobalObject()) {
     384             :       Handle<GlobalDictionary> dictionary(
     385             :           JSGlobalObject::cast(*holder)->global_dictionary());
     386             : 
     387             :       Handle<PropertyCell> cell = PropertyCell::PrepareForValue(
     388         405 :           dictionary, dictionary_entry(), value, details);
     389         405 :       cell->set_value(*value);
     390         405 :       property_details_ = cell->property_details();
     391             :     } else {
     392             :       Handle<NameDictionary> dictionary(holder->property_dictionary());
     393             :       PropertyDetails original_details =
     394             :           dictionary->DetailsAt(dictionary_entry());
     395             :       int enumeration_index = original_details.dictionary_index();
     396             :       DCHECK_GT(enumeration_index, 0);
     397             :       details = details.set_index(enumeration_index);
     398        1185 :       dictionary->SetEntry(dictionary_entry(), *name(), *value, details);
     399        1185 :       property_details_ = details;
     400             :     }
     401        1590 :     state_ = DATA;
     402             :   }
     403             : 
     404       36624 :   WriteDataValue(value, true);
     405             : 
     406             : #if VERIFY_HEAP
     407             :   if (FLAG_verify_heap) {
     408             :     holder->JSObjectVerify();
     409             :   }
     410             : #endif
     411       36624 : }
     412             : 
     413             : // Can only be called when the receiver is a JSObject. JSProxy has to be handled
     414             : // via a trap. Adding properties to primitive values is not observable.
     415             : // Returns true if a new transition has been created, or false if an existing
     416             : // transition was followed.
     417    36905837 : bool LookupIterator::PrepareTransitionToDataProperty(
     418             :     Handle<JSObject> receiver, Handle<Object> value,
     419    36302730 :     PropertyAttributes attributes, Object::StoreFromKeyed store_mode) {
     420             :   DCHECK(receiver.is_identical_to(GetStoreTarget()));
     421    36905837 :   if (state_ == TRANSITION) return false;
     422             : 
     423    72605460 :   if (!IsElement() && name()->IsPrivate()) {
     424     2864385 :     attributes = static_cast<PropertyAttributes>(attributes | DONT_ENUM);
     425             :   }
     426             : 
     427             :   DCHECK(state_ != LookupIterator::ACCESSOR ||
     428             :          (GetAccessors()->IsAccessorInfo() &&
     429             :           AccessorInfo::cast(*GetAccessors())->is_special_data_property()));
     430             :   DCHECK_NE(INTEGER_INDEXED_EXOTIC, state_);
     431             :   DCHECK(state_ == NOT_FOUND || !HolderIsReceiverOrHiddenPrototype());
     432             : 
     433    36302732 :   Handle<Map> map(receiver->map(), isolate_);
     434             : 
     435             :   // Dictionary maps can always have additional data properties.
     436    36302733 :   if (map->is_dictionary_map()) {
     437    15600457 :     state_ = TRANSITION;
     438    15600457 :     if (map->IsJSGlobalObjectMap()) {
     439             :       // Install a property cell.
     440             :       Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(receiver);
     441             :       int entry;
     442             :       Handle<PropertyCell> cell = JSGlobalObject::EnsureEmptyPropertyCell(
     443     7166316 :           global, name(), PropertyCellType::kUninitialized, &entry);
     444             :       Handle<GlobalDictionary> dictionary(global->global_dictionary(),
     445     7166316 :                                           isolate_);
     446             :       DCHECK(cell->value()->IsTheHole(isolate_));
     447             :       DCHECK(!value->IsTheHole(isolate_));
     448     7166316 :       transition_ = cell;
     449             :       // Assign an enumeration index to the property and update
     450             :       // SetNextEnumerationIndex.
     451             :       int index = dictionary->NextEnumerationIndex();
     452     7166316 :       dictionary->SetNextEnumerationIndex(index + 1);
     453             :       property_details_ = PropertyDetails(
     454     7166316 :           kData, attributes, PropertyCellType::kUninitialized, index);
     455             :       PropertyCellType new_type =
     456     7166316 :           PropertyCell::UpdatedType(cell, value, property_details_);
     457     7166316 :       property_details_ = property_details_.set_cell_type(new_type);
     458             :       cell->set_property_details(property_details_);
     459     7166316 :       number_ = entry;
     460     7166316 :       has_property_ = true;
     461             :     } else {
     462             :       // Don't set enumeration index (it will be set during value store).
     463             :       property_details_ =
     464     8434141 :           PropertyDetails(kData, attributes, PropertyCellType::kNoCell);
     465     8434141 :       transition_ = map;
     466             :     }
     467             :     return false;
     468             :   }
     469             : 
     470             :   bool created_new_map;
     471             :   Handle<Map> transition = Map::TransitionToDataProperty(
     472             :       map, name_, value, attributes, kDefaultFieldConstness, store_mode,
     473    20702276 :       &created_new_map);
     474    20702276 :   state_ = TRANSITION;
     475    20702276 :   transition_ = transition;
     476             : 
     477    20702276 :   if (transition->is_dictionary_map()) {
     478             :     // Don't set enumeration index (it will be set during value store).
     479             :     property_details_ =
     480       26085 :         PropertyDetails(kData, attributes, PropertyCellType::kNoCell);
     481             :   } else {
     482    20676192 :     property_details_ = transition->GetLastDescriptorDetails();
     483    20676192 :     has_property_ = true;
     484             :   }
     485    20702277 :   return created_new_map;
     486             : }
     487             : 
     488    36305302 : void LookupIterator::ApplyTransitionToDataProperty(Handle<JSObject> receiver) {
     489             :   DCHECK_EQ(TRANSITION, state_);
     490             : 
     491             :   DCHECK(receiver.is_identical_to(GetStoreTarget()));
     492    36305302 :   holder_ = receiver;
     493    36305304 :   if (receiver->IsJSGlobalObject()) {
     494     7165806 :     state_ = DATA;
     495    36305307 :     return;
     496             :   }
     497             :   Handle<Map> transition = transition_map();
     498    29139498 :   bool simple_transition = transition->GetBackPointer() == receiver->map();
     499    29139495 :   JSObject::MigrateToMap(receiver, transition);
     500             : 
     501    29139500 :   if (simple_transition) {
     502             :     int number = transition->LastAdded();
     503    11369063 :     number_ = static_cast<uint32_t>(number);
     504    11369063 :     property_details_ = transition->GetLastDescriptorDetails();
     505    11369063 :     state_ = DATA;
     506    17770437 :   } else if (receiver->map()->is_dictionary_map()) {
     507             :     Handle<NameDictionary> dictionary(receiver->property_dictionary(),
     508     8460226 :                                       isolate_);
     509             :     int entry;
     510             :     dictionary = NameDictionary::Add(dictionary, name(),
     511             :                                      isolate_->factory()->uninitialized_value(),
     512    16920452 :                                      property_details_, &entry);
     513     8460226 :     receiver->SetProperties(*dictionary);
     514             :     // Reload details containing proper enumeration index value.
     515    16920452 :     property_details_ = dictionary->DetailsAt(entry);
     516     8460226 :     number_ = entry;
     517     8460226 :     has_property_ = true;
     518     8460226 :     state_ = DATA;
     519             : 
     520             :   } else {
     521     9310211 :     ReloadPropertyInformation<false>();
     522             :   }
     523             : }
     524             : 
     525             : 
     526      200852 : void LookupIterator::Delete() {
     527             :   Handle<JSReceiver> holder = Handle<JSReceiver>::cast(holder_);
     528      200852 :   if (IsElement()) {
     529             :     Handle<JSObject> object = Handle<JSObject>::cast(holder);
     530      111661 :     ElementsAccessor* accessor = object->GetElementsAccessor();
     531      111661 :     accessor->Delete(object, number_);
     532             :   } else {
     533             :     bool is_prototype_map = holder->map()->is_prototype_map();
     534             :     RuntimeCallTimerScope stats_scope(
     535             :         isolate_, is_prototype_map
     536             :                       ? &RuntimeCallStats::PrototypeObject_DeleteProperty
     537       89191 :                       : &RuntimeCallStats::Object_DeleteProperty);
     538             : 
     539             :     PropertyNormalizationMode mode =
     540       89191 :         is_prototype_map ? KEEP_INOBJECT_PROPERTIES : CLEAR_INOBJECT_PROPERTIES;
     541             : 
     542       89191 :     if (holder->HasFastProperties()) {
     543             :       JSObject::NormalizeProperties(Handle<JSObject>::cast(holder), mode, 0,
     544       75915 :                                     "DeletingProperty");
     545       75915 :       ReloadPropertyInformation<false>();
     546             :     }
     547       89191 :     JSReceiver::DeleteNormalizedProperty(holder, number_);
     548       89191 :     if (holder->IsJSObject()) {
     549       89185 :       JSObject::ReoptimizeIfPrototype(Handle<JSObject>::cast(holder));
     550             :     }
     551             :   }
     552      200852 :   state_ = NOT_FOUND;
     553      200852 : }
     554             : 
     555      654036 : void LookupIterator::TransitionToAccessorProperty(
     556             :     Handle<Object> getter, Handle<Object> setter,
     557     2480971 :     PropertyAttributes attributes) {
     558             :   DCHECK(!getter->IsNull(isolate_) || !setter->IsNull(isolate_));
     559             :   // Can only be called when the receiver is a JSObject. JSProxy has to be
     560             :   // handled via a trap. Adding properties to primitive values is not
     561             :   // observable.
     562      654036 :   Handle<JSObject> receiver = GetStoreTarget();
     563     1281911 :   if (!IsElement() && name()->IsPrivate()) {
     564          18 :     attributes = static_cast<PropertyAttributes>(attributes | DONT_ENUM);
     565             :   }
     566             : 
     567     1281911 :   if (!IsElement() && !receiver->map()->is_dictionary_map()) {
     568      606689 :     Handle<Map> old_map(receiver->map(), isolate_);
     569             : 
     570      606689 :     if (!holder_.is_identical_to(receiver)) {
     571           0 :       holder_ = receiver;
     572           0 :       state_ = NOT_FOUND;
     573      606689 :     } else if (state_ == INTERCEPTOR) {
     574          36 :       LookupInRegularHolder<false>(*old_map, *holder_);
     575             :     }
     576             :     int descriptor =
     577      606689 :         IsFound() ? static_cast<int>(number_) : DescriptorArray::kNotFound;
     578             : 
     579             :     Handle<Map> new_map = Map::TransitionToAccessorProperty(
     580      606689 :         isolate_, old_map, name_, descriptor, getter, setter, attributes);
     581      606689 :     bool simple_transition = new_map->GetBackPointer() == receiver->map();
     582      606689 :     JSObject::MigrateToMap(receiver, new_map);
     583             : 
     584      606689 :     if (simple_transition) {
     585             :       int number = new_map->LastAdded();
     586       19502 :       number_ = static_cast<uint32_t>(number);
     587       19502 :       property_details_ = new_map->GetLastDescriptorDetails();
     588       19502 :       state_ = ACCESSOR;
     589       19502 :       return;
     590             :     }
     591             : 
     592      587187 :     ReloadPropertyInformation<false>();
     593      587187 :     if (!new_map->is_dictionary_map()) return;
     594             :   }
     595             : 
     596             :   Handle<AccessorPair> pair;
     597      299985 :   if (state() == ACCESSOR && GetAccessors()->IsAccessorPair()) {
     598             :     pair = Handle<AccessorPair>::cast(GetAccessors());
     599             :     // If the component and attributes are identical, nothing has to be done.
     600       11150 :     if (pair->Equals(*getter, *setter)) {
     601          29 :       if (property_details().attributes() == attributes) {
     602           0 :         if (!IsElement()) JSObject::ReoptimizeIfPrototype(receiver);
     603             :         return;
     604             :       }
     605             :     } else {
     606       11121 :       pair = AccessorPair::Copy(pair);
     607       11121 :       pair->SetComponents(*getter, *setter);
     608             :     }
     609             :   } else {
     610      277530 :     pair = factory()->NewAccessorPair();
     611      277530 :     pair->SetComponents(*getter, *setter);
     612             :   }
     613             : 
     614      288680 :   TransitionToAccessorPair(pair, attributes);
     615             : 
     616             : #if VERIFY_HEAP
     617             :   if (FLAG_verify_heap) {
     618             :     receiver->JSObjectVerify();
     619             :   }
     620             : #endif
     621             : }
     622             : 
     623             : 
     624      508346 : void LookupIterator::TransitionToAccessorPair(Handle<Object> pair,
     625      508384 :                                               PropertyAttributes attributes) {
     626      508346 :   Handle<JSObject> receiver = GetStoreTarget();
     627      508346 :   holder_ = receiver;
     628             : 
     629             :   PropertyDetails details(kAccessor, attributes, PropertyCellType::kMutable);
     630             : 
     631      508346 :   if (IsElement()) {
     632             :     // TODO(verwaest): Move code into the element accessor.
     633             :     Handle<SeededNumberDictionary> dictionary =
     634       26173 :         JSObject::NormalizeElements(receiver);
     635             : 
     636             :     dictionary = SeededNumberDictionary::Set(dictionary, index_, pair, receiver,
     637       26173 :                                              details);
     638       26173 :     receiver->RequireSlowElements(*dictionary);
     639             : 
     640       26173 :     if (receiver->HasSlowArgumentsElements()) {
     641             :       FixedArray* parameter_map = FixedArray::cast(receiver->elements());
     642          67 :       uint32_t length = parameter_map->length() - 2;
     643          67 :       if (number_ < length) {
     644          38 :         parameter_map->set(number_ + 2, heap()->the_hole_value());
     645             :       }
     646          67 :       FixedArray::cast(receiver->elements())->set(1, *dictionary);
     647             :     } else {
     648       26106 :       receiver->set_elements(*dictionary);
     649             :     }
     650             : 
     651       26173 :     ReloadPropertyInformation<true>();
     652             :   } else {
     653             :     PropertyNormalizationMode mode = receiver->map()->is_prototype_map()
     654             :                                          ? KEEP_INOBJECT_PROPERTIES
     655      482173 :                                          : CLEAR_INOBJECT_PROPERTIES;
     656             :     // Normalize object to make this operation simple.
     657             :     JSObject::NormalizeProperties(receiver, mode, 0,
     658      482173 :                                   "TransitionToAccessorPair");
     659             : 
     660      482173 :     JSObject::SetNormalizedProperty(receiver, name_, pair, details);
     661      482173 :     JSObject::ReoptimizeIfPrototype(receiver);
     662             : 
     663      482173 :     ReloadPropertyInformation<false>();
     664             :   }
     665      508346 : }
     666             : 
     667          72 : bool LookupIterator::HolderIsReceiver() const {
     668             :   DCHECK(has_property_ || state_ == INTERCEPTOR || state_ == JSPROXY);
     669             :   // Optimization that only works if configuration_ is not mutable.
     670          72 :   if (!check_prototype_chain()) return true;
     671          72 :   return *receiver_ == *holder_;
     672             : }
     673             : 
     674     9169850 : bool LookupIterator::HolderIsReceiverOrHiddenPrototype() const {
     675             :   DCHECK(has_property_ || state_ == INTERCEPTOR || state_ == JSPROXY);
     676             :   // Optimization that only works if configuration_ is not mutable.
     677     9162908 :   if (!check_prototype_chain()) return true;
     678             :   DisallowHeapAllocation no_gc;
     679     9150496 :   if (*receiver_ == *holder_) return true;
     680      349435 :   if (!receiver_->IsJSReceiver()) return false;
     681             :   JSReceiver* current = JSReceiver::cast(*receiver_);
     682             :   JSReceiver* object = *holder_;
     683      347384 :   if (!current->map()->has_hidden_prototype()) return false;
     684             :   // JSProxy do not occur as hidden prototypes.
     685        6942 :   if (object->IsJSProxy()) return false;
     686             :   PrototypeIterator iter(isolate(), current, kStartAtPrototype,
     687             :                          PrototypeIterator::END_AT_NON_HIDDEN);
     688        7353 :   while (!iter.IsAtEnd()) {
     689        6942 :     if (iter.GetCurrent<JSReceiver>() == object) return true;
     690         411 :     iter.Advance();
     691             :   }
     692             :   return false;
     693             : }
     694             : 
     695             : 
     696   117868199 : Handle<Object> LookupIterator::FetchValue() const {
     697             :   Object* result = nullptr;
     698   117868199 :   if (IsElement()) {
     699             :     Handle<JSObject> holder = GetHolder<JSObject>();
     700    47469071 :     ElementsAccessor* accessor = holder->GetElementsAccessor();
     701    47469071 :     return accessor->Get(holder, number_);
     702    70399133 :   } else if (holder_->IsJSGlobalObject()) {
     703             :     Handle<JSGlobalObject> holder = GetHolder<JSGlobalObject>();
     704     5313895 :     result = holder->global_dictionary()->ValueAt(number_);
     705    65085238 :   } else if (!holder_->HasFastProperties()) {
     706     2322490 :     result = holder_->property_dictionary()->ValueAt(number_);
     707    63923995 :   } else if (property_details_.location() == kField) {
     708             :     DCHECK_EQ(kData, property_details_.kind());
     709             :     Handle<JSObject> holder = GetHolder<JSObject>();
     710    66958670 :     FieldIndex field_index = FieldIndex::ForDescriptor(holder->map(), number_);
     711             :     return JSObject::FastPropertyAt(holder, property_details_.representation(),
     712    33479335 :                                     field_index);
     713             :   } else {
     714    30444660 :     result = holder_->map()->instance_descriptors()->GetValue(number_);
     715             :   }
     716    36919800 :   return handle(result, isolate_);
     717             : }
     718             : 
     719           0 : bool LookupIterator::IsConstFieldValueEqualTo(Object* value) const {
     720             :   DCHECK(!IsElement());
     721             :   DCHECK(holder_->HasFastProperties());
     722             :   DCHECK_EQ(kField, property_details_.location());
     723             :   DCHECK_EQ(kConst, property_details_.constness());
     724             :   Handle<JSObject> holder = GetHolder<JSObject>();
     725           0 :   FieldIndex field_index = FieldIndex::ForDescriptor(holder->map(), number_);
     726           0 :   if (property_details_.representation().IsDouble()) {
     727           0 :     if (!value->IsNumber()) return false;
     728             :     uint64_t bits;
     729           0 :     if (holder->IsUnboxedDoubleField(field_index)) {
     730             :       bits = holder->RawFastDoublePropertyAsBitsAt(field_index);
     731             :     } else {
     732           0 :       Object* current_value = holder->RawFastPropertyAt(field_index);
     733             :       DCHECK(current_value->IsMutableHeapNumber());
     734             :       bits = HeapNumber::cast(current_value)->value_as_bits();
     735             :     }
     736             :     // Use bit representation of double to to check for hole double, since
     737             :     // manipulating the signaling NaN used for the hole in C++, e.g. with
     738             :     // bit_cast or value(), will change its value on ia32 (the x87 stack is
     739             :     // used to return values and stores to the stack silently clear the
     740             :     // signalling bit).
     741           0 :     if (bits == kHoleNanInt64) {
     742             :       // Uninitialized double field.
     743             :       return true;
     744             :     }
     745           0 :     return bit_cast<double>(bits) == value->Number();
     746             :   } else {
     747           0 :     Object* current_value = holder->RawFastPropertyAt(field_index);
     748           0 :     return current_value->IsUninitialized(isolate()) || current_value == value;
     749             :   }
     750             : }
     751             : 
     752      166208 : int LookupIterator::GetFieldDescriptorIndex() const {
     753             :   DCHECK(has_property_);
     754             :   DCHECK(holder_->HasFastProperties());
     755             :   DCHECK_EQ(kField, property_details_.location());
     756             :   DCHECK_EQ(kData, property_details_.kind());
     757      166208 :   return descriptor_number();
     758             : }
     759             : 
     760      216210 : int LookupIterator::GetAccessorIndex() const {
     761             :   DCHECK(has_property_);
     762             :   DCHECK(holder_->HasFastProperties());
     763             :   DCHECK_EQ(kDescriptor, property_details_.location());
     764             :   DCHECK_EQ(kAccessor, property_details_.kind());
     765      216210 :   return descriptor_number();
     766             : }
     767             : 
     768             : 
     769      472419 : int LookupIterator::GetConstantIndex() const {
     770             :   DCHECK(has_property_);
     771             :   DCHECK(holder_->HasFastProperties());
     772             :   DCHECK_EQ(kDescriptor, property_details_.location());
     773             :   DCHECK_EQ(kData, property_details_.kind());
     774             :   DCHECK(!FLAG_track_constant_fields);
     775             :   DCHECK(!IsElement());
     776      472419 :   return descriptor_number();
     777             : }
     778             : 
     779           0 : Handle<Map> LookupIterator::GetFieldOwnerMap() const {
     780             :   DCHECK(has_property_);
     781             :   DCHECK(holder_->HasFastProperties());
     782             :   DCHECK_EQ(kField, property_details_.location());
     783             :   DCHECK(!IsElement());
     784             :   Map* holder_map = holder_->map();
     785           0 :   return handle(holder_map->FindFieldOwner(descriptor_number()), isolate_);
     786             : }
     787             : 
     788     1692640 : FieldIndex LookupIterator::GetFieldIndex() const {
     789             :   DCHECK(has_property_);
     790             :   DCHECK(holder_->HasFastProperties());
     791             :   DCHECK_EQ(kField, property_details_.location());
     792             :   DCHECK(!IsElement());
     793             :   Map* holder_map = holder_->map();
     794             :   int index =
     795             :       holder_map->instance_descriptors()->GetFieldIndex(descriptor_number());
     796             :   bool is_double = representation().IsDouble();
     797      846322 :   return FieldIndex::ForPropertyIndex(holder_map, index, is_double);
     798             : }
     799             : 
     800           0 : Handle<FieldType> LookupIterator::GetFieldType() const {
     801             :   DCHECK(has_property_);
     802             :   DCHECK(holder_->HasFastProperties());
     803             :   DCHECK_EQ(kField, property_details_.location());
     804             :   return handle(
     805             :       holder_->map()->instance_descriptors()->GetFieldType(descriptor_number()),
     806           0 :       isolate_);
     807             : }
     808             : 
     809             : 
     810     7956260 : Handle<PropertyCell> LookupIterator::GetPropertyCell() const {
     811             :   DCHECK(!IsElement());
     812             :   Handle<JSGlobalObject> holder = GetHolder<JSGlobalObject>();
     813             :   return handle(holder->global_dictionary()->CellAt(dictionary_entry()),
     814     7956262 :                 isolate_);
     815             : }
     816             : 
     817             : 
     818     8705729 : Handle<Object> LookupIterator::GetAccessors() const {
     819             :   DCHECK_EQ(ACCESSOR, state_);
     820    21257130 :   return FetchValue();
     821             : }
     822             : 
     823             : 
     824    96611071 : Handle<Object> LookupIterator::GetDataValue() const {
     825             :   DCHECK_EQ(DATA, state_);
     826    96611071 :   Handle<Object> value = FetchValue();
     827    96611069 :   return value;
     828             : }
     829             : 
     830    45075441 : void LookupIterator::WriteDataValue(Handle<Object> value,
     831    80862159 :                                     bool initializing_store) {
     832             :   DCHECK_EQ(DATA, state_);
     833             :   Handle<JSReceiver> holder = GetHolder<JSReceiver>();
     834    45075441 :   if (IsElement()) {
     835             :     Handle<JSObject> object = Handle<JSObject>::cast(holder);
     836      901495 :     ElementsAccessor* accessor = object->GetElementsAccessor();
     837     1802990 :     accessor->Set(object, number_, *value);
     838    44173946 :   } else if (holder->HasFastProperties()) {
     839    26179418 :     if (property_details_.location() == kField) {
     840             :       // Check that in case of kConst field the existing value is equal to
     841             :       // |value|.
     842             :       DCHECK_IMPLIES(
     843             :           !initializing_store && property_details_.constness() == kConst,
     844             :           IsConstFieldValueEqualTo(*value));
     845             :       JSObject::cast(*holder)->WriteToField(descriptor_number(),
     846    17792187 :                                             property_details_, *value);
     847             :     } else {
     848             :       DCHECK_EQ(kDescriptor, property_details_.location());
     849             :       DCHECK_EQ(kConst, property_details_.constness());
     850             :     }
     851    17994531 :   } else if (holder->IsJSGlobalObject()) {
     852             :     GlobalDictionary* dictionary =
     853             :         JSGlobalObject::cast(*holder)->global_dictionary();
     854     9410325 :     dictionary->CellAt(dictionary_entry())->set_value(*value);
     855             :   } else {
     856             :     NameDictionary* dictionary = holder->property_dictionary();
     857             :     dictionary->ValueAtPut(dictionary_entry(), *value);
     858             :   }
     859    45075443 : }
     860             : 
     861             : template <bool is_element>
     862      960396 : bool LookupIterator::SkipInterceptor(JSObject* holder) {
     863             :   auto info = GetInterceptor<is_element>(holder);
     864      651063 :   if (!is_element && name_->IsSymbol() && !info->can_intercept_symbols()) {
     865             :     return true;
     866             :   }
     867      960384 :   if (info->non_masking()) {
     868         402 :     switch (interceptor_state_) {
     869             :       case InterceptorState::kUninitialized:
     870         252 :         interceptor_state_ = InterceptorState::kSkipNonMasking;
     871             :       // Fall through.
     872             :       case InterceptorState::kSkipNonMasking:
     873             :         return true;
     874             :       case InterceptorState::kProcessNonMasking:
     875             :         return false;
     876             :     }
     877             :   }
     878      959982 :   return interceptor_state_ == InterceptorState::kProcessNonMasking;
     879             : }
     880             : 
     881   633749307 : JSReceiver* LookupIterator::NextHolder(Map* map) {
     882             :   DisallowHeapAllocation no_gc;
     883   370409570 :   if (map->prototype() == heap()->null_value()) return nullptr;
     884   327328459 :   if (!check_prototype_chain() && !map->has_hidden_prototype()) return nullptr;
     885             :   return JSReceiver::cast(map->prototype());
     886             : }
     887             : 
     888   130208022 : LookupIterator::State LookupIterator::NotFound(JSReceiver* const holder) const {
     889             :   DCHECK(!IsElement());
     890   130336082 :   if (!holder->IsJSTypedArray() || !name_->IsString()) return NOT_FOUND;
     891             : 
     892             :   Handle<String> name_string = Handle<String>::cast(name_);
     893      109873 :   if (name_string->length() == 0) return NOT_FOUND;
     894             : 
     895      109873 :   return IsSpecialIndex(isolate_->unicode_cache(), *name_string)
     896             :              ? INTEGER_INDEXED_EXOTIC
     897      109873 :              : NOT_FOUND;
     898             : }
     899             : 
     900             : namespace {
     901             : 
     902             : template <bool is_element>
     903             : bool HasInterceptor(Map* map) {
     904             :   return is_element ? map->has_indexed_interceptor()
     905             :                     : map->has_named_interceptor();
     906             : }
     907             : 
     908             : }  // namespace
     909             : 
     910             : template <bool is_element>
     911    42389203 : LookupIterator::State LookupIterator::LookupInSpecialHolder(
     912             :     Map* const map, JSReceiver* const holder) {
     913             :   STATIC_ASSERT(INTERCEPTOR == BEFORE_PROPERTY);
     914    42389203 :   switch (state_) {
     915             :     case NOT_FOUND:
     916    35612591 :       if (map->IsJSProxyMap()) {
     917      227468 :         if (is_element || !name_->IsPrivate()) return JSPROXY;
     918             :       }
     919    35375284 :       if (map->is_access_check_needed()) {
     920     6849665 :         if (is_element || !name_->IsPrivate()) return ACCESS_CHECK;
     921             :       }
     922             :     // Fall through.
     923             :     case ACCESS_CHECK:
     924    56766969 :       if (check_interceptor() && HasInterceptor<is_element>(map) &&
     925      960396 :           !SkipInterceptor<is_element>(JSObject::cast(holder))) {
     926      650741 :         if (is_element || !name_->IsPrivate()) return INTERCEPTOR;
     927             :       }
     928             :     // Fall through.
     929             :     case INTERCEPTOR:
     930    35048593 :       if (!is_element && map->IsJSGlobalObjectMap()) {
     931             :         GlobalDictionary* dict =
     932             :             JSGlobalObject::cast(holder)->global_dictionary();
     933             :         int number = dict->FindEntry(name_);
     934    27294107 :         if (number == GlobalDictionary::kNotFound) return NOT_FOUND;
     935    12169842 :         number_ = static_cast<uint32_t>(number);
     936             :         PropertyCell* cell = dict->CellAt(number_);
     937    24339684 :         if (cell->value()->IsTheHole(isolate_)) return NOT_FOUND;
     938    12135374 :         property_details_ = cell->property_details();
     939    12135374 :         has_property_ = true;
     940    12135374 :         switch (property_details_.kind()) {
     941             :           case v8::internal::kData:
     942             :             return DATA;
     943             :           case v8::internal::kAccessor:
     944       50689 :             return ACCESSOR;
     945             :         }
     946             :       }
     947     8075389 :       return LookupInRegularHolder<is_element>(map, holder);
     948             :     case ACCESSOR:
     949             :     case DATA:
     950             :       return NOT_FOUND;
     951             :     case INTEGER_INDEXED_EXOTIC:
     952             :     case JSPROXY:
     953             :     case TRANSITION:
     954           0 :       UNREACHABLE();
     955             :   }
     956           0 :   UNREACHABLE();
     957             : }
     958             : 
     959             : template <bool is_element>
     960   499657435 : LookupIterator::State LookupIterator::LookupInRegularHolder(
     961             :     Map* const map, JSReceiver* const holder) {
     962             :   DisallowHeapAllocation no_gc;
     963   499657435 :   if (interceptor_state_ == InterceptorState::kProcessNonMasking) {
     964             :     return NOT_FOUND;
     965             :   }
     966             : 
     967             :   if (is_element) {
     968             :     JSObject* js_object = JSObject::cast(holder);
     969   274380962 :     ElementsAccessor* accessor = js_object->GetElementsAccessor();
     970             :     FixedArrayBase* backing_store = js_object->elements();
     971   274380961 :     number_ =
     972   274380962 :         accessor->GetEntryForIndex(isolate_, js_object, backing_store, index_);
     973   274380961 :     if (number_ == kMaxUInt32) {
     974   225196019 :       return holder->IsJSTypedArray() ? INTEGER_INDEXED_EXOTIC : NOT_FOUND;
     975             :     }
     976    49184942 :     property_details_ = accessor->GetDetails(js_object, number_);
     977   225276373 :   } else if (!map->is_dictionary_map()) {
     978             :     DescriptorArray* descriptors = map->instance_descriptors();
     979   212491978 :     int number = descriptors->SearchWithCache(isolate_, *name_, map);
     980   212492004 :     if (number == DescriptorArray::kNotFound) return NotFound(holder);
     981    92866074 :     number_ = static_cast<uint32_t>(number);
     982    92866074 :     property_details_ = descriptors->GetDetails(number_);
     983             :   } else {
     984             :     NameDictionary* dict = holder->property_dictionary();
     985             :     int number = dict->FindEntry(name_);
     986    12784395 :     if (number == NameDictionary::kNotFound) return NotFound(holder);
     987     2202300 :     number_ = static_cast<uint32_t>(number);
     988     2202300 :     property_details_ = dict->DetailsAt(number_);
     989             :   }
     990   144253320 :   has_property_ = true;
     991   144253320 :   switch (property_details_.kind()) {
     992             :     case v8::internal::kData:
     993             :       return DATA;
     994             :     case v8::internal::kAccessor:
     995     8920945 :       return ACCESSOR;
     996             :   }
     997             : 
     998           0 :   UNREACHABLE();
     999             : }
    1000             : 
    1001        1968 : Handle<InterceptorInfo> LookupIterator::GetInterceptorForFailedAccessCheck()
    1002        1126 :     const {
    1003             :   DCHECK_EQ(ACCESS_CHECK, state_);
    1004             :   DisallowHeapAllocation no_gc;
    1005             :   AccessCheckInfo* access_check_info =
    1006        1968 :       AccessCheckInfo::Get(isolate_, Handle<JSObject>::cast(holder_));
    1007        1968 :   if (access_check_info) {
    1008             :     Object* interceptor = IsElement() ? access_check_info->indexed_interceptor()
    1009        1126 :                                       : access_check_info->named_interceptor();
    1010        1126 :     if (interceptor) {
    1011         174 :       return handle(InterceptorInfo::cast(interceptor), isolate_);
    1012             :     }
    1013             :   }
    1014        1794 :   return Handle<InterceptorInfo>();
    1015             : }
    1016             : 
    1017     8678271 : bool LookupIterator::TryLookupCachedProperty() {
    1018     6264813 :   return state() == LookupIterator::ACCESSOR &&
    1019    14942404 :          GetAccessors()->IsAccessorPair() && LookupCachedProperty();
    1020             : }
    1021             : 
    1022    18792495 : bool LookupIterator::LookupCachedProperty() {
    1023             :   DCHECK_EQ(state(), LookupIterator::ACCESSOR);
    1024             :   DCHECK(GetAccessors()->IsAccessorPair());
    1025             : 
    1026             :   AccessorPair* accessor_pair = AccessorPair::cast(*GetAccessors());
    1027             :   Handle<Object> getter(accessor_pair->getter(), isolate());
    1028             :   MaybeHandle<Name> maybe_name =
    1029     6264133 :       FunctionTemplateInfo::TryGetCachedPropertyName(isolate(), getter);
    1030     6264133 :   if (maybe_name.is_null()) return false;
    1031             : 
    1032             :   // We have found a cached property! Modify the iterator accordingly.
    1033          96 :   name_ = maybe_name.ToHandleChecked();
    1034          96 :   Restart();
    1035          96 :   CHECK_EQ(state(), LookupIterator::DATA);
    1036             :   return true;
    1037             : }
    1038             : 
    1039             : }  // namespace internal
    1040             : }  // namespace v8

Generated by: LCOV version 1.10