LCOV - code coverage report
Current view: top level - src/objects - js-objects.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1783 1980 90.1 %
Date: 2019-04-17 Functions: 184 191 96.3 %

          Line data    Source code
       1             : // Copyright 2019 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/objects/js-objects.h"
       6             : 
       7             : #include "src/api-arguments-inl.h"
       8             : #include "src/arguments.h"
       9             : #include "src/bootstrapper.h"
      10             : #include "src/compiler.h"
      11             : #include "src/counters.h"
      12             : #include "src/date.h"
      13             : #include "src/elements.h"
      14             : #include "src/field-type.h"
      15             : #include "src/handles-inl.h"
      16             : #include "src/heap/heap-inl.h"
      17             : #include "src/ic/ic.h"
      18             : #include "src/isolate.h"
      19             : #include "src/layout-descriptor.h"
      20             : #include "src/log.h"
      21             : #include "src/lookup.h"
      22             : #include "src/maybe-handles.h"
      23             : #include "src/objects-inl.h"
      24             : #include "src/objects/allocation-site-inl.h"
      25             : #include "src/objects/api-callbacks.h"
      26             : #include "src/objects/arguments-inl.h"
      27             : #include "src/objects/dictionary.h"
      28             : #include "src/objects/fixed-array.h"
      29             : #include "src/objects/heap-number.h"
      30             : #include "src/objects/js-array-buffer.h"
      31             : #include "src/objects/js-array-inl.h"
      32             : #ifdef V8_INTL_SUPPORT
      33             : #include "src/objects/js-break-iterator.h"
      34             : #include "src/objects/js-collator.h"
      35             : #endif  // V8_INTL_SUPPORT
      36             : #include "src/objects/js-collection.h"
      37             : #ifdef V8_INTL_SUPPORT
      38             : #include "src/objects/js-date-time-format.h"
      39             : #endif  // V8_INTL_SUPPORT
      40             : #include "src/objects/js-generator-inl.h"
      41             : #ifdef V8_INTL_SUPPORT
      42             : #include "src/objects/js-list-format.h"
      43             : #include "src/objects/js-locale.h"
      44             : #include "src/objects/js-number-format.h"
      45             : #include "src/objects/js-plural-rules.h"
      46             : #endif  // V8_INTL_SUPPORT
      47             : #include "src/objects/js-promise.h"
      48             : #include "src/objects/js-regexp-inl.h"
      49             : #include "src/objects/js-regexp-string-iterator.h"
      50             : #ifdef V8_INTL_SUPPORT
      51             : #include "src/objects/js-relative-time-format.h"
      52             : #include "src/objects/js-segment-iterator.h"
      53             : #include "src/objects/js-segmenter.h"
      54             : #endif  // V8_INTL_SUPPORT
      55             : #include "src/objects/js-weak-refs.h"
      56             : #include "src/objects/map-inl.h"
      57             : #include "src/objects/module.h"
      58             : #include "src/objects/oddball.h"
      59             : #include "src/objects/property-cell.h"
      60             : #include "src/objects/prototype-info.h"
      61             : #include "src/objects/shared-function-info.h"
      62             : #include "src/ostreams.h"
      63             : #include "src/property-descriptor.h"
      64             : #include "src/property.h"
      65             : #include "src/prototype.h"
      66             : #include "src/string-builder-inl.h"
      67             : #include "src/string-stream.h"
      68             : #include "src/transitions.h"
      69             : #include "src/wasm/wasm-objects.h"
      70             : 
      71             : namespace v8 {
      72             : namespace internal {
      73             : 
      74             : // static
      75     4598957 : Maybe<bool> JSReceiver::HasProperty(LookupIterator* it) {
      76     4706267 :   for (; it->IsFound(); it->Next()) {
      77     1662255 :     switch (it->state()) {
      78             :       case LookupIterator::NOT_FOUND:
      79             :       case LookupIterator::TRANSITION:
      80           0 :         UNREACHABLE();
      81             :       case LookupIterator::JSPROXY:
      82             :         return JSProxy::HasProperty(it->isolate(), it->GetHolder<JSProxy>(),
      83       53689 :                                     it->GetName());
      84             :       case LookupIterator::INTERCEPTOR: {
      85             :         Maybe<PropertyAttributes> result =
      86             :             JSObject::GetPropertyAttributesWithInterceptor(it);
      87       42262 :         if (result.IsNothing()) return Nothing<bool>();
      88       42256 :         if (result.FromJust() != ABSENT) return Just(true);
      89             :         break;
      90             :       }
      91             :       case LookupIterator::ACCESS_CHECK: {
      92       29017 :         if (it->HasAccess()) break;
      93             :         Maybe<PropertyAttributes> result =
      94          40 :             JSObject::GetPropertyAttributesWithFailedAccessCheck(it);
      95          80 :         if (result.IsNothing()) return Nothing<bool>();
      96           0 :         return Just(result.FromJust() != ABSENT);
      97             :       }
      98             :       case LookupIterator::INTEGER_INDEXED_EXOTIC:
      99             :         // TypedArray out-of-bounds access.
     100             :         return Just(false);
     101             :       case LookupIterator::ACCESSOR:
     102             :       case LookupIterator::DATA:
     103             :         return Just(true);
     104             :     }
     105             :   }
     106             :   return Just(false);
     107             : }
     108             : 
     109             : // static
     110      427829 : Maybe<bool> JSReceiver::HasOwnProperty(Handle<JSReceiver> object,
     111             :                                        Handle<Name> name) {
     112      427829 :   if (object->IsJSModuleNamespace()) {
     113             :     PropertyDescriptor desc;
     114             :     return JSReceiver::GetOwnPropertyDescriptor(object->GetIsolate(), object,
     115         171 :                                                 name, &desc);
     116             :   }
     117             : 
     118      427658 :   if (object->IsJSObject()) {  // Shortcut.
     119             :     LookupIterator it = LookupIterator::PropertyOrElement(
     120      426272 :         object->GetIsolate(), object, name, object, LookupIterator::OWN);
     121      426272 :     return HasProperty(&it);
     122             :   }
     123             : 
     124             :   Maybe<PropertyAttributes> attributes =
     125        1386 :       JSReceiver::GetOwnPropertyAttributes(object, name);
     126        1386 :   MAYBE_RETURN(attributes, Nothing<bool>());
     127        1296 :   return Just(attributes.FromJust() != ABSENT);
     128             : }
     129             : 
     130     4128042 : Handle<Object> JSReceiver::GetDataProperty(LookupIterator* it) {
     131     5321836 :   for (; it->IsFound(); it->Next()) {
     132     4672320 :     switch (it->state()) {
     133             :       case LookupIterator::INTERCEPTOR:
     134             :       case LookupIterator::NOT_FOUND:
     135             :       case LookupIterator::TRANSITION:
     136           0 :         UNREACHABLE();
     137             :       case LookupIterator::ACCESS_CHECK:
     138             :         // Support calling this method without an active context, but refuse
     139             :         // access to access-checked objects in that case.
     140      597719 :         if (!it->isolate()->context().is_null() && it->HasAccess()) continue;
     141             :         V8_FALLTHROUGH;
     142             :       case LookupIterator::JSPROXY:
     143             :         it->NotFound();
     144        3002 :         return it->isolate()->factory()->undefined_value();
     145             :       case LookupIterator::ACCESSOR:
     146             :         // TODO(verwaest): For now this doesn't call into AccessorInfo, since
     147             :         // clients don't need it. Update once relevant.
     148             :         it->NotFound();
     149      531799 :         return it->isolate()->factory()->undefined_value();
     150             :       case LookupIterator::INTEGER_INDEXED_EXOTIC:
     151           0 :         return it->isolate()->factory()->undefined_value();
     152             :       case LookupIterator::DATA:
     153     3540622 :         return it->GetDataValue();
     154             :     }
     155             :   }
     156       52619 :   return it->isolate()->factory()->undefined_value();
     157             : }
     158             : 
     159             : // static
     160        1997 : Maybe<bool> JSReceiver::HasInPrototypeChain(Isolate* isolate,
     161             :                                             Handle<JSReceiver> object,
     162             :                                             Handle<Object> proto) {
     163             :   PrototypeIterator iter(isolate, object, kStartAtReceiver);
     164             :   while (true) {
     165     3690553 :     if (!iter.AdvanceFollowingProxies()) return Nothing<bool>();
     166     3690445 :     if (iter.IsAtEnd()) return Just(false);
     167     3688996 :     if (PrototypeIterator::GetCurrent(iter).is_identical_to(proto)) {
     168             :       return Just(true);
     169             :     }
     170             :   }
     171             : }
     172             : 
     173             : namespace {
     174             : 
     175         519 : bool HasExcludedProperty(
     176             :     const ScopedVector<Handle<Object>>* excluded_properties,
     177             :     Handle<Object> search_element) {
     178             :   // TODO(gsathya): Change this to be a hashtable.
     179        1071 :   for (int i = 0; i < excluded_properties->length(); i++) {
     180         894 :     if (search_element->SameValue(*excluded_properties->at(i))) {
     181             :       return true;
     182             :     }
     183             :   }
     184             : 
     185             :   return false;
     186             : }
     187             : 
     188         770 : V8_WARN_UNUSED_RESULT Maybe<bool> FastAssign(
     189             :     Handle<JSReceiver> target, Handle<Object> source,
     190             :     const ScopedVector<Handle<Object>>* excluded_properties, bool use_set) {
     191             :   // Non-empty strings are the only non-JSReceivers that need to be handled
     192             :   // explicitly by Object.assign.
     193         770 :   if (!source->IsJSReceiver()) {
     194          18 :     return Just(!source->IsString() || String::cast(*source)->length() == 0);
     195             :   }
     196             : 
     197             :   // If the target is deprecated, the object will be updated on first store. If
     198             :   // the source for that store equals the target, this will invalidate the
     199             :   // cached representation of the source. Preventively upgrade the target.
     200             :   // Do this on each iteration since any property load could cause deprecation.
     201         761 :   if (target->map()->is_deprecated()) {
     202          18 :     JSObject::MigrateInstance(Handle<JSObject>::cast(target));
     203             :   }
     204             : 
     205             :   Isolate* isolate = target->GetIsolate();
     206             :   Handle<Map> map(JSReceiver::cast(*source)->map(), isolate);
     207             : 
     208         761 :   if (!map->IsJSObjectMap()) return Just(false);
     209         644 :   if (!map->OnlyHasSimpleProperties()) return Just(false);
     210             : 
     211             :   Handle<JSObject> from = Handle<JSObject>::cast(source);
     212         446 :   if (from->elements() != ReadOnlyRoots(isolate).empty_fixed_array()) {
     213             :     return Just(false);
     214             :   }
     215             : 
     216             :   Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
     217             :   int length = map->NumberOfOwnDescriptors();
     218             : 
     219             :   bool stable = true;
     220             : 
     221        1385 :   for (int i = 0; i < length; i++) {
     222             :     Handle<Name> next_key(descriptors->GetKey(i), isolate);
     223             :     Handle<Object> prop_value;
     224             :     // Directly decode from the descriptor array if |from| did not change shape.
     225         519 :     if (stable) {
     226         519 :       PropertyDetails details = descriptors->GetDetails(i);
     227         519 :       if (!details.IsEnumerable()) continue;
     228         492 :       if (details.kind() == kData) {
     229         492 :         if (details.location() == kDescriptor) {
     230           0 :           prop_value = handle(descriptors->GetStrongValue(i), isolate);
     231             :         } else {
     232         492 :           Representation representation = details.representation();
     233         492 :           FieldIndex index = FieldIndex::ForDescriptor(*map, i);
     234         492 :           prop_value = JSObject::FastPropertyAt(from, representation, index);
     235             :         }
     236             :       } else {
     237           0 :         ASSIGN_RETURN_ON_EXCEPTION_VALUE(
     238             :             isolate, prop_value,
     239             :             JSReceiver::GetProperty(isolate, from, next_key), Nothing<bool>());
     240             :         stable = from->map() == *map;
     241             :       }
     242             :     } else {
     243             :       // If the map did change, do a slower lookup. We are still guaranteed that
     244             :       // the object has a simple shape, and that the key is a name.
     245             :       LookupIterator it(from, next_key, from,
     246             :                         LookupIterator::OWN_SKIP_INTERCEPTOR);
     247           0 :       if (!it.IsFound()) continue;
     248             :       DCHECK(it.state() == LookupIterator::DATA ||
     249             :              it.state() == LookupIterator::ACCESSOR);
     250           0 :       if (!it.IsEnumerable()) continue;
     251           0 :       ASSIGN_RETURN_ON_EXCEPTION_VALUE(
     252             :           isolate, prop_value, Object::GetProperty(&it), Nothing<bool>());
     253             :     }
     254             : 
     255         492 :     if (use_set) {
     256             :       LookupIterator it(target, next_key, target);
     257             :       Maybe<bool> result =
     258             :           Object::SetProperty(&it, prop_value, StoreOrigin::kNamed,
     259          36 :                               Just(ShouldThrow::kThrowOnError));
     260          36 :       if (result.IsNothing()) return result;
     261          36 :       if (stable) stable = from->map() == *map;
     262             :     } else {
     263         768 :       if (excluded_properties != nullptr &&
     264         312 :           HasExcludedProperty(excluded_properties, next_key)) {
     265          99 :         continue;
     266             :       }
     267             : 
     268             :       // 4a ii 2. Perform ? CreateDataProperty(target, nextKey, propValue).
     269             :       bool success;
     270             :       LookupIterator it = LookupIterator::PropertyOrElement(
     271         357 :           isolate, target, next_key, &success, LookupIterator::OWN);
     272         357 :       CHECK(success);
     273         714 :       CHECK(JSObject::CreateDataProperty(&it, prop_value, Just(kThrowOnError))
     274             :                 .FromJust());
     275             :     }
     276             :   }
     277             : 
     278             :   return Just(true);
     279             : }
     280             : }  // namespace
     281             : 
     282             : // static
     283         770 : Maybe<bool> JSReceiver::SetOrCopyDataProperties(
     284             :     Isolate* isolate, Handle<JSReceiver> target, Handle<Object> source,
     285             :     const ScopedVector<Handle<Object>>* excluded_properties, bool use_set) {
     286             :   Maybe<bool> fast_assign =
     287         770 :       FastAssign(target, source, excluded_properties, use_set);
     288         770 :   if (fast_assign.IsNothing()) return Nothing<bool>();
     289         770 :   if (fast_assign.FromJust()) return Just(true);
     290             : 
     291         846 :   Handle<JSReceiver> from = Object::ToObject(isolate, source).ToHandleChecked();
     292             :   // 3b. Let keys be ? from.[[OwnPropertyKeys]]().
     293             :   Handle<FixedArray> keys;
     294         846 :   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
     295             :       isolate, keys,
     296             :       KeyAccumulator::GetKeys(from, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
     297             :                               GetKeysConversion::kKeepNumbers),
     298             :       Nothing<bool>());
     299             : 
     300             :   // 4. Repeat for each element nextKey of keys in List order,
     301        3967 :   for (int j = 0; j < keys->length(); ++j) {
     302             :     Handle<Object> next_key(keys->get(j), isolate);
     303             :     // 4a i. Let desc be ? from.[[GetOwnProperty]](nextKey).
     304             :     PropertyDescriptor desc;
     305             :     Maybe<bool> found =
     306        1862 :         JSReceiver::GetOwnPropertyDescriptor(isolate, from, next_key, &desc);
     307        1925 :     if (found.IsNothing()) return Nothing<bool>();
     308             :     // 4a ii. If desc is not undefined and desc.[[Enumerable]] is true, then
     309        3652 :     if (found.FromJust() && desc.enumerable()) {
     310             :       // 4a ii 1. Let propValue be ? Get(from, nextKey).
     311             :       Handle<Object> prop_value;
     312        2385 :       ASSIGN_RETURN_ON_EXCEPTION_VALUE(
     313             :           isolate, prop_value,
     314             :           Runtime::GetObjectProperty(isolate, from, next_key), Nothing<bool>());
     315             : 
     316        1152 :       if (use_set) {
     317             :         // 4c ii 2. Let status be ? Set(to, nextKey, propValue, true).
     318             :         Handle<Object> status;
     319        1530 :         ASSIGN_RETURN_ON_EXCEPTION_VALUE(
     320             :             isolate, status,
     321             :             Runtime::SetObjectProperty(isolate, target, next_key, prop_value,
     322             :                                        StoreOrigin::kMaybeKeyed,
     323             :                                        Just(ShouldThrow::kThrowOnError)),
     324             :             Nothing<bool>());
     325             :       } else {
     326         594 :         if (excluded_properties != nullptr &&
     327         207 :             HasExcludedProperty(excluded_properties, next_key)) {
     328          72 :           continue;
     329             :         }
     330             : 
     331             :         // 4a ii 2. Perform ! CreateDataProperty(target, nextKey, propValue).
     332             :         bool success;
     333             :         LookupIterator it = LookupIterator::PropertyOrElement(
     334         315 :             isolate, target, next_key, &success, LookupIterator::OWN);
     335         315 :         CHECK(success);
     336         630 :         CHECK(JSObject::CreateDataProperty(&it, prop_value, Just(kThrowOnError))
     337             :                   .FromJust());
     338             :       }
     339             :     }
     340             :   }
     341             : 
     342             :   return Just(true);
     343             : }
     344             : 
     345      878080 : String JSReceiver::class_name() {
     346             :   ReadOnlyRoots roots = GetReadOnlyRoots();
     347      878080 :   if (IsFunction()) return roots.Function_string();
     348      878070 :   if (IsJSArgumentsObject()) return roots.Arguments_string();
     349      878070 :   if (IsJSArray()) return roots.Array_string();
     350      873980 :   if (IsJSArrayBuffer()) {
     351           0 :     if (JSArrayBuffer::cast(*this)->is_shared()) {
     352             :       return roots.SharedArrayBuffer_string();
     353             :     }
     354             :     return roots.ArrayBuffer_string();
     355             :   }
     356      873980 :   if (IsJSArrayIterator()) return roots.ArrayIterator_string();
     357      873980 :   if (IsJSDate()) return roots.Date_string();
     358      873971 :   if (IsJSError()) return roots.Error_string();
     359      873971 :   if (IsJSGeneratorObject()) return roots.Generator_string();
     360      873971 :   if (IsJSMap()) return roots.Map_string();
     361      873971 :   if (IsJSMapIterator()) return roots.MapIterator_string();
     362      873971 :   if (IsJSProxy()) {
     363             :     return map()->is_callable() ? roots.Function_string()
     364        1113 :                                 : roots.Object_string();
     365             :   }
     366      872858 :   if (IsJSRegExp()) return roots.RegExp_string();
     367      872444 :   if (IsJSSet()) return roots.Set_string();
     368      872444 :   if (IsJSSetIterator()) return roots.SetIterator_string();
     369      872444 :   if (IsJSTypedArray()) {
     370             : #define SWITCH_KIND(Type, type, TYPE, ctype)       \
     371             :   if (map()->elements_kind() == TYPE##_ELEMENTS) { \
     372             :     return roots.Type##Array_string();             \
     373             :   }
     374        4266 :     TYPED_ARRAYS(SWITCH_KIND)
     375             : #undef SWITCH_KIND
     376             :   }
     377      871733 :   if (IsJSValue()) {
     378             :     Object value = JSValue::cast(*this)->value();
     379        2649 :     if (value->IsBoolean()) return roots.Boolean_string();
     380        1818 :     if (value->IsString()) return roots.String_string();
     381         879 :     if (value->IsNumber()) return roots.Number_string();
     382          10 :     if (value->IsBigInt()) return roots.BigInt_string();
     383          10 :     if (value->IsSymbol()) return roots.Symbol_string();
     384           0 :     if (value->IsScript()) return roots.Script_string();
     385           0 :     UNREACHABLE();
     386             :   }
     387      869084 :   if (IsJSWeakMap()) return roots.WeakMap_string();
     388      869084 :   if (IsJSWeakSet()) return roots.WeakSet_string();
     389      869084 :   if (IsJSGlobalProxy()) return roots.global_string();
     390             : 
     391      815670 :   Object maybe_constructor = map()->GetConstructor();
     392      815670 :   if (maybe_constructor->IsJSFunction()) {
     393             :     JSFunction constructor = JSFunction::cast(maybe_constructor);
     394      815538 :     if (constructor->shared()->IsApiFunction()) {
     395             :       maybe_constructor = constructor->shared()->get_api_func_data();
     396             :     }
     397             :   }
     398             : 
     399      815670 :   if (maybe_constructor->IsFunctionTemplateInfo()) {
     400             :     FunctionTemplateInfo info = FunctionTemplateInfo::cast(maybe_constructor);
     401        3356 :     if (info->class_name()->IsString()) return String::cast(info->class_name());
     402             :   }
     403             : 
     404             :   return roots.Object_string();
     405             : }
     406             : 
     407             : namespace {
     408     3925403 : std::pair<MaybeHandle<JSFunction>, Handle<String>> GetConstructorHelper(
     409             :     Handle<JSReceiver> receiver) {
     410             :   Isolate* isolate = receiver->GetIsolate();
     411             : 
     412             :   // If the object was instantiated simply with base == new.target, the
     413             :   // constructor on the map provides the most accurate name.
     414             :   // Don't provide the info for prototypes, since their constructors are
     415             :   // reclaimed and replaced by Object in OptimizeAsPrototype.
     416    11775521 :   if (!receiver->IsJSProxy() && receiver->map()->new_target_is_base() &&
     417             :       !receiver->map()->is_prototype_map()) {
     418     3753972 :     Object maybe_constructor = receiver->map()->GetConstructor();
     419     3753972 :     if (maybe_constructor->IsJSFunction()) {
     420             :       JSFunction constructor = JSFunction::cast(maybe_constructor);
     421     3515222 :       String name = constructor->shared()->DebugName();
     422     6433961 :       if (name->length() != 0 &&
     423     2918739 :           !name->Equals(ReadOnlyRoots(isolate).Object_string())) {
     424             :         return std::make_pair(handle(constructor, isolate),
     425     2035809 :                               handle(name, isolate));
     426             :       }
     427      238750 :     } else if (maybe_constructor->IsFunctionTemplateInfo()) {
     428             :       FunctionTemplateInfo info = FunctionTemplateInfo::cast(maybe_constructor);
     429           0 :       if (info->class_name()->IsString()) {
     430             :         return std::make_pair(
     431             :             MaybeHandle<JSFunction>(),
     432             :             handle(String::cast(info->class_name()), isolate));
     433             :       }
     434             :     }
     435             :   }
     436             : 
     437             :   Handle<Object> maybe_tag = JSReceiver::GetDataProperty(
     438     1889594 :       receiver, isolate->factory()->to_string_tag_symbol());
     439     1889594 :   if (maybe_tag->IsString())
     440             :     return std::make_pair(MaybeHandle<JSFunction>(),
     441             :                           Handle<String>::cast(maybe_tag));
     442             : 
     443     1173249 :   PrototypeIterator iter(isolate, receiver);
     444     1173249 :   if (iter.IsAtEnd()) {
     445             :     return std::make_pair(MaybeHandle<JSFunction>(),
     446      960012 :                           handle(receiver->class_name(), isolate));
     447             :   }
     448             : 
     449             :   Handle<JSReceiver> start = PrototypeIterator::GetCurrent<JSReceiver>(iter);
     450             :   LookupIterator it(receiver, isolate->factory()->constructor_string(), start,
     451             :                     LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
     452      693243 :   Handle<Object> maybe_constructor = JSReceiver::GetDataProperty(&it);
     453      693243 :   if (maybe_constructor->IsJSFunction()) {
     454             :     JSFunction constructor = JSFunction::cast(*maybe_constructor);
     455      693243 :     String name = constructor->shared()->DebugName();
     456             : 
     457     1333460 :     if (name->length() != 0 &&
     458      640217 :         !name->Equals(ReadOnlyRoots(isolate).Object_string())) {
     459             :       return std::make_pair(handle(constructor, isolate),
     460      307382 :                             handle(name, isolate));
     461             :     }
     462             :   }
     463             : 
     464             :   return std::make_pair(MaybeHandle<JSFunction>(),
     465      771722 :                         handle(receiver->class_name(), isolate));
     466             : }
     467             : }  // anonymous namespace
     468             : 
     469             : // static
     470      141847 : MaybeHandle<JSFunction> JSReceiver::GetConstructor(
     471             :     Handle<JSReceiver> receiver) {
     472      141847 :   return GetConstructorHelper(receiver).first;
     473             : }
     474             : 
     475             : // static
     476     3783556 : Handle<String> JSReceiver::GetConstructorName(Handle<JSReceiver> receiver) {
     477     3783556 :   return GetConstructorHelper(receiver).second;
     478             : }
     479             : 
     480      406932 : Handle<NativeContext> JSReceiver::GetCreationContext() {
     481      406932 :   JSReceiver receiver = *this;
     482             :   // Externals are JSObjects with null as a constructor.
     483             :   DCHECK(!receiver->IsExternal(GetIsolate()));
     484      406932 :   Object constructor = receiver->map()->GetConstructor();
     485      406932 :   JSFunction function;
     486      406932 :   if (constructor->IsJSFunction()) {
     487      195931 :     function = JSFunction::cast(constructor);
     488      211001 :   } else if (constructor->IsFunctionTemplateInfo()) {
     489             :     // Remote objects don't have a creation context.
     490           2 :     return Handle<NativeContext>::null();
     491      210999 :   } else if (receiver->IsJSGeneratorObject()) {
     492           0 :     function = JSGeneratorObject::cast(receiver)->function();
     493             :   } else {
     494             :     // Functions have null as a constructor,
     495             :     // but any JSFunction knows its context immediately.
     496      210999 :     CHECK(receiver->IsJSFunction());
     497      210999 :     function = JSFunction::cast(receiver);
     498             :   }
     499             : 
     500      406930 :   return function->has_context()
     501             :              ? Handle<NativeContext>(function->context()->native_context(),
     502             :                                      receiver->GetIsolate())
     503      406930 :              : Handle<NativeContext>::null();
     504             : }
     505             : 
     506             : // static
     507        3752 : MaybeHandle<NativeContext> JSReceiver::GetFunctionRealm(
     508             :     Handle<JSReceiver> receiver) {
     509        3752 :   if (receiver->IsJSProxy()) {
     510          36 :     return JSProxy::GetFunctionRealm(Handle<JSProxy>::cast(receiver));
     511             :   }
     512             : 
     513        3716 :   if (receiver->IsJSFunction()) {
     514        3707 :     return JSFunction::GetFunctionRealm(Handle<JSFunction>::cast(receiver));
     515             :   }
     516             : 
     517           9 :   if (receiver->IsJSBoundFunction()) {
     518             :     return JSBoundFunction::GetFunctionRealm(
     519           9 :         Handle<JSBoundFunction>::cast(receiver));
     520             :   }
     521             : 
     522             :   return JSObject::GetFunctionRealm(Handle<JSObject>::cast(receiver));
     523             : }
     524             : 
     525             : // static
     526        7941 : MaybeHandle<NativeContext> JSReceiver::GetContextForMicrotask(
     527             :     Handle<JSReceiver> receiver) {
     528             :   Isolate* isolate = receiver->GetIsolate();
     529       16350 :   while (receiver->IsJSBoundFunction() || receiver->IsJSProxy()) {
     530         468 :     if (receiver->IsJSBoundFunction()) {
     531             :       receiver = handle(
     532             :           Handle<JSBoundFunction>::cast(receiver)->bound_target_function(),
     533             :           isolate);
     534             :     } else {
     535             :       DCHECK(receiver->IsJSProxy());
     536             :       Handle<Object> target(Handle<JSProxy>::cast(receiver)->target(), isolate);
     537           2 :       if (!target->IsJSReceiver()) return MaybeHandle<NativeContext>();
     538             :       receiver = Handle<JSReceiver>::cast(target);
     539             :     }
     540             :   }
     541             : 
     542        7940 :   if (!receiver->IsJSFunction()) return MaybeHandle<NativeContext>();
     543        7940 :   return handle(Handle<JSFunction>::cast(receiver)->native_context(), isolate);
     544             : }
     545             : 
     546    15631286 : Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes(
     547             :     LookupIterator* it) {
     548    20231777 :   for (; it->IsFound(); it->Next()) {
     549    12175828 :     switch (it->state()) {
     550             :       case LookupIterator::NOT_FOUND:
     551             :       case LookupIterator::TRANSITION:
     552           0 :         UNREACHABLE();
     553             :       case LookupIterator::JSPROXY:
     554         909 :         return JSProxy::GetPropertyAttributes(it);
     555             :       case LookupIterator::INTERCEPTOR: {
     556             :         Maybe<PropertyAttributes> result =
     557             :             JSObject::GetPropertyAttributesWithInterceptor(it);
     558         677 :         if (result.IsNothing()) return result;
     559         677 :         if (result.FromJust() != ABSENT) return result;
     560             :         break;
     561             :       }
     562             :       case LookupIterator::ACCESS_CHECK:
     563     2300003 :         if (it->HasAccess()) break;
     564          81 :         return JSObject::GetPropertyAttributesWithFailedAccessCheck(it);
     565             :       case LookupIterator::INTEGER_INDEXED_EXOTIC:
     566             :         return Just(ABSENT);
     567             :       case LookupIterator::ACCESSOR:
     568      216167 :         if (it->GetHolder<Object>()->IsJSModuleNamespace()) {
     569         792 :           return JSModuleNamespace::GetPropertyAttributes(it);
     570             :         } else {
     571             :           return Just(it->property_attributes());
     572             :         }
     573             :       case LookupIterator::DATA:
     574             :         return Just(it->property_attributes());
     575             :     }
     576             :   }
     577             :   return Just(ABSENT);
     578             : }
     579             : 
     580             : namespace {
     581             : 
     582       39176 : Object SetHashAndUpdateProperties(HeapObject properties, int hash) {
     583             :   DCHECK_NE(PropertyArray::kNoHashSentinel, hash);
     584             :   DCHECK(PropertyArray::HashField::is_valid(hash));
     585             : 
     586             :   ReadOnlyRoots roots = properties->GetReadOnlyRoots();
     587       44922 :   if (properties == roots.empty_fixed_array() ||
     588       44912 :       properties == roots.empty_property_array() ||
     589             :       properties == roots.empty_property_dictionary()) {
     590       33818 :     return Smi::FromInt(hash);
     591             :   }
     592             : 
     593        5358 :   if (properties->IsPropertyArray()) {
     594         156 :     PropertyArray::cast(properties)->SetHash(hash);
     595             :     DCHECK_LT(0, PropertyArray::cast(properties)->length());
     596         156 :     return properties;
     597             :   }
     598             : 
     599        5202 :   if (properties->IsGlobalDictionary()) {
     600             :     GlobalDictionary::cast(properties)->SetHash(hash);
     601           0 :     return properties;
     602             :   }
     603             : 
     604             :   DCHECK(properties->IsNameDictionary());
     605             :   NameDictionary::cast(properties)->SetHash(hash);
     606        5202 :   return properties;
     607             : }
     608             : 
     609    36122269 : int GetIdentityHashHelper(JSReceiver object) {
     610             :   DisallowHeapAllocation no_gc;
     611             :   Object properties = object->raw_properties_or_hash();
     612    36122269 :   if (properties->IsSmi()) {
     613       39274 :     return Smi::ToInt(properties);
     614             :   }
     615             : 
     616    36082995 :   if (properties->IsPropertyArray()) {
     617             :     return PropertyArray::cast(properties)->Hash();
     618             :   }
     619             : 
     620    20163542 :   if (properties->IsNameDictionary()) {
     621             :     return NameDictionary::cast(properties)->Hash();
     622             :   }
     623             : 
     624    17321908 :   if (properties->IsGlobalDictionary()) {
     625             :     return GlobalDictionary::cast(properties)->Hash();
     626             :   }
     627             : 
     628             : #ifdef DEBUG
     629             :   ReadOnlyRoots roots = object->GetReadOnlyRoots();
     630             :   DCHECK(properties == roots.empty_fixed_array() ||
     631             :          properties == roots.empty_property_dictionary());
     632             : #endif
     633             : 
     634             :   return PropertyArray::kNoHashSentinel;
     635             : }
     636             : }  // namespace
     637             : 
     638       33888 : void JSReceiver::SetIdentityHash(int hash) {
     639             :   DisallowHeapAllocation no_gc;
     640             :   DCHECK_NE(PropertyArray::kNoHashSentinel, hash);
     641             :   DCHECK(PropertyArray::HashField::is_valid(hash));
     642             : 
     643       33888 :   HeapObject existing_properties = HeapObject::cast(raw_properties_or_hash());
     644       33888 :   Object new_properties = SetHashAndUpdateProperties(existing_properties, hash);
     645       33888 :   set_raw_properties_or_hash(new_properties);
     646       33888 : }
     647             : 
     648    36059450 : void JSReceiver::SetProperties(HeapObject properties) {
     649             :   DCHECK_IMPLIES(properties->IsPropertyArray() &&
     650             :                      PropertyArray::cast(properties)->length() == 0,
     651             :                  properties == GetReadOnlyRoots().empty_property_array());
     652             :   DisallowHeapAllocation no_gc;
     653    36059450 :   int hash = GetIdentityHashHelper(*this);
     654    36059460 :   Object new_properties = properties;
     655             : 
     656             :   // TODO(cbruni): Make GetIdentityHashHelper return a bool so that we
     657             :   // don't have to manually compare against kNoHashSentinel.
     658    36059460 :   if (hash != PropertyArray::kNoHashSentinel) {
     659        5288 :     new_properties = SetHashAndUpdateProperties(properties, hash);
     660             :   }
     661             : 
     662    36059460 :   set_raw_properties_or_hash(new_properties);
     663    36059463 : }
     664             : 
     665       41188 : Object JSReceiver::GetIdentityHash() {
     666             :   DisallowHeapAllocation no_gc;
     667             : 
     668       41188 :   int hash = GetIdentityHashHelper(*this);
     669       41188 :   if (hash == PropertyArray::kNoHashSentinel) {
     670        2314 :     return GetReadOnlyRoots().undefined_value();
     671             :   }
     672             : 
     673       38874 :   return Smi::FromInt(hash);
     674             : }
     675             : 
     676             : // static
     677       33853 : Smi JSReceiver::CreateIdentityHash(Isolate* isolate, JSReceiver key) {
     678             :   DisallowHeapAllocation no_gc;
     679       33853 :   int hash = isolate->GenerateIdentityHash(PropertyArray::HashField::kMax);
     680             :   DCHECK_NE(PropertyArray::kNoHashSentinel, hash);
     681             : 
     682       33853 :   key->SetIdentityHash(hash);
     683       33853 :   return Smi::FromInt(hash);
     684             : }
     685             : 
     686       21616 : Smi JSReceiver::GetOrCreateIdentityHash(Isolate* isolate) {
     687             :   DisallowHeapAllocation no_gc;
     688             : 
     689       21616 :   int hash = GetIdentityHashHelper(*this);
     690       21616 :   if (hash != PropertyArray::kNoHashSentinel) {
     691             :     return Smi::FromInt(hash);
     692             :   }
     693             : 
     694       21106 :   return JSReceiver::CreateIdentityHash(isolate, *this);
     695             : }
     696             : 
     697       54307 : void JSReceiver::DeleteNormalizedProperty(Handle<JSReceiver> object,
     698             :                                           int entry) {
     699             :   DCHECK(!object->HasFastProperties());
     700             :   Isolate* isolate = object->GetIsolate();
     701             : 
     702       54307 :   if (object->IsJSGlobalObject()) {
     703             :     // If we have a global object, invalidate the cell and swap in a new one.
     704             :     Handle<GlobalDictionary> dictionary(
     705             :         JSGlobalObject::cast(*object)->global_dictionary(), isolate);
     706             :     DCHECK_NE(GlobalDictionary::kNotFound, entry);
     707             : 
     708       11297 :     auto cell = PropertyCell::InvalidateEntry(isolate, dictionary, entry);
     709       22594 :     cell->set_value(ReadOnlyRoots(isolate).the_hole_value());
     710       22594 :     cell->set_property_details(
     711             :         PropertyDetails::Empty(PropertyCellType::kUninitialized));
     712             :   } else {
     713       86020 :     Handle<NameDictionary> dictionary(object->property_dictionary(), isolate);
     714             :     DCHECK_NE(NameDictionary::kNotFound, entry);
     715             : 
     716       43010 :     dictionary = NameDictionary::DeleteEntry(isolate, dictionary, entry);
     717       86020 :     object->SetProperties(*dictionary);
     718             :   }
     719       54307 :   if (object->map()->is_prototype_map()) {
     720             :     // Invalidate prototype validity cell as this may invalidate transitioning
     721             :     // store IC handlers.
     722             :     JSObject::InvalidatePrototypeChains(object->map());
     723             :   }
     724       54307 : }
     725             : 
     726     6390763 : Maybe<bool> JSReceiver::DeleteProperty(LookupIterator* it,
     727             :                                        LanguageMode language_mode) {
     728     6390763 :   it->UpdateProtector();
     729             : 
     730             :   Isolate* isolate = it->isolate();
     731             : 
     732     6390763 :   if (it->state() == LookupIterator::JSPROXY) {
     733             :     return JSProxy::DeletePropertyOrElement(it->GetHolder<JSProxy>(),
     734       28928 :                                             it->GetName(), language_mode);
     735             :   }
     736             : 
     737     6361835 :   if (it->GetReceiver()->IsJSProxy()) {
     738          39 :     if (it->state() != LookupIterator::NOT_FOUND) {
     739             :       DCHECK_EQ(LookupIterator::DATA, it->state());
     740             :       DCHECK(it->name()->IsPrivate());
     741           6 :       it->Delete();
     742             :     }
     743             :     return Just(true);
     744             :   }
     745             :   Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
     746             : 
     747     6381630 :   for (; it->IsFound(); it->Next()) {
     748      170391 :     switch (it->state()) {
     749             :       case LookupIterator::JSPROXY:
     750             :       case LookupIterator::NOT_FOUND:
     751             :       case LookupIterator::TRANSITION:
     752           0 :         UNREACHABLE();
     753             :       case LookupIterator::ACCESS_CHECK:
     754        9877 :         if (it->HasAccess()) break;
     755          36 :         isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>());
     756          36 :         RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
     757             :         return Just(false);
     758             :       case LookupIterator::INTERCEPTOR: {
     759             :         ShouldThrow should_throw =
     760         100 :             is_sloppy(language_mode) ? kDontThrow : kThrowOnError;
     761             :         Maybe<bool> result =
     762         100 :             JSObject::DeletePropertyWithInterceptor(it, should_throw);
     763             :         // An exception was thrown in the interceptor. Propagate.
     764         124 :         if (isolate->has_pending_exception()) return Nothing<bool>();
     765             :         // Delete with interceptor succeeded. Return result.
     766             :         // TODO(neis): In strict mode, we should probably throw if the
     767             :         // interceptor returns false.
     768         100 :         if (result.IsJust()) return result;
     769          76 :         break;
     770             :       }
     771             :       case LookupIterator::INTEGER_INDEXED_EXOTIC:
     772             :         return Just(true);
     773             :       case LookupIterator::DATA:
     774             :       case LookupIterator::ACCESSOR: {
     775      160369 :         if (!it->IsConfigurable()) {
     776             :           // Fail if the property is not configurable.
     777        2554 :           if (is_strict(language_mode)) {
     778        1502 :             isolate->Throw(*isolate->factory()->NewTypeError(
     779             :                 MessageTemplate::kStrictDeleteProperty, it->GetName(),
     780        2253 :                 receiver));
     781             :             return Nothing<bool>();
     782             :           }
     783             :           return Just(false);
     784             :         }
     785             : 
     786      157815 :         it->Delete();
     787             : 
     788             :         return Just(true);
     789             :       }
     790             :     }
     791             :   }
     792             : 
     793             :   return Just(true);
     794             : }
     795             : 
     796        1027 : Maybe<bool> JSReceiver::DeleteElement(Handle<JSReceiver> object, uint32_t index,
     797             :                                       LanguageMode language_mode) {
     798             :   LookupIterator it(object->GetIsolate(), object, index, object,
     799             :                     LookupIterator::OWN);
     800        1027 :   return DeleteProperty(&it, language_mode);
     801             : }
     802             : 
     803         891 : Maybe<bool> JSReceiver::DeleteProperty(Handle<JSReceiver> object,
     804             :                                        Handle<Name> name,
     805             :                                        LanguageMode language_mode) {
     806             :   LookupIterator it(object, name, object, LookupIterator::OWN);
     807         891 :   return DeleteProperty(&it, language_mode);
     808             : }
     809             : 
     810       32766 : Maybe<bool> JSReceiver::DeletePropertyOrElement(Handle<JSReceiver> object,
     811             :                                                 Handle<Name> name,
     812             :                                                 LanguageMode language_mode) {
     813             :   LookupIterator it = LookupIterator::PropertyOrElement(
     814       32766 :       object->GetIsolate(), object, name, object, LookupIterator::OWN);
     815       32766 :   return DeleteProperty(&it, language_mode);
     816             : }
     817             : 
     818             : // ES6 19.1.2.4
     819             : // static
     820      114595 : Object JSReceiver::DefineProperty(Isolate* isolate, Handle<Object> object,
     821             :                                   Handle<Object> key,
     822             :                                   Handle<Object> attributes) {
     823             :   // 1. If Type(O) is not Object, throw a TypeError exception.
     824      114595 :   if (!object->IsJSReceiver()) {
     825             :     Handle<String> fun_name =
     826          63 :         isolate->factory()->InternalizeUtf8String("Object.defineProperty");
     827         126 :     THROW_NEW_ERROR_RETURN_FAILURE(
     828             :         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, fun_name));
     829             :   }
     830             :   // 2. Let key be ToPropertyKey(P).
     831             :   // 3. ReturnIfAbrupt(key).
     832      229064 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key,
     833             :                                      Object::ToPropertyKey(isolate, key));
     834             :   // 4. Let desc be ToPropertyDescriptor(Attributes).
     835             :   // 5. ReturnIfAbrupt(desc).
     836             :   PropertyDescriptor desc;
     837      114532 :   if (!PropertyDescriptor::ToPropertyDescriptor(isolate, attributes, &desc)) {
     838         135 :     return ReadOnlyRoots(isolate).exception();
     839             :   }
     840             :   // 6. Let success be DefinePropertyOrThrow(O,key, desc).
     841             :   Maybe<bool> success =
     842             :       DefineOwnProperty(isolate, Handle<JSReceiver>::cast(object), key, &desc,
     843      114397 :                         Just(kThrowOnError));
     844             :   // 7. ReturnIfAbrupt(success).
     845      115464 :   MAYBE_RETURN(success, ReadOnlyRoots(isolate).exception());
     846      113330 :   CHECK(success.FromJust());
     847             :   // 8. Return O.
     848             :   return *object;
     849             : }
     850             : 
     851             : // ES6 19.1.2.3.1
     852             : // static
     853        1829 : MaybeHandle<Object> JSReceiver::DefineProperties(Isolate* isolate,
     854             :                                                  Handle<Object> object,
     855             :                                                  Handle<Object> properties) {
     856             :   // 1. If Type(O) is not Object, throw a TypeError exception.
     857        1829 :   if (!object->IsJSReceiver()) {
     858             :     Handle<String> fun_name =
     859          27 :         isolate->factory()->InternalizeUtf8String("Object.defineProperties");
     860          54 :     THROW_NEW_ERROR(isolate,
     861             :                     NewTypeError(MessageTemplate::kCalledOnNonObject, fun_name),
     862             :                     Object);
     863             :   }
     864             :   // 2. Let props be ToObject(Properties).
     865             :   // 3. ReturnIfAbrupt(props).
     866             :   Handle<JSReceiver> props;
     867        3604 :   ASSIGN_RETURN_ON_EXCEPTION(isolate, props,
     868             :                              Object::ToObject(isolate, properties), Object);
     869             : 
     870             :   // 4. Let keys be props.[[OwnPropertyKeys]]().
     871             :   // 5. ReturnIfAbrupt(keys).
     872             :   Handle<FixedArray> keys;
     873        3586 :   ASSIGN_RETURN_ON_EXCEPTION(
     874             :       isolate, keys,
     875             :       KeyAccumulator::GetKeys(props, KeyCollectionMode::kOwnOnly,
     876             :                               ALL_PROPERTIES),
     877             :       Object);
     878             :   // 6. Let descriptors be an empty List.
     879             :   int capacity = keys->length();
     880        1793 :   std::vector<PropertyDescriptor> descriptors(capacity);
     881             :   size_t descriptors_index = 0;
     882             :   // 7. Repeat for each element nextKey of keys in List order,
     883       11791 :   for (int i = 0; i < keys->length(); ++i) {
     884             :     Handle<Object> next_key(keys->get(i), isolate);
     885             :     // 7a. Let propDesc be props.[[GetOwnProperty]](nextKey).
     886             :     // 7b. ReturnIfAbrupt(propDesc).
     887        5224 :     bool success = false;
     888             :     LookupIterator it = LookupIterator::PropertyOrElement(
     889        5224 :         isolate, props, next_key, &success, LookupIterator::OWN);
     890             :     DCHECK(success);
     891        5224 :     Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
     892        5224 :     if (maybe.IsNothing()) return MaybeHandle<Object>();
     893             :     PropertyAttributes attrs = maybe.FromJust();
     894             :     // 7c. If propDesc is not undefined and propDesc.[[Enumerable]] is true:
     895        6348 :     if (attrs == ABSENT) continue;
     896        5224 :     if (attrs & DONT_ENUM) continue;
     897             :     // 7c i. Let descObj be Get(props, nextKey).
     898             :     // 7c ii. ReturnIfAbrupt(descObj).
     899             :     Handle<Object> desc_obj;
     900        8200 :     ASSIGN_RETURN_ON_EXCEPTION(isolate, desc_obj, Object::GetProperty(&it),
     901             :                                Object);
     902             :     // 7c iii. Let desc be ToPropertyDescriptor(descObj).
     903        4100 :     success = PropertyDescriptor::ToPropertyDescriptor(
     904        4100 :         isolate, desc_obj, &descriptors[descriptors_index]);
     905             :     // 7c iv. ReturnIfAbrupt(desc).
     906        4100 :     if (!success) return MaybeHandle<Object>();
     907             :     // 7c v. Append the pair (a two element List) consisting of nextKey and
     908             :     //       desc to the end of descriptors.
     909             :     descriptors[descriptors_index].set_name(next_key);
     910        3875 :     descriptors_index++;
     911             :   }
     912             :   // 8. For each pair from descriptors in list order,
     913        8544 :   for (size_t i = 0; i < descriptors_index; ++i) {
     914             :     PropertyDescriptor* desc = &descriptors[i];
     915             :     // 8a. Let P be the first element of pair.
     916             :     // 8b. Let desc be the second element of pair.
     917             :     // 8c. Let status be DefinePropertyOrThrow(O, P, desc).
     918             :     Maybe<bool> status =
     919             :         DefineOwnProperty(isolate, Handle<JSReceiver>::cast(object),
     920        3488 :                           desc->name(), desc, Just(kThrowOnError));
     921             :     // 8d. ReturnIfAbrupt(status).
     922        3488 :     if (status.IsNothing()) return MaybeHandle<Object>();
     923        3488 :     CHECK(status.FromJust());
     924             :   }
     925             :   // 9. Return o.
     926        1568 :   return object;
     927             : }
     928             : 
     929             : // static
     930      587073 : Maybe<bool> JSReceiver::DefineOwnProperty(Isolate* isolate,
     931             :                                           Handle<JSReceiver> object,
     932             :                                           Handle<Object> key,
     933             :                                           PropertyDescriptor* desc,
     934             :                                           Maybe<ShouldThrow> should_throw) {
     935      587073 :   if (object->IsJSArray()) {
     936             :     return JSArray::DefineOwnProperty(isolate, Handle<JSArray>::cast(object),
     937       29678 :                                       key, desc, should_throw);
     938             :   }
     939      557395 :   if (object->IsJSProxy()) {
     940             :     return JSProxy::DefineOwnProperty(isolate, Handle<JSProxy>::cast(object),
     941       55721 :                                       key, desc, should_throw);
     942             :   }
     943      501674 :   if (object->IsJSTypedArray()) {
     944             :     return JSTypedArray::DefineOwnProperty(
     945        3610 :         isolate, Handle<JSTypedArray>::cast(object), key, desc, should_throw);
     946             :   }
     947             : 
     948             :   // OrdinaryDefineOwnProperty, by virtue of calling
     949             :   // DefineOwnPropertyIgnoreAttributes, can handle arguments
     950             :   // (ES#sec-arguments-exotic-objects-defineownproperty-p-desc).
     951             :   return OrdinaryDefineOwnProperty(isolate, Handle<JSObject>::cast(object), key,
     952      498064 :                                    desc, should_throw);
     953             : }
     954             : 
     955             : // static
     956      537031 : Maybe<bool> JSReceiver::OrdinaryDefineOwnProperty(
     957             :     Isolate* isolate, Handle<JSObject> object, Handle<Object> key,
     958             :     PropertyDescriptor* desc, Maybe<ShouldThrow> should_throw) {
     959      537031 :   bool success = false;
     960             :   DCHECK(key->IsName() || key->IsNumber());  // |key| is a PropertyKey...
     961             :   LookupIterator it = LookupIterator::PropertyOrElement(
     962      537031 :       isolate, object, key, &success, LookupIterator::OWN);
     963             :   DCHECK(success);  // ...so creating a LookupIterator can't fail.
     964             : 
     965             :   // Deal with access checks first.
     966      537031 :   if (it.state() == LookupIterator::ACCESS_CHECK) {
     967        2459 :     if (!it.HasAccess()) {
     968          30 :       isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>());
     969          30 :       RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
     970             :       return Just(true);
     971             :     }
     972        2429 :     it.Next();
     973             :   }
     974             : 
     975      537001 :   return OrdinaryDefineOwnProperty(&it, desc, should_throw);
     976             : }
     977             : 
     978             : namespace {
     979             : 
     980      135010 : MaybeHandle<Object> GetPropertyWithInterceptorInternal(
     981             :     LookupIterator* it, Handle<InterceptorInfo> interceptor, bool* done) {
     982      135010 :   *done = false;
     983             :   Isolate* isolate = it->isolate();
     984             :   // Make sure that the top context does not change when doing callbacks or
     985             :   // interceptor calls.
     986             :   AssertNoContextChange ncc(isolate);
     987             : 
     988      135010 :   if (interceptor->getter()->IsUndefined(isolate)) {
     989         254 :     return isolate->factory()->undefined_value();
     990             :   }
     991             : 
     992             :   Handle<JSObject> holder = it->GetHolder<JSObject>();
     993             :   Handle<Object> result;
     994             :   Handle<Object> receiver = it->GetReceiver();
     995      134756 :   if (!receiver->IsJSReceiver()) {
     996          32 :     ASSIGN_RETURN_ON_EXCEPTION(
     997             :         isolate, receiver, Object::ConvertReceiver(isolate, receiver), Object);
     998             :   }
     999             :   PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
    1000      134756 :                                  *holder, Just(kDontThrow));
    1001             : 
    1002      134756 :   if (it->IsElement()) {
    1003        2350 :     result = args.CallIndexedGetter(interceptor, it->index());
    1004             :   } else {
    1005      132406 :     result = args.CallNamedGetter(interceptor, it->name());
    1006             :   }
    1007             : 
    1008      134756 :   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
    1009      266197 :   if (result.is_null()) return isolate->factory()->undefined_value();
    1010        3259 :   *done = true;
    1011             :   // Rebox handle before return
    1012        3259 :   return handle(*result, isolate);
    1013             : }
    1014             : 
    1015      292441 : Maybe<PropertyAttributes> GetPropertyAttributesWithInterceptorInternal(
    1016             :     LookupIterator* it, Handle<InterceptorInfo> interceptor) {
    1017             :   Isolate* isolate = it->isolate();
    1018             :   // Make sure that the top context does not change when doing
    1019             :   // callbacks or interceptor calls.
    1020             :   AssertNoContextChange ncc(isolate);
    1021             :   HandleScope scope(isolate);
    1022             : 
    1023             :   Handle<JSObject> holder = it->GetHolder<JSObject>();
    1024             :   DCHECK_IMPLIES(!it->IsElement() && it->name()->IsSymbol(),
    1025             :                  interceptor->can_intercept_symbols());
    1026             :   Handle<Object> receiver = it->GetReceiver();
    1027      292441 :   if (!receiver->IsJSReceiver()) {
    1028          24 :     ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
    1029             :                                      Object::ConvertReceiver(isolate, receiver),
    1030             :                                      Nothing<PropertyAttributes>());
    1031             :   }
    1032             :   PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
    1033      292441 :                                  *holder, Just(kDontThrow));
    1034      292441 :   if (!interceptor->query()->IsUndefined(isolate)) {
    1035             :     Handle<Object> result;
    1036       35586 :     if (it->IsElement()) {
    1037        5340 :       result = args.CallIndexedQuery(interceptor, it->index());
    1038             :     } else {
    1039       30246 :       result = args.CallNamedQuery(interceptor, it->name());
    1040             :     }
    1041       35586 :     if (!result.is_null()) {
    1042             :       int32_t value;
    1043       28385 :       CHECK(result->ToInt32(&value));
    1044       28385 :       return Just(static_cast<PropertyAttributes>(value));
    1045             :     }
    1046      256855 :   } else if (!interceptor->getter()->IsUndefined(isolate)) {
    1047             :     // TODO(verwaest): Use GetPropertyWithInterceptor?
    1048             :     Handle<Object> result;
    1049      256735 :     if (it->IsElement()) {
    1050      241208 :       result = args.CallIndexedGetter(interceptor, it->index());
    1051             :     } else {
    1052       15527 :       result = args.CallNamedGetter(interceptor, it->name());
    1053             :     }
    1054      256735 :     if (!result.is_null()) return Just(DONT_ENUM);
    1055             :   }
    1056             : 
    1057      247636 :   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
    1058             :   return Just(ABSENT);
    1059             : }
    1060             : 
    1061      193298 : Maybe<bool> SetPropertyWithInterceptorInternal(
    1062             :     LookupIterator* it, Handle<InterceptorInfo> interceptor,
    1063             :     Maybe<ShouldThrow> should_throw, Handle<Object> value) {
    1064             :   Isolate* isolate = it->isolate();
    1065             :   // Make sure that the top context does not change when doing callbacks or
    1066             :   // interceptor calls.
    1067             :   AssertNoContextChange ncc(isolate);
    1068             : 
    1069      193298 :   if (interceptor->setter()->IsUndefined(isolate)) return Just(false);
    1070             : 
    1071             :   Handle<JSObject> holder = it->GetHolder<JSObject>();
    1072             :   bool result;
    1073             :   Handle<Object> receiver = it->GetReceiver();
    1074      186484 :   if (!receiver->IsJSReceiver()) {
    1075           0 :     ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
    1076             :                                      Object::ConvertReceiver(isolate, receiver),
    1077             :                                      Nothing<bool>());
    1078             :   }
    1079             :   PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
    1080      186484 :                                  *holder, should_throw);
    1081             : 
    1082      186484 :   if (it->IsElement()) {
    1083             :     // TODO(neis): In the future, we may want to actually return the
    1084             :     // interceptor's result, which then should be a boolean.
    1085      131338 :     result = !args.CallIndexedSetter(interceptor, it->index(), value).is_null();
    1086             :   } else {
    1087      241630 :     result = !args.CallNamedSetter(interceptor, it->name(), value).is_null();
    1088             :   }
    1089             : 
    1090      186484 :   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
    1091             :   return Just(result);
    1092             : }
    1093             : 
    1094         183 : Maybe<bool> DefinePropertyWithInterceptorInternal(
    1095             :     LookupIterator* it, Handle<InterceptorInfo> interceptor,
    1096             :     Maybe<ShouldThrow> should_throw, PropertyDescriptor& desc) {
    1097             :   Isolate* isolate = it->isolate();
    1098             :   // Make sure that the top context does not change when doing callbacks or
    1099             :   // interceptor calls.
    1100             :   AssertNoContextChange ncc(isolate);
    1101             : 
    1102         183 :   if (interceptor->definer()->IsUndefined(isolate)) return Just(false);
    1103             : 
    1104             :   Handle<JSObject> holder = it->GetHolder<JSObject>();
    1105             :   bool result;
    1106             :   Handle<Object> receiver = it->GetReceiver();
    1107          87 :   if (!receiver->IsJSReceiver()) {
    1108           0 :     ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
    1109             :                                      Object::ConvertReceiver(isolate, receiver),
    1110             :                                      Nothing<bool>());
    1111             :   }
    1112             :   PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
    1113          87 :                                  *holder, should_throw);
    1114             : 
    1115             :   std::unique_ptr<v8::PropertyDescriptor> descriptor(
    1116         174 :       new v8::PropertyDescriptor());
    1117          87 :   if (PropertyDescriptor::IsAccessorDescriptor(&desc)) {
    1118          33 :     descriptor.reset(new v8::PropertyDescriptor(
    1119          66 :         v8::Utils::ToLocal(desc.get()), v8::Utils::ToLocal(desc.set())));
    1120          54 :   } else if (PropertyDescriptor::IsDataDescriptor(&desc)) {
    1121          44 :     if (desc.has_writable()) {
    1122           6 :       descriptor.reset(new v8::PropertyDescriptor(
    1123          12 :           v8::Utils::ToLocal(desc.value()), desc.writable()));
    1124             :     } else {
    1125          38 :       descriptor.reset(
    1126          76 :           new v8::PropertyDescriptor(v8::Utils::ToLocal(desc.value())));
    1127             :     }
    1128             :   }
    1129          87 :   if (desc.has_enumerable()) {
    1130          24 :     descriptor->set_enumerable(desc.enumerable());
    1131             :   }
    1132          87 :   if (desc.has_configurable()) {
    1133          24 :     descriptor->set_configurable(desc.configurable());
    1134             :   }
    1135             : 
    1136          87 :   if (it->IsElement()) {
    1137          48 :     result = !args.CallIndexedDefiner(interceptor, it->index(), *descriptor)
    1138          24 :                   .is_null();
    1139             :   } else {
    1140             :     result =
    1141         126 :         !args.CallNamedDefiner(interceptor, it->name(), *descriptor).is_null();
    1142             :   }
    1143             : 
    1144          87 :   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
    1145             :   return Just(result);
    1146             : }
    1147             : 
    1148             : }  // namespace
    1149             : 
    1150             : // ES6 9.1.6.1
    1151             : // static
    1152      536997 : Maybe<bool> JSReceiver::OrdinaryDefineOwnProperty(
    1153             :     LookupIterator* it, PropertyDescriptor* desc,
    1154             :     Maybe<ShouldThrow> should_throw) {
    1155             :   Isolate* isolate = it->isolate();
    1156             :   // 1. Let current be O.[[GetOwnProperty]](P).
    1157             :   // 2. ReturnIfAbrupt(current).
    1158             :   PropertyDescriptor current;
    1159     1073993 :   MAYBE_RETURN(GetOwnPropertyDescriptor(it, &current), Nothing<bool>());
    1160             : 
    1161      536978 :   it->Restart();
    1162             :   // Handle interceptor
    1163      910489 :   for (; it->IsFound(); it->Next()) {
    1164      186810 :     if (it->state() == LookupIterator::INTERCEPTOR) {
    1165         183 :       if (it->HolderIsReceiverOrHiddenPrototype()) {
    1166             :         Maybe<bool> result = DefinePropertyWithInterceptorInternal(
    1167         183 :             it, it->GetInterceptor(), should_throw, *desc);
    1168         366 :         if (result.IsNothing() || result.FromJust()) {
    1169          54 :           return result;
    1170             :         }
    1171             :       }
    1172             :     }
    1173             :   }
    1174             : 
    1175             :   // TODO(jkummerow/verwaest): It would be nice if we didn't have to reset
    1176             :   // the iterator every time. Currently, the reasons why we need it are:
    1177             :   // - handle interceptors correctly
    1178             :   // - handle accessors correctly (which might change the holder's map)
    1179      536923 :   it->Restart();
    1180             :   // 3. Let extensible be the value of the [[Extensible]] internal slot of O.
    1181      536927 :   Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
    1182      536927 :   bool extensible = JSObject::IsExtensible(object);
    1183             : 
    1184             :   return ValidateAndApplyPropertyDescriptor(
    1185      536923 :       isolate, it, extensible, desc, &current, should_throw, Handle<Name>());
    1186             : }
    1187             : 
    1188             : // ES6 9.1.6.2
    1189             : // static
    1190        4608 : Maybe<bool> JSReceiver::IsCompatiblePropertyDescriptor(
    1191             :     Isolate* isolate, bool extensible, PropertyDescriptor* desc,
    1192             :     PropertyDescriptor* current, Handle<Name> property_name,
    1193             :     Maybe<ShouldThrow> should_throw) {
    1194             :   // 1. Return ValidateAndApplyPropertyDescriptor(undefined, undefined,
    1195             :   //    Extensible, Desc, Current).
    1196             :   return ValidateAndApplyPropertyDescriptor(
    1197        4608 :       isolate, nullptr, extensible, desc, current, should_throw, property_name);
    1198             : }
    1199             : 
    1200             : // ES6 9.1.6.3
    1201             : // static
    1202      541530 : Maybe<bool> JSReceiver::ValidateAndApplyPropertyDescriptor(
    1203             :     Isolate* isolate, LookupIterator* it, bool extensible,
    1204             :     PropertyDescriptor* desc, PropertyDescriptor* current,
    1205             :     Maybe<ShouldThrow> should_throw, Handle<Name> property_name) {
    1206             :   // We either need a LookupIterator, or a property name.
    1207             :   DCHECK((it == nullptr) != property_name.is_null());
    1208             :   Handle<JSObject> object;
    1209             :   if (it != nullptr) object = Handle<JSObject>::cast(it->GetReceiver());
    1210             :   bool desc_is_data_descriptor = PropertyDescriptor::IsDataDescriptor(desc);
    1211             :   bool desc_is_accessor_descriptor =
    1212             :       PropertyDescriptor::IsAccessorDescriptor(desc);
    1213             :   bool desc_is_generic_descriptor =
    1214             :       PropertyDescriptor::IsGenericDescriptor(desc);
    1215             :   // 1. (Assert)
    1216             :   // 2. If current is undefined, then
    1217      541530 :   if (current->is_empty()) {
    1218             :     // 2a. If extensible is false, return false.
    1219      355421 :     if (!extensible) {
    1220         310 :       RETURN_FAILURE(
    1221             :           isolate, GetShouldThrow(isolate, should_throw),
    1222             :           NewTypeError(MessageTemplate::kDefineDisallowed,
    1223             :                        it != nullptr ? it->GetName() : property_name));
    1224             :     }
    1225             :     // 2c. If IsGenericDescriptor(Desc) or IsDataDescriptor(Desc) is true, then:
    1226             :     // (This is equivalent to !IsAccessorDescriptor(desc).)
    1227             :     DCHECK((desc_is_generic_descriptor || desc_is_data_descriptor) ==
    1228             :            !desc_is_accessor_descriptor);
    1229      355309 :     if (!desc_is_accessor_descriptor) {
    1230             :       // 2c i. If O is not undefined, create an own data property named P of
    1231             :       // object O whose [[Value]], [[Writable]], [[Enumerable]] and
    1232             :       // [[Configurable]] attribute values are described by Desc. If the value
    1233             :       // of an attribute field of Desc is absent, the attribute of the newly
    1234             :       // created property is set to its default value.
    1235      287320 :       if (it != nullptr) {
    1236      284765 :         if (!desc->has_writable()) desc->set_writable(false);
    1237      284765 :         if (!desc->has_enumerable()) desc->set_enumerable(false);
    1238      284765 :         if (!desc->has_configurable()) desc->set_configurable(false);
    1239             :         Handle<Object> value(
    1240             :             desc->has_value()
    1241             :                 ? desc->value()
    1242      294276 :                 : Handle<Object>::cast(isolate->factory()->undefined_value()));
    1243             :         MaybeHandle<Object> result =
    1244             :             JSObject::DefineOwnPropertyIgnoreAttributes(it, value,
    1245      284765 :                                                         desc->ToAttributes());
    1246      284768 :         if (result.is_null()) return Nothing<bool>();
    1247             :       }
    1248             :     } else {
    1249             :       // 2d. Else Desc must be an accessor Property Descriptor,
    1250             :       DCHECK(desc_is_accessor_descriptor);
    1251             :       // 2d i. If O is not undefined, create an own accessor property named P
    1252             :       // of object O whose [[Get]], [[Set]], [[Enumerable]] and
    1253             :       // [[Configurable]] attribute values are described by Desc. If the value
    1254             :       // of an attribute field of Desc is absent, the attribute of the newly
    1255             :       // created property is set to its default value.
    1256       67989 :       if (it != nullptr) {
    1257       67845 :         if (!desc->has_enumerable()) desc->set_enumerable(false);
    1258       67845 :         if (!desc->has_configurable()) desc->set_configurable(false);
    1259             :         Handle<Object> getter(
    1260             :             desc->has_get()
    1261             :                 ? desc->get()
    1262       80490 :                 : Handle<Object>::cast(isolate->factory()->null_value()));
    1263             :         Handle<Object> setter(
    1264             :             desc->has_set()
    1265             :                 ? desc->set()
    1266      109760 :                 : Handle<Object>::cast(isolate->factory()->null_value()));
    1267             :         MaybeHandle<Object> result =
    1268       67845 :             JSObject::DefineAccessor(it, getter, setter, desc->ToAttributes());
    1269       67845 :         if (result.is_null()) return Nothing<bool>();
    1270             :       }
    1271             :     }
    1272             :     // 2e. Return true.
    1273             :     return Just(true);
    1274             :   }
    1275             :   // 3. Return true, if every field in Desc is absent.
    1276             :   // 4. Return true, if every field in Desc also occurs in current and the
    1277             :   // value of every field in Desc is the same value as the corresponding field
    1278             :   // in current when compared using the SameValue algorithm.
    1279      330086 :   if ((!desc->has_enumerable() ||
    1280       69952 :        desc->enumerable() == current->enumerable()) &&
    1281       46694 :       (!desc->has_configurable() ||
    1282       67576 :        desc->configurable() == current->configurable()) &&
    1283       49911 :       (!desc->has_value() ||
    1284      278985 :        (current->has_value() && current->value()->SameValue(*desc->value()))) &&
    1285       26536 :       (!desc->has_writable() ||
    1286       68824 :        (current->has_writable() && current->writable() == desc->writable())) &&
    1287        5821 :       (!desc->has_get() ||
    1288      412914 :        (current->has_get() && current->get()->SameValue(*desc->get()))) &&
    1289        7215 :       (!desc->has_set() ||
    1290        7017 :        (current->has_set() && current->set()->SameValue(*desc->set())))) {
    1291             :     return Just(true);
    1292             :   }
    1293             :   // 5. If the [[Configurable]] field of current is false, then
    1294      156510 :   if (!current->configurable()) {
    1295             :     // 5a. Return false, if the [[Configurable]] field of Desc is true.
    1296        7879 :     if (desc->has_configurable() && desc->configurable()) {
    1297         543 :       RETURN_FAILURE(
    1298             :           isolate, GetShouldThrow(isolate, should_throw),
    1299             :           NewTypeError(MessageTemplate::kRedefineDisallowed,
    1300             :                        it != nullptr ? it->GetName() : property_name));
    1301             :     }
    1302             :     // 5b. Return false, if the [[Enumerable]] field of Desc is present and the
    1303             :     // [[Enumerable]] fields of current and Desc are the Boolean negation of
    1304             :     // each other.
    1305        7215 :     if (desc->has_enumerable() && desc->enumerable() != current->enumerable()) {
    1306         284 :       RETURN_FAILURE(
    1307             :           isolate, GetShouldThrow(isolate, should_throw),
    1308             :           NewTypeError(MessageTemplate::kRedefineDisallowed,
    1309             :                        it != nullptr ? it->GetName() : property_name));
    1310             :     }
    1311             :   }
    1312             : 
    1313             :   bool current_is_data_descriptor =
    1314             :       PropertyDescriptor::IsDataDescriptor(current);
    1315             :   // 6. If IsGenericDescriptor(Desc) is true, no further validation is required.
    1316      156211 :   if (desc_is_generic_descriptor) {
    1317             :     // Nothing to see here.
    1318             : 
    1319             :     // 7. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) have
    1320             :     // different results, then:
    1321      155303 :   } else if (current_is_data_descriptor != desc_is_data_descriptor) {
    1322             :     // 7a. Return false, if the [[Configurable]] field of current is false.
    1323      118101 :     if (!current->configurable()) {
    1324         431 :       RETURN_FAILURE(
    1325             :           isolate, GetShouldThrow(isolate, should_throw),
    1326             :           NewTypeError(MessageTemplate::kRedefineDisallowed,
    1327             :                        it != nullptr ? it->GetName() : property_name));
    1328             :     }
    1329             :     // 7b. If IsDataDescriptor(current) is true, then:
    1330             :     if (current_is_data_descriptor) {
    1331             :       // 7b i. If O is not undefined, convert the property named P of object O
    1332             :       // from a data property to an accessor property. Preserve the existing
    1333             :       // values of the converted property's [[Configurable]] and [[Enumerable]]
    1334             :       // attributes and set the rest of the property's attributes to their
    1335             :       // default values.
    1336             :       // --> Folded into step 10.
    1337             :     } else {
    1338             :       // 7c i. If O is not undefined, convert the property named P of object O
    1339             :       // from an accessor property to a data property. Preserve the existing
    1340             :       // values of the converted property’s [[Configurable]] and [[Enumerable]]
    1341             :       // attributes and set the rest of the property’s attributes to their
    1342             :       // default values.
    1343             :       // --> Folded into step 10.
    1344             :     }
    1345             : 
    1346             :     // 8. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) are both
    1347             :     // true, then:
    1348       37202 :   } else if (current_is_data_descriptor && desc_is_data_descriptor) {
    1349             :     // 8a. If the [[Configurable]] field of current is false, then:
    1350       26189 :     if (!current->configurable()) {
    1351             :       // 8a i. Return false, if the [[Writable]] field of current is false and
    1352             :       // the [[Writable]] field of Desc is true.
    1353        4315 :       if (!current->writable() && desc->has_writable() && desc->writable()) {
    1354         189 :         RETURN_FAILURE(
    1355             :             isolate, GetShouldThrow(isolate, should_throw),
    1356             :             NewTypeError(MessageTemplate::kRedefineDisallowed,
    1357             :                          it != nullptr ? it->GetName() : property_name));
    1358             :       }
    1359             :       // 8a ii. If the [[Writable]] field of current is false, then:
    1360        3855 :       if (!current->writable()) {
    1361             :         // 8a ii 1. Return false, if the [[Value]] field of Desc is present and
    1362             :         // SameValue(Desc.[[Value]], current.[[Value]]) is false.
    1363         506 :         if (desc->has_value() && !desc->value()->SameValue(*current->value())) {
    1364         847 :           RETURN_FAILURE(
    1365             :               isolate, GetShouldThrow(isolate, should_throw),
    1366             :               NewTypeError(MessageTemplate::kRedefineDisallowed,
    1367             :                            it != nullptr ? it->GetName() : property_name));
    1368             :         }
    1369             :       }
    1370             :     }
    1371             :   } else {
    1372             :     // 9. Else IsAccessorDescriptor(current) and IsAccessorDescriptor(Desc)
    1373             :     // are both true,
    1374             :     DCHECK(PropertyDescriptor::IsAccessorDescriptor(current) &&
    1375             :            desc_is_accessor_descriptor);
    1376             :     // 9a. If the [[Configurable]] field of current is false, then:
    1377       11013 :     if (!current->configurable()) {
    1378             :       // 9a i. Return false, if the [[Set]] field of Desc is present and
    1379             :       // SameValue(Desc.[[Set]], current.[[Set]]) is false.
    1380         143 :       if (desc->has_set() && !desc->set()->SameValue(*current->set())) {
    1381         117 :         RETURN_FAILURE(
    1382             :             isolate, GetShouldThrow(isolate, should_throw),
    1383             :             NewTypeError(MessageTemplate::kRedefineDisallowed,
    1384             :                          it != nullptr ? it->GetName() : property_name));
    1385             :       }
    1386             :       // 9a ii. Return false, if the [[Get]] field of Desc is present and
    1387             :       // SameValue(Desc.[[Get]], current.[[Get]]) is false.
    1388         106 :       if (desc->has_get() && !desc->get()->SameValue(*current->get())) {
    1389         170 :         RETURN_FAILURE(
    1390             :             isolate, GetShouldThrow(isolate, should_throw),
    1391             :             NewTypeError(MessageTemplate::kRedefineDisallowed,
    1392             :                          it != nullptr ? it->GetName() : property_name));
    1393             :       }
    1394             :     }
    1395             :   }
    1396             : 
    1397             :   // 10. If O is not undefined, then:
    1398      155687 :   if (it != nullptr) {
    1399             :     // 10a. For each field of Desc that is present, set the corresponding
    1400             :     // attribute of the property named P of object O to the value of the field.
    1401             :     PropertyAttributes attrs = NONE;
    1402             : 
    1403      155426 :     if (desc->has_enumerable()) {
    1404             :       attrs = static_cast<PropertyAttributes>(
    1405      121201 :           attrs | (desc->enumerable() ? NONE : DONT_ENUM));
    1406             :     } else {
    1407             :       attrs = static_cast<PropertyAttributes>(
    1408       34225 :           attrs | (current->enumerable() ? NONE : DONT_ENUM));
    1409             :     }
    1410      155426 :     if (desc->has_configurable()) {
    1411             :       attrs = static_cast<PropertyAttributes>(
    1412      133309 :           attrs | (desc->configurable() ? NONE : DONT_DELETE));
    1413             :     } else {
    1414             :       attrs = static_cast<PropertyAttributes>(
    1415       22117 :           attrs | (current->configurable() ? NONE : DONT_DELETE));
    1416             :     }
    1417      284665 :     if (desc_is_data_descriptor ||
    1418      129239 :         (desc_is_generic_descriptor && current_is_data_descriptor)) {
    1419       26996 :       if (desc->has_writable()) {
    1420             :         attrs = static_cast<PropertyAttributes>(
    1421       24107 :             attrs | (desc->writable() ? NONE : READ_ONLY));
    1422             :       } else {
    1423             :         attrs = static_cast<PropertyAttributes>(
    1424        2889 :             attrs | (current->writable() ? NONE : READ_ONLY));
    1425             :       }
    1426             :       Handle<Object> value(
    1427             :           desc->has_value() ? desc->value()
    1428             :                             : current->has_value()
    1429             :                                   ? current->value()
    1430             :                                   : Handle<Object>::cast(
    1431       29817 :                                         isolate->factory()->undefined_value()));
    1432             :       return JSObject::DefineOwnPropertyIgnoreAttributes(it, value, attrs,
    1433       26996 :                                                          should_throw);
    1434             :     } else {
    1435             :       DCHECK(desc_is_accessor_descriptor ||
    1436             :              (desc_is_generic_descriptor &&
    1437             :               PropertyDescriptor::IsAccessorDescriptor(current)));
    1438             :       Handle<Object> getter(
    1439             :           desc->has_get()
    1440             :               ? desc->get()
    1441             :               : current->has_get()
    1442             :                     ? current->get()
    1443      135942 :                     : Handle<Object>::cast(isolate->factory()->null_value()));
    1444             :       Handle<Object> setter(
    1445             :           desc->has_set()
    1446             :               ? desc->set()
    1447             :               : current->has_set()
    1448             :                     ? current->set()
    1449      365808 :                     : Handle<Object>::cast(isolate->factory()->null_value()));
    1450             :       MaybeHandle<Object> result =
    1451      128430 :           JSObject::DefineAccessor(it, getter, setter, attrs);
    1452      128430 :       if (result.is_null()) return Nothing<bool>();
    1453             :     }
    1454             :   }
    1455             : 
    1456             :   // 11. Return true.
    1457             :   return Just(true);
    1458             : }
    1459             : 
    1460             : // static
    1461      104786 : Maybe<bool> JSReceiver::CreateDataProperty(Isolate* isolate,
    1462             :                                            Handle<JSReceiver> object,
    1463             :                                            Handle<Name> key,
    1464             :                                            Handle<Object> value,
    1465             :                                            Maybe<ShouldThrow> should_throw) {
    1466             :   LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, key,
    1467      104786 :                                                         LookupIterator::OWN);
    1468      104786 :   return CreateDataProperty(&it, value, should_throw);
    1469             : }
    1470             : 
    1471             : // static
    1472     1138501 : Maybe<bool> JSReceiver::CreateDataProperty(LookupIterator* it,
    1473             :                                            Handle<Object> value,
    1474             :                                            Maybe<ShouldThrow> should_throw) {
    1475             :   DCHECK(!it->check_prototype_chain());
    1476             :   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
    1477             :   Isolate* isolate = receiver->GetIsolate();
    1478             : 
    1479     1138501 :   if (receiver->IsJSObject()) {
    1480     1137483 :     return JSObject::CreateDataProperty(it, value, should_throw);  // Shortcut.
    1481             :   }
    1482             : 
    1483             :   PropertyDescriptor new_desc;
    1484             :   new_desc.set_value(value);
    1485             :   new_desc.set_writable(true);
    1486             :   new_desc.set_enumerable(true);
    1487             :   new_desc.set_configurable(true);
    1488             : 
    1489             :   return JSReceiver::DefineOwnProperty(isolate, receiver, it->GetName(),
    1490        2036 :                                        &new_desc, should_throw);
    1491             : }
    1492             : 
    1493             : // static
    1494     3188176 : Maybe<bool> JSReceiver::GetOwnPropertyDescriptor(Isolate* isolate,
    1495             :                                                  Handle<JSReceiver> object,
    1496             :                                                  Handle<Object> key,
    1497             :                                                  PropertyDescriptor* desc) {
    1498     3188176 :   bool success = false;
    1499             :   DCHECK(key->IsName() || key->IsNumber());  // |key| is a PropertyKey...
    1500             :   LookupIterator it = LookupIterator::PropertyOrElement(
    1501     3188176 :       isolate, object, key, &success, LookupIterator::OWN);
    1502             :   DCHECK(success);  // ...so creating a LookupIterator can't fail.
    1503     3188176 :   return GetOwnPropertyDescriptor(&it, desc);
    1504             : }
    1505             : 
    1506             : namespace {
    1507             : 
    1508     3695967 : Maybe<bool> GetPropertyDescriptorWithInterceptor(LookupIterator* it,
    1509             :                                                  PropertyDescriptor* desc) {
    1510     3695967 :   if (it->state() == LookupIterator::ACCESS_CHECK) {
    1511     2310449 :     if (it->HasAccess()) {
    1512     2310399 :       it->Next();
    1513          50 :     } else if (!JSObject::AllCanRead(it) ||
    1514             :                it->state() != LookupIterator::INTERCEPTOR) {
    1515          50 :       it->Restart();
    1516             :       return Just(false);
    1517             :     }
    1518             :   }
    1519             : 
    1520     3695917 :   if (it->state() != LookupIterator::INTERCEPTOR) return Just(false);
    1521             : 
    1522             :   Isolate* isolate = it->isolate();
    1523         555 :   Handle<InterceptorInfo> interceptor = it->GetInterceptor();
    1524         555 :   if (interceptor->descriptor()->IsUndefined(isolate)) return Just(false);
    1525             : 
    1526             :   Handle<Object> result;
    1527             :   Handle<JSObject> holder = it->GetHolder<JSObject>();
    1528             : 
    1529             :   Handle<Object> receiver = it->GetReceiver();
    1530          45 :   if (!receiver->IsJSReceiver()) {
    1531           0 :     ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
    1532             :                                      Object::ConvertReceiver(isolate, receiver),
    1533             :                                      Nothing<bool>());
    1534             :   }
    1535             : 
    1536             :   PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
    1537          45 :                                  *holder, Just(kDontThrow));
    1538          45 :   if (it->IsElement()) {
    1539          12 :     result = args.CallIndexedDescriptor(interceptor, it->index());
    1540             :   } else {
    1541          33 :     result = args.CallNamedDescriptor(interceptor, it->name());
    1542             :   }
    1543          45 :   if (!result.is_null()) {
    1544             :     // Request successfully intercepted, try to set the property
    1545             :     // descriptor.
    1546          12 :     Utils::ApiCheck(
    1547          12 :         PropertyDescriptor::ToPropertyDescriptor(isolate, result, desc),
    1548             :         it->IsElement() ? "v8::IndexedPropertyDescriptorCallback"
    1549             :                         : "v8::NamedPropertyDescriptorCallback",
    1550             :         "Invalid property descriptor.");
    1551             : 
    1552             :     return Just(true);
    1553             :   }
    1554             : 
    1555          33 :   it->Next();
    1556             :   return Just(false);
    1557             : }
    1558             : }  // namespace
    1559             : 
    1560             : // ES6 9.1.5.1
    1561             : // Returns true on success, false if the property didn't exist, nothing if
    1562             : // an exception was thrown.
    1563             : // static
    1564     3727508 : Maybe<bool> JSReceiver::GetOwnPropertyDescriptor(LookupIterator* it,
    1565             :                                                  PropertyDescriptor* desc) {
    1566             :   Isolate* isolate = it->isolate();
    1567             :   // "Virtual" dispatch.
    1568     7071424 :   if (it->IsFound() && it->GetHolder<JSReceiver>()->IsJSProxy()) {
    1569             :     return JSProxy::GetOwnPropertyDescriptor(isolate, it->GetHolder<JSProxy>(),
    1570       31540 :                                              it->GetName(), desc);
    1571             :   }
    1572             : 
    1573     3695968 :   Maybe<bool> intercepted = GetPropertyDescriptorWithInterceptor(it, desc);
    1574     3695968 :   MAYBE_RETURN(intercepted, Nothing<bool>());
    1575     3695968 :   if (intercepted.FromJust()) {
    1576             :     return Just(true);
    1577             :   }
    1578             : 
    1579             :   // Request was not intercepted, continue as normal.
    1580             :   // 1. (Assert)
    1581             :   // 2. If O does not have an own property with key P, return undefined.
    1582     3695956 :   Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(it);
    1583     3695956 :   MAYBE_RETURN(maybe, Nothing<bool>());
    1584             :   PropertyAttributes attrs = maybe.FromJust();
    1585     3695766 :   if (attrs == ABSENT) return Just(false);
    1586             :   DCHECK(!isolate->has_pending_exception());
    1587             : 
    1588             :   // 3. Let D be a newly created Property Descriptor with no fields.
    1589             :   DCHECK(desc->is_empty());
    1590             :   // 4. Let X be O's own property whose key is P.
    1591             :   // 5. If X is a data property, then
    1592     3484160 :   bool is_accessor_pair = it->state() == LookupIterator::ACCESSOR &&
    1593      172298 :                           it->GetAccessors()->IsAccessorPair();
    1594     3311862 :   if (!is_accessor_pair) {
    1595             :     // 5a. Set D.[[Value]] to the value of X's [[Value]] attribute.
    1596             :     Handle<Object> value;
    1597     6531359 :     if (!Object::GetProperty(it).ToHandle(&value)) {
    1598             :       DCHECK(isolate->has_pending_exception());
    1599             :       return Nothing<bool>();
    1600             :     }
    1601             :     desc->set_value(value);
    1602             :     // 5b. Set D.[[Writable]] to the value of X's [[Writable]] attribute
    1603     3265680 :     desc->set_writable((attrs & READ_ONLY) == 0);
    1604             :   } else {
    1605             :     // 6. Else X is an accessor property, so
    1606             :     Handle<AccessorPair> accessors =
    1607       46183 :         Handle<AccessorPair>::cast(it->GetAccessors());
    1608             :     // 6a. Set D.[[Get]] to the value of X's [[Get]] attribute.
    1609       46183 :     desc->set_get(
    1610             :         AccessorPair::GetComponent(isolate, accessors, ACCESSOR_GETTER));
    1611             :     // 6b. Set D.[[Set]] to the value of X's [[Set]] attribute.
    1612       46183 :     desc->set_set(
    1613             :         AccessorPair::GetComponent(isolate, accessors, ACCESSOR_SETTER));
    1614             :   }
    1615             : 
    1616             :   // 7. Set D.[[Enumerable]] to the value of X's [[Enumerable]] attribute.
    1617     3311863 :   desc->set_enumerable((attrs & DONT_ENUM) == 0);
    1618             :   // 8. Set D.[[Configurable]] to the value of X's [[Configurable]] attribute.
    1619     3311863 :   desc->set_configurable((attrs & DONT_DELETE) == 0);
    1620             :   // 9. Return D.
    1621             :   DCHECK(PropertyDescriptor::IsAccessorDescriptor(desc) !=
    1622             :          PropertyDescriptor::IsDataDescriptor(desc));
    1623             :   return Just(true);
    1624             : }
    1625    10450223 : Maybe<bool> JSReceiver::SetIntegrityLevel(Handle<JSReceiver> receiver,
    1626             :                                           IntegrityLevel level,
    1627             :                                           ShouldThrow should_throw) {
    1628             :   DCHECK(level == SEALED || level == FROZEN);
    1629             : 
    1630    10450223 :   if (receiver->IsJSObject()) {
    1631             :     Handle<JSObject> object = Handle<JSObject>::cast(receiver);
    1632             : 
    1633    20899580 :     if (!object->HasSloppyArgumentsElements() &&
    1634             :         !object->IsJSModuleNamespace()) {  // Fast path.
    1635             :       // Prevent memory leaks by not adding unnecessary transitions.
    1636    10449697 :       Maybe<bool> test = JSObject::TestIntegrityLevel(object, level);
    1637    10449698 :       MAYBE_RETURN(test, Nothing<bool>());
    1638    10449699 :       if (test.FromJust()) return test;
    1639             : 
    1640      236205 :       if (level == SEALED) {
    1641             :         return JSObject::PreventExtensionsWithTransition<SEALED>(object,
    1642        2746 :                                                                  should_throw);
    1643             :       } else {
    1644             :         return JSObject::PreventExtensionsWithTransition<FROZEN>(object,
    1645      233459 :                                                                  should_throw);
    1646             :       }
    1647             :     }
    1648             :   }
    1649             : 
    1650             :   Isolate* isolate = receiver->GetIsolate();
    1651             : 
    1652        1057 :   MAYBE_RETURN(JSReceiver::PreventExtensions(receiver, should_throw),
    1653             :                Nothing<bool>());
    1654             : 
    1655             :   Handle<FixedArray> keys;
    1656         530 :   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
    1657             :       isolate, keys, JSReceiver::OwnPropertyKeys(receiver), Nothing<bool>());
    1658             : 
    1659             :   PropertyDescriptor no_conf;
    1660             :   no_conf.set_configurable(false);
    1661             : 
    1662             :   PropertyDescriptor no_conf_no_write;
    1663             :   no_conf_no_write.set_configurable(false);
    1664             :   no_conf_no_write.set_writable(false);
    1665             : 
    1666         530 :   if (level == SEALED) {
    1667         430 :     for (int i = 0; i < keys->length(); ++i) {
    1668             :       Handle<Object> key(keys->get(i), isolate);
    1669         332 :       MAYBE_RETURN(DefineOwnProperty(isolate, receiver, key, &no_conf,
    1670             :                                      Just(kThrowOnError)),
    1671             :                    Nothing<bool>());
    1672             :     }
    1673             :     return Just(true);
    1674             :   }
    1675             : 
    1676        2916 :   for (int i = 0; i < keys->length(); ++i) {
    1677             :     Handle<Object> key(keys->get(i), isolate);
    1678             :     PropertyDescriptor current_desc;
    1679             :     Maybe<bool> owned = JSReceiver::GetOwnPropertyDescriptor(
    1680        1296 :         isolate, receiver, key, &current_desc);
    1681        1332 :     MAYBE_RETURN(owned, Nothing<bool>());
    1682        1287 :     if (owned.FromJust()) {
    1683             :       PropertyDescriptor desc =
    1684             :           PropertyDescriptor::IsAccessorDescriptor(&current_desc)
    1685             :               ? no_conf
    1686        1287 :               : no_conf_no_write;
    1687        2574 :       MAYBE_RETURN(
    1688             :           DefineOwnProperty(isolate, receiver, key, &desc, Just(kThrowOnError)),
    1689             :           Nothing<bool>());
    1690             :     }
    1691             :   }
    1692             :   return Just(true);
    1693             : }
    1694             : 
    1695             : namespace {
    1696         298 : Maybe<bool> GenericTestIntegrityLevel(Handle<JSReceiver> receiver,
    1697             :                                       PropertyAttributes level) {
    1698             :   DCHECK(level == SEALED || level == FROZEN);
    1699             : 
    1700         298 :   Maybe<bool> extensible = JSReceiver::IsExtensible(receiver);
    1701         298 :   MAYBE_RETURN(extensible, Nothing<bool>());
    1702         298 :   if (extensible.FromJust()) return Just(false);
    1703             : 
    1704             :   Isolate* isolate = receiver->GetIsolate();
    1705             : 
    1706             :   Handle<FixedArray> keys;
    1707         161 :   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
    1708             :       isolate, keys, JSReceiver::OwnPropertyKeys(receiver), Nothing<bool>());
    1709             : 
    1710        4791 :   for (int i = 0; i < keys->length(); ++i) {
    1711             :     Handle<Object> key(keys->get(i), isolate);
    1712             :     PropertyDescriptor current_desc;
    1713             :     Maybe<bool> owned = JSReceiver::GetOwnPropertyDescriptor(
    1714        2396 :         isolate, receiver, key, &current_desc);
    1715        2477 :     MAYBE_RETURN(owned, Nothing<bool>());
    1716        2369 :     if (owned.FromJust()) {
    1717        2369 :       if (current_desc.configurable()) return Just(false);
    1718        3538 :       if (level == FROZEN &&
    1719        3529 :           PropertyDescriptor::IsDataDescriptor(&current_desc) &&
    1720             :           current_desc.writable()) {
    1721             :         return Just(false);
    1722             :       }
    1723             :     }
    1724             :   }
    1725             :   return Just(true);
    1726             : }
    1727             : 
    1728             : }  // namespace
    1729             : 
    1730        1486 : Maybe<bool> JSReceiver::TestIntegrityLevel(Handle<JSReceiver> receiver,
    1731             :                                            IntegrityLevel level) {
    1732        1486 :   if (!receiver->map()->IsCustomElementsReceiverMap()) {
    1733             :     return JSObject::TestIntegrityLevel(Handle<JSObject>::cast(receiver),
    1734        1333 :                                         level);
    1735             :   }
    1736         153 :   return GenericTestIntegrityLevel(receiver, level);
    1737             : }
    1738             : 
    1739       88057 : Maybe<bool> JSReceiver::PreventExtensions(Handle<JSReceiver> object,
    1740             :                                           ShouldThrow should_throw) {
    1741       88057 :   if (object->IsJSProxy()) {
    1742             :     return JSProxy::PreventExtensions(Handle<JSProxy>::cast(object),
    1743       81871 :                                       should_throw);
    1744             :   }
    1745             :   DCHECK(object->IsJSObject());
    1746             :   return JSObject::PreventExtensions(Handle<JSObject>::cast(object),
    1747        6186 :                                      should_throw);
    1748             : }
    1749             : 
    1750     1013582 : Maybe<bool> JSReceiver::IsExtensible(Handle<JSReceiver> object) {
    1751     1013582 :   if (object->IsJSProxy()) {
    1752       81844 :     return JSProxy::IsExtensible(Handle<JSProxy>::cast(object));
    1753             :   }
    1754      931738 :   return Just(JSObject::IsExtensible(Handle<JSObject>::cast(object)));
    1755             : }
    1756             : 
    1757             : // static
    1758     1881588 : MaybeHandle<Object> JSReceiver::ToPrimitive(Handle<JSReceiver> receiver,
    1759             :                                             ToPrimitiveHint hint) {
    1760             :   Isolate* const isolate = receiver->GetIsolate();
    1761             :   Handle<Object> exotic_to_prim;
    1762     3763176 :   ASSIGN_RETURN_ON_EXCEPTION(
    1763             :       isolate, exotic_to_prim,
    1764             :       Object::GetMethod(receiver, isolate->factory()->to_primitive_symbol()),
    1765             :       Object);
    1766     1881574 :   if (!exotic_to_prim->IsUndefined(isolate)) {
    1767             :     Handle<Object> hint_string =
    1768        3454 :         isolate->factory()->ToPrimitiveHintString(hint);
    1769             :     Handle<Object> result;
    1770        6908 :     ASSIGN_RETURN_ON_EXCEPTION(
    1771             :         isolate, result,
    1772             :         Execution::Call(isolate, exotic_to_prim, receiver, 1, &hint_string),
    1773             :         Object);
    1774        3319 :     if (result->IsPrimitive()) return result;
    1775           0 :     THROW_NEW_ERROR(isolate,
    1776             :                     NewTypeError(MessageTemplate::kCannotConvertToPrimitive),
    1777             :                     Object);
    1778             :   }
    1779             :   return OrdinaryToPrimitive(receiver, (hint == ToPrimitiveHint::kString)
    1780             :                                            ? OrdinaryToPrimitiveHint::kString
    1781     1878120 :                                            : OrdinaryToPrimitiveHint::kNumber);
    1782             : }
    1783             : 
    1784             : // static
    1785     1878120 : MaybeHandle<Object> JSReceiver::OrdinaryToPrimitive(
    1786             :     Handle<JSReceiver> receiver, OrdinaryToPrimitiveHint hint) {
    1787             :   Isolate* const isolate = receiver->GetIsolate();
    1788     9390600 :   Handle<String> method_names[2];
    1789     1878120 :   switch (hint) {
    1790             :     case OrdinaryToPrimitiveHint::kNumber:
    1791        6127 :       method_names[0] = isolate->factory()->valueOf_string();
    1792        6127 :       method_names[1] = isolate->factory()->toString_string();
    1793        6127 :       break;
    1794             :     case OrdinaryToPrimitiveHint::kString:
    1795     1871993 :       method_names[0] = isolate->factory()->toString_string();
    1796     1871993 :       method_names[1] = isolate->factory()->valueOf_string();
    1797     1871993 :       break;
    1798             :   }
    1799     1881606 :   for (Handle<String> name : method_names) {
    1800             :     Handle<Object> method;
    1801     3759636 :     ASSIGN_RETURN_ON_EXCEPTION(isolate, method,
    1802             :                                JSReceiver::GetProperty(isolate, receiver, name),
    1803             :                                Object);
    1804     1879800 :     if (method->IsCallable()) {
    1805             :       Handle<Object> result;
    1806     3758952 :       ASSIGN_RETURN_ON_EXCEPTION(
    1807             :           isolate, result,
    1808             :           Execution::Call(isolate, method, receiver, 0, nullptr), Object);
    1809     1870646 :       if (result->IsPrimitive()) return result;
    1810             :     }
    1811             :   }
    1812          90 :   THROW_NEW_ERROR(isolate,
    1813             :                   NewTypeError(MessageTemplate::kCannotConvertToPrimitive),
    1814             :                   Object);
    1815             : }
    1816             : 
    1817        1414 : V8_WARN_UNUSED_RESULT Maybe<bool> FastGetOwnValuesOrEntries(
    1818             :     Isolate* isolate, Handle<JSReceiver> receiver, bool get_entries,
    1819             :     Handle<FixedArray>* result) {
    1820             :   Handle<Map> map(JSReceiver::cast(*receiver)->map(), isolate);
    1821             : 
    1822        1414 :   if (!map->IsJSObjectMap()) return Just(false);
    1823        1414 :   if (!map->OnlyHasSimpleProperties()) return Just(false);
    1824             : 
    1825             :   Handle<JSObject> object(JSObject::cast(*receiver), isolate);
    1826             : 
    1827             :   Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
    1828             :   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
    1829             :   int number_of_own_elements =
    1830        2828 :       object->GetElementsAccessor()->GetCapacity(*object, object->elements());
    1831             :   Handle<FixedArray> values_or_entries = isolate->factory()->NewFixedArray(
    1832        1414 :       number_of_own_descriptors + number_of_own_elements);
    1833        1414 :   int count = 0;
    1834             : 
    1835        1414 :   if (object->elements() != ReadOnlyRoots(isolate).empty_fixed_array()) {
    1836        2016 :     MAYBE_RETURN(object->GetElementsAccessor()->CollectValuesOrEntries(
    1837             :                      isolate, object, values_or_entries, get_entries, &count,
    1838             :                      ENUMERABLE_STRINGS),
    1839             :                  Nothing<bool>());
    1840             :   }
    1841             : 
    1842             :   bool stable = object->map() == *map;
    1843             : 
    1844        5368 :   for (int index = 0; index < number_of_own_descriptors; index++) {
    1845             :     Handle<Name> next_key(descriptors->GetKey(index), isolate);
    1846        1977 :     if (!next_key->IsString()) continue;
    1847             :     Handle<Object> prop_value;
    1848             : 
    1849             :     // Directly decode from the descriptor array if |from| did not change shape.
    1850        1797 :     if (stable) {
    1851        1707 :       PropertyDetails details = descriptors->GetDetails(index);
    1852        1707 :       if (!details.IsEnumerable()) continue;
    1853        1212 :       if (details.kind() == kData) {
    1854        1176 :         if (details.location() == kDescriptor) {
    1855             :           prop_value = handle(descriptors->GetStrongValue(index), isolate);
    1856             :         } else {
    1857        1176 :           Representation representation = details.representation();
    1858        1176 :           FieldIndex field_index = FieldIndex::ForDescriptor(*map, index);
    1859             :           prop_value =
    1860        1176 :               JSObject::FastPropertyAt(object, representation, field_index);
    1861             :         }
    1862             :       } else {
    1863          72 :         ASSIGN_RETURN_ON_EXCEPTION_VALUE(
    1864             :             isolate, prop_value,
    1865             :             JSReceiver::GetProperty(isolate, object, next_key),
    1866             :             Nothing<bool>());
    1867             :         stable = object->map() == *map;
    1868             :       }
    1869             :     } else {
    1870             :       // If the map did change, do a slower lookup. We are still guaranteed that
    1871             :       // the object has a simple shape, and that the key is a name.
    1872             :       LookupIterator it(isolate, object, next_key,
    1873          90 :                         LookupIterator::OWN_SKIP_INTERCEPTOR);
    1874         162 :       if (!it.IsFound()) continue;
    1875             :       DCHECK(it.state() == LookupIterator::DATA ||
    1876             :              it.state() == LookupIterator::ACCESSOR);
    1877          54 :       if (!it.IsEnumerable()) continue;
    1878          36 :       ASSIGN_RETURN_ON_EXCEPTION_VALUE(
    1879             :           isolate, prop_value, Object::GetProperty(&it), Nothing<bool>());
    1880             :     }
    1881             : 
    1882        1230 :     if (get_entries) {
    1883         816 :       prop_value = MakeEntryPair(isolate, next_key, prop_value);
    1884             :     }
    1885             : 
    1886        2460 :     values_or_entries->set(count, *prop_value);
    1887        1230 :     count++;
    1888             :   }
    1889             : 
    1890             :   DCHECK_LE(count, values_or_entries->length());
    1891        1414 :   *result = FixedArray::ShrinkOrEmpty(isolate, values_or_entries, count);
    1892             :   return Just(true);
    1893             : }
    1894             : 
    1895        2161 : MaybeHandle<FixedArray> GetOwnValuesOrEntries(Isolate* isolate,
    1896             :                                               Handle<JSReceiver> object,
    1897             :                                               PropertyFilter filter,
    1898             :                                               bool try_fast_path,
    1899             :                                               bool get_entries) {
    1900             :   Handle<FixedArray> values_or_entries;
    1901        2161 :   if (try_fast_path && filter == ENUMERABLE_STRINGS) {
    1902             :     Maybe<bool> fast_values_or_entries = FastGetOwnValuesOrEntries(
    1903        1414 :         isolate, object, get_entries, &values_or_entries);
    1904        1414 :     if (fast_values_or_entries.IsNothing()) return MaybeHandle<FixedArray>();
    1905        1414 :     if (fast_values_or_entries.FromJust()) return values_or_entries;
    1906             :   }
    1907             : 
    1908             :   PropertyFilter key_filter =
    1909         747 :       static_cast<PropertyFilter>(filter & ~ONLY_ENUMERABLE);
    1910             : 
    1911             :   Handle<FixedArray> keys;
    1912        1494 :   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
    1913             :       isolate, keys,
    1914             :       KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly, key_filter,
    1915             :                               GetKeysConversion::kConvertToString),
    1916             :       MaybeHandle<FixedArray>());
    1917             : 
    1918         720 :   values_or_entries = isolate->factory()->NewFixedArray(keys->length());
    1919             :   int length = 0;
    1920             : 
    1921        5190 :   for (int i = 0; i < keys->length(); ++i) {
    1922             :     Handle<Name> key = Handle<Name>::cast(handle(keys->get(i), isolate));
    1923             : 
    1924        2271 :     if (filter & ONLY_ENUMERABLE) {
    1925             :       PropertyDescriptor descriptor;
    1926             :       Maybe<bool> did_get_descriptor = JSReceiver::GetOwnPropertyDescriptor(
    1927        2271 :           isolate, object, key, &descriptor);
    1928        2271 :       MAYBE_RETURN(did_get_descriptor, MaybeHandle<FixedArray>());
    1929        4413 :       if (!did_get_descriptor.FromJust() || !descriptor.enumerable()) continue;
    1930             :     }
    1931             : 
    1932             :     Handle<Object> value;
    1933        2952 :     ASSIGN_RETURN_ON_EXCEPTION_VALUE(
    1934             :         isolate, value, Object::GetPropertyOrElement(isolate, object, key),
    1935             :         MaybeHandle<FixedArray>());
    1936             : 
    1937        1476 :     if (get_entries) {
    1938             :       Handle<FixedArray> entry_storage =
    1939         981 :           isolate->factory()->NewUninitializedFixedArray(2);
    1940        1962 :       entry_storage->set(0, *key);
    1941         981 :       entry_storage->set(1, *value);
    1942             :       value = isolate->factory()->NewJSArrayWithElements(entry_storage,
    1943         981 :                                                          PACKED_ELEMENTS, 2);
    1944             :     }
    1945             : 
    1946        1476 :     values_or_entries->set(length, *value);
    1947        1476 :     length++;
    1948             :   }
    1949             :   DCHECK_LE(length, values_or_entries->length());
    1950         684 :   return FixedArray::ShrinkOrEmpty(isolate, values_or_entries, length);
    1951             : }
    1952             : 
    1953         909 : MaybeHandle<FixedArray> JSReceiver::GetOwnValues(Handle<JSReceiver> object,
    1954             :                                                  PropertyFilter filter,
    1955             :                                                  bool try_fast_path) {
    1956             :   return GetOwnValuesOrEntries(object->GetIsolate(), object, filter,
    1957        1818 :                                try_fast_path, false);
    1958             : }
    1959             : 
    1960        1252 : MaybeHandle<FixedArray> JSReceiver::GetOwnEntries(Handle<JSReceiver> object,
    1961             :                                                   PropertyFilter filter,
    1962             :                                                   bool try_fast_path) {
    1963             :   return GetOwnValuesOrEntries(object->GetIsolate(), object, filter,
    1964        2504 :                                try_fast_path, true);
    1965             : }
    1966             : 
    1967        5412 : Handle<FixedArray> JSReceiver::GetOwnElementIndices(Isolate* isolate,
    1968             :                                                     Handle<JSReceiver> receiver,
    1969             :                                                     Handle<JSObject> object) {
    1970             :   KeyAccumulator accumulator(isolate, KeyCollectionMode::kOwnOnly,
    1971             :                              ALL_PROPERTIES);
    1972        5412 :   accumulator.CollectOwnElementIndices(receiver, object);
    1973             :   Handle<FixedArray> keys =
    1974        5412 :       accumulator.GetKeys(GetKeysConversion::kKeepNumbers);
    1975             :   DCHECK(keys->ContainsSortedNumbers());
    1976        5412 :   return keys;
    1977             : }
    1978      281063 : Maybe<bool> JSReceiver::SetPrototype(Handle<JSReceiver> object,
    1979             :                                      Handle<Object> value, bool from_javascript,
    1980             :                                      ShouldThrow should_throw) {
    1981      281063 :   if (object->IsJSProxy()) {
    1982             :     return JSProxy::SetPrototype(Handle<JSProxy>::cast(object), value,
    1983       72701 :                                  from_javascript, should_throw);
    1984             :   }
    1985             :   return JSObject::SetPrototype(Handle<JSObject>::cast(object), value,
    1986      208362 :                                 from_javascript, should_throw);
    1987             : }
    1988             : 
    1989        4282 : bool JSReceiver::HasProxyInPrototype(Isolate* isolate) {
    1990       31054 :   for (PrototypeIterator iter(isolate, *this, kStartAtReceiver,
    1991             :                               PrototypeIterator::END_AT_NULL);
    1992       13386 :        !iter.IsAtEnd(); iter.AdvanceIgnoringProxies()) {
    1993       13413 :     if (iter.GetCurrent()->IsJSProxy()) return true;
    1994             :   }
    1995        4255 :   return false;
    1996             : }
    1997             : 
    1998           0 : bool JSReceiver::HasComplexElements() {
    1999           0 :   if (IsJSProxy()) return true;
    2000           0 :   JSObject this_object = JSObject::cast(*this);
    2001           0 :   if (this_object->HasIndexedInterceptor()) {
    2002             :     return true;
    2003             :   }
    2004           0 :   if (!this_object->HasDictionaryElements()) return false;
    2005           0 :   return this_object->element_dictionary()->HasComplexElements();
    2006             : }
    2007             : 
    2008             : // static
    2009     2807237 : MaybeHandle<JSObject> JSObject::New(Handle<JSFunction> constructor,
    2010             :                                     Handle<JSReceiver> new_target,
    2011             :                                     Handle<AllocationSite> site) {
    2012             :   // If called through new, new.target can be:
    2013             :   // - a subclass of constructor,
    2014             :   // - a proxy wrapper around constructor, or
    2015             :   // - the constructor itself.
    2016             :   // If called through Reflect.construct, it's guaranteed to be a constructor.
    2017             :   Isolate* const isolate = constructor->GetIsolate();
    2018             :   DCHECK(constructor->IsConstructor());
    2019             :   DCHECK(new_target->IsConstructor());
    2020             :   DCHECK(!constructor->has_initial_map() ||
    2021             :          constructor->initial_map()->instance_type() != JS_FUNCTION_TYPE);
    2022             : 
    2023             :   Handle<Map> initial_map;
    2024     5614477 :   ASSIGN_RETURN_ON_EXCEPTION(
    2025             :       isolate, initial_map,
    2026             :       JSFunction::GetDerivedMap(isolate, constructor, new_target), JSObject);
    2027             :   Handle<JSObject> result = isolate->factory()->NewJSObjectFromMap(
    2028     2807159 :       initial_map, AllocationType::kYoung, site);
    2029     2807146 :   if (initial_map->is_dictionary_map()) {
    2030             :     Handle<NameDictionary> dictionary =
    2031           0 :         NameDictionary::New(isolate, NameDictionary::kInitialCapacity);
    2032           0 :     result->SetProperties(*dictionary);
    2033             :   }
    2034     2807146 :   isolate->counters()->constructed_objects()->Increment();
    2035     2807151 :   isolate->counters()->constructed_objects_runtime()->Increment();
    2036     2807152 :   return result;
    2037             : }
    2038             : 
    2039             : // 9.1.12 ObjectCreate ( proto [ , internalSlotsList ] )
    2040             : // Notice: This is NOT 19.1.2.2 Object.create ( O, Properties )
    2041      120964 : MaybeHandle<JSObject> JSObject::ObjectCreate(Isolate* isolate,
    2042             :                                              Handle<Object> prototype) {
    2043             :   // Generate the map with the specified {prototype} based on the Object
    2044             :   // function's initial map from the current native context.
    2045             :   // TODO(bmeurer): Use a dedicated cache for Object.create; think about
    2046             :   // slack tracking for Object.create.
    2047             :   Handle<Map> map =
    2048      120964 :       Map::GetObjectCreateMap(isolate, Handle<HeapObject>::cast(prototype));
    2049             : 
    2050             :   // Actually allocate the object.
    2051             :   Handle<JSObject> object;
    2052      120964 :   if (map->is_dictionary_map()) {
    2053         365 :     object = isolate->factory()->NewSlowJSObjectFromMap(map);
    2054             :   } else {
    2055      120599 :     object = isolate->factory()->NewJSObjectFromMap(map);
    2056             :   }
    2057      120964 :   return object;
    2058             : }
    2059             : 
    2060     4348209 : void JSObject::EnsureWritableFastElements(Handle<JSObject> object) {
    2061             :   DCHECK(object->HasSmiOrObjectElements() ||
    2062             :          object->HasFastStringWrapperElements() ||
    2063             :          object->HasFrozenOrSealedElements());
    2064             :   FixedArray raw_elems = FixedArray::cast(object->elements());
    2065             :   Isolate* isolate = object->GetIsolate();
    2066     8682198 :   if (raw_elems->map() != ReadOnlyRoots(isolate).fixed_cow_array_map()) return;
    2067             :   Handle<FixedArray> elems(raw_elems, isolate);
    2068             :   Handle<FixedArray> writable_elems = isolate->factory()->CopyFixedArrayWithMap(
    2069       14220 :       elems, isolate->factory()->fixed_array_map());
    2070       28440 :   object->set_elements(*writable_elems);
    2071       14220 :   isolate->counters()->cow_arrays_converted()->Increment();
    2072             : }
    2073             : 
    2074     5947976 : int JSObject::GetHeaderSize(InstanceType type,
    2075             :                             bool function_has_prototype_slot) {
    2076     5947976 :   switch (type) {
    2077             :     case JS_OBJECT_TYPE:
    2078             :     case JS_API_OBJECT_TYPE:
    2079             :     case JS_SPECIAL_API_OBJECT_TYPE:
    2080             :       return JSObject::kHeaderSize;
    2081             :     case JS_GENERATOR_OBJECT_TYPE:
    2082        7347 :       return JSGeneratorObject::kSize;
    2083             :     case JS_ASYNC_FUNCTION_OBJECT_TYPE:
    2084           0 :       return JSAsyncFunctionObject::kSize;
    2085             :     case JS_ASYNC_GENERATOR_OBJECT_TYPE:
    2086        1375 :       return JSAsyncGeneratorObject::kSize;
    2087             :     case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
    2088           0 :       return JSAsyncFromSyncIterator::kSize;
    2089             :     case JS_GLOBAL_PROXY_TYPE:
    2090       56440 :       return JSGlobalProxy::kSize;
    2091             :     case JS_GLOBAL_OBJECT_TYPE:
    2092       57061 :       return JSGlobalObject::kSize;
    2093             :     case JS_BOUND_FUNCTION_TYPE:
    2094         841 :       return JSBoundFunction::kSize;
    2095             :     case JS_FUNCTION_TYPE:
    2096      480264 :       return JSFunction::GetHeaderSize(function_has_prototype_slot);
    2097             :     case JS_VALUE_TYPE:
    2098        4864 :       return JSValue::kSize;
    2099             :     case JS_DATE_TYPE:
    2100        1242 :       return JSDate::kSize;
    2101             :     case JS_ARRAY_TYPE:
    2102       56989 :       return JSArray::kSize;
    2103             :     case JS_ARRAY_BUFFER_TYPE:
    2104     1027377 :       return JSArrayBuffer::kHeaderSize;
    2105             :     case JS_ARRAY_ITERATOR_TYPE:
    2106         189 :       return JSArrayIterator::kSize;
    2107             :     case JS_TYPED_ARRAY_TYPE:
    2108       10856 :       return JSTypedArray::kHeaderSize;
    2109             :     case JS_DATA_VIEW_TYPE:
    2110        8311 :       return JSDataView::kHeaderSize;
    2111             :     case JS_SET_TYPE:
    2112         585 :       return JSSet::kSize;
    2113             :     case JS_MAP_TYPE:
    2114         636 :       return JSMap::kSize;
    2115             :     case JS_SET_KEY_VALUE_ITERATOR_TYPE:
    2116             :     case JS_SET_VALUE_ITERATOR_TYPE:
    2117          63 :       return JSSetIterator::kSize;
    2118             :     case JS_MAP_KEY_ITERATOR_TYPE:
    2119             :     case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
    2120             :     case JS_MAP_VALUE_ITERATOR_TYPE:
    2121          45 :       return JSMapIterator::kSize;
    2122             :     case WEAK_CELL_TYPE:
    2123           0 :       return WeakCell::kSize;
    2124             :     case JS_WEAK_REF_TYPE:
    2125           0 :       return JSWeakRef::kSize;
    2126             :     case JS_FINALIZATION_GROUP_TYPE:
    2127           0 :       return JSFinalizationGroup::kSize;
    2128             :     case JS_FINALIZATION_GROUP_CLEANUP_ITERATOR_TYPE:
    2129           0 :       return JSFinalizationGroupCleanupIterator::kSize;
    2130             :     case JS_WEAK_MAP_TYPE:
    2131         448 :       return JSWeakMap::kSize;
    2132             :     case JS_WEAK_SET_TYPE:
    2133         325 :       return JSWeakSet::kSize;
    2134             :     case JS_PROMISE_TYPE:
    2135         515 :       return JSPromise::kSize;
    2136             :     case JS_REGEXP_TYPE:
    2137        1640 :       return JSRegExp::kSize;
    2138             :     case JS_REGEXP_STRING_ITERATOR_TYPE:
    2139           0 :       return JSRegExpStringIterator::kSize;
    2140             :     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
    2141             :       return JSObject::kHeaderSize;
    2142             :     case JS_MESSAGE_OBJECT_TYPE:
    2143           0 :       return JSMessageObject::kSize;
    2144             :     case JS_ARGUMENTS_TYPE:
    2145             :       return JSObject::kHeaderSize;
    2146             :     case JS_ERROR_TYPE:
    2147             :       return JSObject::kHeaderSize;
    2148             :     case JS_STRING_ITERATOR_TYPE:
    2149           0 :       return JSStringIterator::kSize;
    2150             :     case JS_MODULE_NAMESPACE_TYPE:
    2151         126 :       return JSModuleNamespace::kHeaderSize;
    2152             : #ifdef V8_INTL_SUPPORT
    2153             :     case JS_INTL_V8_BREAK_ITERATOR_TYPE:
    2154          18 :       return JSV8BreakIterator::kSize;
    2155             :     case JS_INTL_COLLATOR_TYPE:
    2156           0 :       return JSCollator::kSize;
    2157             :     case JS_INTL_DATE_TIME_FORMAT_TYPE:
    2158           0 :       return JSDateTimeFormat::kSize;
    2159             :     case JS_INTL_LIST_FORMAT_TYPE:
    2160          18 :       return JSListFormat::kSize;
    2161             :     case JS_INTL_LOCALE_TYPE:
    2162          18 :       return JSLocale::kSize;
    2163             :     case JS_INTL_NUMBER_FORMAT_TYPE:
    2164           0 :       return JSNumberFormat::kSize;
    2165             :     case JS_INTL_PLURAL_RULES_TYPE:
    2166           0 :       return JSPluralRules::kSize;
    2167             :     case JS_INTL_RELATIVE_TIME_FORMAT_TYPE:
    2168          18 :       return JSRelativeTimeFormat::kSize;
    2169             :     case JS_INTL_SEGMENT_ITERATOR_TYPE:
    2170           0 :       return JSSegmentIterator::kSize;
    2171             :     case JS_INTL_SEGMENTER_TYPE:
    2172          18 :       return JSSegmenter::kSize;
    2173             : #endif  // V8_INTL_SUPPORT
    2174             :     case WASM_GLOBAL_TYPE:
    2175           0 :       return WasmGlobalObject::kSize;
    2176             :     case WASM_INSTANCE_TYPE:
    2177           0 :       return WasmInstanceObject::kSize;
    2178             :     case WASM_MEMORY_TYPE:
    2179           0 :       return WasmMemoryObject::kSize;
    2180             :     case WASM_MODULE_TYPE:
    2181           0 :       return WasmModuleObject::kSize;
    2182             :     case WASM_TABLE_TYPE:
    2183           0 :       return WasmTableObject::kSize;
    2184             :     case WASM_EXCEPTION_TYPE:
    2185           0 :       return WasmExceptionObject::kSize;
    2186             :     default:
    2187           0 :       UNREACHABLE();
    2188             :   }
    2189             : }
    2190             : 
    2191             : // static
    2192        1240 : bool JSObject::AllCanRead(LookupIterator* it) {
    2193             :   // Skip current iteration, it's in state ACCESS_CHECK or INTERCEPTOR, both of
    2194             :   // which have already been checked.
    2195             :   DCHECK(it->state() == LookupIterator::ACCESS_CHECK ||
    2196             :          it->state() == LookupIterator::INTERCEPTOR);
    2197        2411 :   for (it->Next(); it->IsFound(); it->Next()) {
    2198        1241 :     if (it->state() == LookupIterator::ACCESSOR) {
    2199         122 :       auto accessors = it->GetAccessors();
    2200         122 :       if (accessors->IsAccessorInfo()) {
    2201          77 :         if (AccessorInfo::cast(*accessors)->all_can_read()) return true;
    2202             :       }
    2203        1119 :     } else if (it->state() == LookupIterator::INTERCEPTOR) {
    2204        1260 :       if (it->GetInterceptor()->all_can_read()) return true;
    2205         489 :     } else if (it->state() == LookupIterator::JSPROXY) {
    2206             :       // Stop lookupiterating. And no, AllCanNotRead.
    2207             :       return false;
    2208             :     }
    2209             :   }
    2210             :   return false;
    2211             : }
    2212             : 
    2213        1174 : MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
    2214             :     LookupIterator* it) {
    2215             :   Isolate* isolate = it->isolate();
    2216        1174 :   Handle<JSObject> checked = it->GetHolder<JSObject>();
    2217             :   Handle<InterceptorInfo> interceptor =
    2218        1174 :       it->GetInterceptorForFailedAccessCheck();
    2219        1174 :   if (interceptor.is_null()) {
    2220        1079 :     while (AllCanRead(it)) {
    2221          46 :       if (it->state() == LookupIterator::ACCESSOR) {
    2222          52 :         return Object::GetPropertyWithAccessor(it);
    2223             :       }
    2224             :       DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
    2225             :       bool done;
    2226             :       Handle<Object> result;
    2227          30 :       ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
    2228             :                                  GetPropertyWithInterceptor(it, &done), Object);
    2229          30 :       if (done) return result;
    2230             :     }
    2231             : 
    2232             :   } else {
    2233             :     Handle<Object> result;
    2234             :     bool done;
    2235         230 :     ASSIGN_RETURN_ON_EXCEPTION(
    2236             :         isolate, result,
    2237             :         GetPropertyWithInterceptorInternal(it, interceptor, &done), Object);
    2238         105 :     if (done) return result;
    2239             :   }
    2240             : 
    2241             :   // Cross-Origin [[Get]] of Well-Known Symbols does not throw, and returns
    2242             :   // undefined.
    2243        1083 :   Handle<Name> name = it->GetName();
    2244        1140 :   if (name->IsSymbol() && Symbol::cast(*name)->is_well_known_symbol()) {
    2245          52 :     return it->factory()->undefined_value();
    2246             :   }
    2247             : 
    2248        1031 :   isolate->ReportFailedAccessCheck(checked);
    2249        1031 :   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
    2250           0 :   return it->factory()->undefined_value();
    2251             : }
    2252             : 
    2253         121 : Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithFailedAccessCheck(
    2254             :     LookupIterator* it) {
    2255             :   Isolate* isolate = it->isolate();
    2256         121 :   Handle<JSObject> checked = it->GetHolder<JSObject>();
    2257             :   Handle<InterceptorInfo> interceptor =
    2258         121 :       it->GetInterceptorForFailedAccessCheck();
    2259         121 :   if (interceptor.is_null()) {
    2260         121 :     while (AllCanRead(it)) {
    2261          10 :       if (it->state() == LookupIterator::ACCESSOR) {
    2262             :         return Just(it->property_attributes());
    2263             :       }
    2264             :       DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
    2265             :       auto result = GetPropertyAttributesWithInterceptor(it);
    2266           0 :       if (isolate->has_scheduled_exception()) break;
    2267           0 :       if (result.IsJust() && result.FromJust() != ABSENT) return result;
    2268             :     }
    2269             :   } else {
    2270             :     Maybe<PropertyAttributes> result =
    2271           0 :         GetPropertyAttributesWithInterceptorInternal(it, interceptor);
    2272           0 :     if (isolate->has_pending_exception()) return Nothing<PropertyAttributes>();
    2273           0 :     if (result.FromMaybe(ABSENT) != ABSENT) return result;
    2274             :   }
    2275         111 :   isolate->ReportFailedAccessCheck(checked);
    2276         111 :   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
    2277             :   return Just(ABSENT);
    2278             : }
    2279             : 
    2280             : // static
    2281          78 : bool JSObject::AllCanWrite(LookupIterator* it) {
    2282         304 :   for (; it->IsFound() && it->state() != LookupIterator::JSPROXY; it->Next()) {
    2283         123 :     if (it->state() == LookupIterator::ACCESSOR) {
    2284          25 :       Handle<Object> accessors = it->GetAccessors();
    2285          25 :       if (accessors->IsAccessorInfo()) {
    2286          15 :         if (AccessorInfo::cast(*accessors)->all_can_write()) return true;
    2287             :       }
    2288             :     }
    2289             :   }
    2290             :   return false;
    2291             : }
    2292             : 
    2293         108 : Maybe<bool> JSObject::SetPropertyWithFailedAccessCheck(
    2294             :     LookupIterator* it, Handle<Object> value, Maybe<ShouldThrow> should_throw) {
    2295             :   Isolate* isolate = it->isolate();
    2296         108 :   Handle<JSObject> checked = it->GetHolder<JSObject>();
    2297             :   Handle<InterceptorInfo> interceptor =
    2298         108 :       it->GetInterceptorForFailedAccessCheck();
    2299         108 :   if (interceptor.is_null()) {
    2300          78 :     if (AllCanWrite(it)) {
    2301          10 :       return Object::SetPropertyWithAccessor(it, value, should_throw);
    2302             :     }
    2303             :   } else {
    2304             :     Maybe<bool> result = SetPropertyWithInterceptorInternal(
    2305          30 :         it, interceptor, should_throw, value);
    2306          60 :     if (isolate->has_pending_exception()) return Nothing<bool>();
    2307          20 :     if (result.IsJust()) return result;
    2308             :   }
    2309          68 :   isolate->ReportFailedAccessCheck(checked);
    2310          68 :   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
    2311             :   return Just(true);
    2312             : }
    2313             : 
    2314      338783 : void JSObject::SetNormalizedProperty(Handle<JSObject> object, Handle<Name> name,
    2315             :                                      Handle<Object> value,
    2316             :                                      PropertyDetails details) {
    2317             :   DCHECK(!object->HasFastProperties());
    2318             :   DCHECK(name->IsUniqueName());
    2319             :   Isolate* isolate = object->GetIsolate();
    2320             : 
    2321      338783 :   uint32_t hash = name->Hash();
    2322             : 
    2323      338783 :   if (object->IsJSGlobalObject()) {
    2324             :     Handle<JSGlobalObject> global_obj = Handle<JSGlobalObject>::cast(object);
    2325             :     Handle<GlobalDictionary> dictionary(global_obj->global_dictionary(),
    2326             :                                         isolate);
    2327       19254 :     int entry = dictionary->FindEntry(ReadOnlyRoots(isolate), name, hash);
    2328             : 
    2329        9627 :     if (entry == GlobalDictionary::kNotFound) {
    2330             :       DCHECK_IMPLIES(global_obj->map()->is_prototype_map(),
    2331             :                      Map::IsPrototypeChainInvalidated(global_obj->map()));
    2332        1020 :       auto cell = isolate->factory()->NewPropertyCell(name);
    2333        1020 :       cell->set_value(*value);
    2334             :       auto cell_type = value->IsUndefined(isolate)
    2335             :                            ? PropertyCellType::kUndefined
    2336        1020 :                            : PropertyCellType::kConstant;
    2337             :       details = details.set_cell_type(cell_type);
    2338             :       value = cell;
    2339             :       dictionary =
    2340        1020 :           GlobalDictionary::Add(isolate, dictionary, name, value, details);
    2341        2040 :       global_obj->set_global_dictionary(*dictionary);
    2342             :     } else {
    2343             :       Handle<PropertyCell> cell = PropertyCell::PrepareForValue(
    2344        8607 :           isolate, dictionary, entry, value, details);
    2345        8607 :       cell->set_value(*value);
    2346             :     }
    2347             :   } else {
    2348      658312 :     Handle<NameDictionary> dictionary(object->property_dictionary(), isolate);
    2349             : 
    2350      329156 :     int entry = dictionary->FindEntry(isolate, name);
    2351      329156 :     if (entry == NameDictionary::kNotFound) {
    2352             :       DCHECK_IMPLIES(object->map()->is_prototype_map(),
    2353             :                      Map::IsPrototypeChainInvalidated(object->map()));
    2354             :       dictionary =
    2355       98339 :           NameDictionary::Add(isolate, dictionary, name, value, details);
    2356      196678 :       object->SetProperties(*dictionary);
    2357             :     } else {
    2358      230817 :       PropertyDetails original_details = dictionary->DetailsAt(entry);
    2359             :       int enumeration_index = original_details.dictionary_index();
    2360             :       DCHECK_GT(enumeration_index, 0);
    2361             :       details = details.set_index(enumeration_index);
    2362      461634 :       dictionary->SetEntry(isolate, entry, *name, *value, details);
    2363             :     }
    2364             :   }
    2365      338783 : }
    2366             : 
    2367       34829 : void JSObject::JSObjectShortPrint(StringStream* accumulator) {
    2368       34829 :   switch (map()->instance_type()) {
    2369             :     case JS_ARRAY_TYPE: {
    2370             :       double length = JSArray::cast(*this)->length()->IsUndefined()
    2371             :                           ? 0
    2372        1005 :                           : JSArray::cast(*this)->length()->Number();
    2373        1005 :       accumulator->Add("<JSArray[%u]>", static_cast<uint32_t>(length));
    2374        1005 :       break;
    2375             :     }
    2376             :     case JS_BOUND_FUNCTION_TYPE: {
    2377             :       JSBoundFunction bound_function = JSBoundFunction::cast(*this);
    2378           0 :       accumulator->Add("<JSBoundFunction");
    2379           0 :       accumulator->Add(" (BoundTargetFunction %p)>",
    2380             :                        reinterpret_cast<void*>(
    2381           0 :                            bound_function->bound_target_function().ptr()));
    2382             :       break;
    2383             :     }
    2384             :     case JS_WEAK_MAP_TYPE: {
    2385           0 :       accumulator->Add("<JSWeakMap>");
    2386           0 :       break;
    2387             :     }
    2388             :     case JS_WEAK_SET_TYPE: {
    2389           0 :       accumulator->Add("<JSWeakSet>");
    2390           0 :       break;
    2391             :     }
    2392             :     case JS_REGEXP_TYPE: {
    2393          18 :       accumulator->Add("<JSRegExp");
    2394             :       JSRegExp regexp = JSRegExp::cast(*this);
    2395          18 :       if (regexp->source()->IsString()) {
    2396          18 :         accumulator->Add(" ");
    2397          18 :         String::cast(regexp->source())->StringShortPrint(accumulator);
    2398             :       }
    2399          18 :       accumulator->Add(">");
    2400             : 
    2401             :       break;
    2402             :     }
    2403             :     case JS_FUNCTION_TYPE: {
    2404             :       JSFunction function = JSFunction::cast(*this);
    2405       22363 :       Object fun_name = function->shared()->DebugName();
    2406             :       bool printed = false;
    2407       22363 :       if (fun_name->IsString()) {
    2408             :         String str = String::cast(fun_name);
    2409       22363 :         if (str->length() > 0) {
    2410       17671 :           accumulator->Add("<JSFunction ");
    2411       17671 :           accumulator->Put(str);
    2412             :           printed = true;
    2413             :         }
    2414             :       }
    2415       22363 :       if (!printed) {
    2416        4692 :         accumulator->Add("<JSFunction");
    2417             :       }
    2418       22363 :       if (FLAG_trace_file_names) {
    2419           0 :         Object source_name = Script::cast(function->shared()->script())->name();
    2420           0 :         if (source_name->IsString()) {
    2421             :           String str = String::cast(source_name);
    2422           0 :           if (str->length() > 0) {
    2423           0 :             accumulator->Add(" <");
    2424           0 :             accumulator->Put(str);
    2425           0 :             accumulator->Add(">");
    2426             :           }
    2427             :         }
    2428             :       }
    2429       22363 :       accumulator->Add(" (sfi = %p)",
    2430       22363 :                        reinterpret_cast<void*>(function->shared().ptr()));
    2431       22363 :       accumulator->Put('>');
    2432             :       break;
    2433             :     }
    2434             :     case JS_GENERATOR_OBJECT_TYPE: {
    2435           0 :       accumulator->Add("<JSGenerator>");
    2436           0 :       break;
    2437             :     }
    2438             :     case JS_ASYNC_FUNCTION_OBJECT_TYPE: {
    2439           0 :       accumulator->Add("<JSAsyncFunctionObject>");
    2440           0 :       break;
    2441             :     }
    2442             :     case JS_ASYNC_GENERATOR_OBJECT_TYPE: {
    2443           0 :       accumulator->Add("<JS AsyncGenerator>");
    2444           0 :       break;
    2445             :     }
    2446             : 
    2447             :     // All other JSObjects are rather similar to each other (JSObject,
    2448             :     // JSGlobalProxy, JSGlobalObject, JSUndetectable, JSValue).
    2449             :     default: {
    2450       11443 :       Map map_of_this = map();
    2451             :       Heap* heap = GetHeap();
    2452       11443 :       Object constructor = map_of_this->GetConstructor();
    2453             :       bool printed = false;
    2454       22886 :       if (constructor->IsHeapObject() &&
    2455       11443 :           !heap->Contains(HeapObject::cast(constructor))) {
    2456           0 :         accumulator->Add("!!!INVALID CONSTRUCTOR!!!");
    2457             :       } else {
    2458             :         bool global_object = IsJSGlobalProxy();
    2459       11443 :         if (constructor->IsJSFunction()) {
    2460       11443 :           if (!heap->Contains(JSFunction::cast(constructor)->shared())) {
    2461           0 :             accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!");
    2462             :           } else {
    2463             :             String constructor_name =
    2464       11443 :                 JSFunction::cast(constructor)->shared()->Name();
    2465       11443 :             if (constructor_name->length() > 0) {
    2466       10050 :               accumulator->Add(global_object ? "<GlobalObject " : "<");
    2467       10050 :               accumulator->Put(constructor_name);
    2468       10050 :               accumulator->Add(
    2469             :                   " %smap = %p",
    2470             :                   map_of_this->is_deprecated() ? "deprecated-" : "",
    2471       10050 :                   map_of_this);
    2472             :               printed = true;
    2473             :             }
    2474             :           }
    2475           0 :         } else if (constructor->IsFunctionTemplateInfo()) {
    2476           0 :           accumulator->Add(global_object ? "<RemoteObject>" : "<RemoteObject>");
    2477             :           printed = true;
    2478             :         }
    2479       11443 :         if (!printed) {
    2480        1393 :           accumulator->Add("<JS%sObject", global_object ? "Global " : "");
    2481             :         }
    2482             :       }
    2483       11443 :       if (IsJSValue()) {
    2484          84 :         accumulator->Add(" value = ");
    2485          84 :         JSValue::cast(*this)->value()->ShortPrint(accumulator);
    2486             :       }
    2487       11443 :       accumulator->Put('>');
    2488             :       break;
    2489             :     }
    2490             :   }
    2491       34829 : }
    2492             : 
    2493           0 : void JSObject::PrintElementsTransition(FILE* file, Handle<JSObject> object,
    2494             :                                        ElementsKind from_kind,
    2495             :                                        Handle<FixedArrayBase> from_elements,
    2496             :                                        ElementsKind to_kind,
    2497             :                                        Handle<FixedArrayBase> to_elements) {
    2498           0 :   if (from_kind != to_kind) {
    2499           0 :     OFStream os(file);
    2500           0 :     os << "elements transition [" << ElementsKindToString(from_kind) << " -> "
    2501           0 :        << ElementsKindToString(to_kind) << "] in ";
    2502           0 :     JavaScriptFrame::PrintTop(object->GetIsolate(), file, false, true);
    2503           0 :     PrintF(file, " for ");
    2504           0 :     object->ShortPrint(file);
    2505           0 :     PrintF(file, " from ");
    2506           0 :     from_elements->ShortPrint(file);
    2507           0 :     PrintF(file, " to ");
    2508           0 :     to_elements->ShortPrint(file);
    2509           0 :     PrintF(file, "\n");
    2510             :   }
    2511           0 : }
    2512             : 
    2513           0 : void JSObject::PrintInstanceMigration(FILE* file, Map original_map,
    2514             :                                       Map new_map) {
    2515           0 :   if (new_map->is_dictionary_map()) {
    2516           0 :     PrintF(file, "[migrating to slow]\n");
    2517           0 :     return;
    2518             :   }
    2519           0 :   PrintF(file, "[migrating]");
    2520           0 :   DescriptorArray o = original_map->instance_descriptors();
    2521           0 :   DescriptorArray n = new_map->instance_descriptors();
    2522           0 :   for (int i = 0; i < original_map->NumberOfOwnDescriptors(); i++) {
    2523           0 :     Representation o_r = o->GetDetails(i).representation();
    2524           0 :     Representation n_r = n->GetDetails(i).representation();
    2525           0 :     if (!o_r.Equals(n_r)) {
    2526           0 :       String::cast(o->GetKey(i))->PrintOn(file);
    2527           0 :       PrintF(file, ":%s->%s ", o_r.Mnemonic(), n_r.Mnemonic());
    2528           0 :     } else if (o->GetDetails(i).location() == kDescriptor &&
    2529           0 :                n->GetDetails(i).location() == kField) {
    2530             :       Name name = o->GetKey(i);
    2531           0 :       if (name->IsString()) {
    2532           0 :         String::cast(name)->PrintOn(file);
    2533             :       } else {
    2534           0 :         PrintF(file, "{symbol %p}", reinterpret_cast<void*>(name.ptr()));
    2535             :       }
    2536           0 :       PrintF(file, " ");
    2537             :     }
    2538             :   }
    2539           0 :   if (original_map->elements_kind() != new_map->elements_kind()) {
    2540           0 :     PrintF(file, "elements_kind[%i->%i]", original_map->elements_kind(),
    2541           0 :            new_map->elements_kind());
    2542             :   }
    2543           0 :   PrintF(file, "\n");
    2544             : }
    2545             : 
    2546      352392 : bool JSObject::IsUnmodifiedApiObject(FullObjectSlot o) {
    2547             :   Object object = *o;
    2548      352392 :   if (object->IsSmi()) return false;
    2549             :   HeapObject heap_object = HeapObject::cast(object);
    2550      352392 :   if (!object->IsJSObject()) return false;
    2551       26384 :   JSObject js_object = JSObject::cast(object);
    2552       26384 :   if (!js_object->IsDroppableApiWrapper()) return false;
    2553          71 :   Object maybe_constructor = js_object->map()->GetConstructor();
    2554          71 :   if (!maybe_constructor->IsJSFunction()) return false;
    2555             :   JSFunction constructor = JSFunction::cast(maybe_constructor);
    2556          71 :   if (js_object->elements()->length() != 0) return false;
    2557             :   // Check that the object is not a key in a WeakMap (over-approximation).
    2558         132 :   if (!js_object->GetIdentityHash()->IsUndefined()) return false;
    2559             : 
    2560             :   return constructor->initial_map() == heap_object->map();
    2561             : }
    2562             : 
    2563             : // static
    2564     4426518 : void JSObject::UpdatePrototypeUserRegistration(Handle<Map> old_map,
    2565             :                                                Handle<Map> new_map,
    2566             :                                                Isolate* isolate) {
    2567             :   DCHECK(old_map->is_prototype_map());
    2568             :   DCHECK(new_map->is_prototype_map());
    2569     4426518 :   bool was_registered = JSObject::UnregisterPrototypeUser(old_map, isolate);
    2570     4426516 :   new_map->set_prototype_info(old_map->prototype_info());
    2571     4426519 :   old_map->set_prototype_info(Smi::kZero);
    2572     4426518 :   if (FLAG_trace_prototype_users) {
    2573           0 :     PrintF("Moving prototype_info %p from map %p to map %p.\n",
    2574             :            reinterpret_cast<void*>(new_map->prototype_info()->ptr()),
    2575             :            reinterpret_cast<void*>(old_map->ptr()),
    2576           0 :            reinterpret_cast<void*>(new_map->ptr()));
    2577             :   }
    2578     4426518 :   if (was_registered) {
    2579      193627 :     if (new_map->prototype_info()->IsPrototypeInfo()) {
    2580             :       // The new map isn't registered with its prototype yet; reflect this fact
    2581             :       // in the PrototypeInfo it just inherited from the old map.
    2582             :       PrototypeInfo::cast(new_map->prototype_info())
    2583             :           ->set_registry_slot(PrototypeInfo::UNREGISTERED);
    2584             :     }
    2585      193627 :     JSObject::LazyRegisterPrototypeUser(new_map, isolate);
    2586             :   }
    2587     4426519 : }
    2588             : 
    2589             : // static
    2590    30906780 : void JSObject::NotifyMapChange(Handle<Map> old_map, Handle<Map> new_map,
    2591             :                                Isolate* isolate) {
    2592    30906780 :   if (!old_map->is_prototype_map()) return;
    2593             : 
    2594             :   InvalidatePrototypeChains(*old_map);
    2595             : 
    2596             :   // If the map was registered with its prototype before, ensure that it
    2597             :   // registers with its new prototype now. This preserves the invariant that
    2598             :   // when a map on a prototype chain is registered with its prototype, then
    2599             :   // all prototypes further up the chain are also registered with their
    2600             :   // respective prototypes.
    2601     4426518 :   UpdatePrototypeUserRegistration(old_map, new_map, isolate);
    2602             : }
    2603             : 
    2604             : namespace {
    2605             : // To migrate a fast instance to a fast map:
    2606             : // - First check whether the instance needs to be rewritten. If not, simply
    2607             : //   change the map.
    2608             : // - Otherwise, allocate a fixed array large enough to hold all fields, in
    2609             : //   addition to unused space.
    2610             : // - Copy all existing properties in, in the following order: backing store
    2611             : //   properties, unused fields, inobject properties.
    2612             : // - If all allocation succeeded, commit the state atomically:
    2613             : //   * Copy inobject properties from the backing store back into the object.
    2614             : //   * Trim the difference in instance size of the object. This also cleanly
    2615             : //     frees inobject properties that moved to the backing store.
    2616             : //   * If there are properties left in the backing store, trim of the space used
    2617             : //     to temporarily store the inobject properties.
    2618             : //   * If there are properties left in the backing store, install the backing
    2619             : //     store.
    2620    29243318 : void MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
    2621             :   Isolate* isolate = object->GetIsolate();
    2622             :   Handle<Map> old_map(object->map(), isolate);
    2623             :   // In case of a regular transition.
    2624    58486639 :   if (new_map->GetBackPointer() == *old_map) {
    2625             :     // If the map does not add named properties, simply set the map.
    2626    12974888 :     if (old_map->NumberOfOwnDescriptors() ==
    2627             :         new_map->NumberOfOwnDescriptors()) {
    2628      532449 :       object->synchronized_set_map(*new_map);
    2629      532447 :       return;
    2630             :     }
    2631             : 
    2632    12442439 :     PropertyDetails details = new_map->GetLastDescriptorDetails();
    2633    12442443 :     int target_index = details.field_index() - new_map->GetInObjectProperties();
    2634    24884889 :     int property_array_length = object->property_array()->length();
    2635    27156069 :     bool have_space = old_map->UnusedPropertyFields() > 0 ||
    2636     4520330 :                       (details.location() == kField && target_index >= 0 &&
    2637     2260165 :                        property_array_length > target_index);
    2638             :     // Either new_map adds an kDescriptor property, or a kField property for
    2639             :     // which there is still space, and which does not require a mutable double
    2640             :     // box (an out-of-object double).
    2641    24884882 :     if (details.location() == kDescriptor ||
    2642    13899497 :         (have_space && ((FLAG_unbox_double_fields && target_index < 0) ||
    2643             :                         !details.representation().IsDouble()))) {
    2644    10179519 :       object->synchronized_set_map(*new_map);
    2645    10179521 :       return;
    2646             :     }
    2647             : 
    2648             :     // If there is still space in the object, we need to allocate a mutable
    2649             :     // double box.
    2650     2262922 :     if (have_space) {
    2651             :       FieldIndex index =
    2652        3005 :           FieldIndex::ForDescriptor(*new_map, new_map->LastAdded());
    2653             :       DCHECK(details.representation().IsDouble());
    2654             :       DCHECK(!new_map->IsUnboxedDoubleField(index));
    2655             :       auto value = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
    2656        6010 :       object->RawFastPropertyAtPut(index, *value);
    2657        3005 :       object->synchronized_set_map(*new_map);
    2658             :       return;
    2659             :     }
    2660             : 
    2661             :     // This migration is a transition from a map that has run out of property
    2662             :     // space. Extend the backing store.
    2663     2259917 :     int grow_by = new_map->UnusedPropertyFields() + 1;
    2664     4519834 :     Handle<PropertyArray> old_storage(object->property_array(), isolate);
    2665             :     Handle<PropertyArray> new_storage =
    2666     2259917 :         isolate->factory()->CopyPropertyArrayAndGrow(old_storage, grow_by);
    2667             : 
    2668             :     // Properly initialize newly added property.
    2669             :     Handle<Object> value;
    2670     2259917 :     if (details.representation().IsDouble()) {
    2671             :       value = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
    2672             :     } else {
    2673             :       value = isolate->factory()->uninitialized_value();
    2674             :     }
    2675             :     DCHECK_EQ(kField, details.location());
    2676             :     DCHECK_EQ(kData, details.kind());
    2677             :     DCHECK_GE(target_index, 0);  // Must be a backing store index.
    2678     2259917 :     new_storage->set(target_index, *value);
    2679             : 
    2680             :     // From here on we cannot fail and we shouldn't GC anymore.
    2681             :     DisallowHeapAllocation no_allocation;
    2682             : 
    2683             :     // Set the new property value and do the map transition.
    2684     4519834 :     object->SetProperties(*new_storage);
    2685     2259917 :     object->synchronized_set_map(*new_map);
    2686     2259917 :     return;
    2687             :   }
    2688             : 
    2689             :   int old_number_of_fields;
    2690    16268432 :   int number_of_fields = new_map->NumberOfFields();
    2691    16268440 :   int inobject = new_map->GetInObjectProperties();
    2692    16268442 :   int unused = new_map->UnusedPropertyFields();
    2693             : 
    2694             :   // Nothing to do if no functions were converted to fields and no smis were
    2695             :   // converted to doubles.
    2696    16268446 :   if (!old_map->InstancesNeedRewriting(*new_map, number_of_fields, inobject,
    2697             :                                        unused, &old_number_of_fields)) {
    2698     6347336 :     object->synchronized_set_map(*new_map);
    2699     6347342 :     return;
    2700             :   }
    2701             : 
    2702     9921111 :   int total_size = number_of_fields + unused;
    2703     9921111 :   int external = total_size - inobject;
    2704     9921111 :   Handle<PropertyArray> array = isolate->factory()->NewPropertyArray(external);
    2705             : 
    2706             :   // We use this array to temporarily store the inobject properties.
    2707             :   Handle<FixedArray> inobject_props =
    2708     9921106 :       isolate->factory()->NewFixedArray(inobject);
    2709             : 
    2710             :   Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors(),
    2711             :                                           isolate);
    2712             :   Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors(),
    2713             :                                           isolate);
    2714             :   int old_nof = old_map->NumberOfOwnDescriptors();
    2715             :   int new_nof = new_map->NumberOfOwnDescriptors();
    2716             : 
    2717             :   // This method only supports generalizing instances to at least the same
    2718             :   // number of properties.
    2719             :   DCHECK(old_nof <= new_nof);
    2720             : 
    2721   172121271 :   for (int i = 0; i < old_nof; i++) {
    2722    81100076 :     PropertyDetails details = new_descriptors->GetDetails(i);
    2723    81100071 :     if (details.location() != kField) continue;
    2724             :     DCHECK_EQ(kData, details.kind());
    2725    77140846 :     PropertyDetails old_details = old_descriptors->GetDetails(i);
    2726             :     Representation old_representation = old_details.representation();
    2727             :     Representation representation = details.representation();
    2728             :     Handle<Object> value;
    2729    77140849 :     if (old_details.location() == kDescriptor) {
    2730        1097 :       if (old_details.kind() == kAccessor) {
    2731             :         // In case of kAccessor -> kData property reconfiguration, the property
    2732             :         // must already be prepared for data of certain type.
    2733             :         DCHECK(!details.representation().IsNone());
    2734        1097 :         if (details.representation().IsDouble()) {
    2735             :           value = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
    2736             :         } else {
    2737             :           value = isolate->factory()->uninitialized_value();
    2738             :         }
    2739             :       } else {
    2740             :         DCHECK_EQ(kData, old_details.kind());
    2741             :         value = handle(old_descriptors->GetStrongValue(i), isolate);
    2742             :         DCHECK(!old_representation.IsDouble() && !representation.IsDouble());
    2743             :       }
    2744             :     } else {
    2745             :       DCHECK_EQ(kField, old_details.location());
    2746    77139752 :       FieldIndex index = FieldIndex::ForDescriptor(*old_map, i);
    2747    77139749 :       if (object->IsUnboxedDoubleField(index)) {
    2748             :         uint64_t old_bits = object->RawFastDoublePropertyAsBitsAt(index);
    2749        2971 :         if (representation.IsDouble()) {
    2750             :           value = isolate->factory()->NewMutableHeapNumberFromBits(old_bits);
    2751             :         } else {
    2752             :           value = isolate->factory()->NewHeapNumberFromBits(old_bits);
    2753             :         }
    2754             :       } else {
    2755   154273572 :         value = handle(object->RawFastPropertyAt(index), isolate);
    2756    77136789 :         if (!old_representation.IsDouble() && representation.IsDouble()) {
    2757             :           DCHECK_IMPLIES(old_representation.IsNone(),
    2758             :                          value->IsUninitialized(isolate));
    2759        2043 :           value = Object::NewStorageFor(isolate, value, representation);
    2760    77134746 :         } else if (old_representation.IsDouble() &&
    2761             :                    !representation.IsDouble()) {
    2762         301 :           value = Object::WrapForRead(isolate, value, old_representation);
    2763             :         }
    2764             :       }
    2765             :     }
    2766             :     DCHECK(!(representation.IsDouble() && value->IsSmi()));
    2767   154281727 :     int target_index = new_descriptors->GetFieldIndex(i);
    2768    77140869 :     if (target_index < inobject) {
    2769     5378125 :       inobject_props->set(target_index, *value);
    2770             :     } else {
    2771   143525488 :       array->set(target_index - inobject, *value);
    2772             :     }
    2773             :   }
    2774             : 
    2775    29756136 :   for (int i = old_nof; i < new_nof; i++) {
    2776     9917498 :     PropertyDetails details = new_descriptors->GetDetails(i);
    2777     9917498 :     if (details.location() != kField) continue;
    2778             :     DCHECK_EQ(kData, details.kind());
    2779             :     Handle<Object> value;
    2780     9917498 :     if (details.representation().IsDouble()) {
    2781             :       value = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
    2782             :     } else {
    2783             :       value = isolate->factory()->uninitialized_value();
    2784             :     }
    2785    19835002 :     int target_index = new_descriptors->GetFieldIndex(i);
    2786     9917504 :     if (target_index < inobject) {
    2787     5726209 :       inobject_props->set(target_index, *value);
    2788             :     } else {
    2789     8382590 :       array->set(target_index - inobject, *value);
    2790             :     }
    2791             :   }
    2792             : 
    2793             :   // From here on we cannot fail and we shouldn't GC anymore.
    2794             :   DisallowHeapAllocation no_allocation;
    2795             : 
    2796             :   Heap* heap = isolate->heap();
    2797             : 
    2798             :   int old_instance_size = old_map->instance_size();
    2799             : 
    2800     9921121 :   heap->NotifyObjectLayoutChange(*object, old_instance_size, no_allocation);
    2801             : 
    2802             :   // Copy (real) inobject properties. If necessary, stop at number_of_fields to
    2803             :   // avoid overwriting |one_pointer_filler_map|.
    2804             :   int limit = Min(inobject, number_of_fields);
    2805    32129802 :   for (int i = 0; i < limit; i++) {
    2806    11104339 :     FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
    2807             :     Object value = inobject_props->get(i);
    2808             :     // Can't use JSObject::FastPropertyAtPut() because proper map was not set
    2809             :     // yet.
    2810    11104342 :     if (new_map->IsUnboxedDoubleField(index)) {
    2811             :       DCHECK(value->IsMutableHeapNumber());
    2812             :       // Ensure that all bits of the double value are preserved.
    2813             :       object->RawFastDoublePropertyAsBitsAtPut(
    2814             :           index, MutableHeapNumber::cast(value)->value_as_bits());
    2815        7962 :       if (i < old_number_of_fields && !old_map->IsUnboxedDoubleField(index)) {
    2816             :         // Transition from tagged to untagged slot.
    2817        1458 :         heap->ClearRecordedSlot(*object, object->RawField(index.offset()));
    2818             :       } else {
    2819             : #ifdef DEBUG
    2820             :         heap->VerifyClearedSlot(*object, object->RawField(index.offset()));
    2821             : #endif
    2822             :       }
    2823             :     } else {
    2824    11100358 :       object->RawFastPropertyAtPut(index, value);
    2825             :     }
    2826             :   }
    2827             : 
    2828    19842244 :   object->SetProperties(*array);
    2829             : 
    2830             :   // Create filler object past the new instance size.
    2831             :   int new_instance_size = new_map->instance_size();
    2832     9921114 :   int instance_size_delta = old_instance_size - new_instance_size;
    2833             :   DCHECK_GE(instance_size_delta, 0);
    2834             : 
    2835     9921114 :   if (instance_size_delta > 0) {
    2836             :     Address address = object->address();
    2837             :     heap->CreateFillerObjectAt(address + new_instance_size, instance_size_delta,
    2838          16 :                                ClearRecordedSlots::kYes);
    2839             :   }
    2840             : 
    2841             :   // We are storing the new map using release store after creating a filler for
    2842             :   // the left-over space to avoid races with the sweeper thread.
    2843     9921114 :   object->synchronized_set_map(*new_map);
    2844             : }
    2845             : 
    2846      678997 : void MigrateFastToSlow(Handle<JSObject> object, Handle<Map> new_map,
    2847             :                        int expected_additional_properties) {
    2848             :   // The global object is always normalized.
    2849             :   DCHECK(!object->IsJSGlobalObject());
    2850             :   // JSGlobalProxy must never be normalized
    2851             :   DCHECK(!object->IsJSGlobalProxy());
    2852             : 
    2853             :   DCHECK_IMPLIES(new_map->is_prototype_map(),
    2854             :                  Map::IsPrototypeChainInvalidated(*new_map));
    2855             : 
    2856             :   Isolate* isolate = object->GetIsolate();
    2857             :   HandleScope scope(isolate);
    2858             :   Handle<Map> map(object->map(), isolate);
    2859             : 
    2860             :   // Allocate new content.
    2861             :   int real_size = map->NumberOfOwnDescriptors();
    2862             :   int property_count = real_size;
    2863      678997 :   if (expected_additional_properties > 0) {
    2864         566 :     property_count += expected_additional_properties;
    2865             :   } else {
    2866             :     // Make space for two more properties.
    2867      678431 :     property_count += NameDictionary::kInitialCapacity;
    2868             :   }
    2869             :   Handle<NameDictionary> dictionary =
    2870      678997 :       NameDictionary::New(isolate, property_count);
    2871             : 
    2872             :   Handle<DescriptorArray> descs(map->instance_descriptors(), isolate);
    2873     4679942 :   for (int i = 0; i < real_size; i++) {
    2874     2000470 :     PropertyDetails details = descs->GetDetails(i);
    2875             :     Handle<Name> key(descs->GetKey(i), isolate);
    2876             :     Handle<Object> value;
    2877     2000472 :     if (details.location() == kField) {
    2878     1733335 :       FieldIndex index = FieldIndex::ForDescriptor(*map, i);
    2879     1733332 :       if (details.kind() == kData) {
    2880     1733332 :         if (object->IsUnboxedDoubleField(index)) {
    2881             :           double old_value = object->RawFastDoublePropertyAt(index);
    2882         864 :           value = isolate->factory()->NewHeapNumber(old_value);
    2883             :         } else {
    2884     3464928 :           value = handle(object->RawFastPropertyAt(index), isolate);
    2885     1732461 :           if (details.representation().IsDouble()) {
    2886             :             DCHECK(value->IsMutableHeapNumber());
    2887             :             double old_value = Handle<MutableHeapNumber>::cast(value)->value();
    2888         303 :             value = isolate->factory()->NewHeapNumber(old_value);
    2889             :           }
    2890             :         }
    2891             :       } else {
    2892             :         DCHECK_EQ(kAccessor, details.kind());
    2893           0 :         value = handle(object->RawFastPropertyAt(index), isolate);
    2894             :       }
    2895             : 
    2896             :     } else {
    2897             :       DCHECK_EQ(kDescriptor, details.location());
    2898             :       value = handle(descs->GetStrongValue(i), isolate);
    2899             :     }
    2900             :     DCHECK(!value.is_null());
    2901             :     PropertyDetails d(details.kind(), details.attributes(),
    2902             :                       PropertyCellType::kNoCell);
    2903     2000462 :     dictionary = NameDictionary::Add(isolate, dictionary, key, value, d);
    2904             :   }
    2905             : 
    2906             :   // Copy the next enumeration index from instance descriptor.
    2907      678999 :   dictionary->SetNextEnumerationIndex(real_size + 1);
    2908             : 
    2909             :   // From here on we cannot fail and we shouldn't GC anymore.
    2910             :   DisallowHeapAllocation no_allocation;
    2911             : 
    2912             :   Heap* heap = isolate->heap();
    2913             :   int old_instance_size = map->instance_size();
    2914      678999 :   heap->NotifyObjectLayoutChange(*object, old_instance_size, no_allocation);
    2915             : 
    2916             :   // Resize the object in the heap if necessary.
    2917             :   int new_instance_size = new_map->instance_size();
    2918      678999 :   int instance_size_delta = old_instance_size - new_instance_size;
    2919             :   DCHECK_GE(instance_size_delta, 0);
    2920             : 
    2921      678999 :   if (instance_size_delta > 0) {
    2922             :     heap->CreateFillerObjectAt(object->address() + new_instance_size,
    2923      300613 :                                instance_size_delta, ClearRecordedSlots::kYes);
    2924             :   }
    2925             : 
    2926             :   // We are storing the new map using release store after creating a filler for
    2927             :   // the left-over space to avoid races with the sweeper thread.
    2928      678999 :   object->synchronized_set_map(*new_map);
    2929             : 
    2930     1357998 :   object->SetProperties(*dictionary);
    2931             : 
    2932             :   // Ensure that in-object space of slow-mode object does not contain random
    2933             :   // garbage.
    2934      678999 :   int inobject_properties = new_map->GetInObjectProperties();
    2935      678999 :   if (inobject_properties) {
    2936             :     Heap* heap = isolate->heap();
    2937      566652 :     heap->ClearRecordedSlotRange(
    2938             :         object->address() + map->GetInObjectPropertyOffset(0),
    2939      283326 :         object->address() + new_instance_size);
    2940             : 
    2941     2742945 :     for (int i = 0; i < inobject_properties; i++) {
    2942     1229809 :       FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
    2943     1229810 :       object->RawFastPropertyAtPut(index, Smi::kZero);
    2944             :     }
    2945             :   }
    2946             : 
    2947      678999 :   isolate->counters()->props_to_dictionary()->Increment();
    2948             : 
    2949             : #ifdef DEBUG
    2950             :   if (FLAG_trace_normalization) {
    2951             :     StdoutStream os;
    2952             :     os << "Object properties have been normalized:\n";
    2953             :     object->Print(os);
    2954             :   }
    2955             : #endif
    2956      678999 : }
    2957             : 
    2958             : }  // namespace
    2959             : 
    2960    33501061 : void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map,
    2961             :                             int expected_additional_properties) {
    2962    33501061 :   if (object->map() == *new_map) return;
    2963             :   Handle<Map> old_map(object->map(), object->GetIsolate());
    2964    30477668 :   NotifyMapChange(old_map, new_map, object->GetIsolate());
    2965             : 
    2966    30477678 :   if (old_map->is_dictionary_map()) {
    2967             :     // For slow-to-fast migrations JSObject::MigrateSlowToFast()
    2968             :     // must be used instead.
    2969      555347 :     CHECK(new_map->is_dictionary_map());
    2970             : 
    2971             :     // Slow-to-slow migration is trivial.
    2972      555347 :     object->synchronized_set_map(*new_map);
    2973    29922331 :   } else if (!new_map->is_dictionary_map()) {
    2974    29243333 :     MigrateFastToFast(object, new_map);
    2975    29243336 :     if (old_map->is_prototype_map()) {
    2976             :       DCHECK(!old_map->is_stable());
    2977             :       DCHECK(new_map->is_stable());
    2978             :       DCHECK(new_map->owns_descriptors());
    2979             :       DCHECK(old_map->owns_descriptors());
    2980             :       // Transfer ownership to the new map. Keep the descriptor pointer of the
    2981             :       // old map intact because the concurrent marker might be iterating the
    2982             :       // object with the old map.
    2983     4001175 :       old_map->set_owns_descriptors(false);
    2984             :       DCHECK(old_map->is_abandoned_prototype_map());
    2985             :       // Ensure that no transition was inserted for prototype migrations.
    2986             :       DCHECK_EQ(0, TransitionsAccessor(object->GetIsolate(), old_map)
    2987             :                        .NumberOfTransitions());
    2988             :       DCHECK(new_map->GetBackPointer()->IsUndefined());
    2989             :       DCHECK(object->map() != *old_map);
    2990             :     }
    2991             :   } else {
    2992      678998 :     MigrateFastToSlow(object, new_map, expected_additional_properties);
    2993             :   }
    2994             : 
    2995             :   // Careful: Don't allocate here!
    2996             :   // For some callers of this method, |object| might be in an inconsistent
    2997             :   // state now: the new map might have a new elements_kind, but the object's
    2998             :   // elements pointer hasn't been updated yet. Callers will fix this, but in
    2999             :   // the meantime, (indirectly) calling JSObjectVerify() must be avoided.
    3000             :   // When adding code here, add a DisallowHeapAllocation too.
    3001             : }
    3002             : 
    3003      298784 : void JSObject::ForceSetPrototype(Handle<JSObject> object,
    3004             :                                  Handle<HeapObject> proto) {
    3005             :   // object.__proto__ = proto;
    3006             :   Handle<Map> old_map = Handle<Map>(object->map(), object->GetIsolate());
    3007             :   Handle<Map> new_map =
    3008      298784 :       Map::Copy(object->GetIsolate(), old_map, "ForceSetPrototype");
    3009      298784 :   Map::SetPrototype(object->GetIsolate(), new_map, proto);
    3010      298784 :   JSObject::MigrateToMap(object, new_map);
    3011      298784 : }
    3012             : 
    3013      193061 : Maybe<bool> JSObject::SetPropertyWithInterceptor(
    3014             :     LookupIterator* it, Maybe<ShouldThrow> should_throw, Handle<Object> value) {
    3015             :   DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
    3016             :   return SetPropertyWithInterceptorInternal(it, it->GetInterceptor(),
    3017      193268 :                                             should_throw, value);
    3018             : }
    3019             : 
    3020     1181667 : Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object,
    3021             :                                                ElementsKind to_kind) {
    3022             :   Handle<Map> map(object->map(), object->GetIsolate());
    3023     2363336 :   return Map::TransitionElementsTo(object->GetIsolate(), map, to_kind);
    3024             : }
    3025             : 
    3026             : // static
    3027           0 : MaybeHandle<NativeContext> JSObject::GetFunctionRealm(Handle<JSObject> object) {
    3028             :   DCHECK(object->map()->is_constructor());
    3029             :   DCHECK(!object->IsJSFunction());
    3030           0 :   return object->GetCreationContext();
    3031             : }
    3032             : 
    3033     7684076 : void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) {
    3034             :   DCHECK(object->map()->GetInObjectProperties() ==
    3035             :          map->GetInObjectProperties());
    3036             :   ElementsKind obj_kind = object->map()->elements_kind();
    3037             :   ElementsKind map_kind = map->elements_kind();
    3038     7684076 :   if (map_kind != obj_kind) {
    3039             :     ElementsKind to_kind = GetMoreGeneralElementsKind(map_kind, obj_kind);
    3040          27 :     if (IsDictionaryElementsKind(obj_kind)) {
    3041             :       to_kind = obj_kind;
    3042             :     }
    3043          27 :     if (IsDictionaryElementsKind(to_kind)) {
    3044          27 :       NormalizeElements(object);
    3045             :     } else {
    3046           0 :       TransitionElementsKind(object, to_kind);
    3047             :     }
    3048          54 :     map = Map::ReconfigureElementsKind(object->GetIsolate(), map, to_kind);
    3049             :   }
    3050     7684076 :   int number_of_fields = map->NumberOfFields();
    3051     7684076 :   int inobject = map->GetInObjectProperties();
    3052     7684076 :   int unused = map->UnusedPropertyFields();
    3053     7684076 :   int total_size = number_of_fields + unused;
    3054     7684076 :   int external = total_size - inobject;
    3055             :   // Allocate mutable double boxes if necessary. It is always necessary if we
    3056             :   // have external properties, but is also necessary if we only have inobject
    3057             :   // properties but don't unbox double fields.
    3058     7684076 :   if (!FLAG_unbox_double_fields || external > 0) {
    3059             :     Isolate* isolate = object->GetIsolate();
    3060             : 
    3061             :     Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
    3062             :     Handle<FixedArray> storage;
    3063             :     if (!FLAG_unbox_double_fields) {
    3064             :       storage = isolate->factory()->NewFixedArray(inobject);
    3065             :     }
    3066             : 
    3067             :     Handle<PropertyArray> array =
    3068     2920144 :         isolate->factory()->NewPropertyArray(external);
    3069             : 
    3070    38681882 :     for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
    3071    17880869 :       PropertyDetails details = descriptors->GetDetails(i);
    3072             :       Representation representation = details.representation();
    3073    35761630 :       if (!representation.IsDouble()) continue;
    3074        6296 :       FieldIndex index = FieldIndex::ForDescriptor(*map, i);
    3075        6296 :       if (map->IsUnboxedDoubleField(index)) continue;
    3076             :       auto box = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
    3077         108 :       if (index.is_inobject()) {
    3078           0 :         storage->set(index.property_index(), *box);
    3079             :       } else {
    3080         216 :         array->set(index.outobject_array_index(), *box);
    3081             :       }
    3082             :     }
    3083             : 
    3084     5840288 :     object->SetProperties(*array);
    3085             : 
    3086             :     if (!FLAG_unbox_double_fields) {
    3087             :       for (int i = 0; i < inobject; i++) {
    3088             :         FieldIndex index = FieldIndex::ForPropertyIndex(*map, i);
    3089             :         Object value = storage->get(i);
    3090             :         object->RawFastPropertyAtPut(index, value);
    3091             :       }
    3092             :     }
    3093             :   }
    3094     7684076 :   object->synchronized_set_map(*map);
    3095     7684076 : }
    3096             : 
    3097         423 : void JSObject::MigrateInstance(Handle<JSObject> object) {
    3098             :   Handle<Map> original_map(object->map(), object->GetIsolate());
    3099         423 :   Handle<Map> map = Map::Update(object->GetIsolate(), original_map);
    3100         423 :   map->set_is_migration_target(true);
    3101         423 :   MigrateToMap(object, map);
    3102         423 :   if (FLAG_trace_migration) {
    3103           0 :     object->PrintInstanceMigration(stdout, *original_map, *map);
    3104             :   }
    3105             : #if VERIFY_HEAP
    3106             :   if (FLAG_verify_heap) {
    3107             :     object->JSObjectVerify(object->GetIsolate());
    3108             :   }
    3109             : #endif
    3110         423 : }
    3111             : 
    3112             : // static
    3113        7212 : bool JSObject::TryMigrateInstance(Handle<JSObject> object) {
    3114             :   Isolate* isolate = object->GetIsolate();
    3115             :   DisallowDeoptimization no_deoptimization(isolate);
    3116             :   Handle<Map> original_map(object->map(), isolate);
    3117             :   Handle<Map> new_map;
    3118       14424 :   if (!Map::TryUpdate(isolate, original_map).ToHandle(&new_map)) {
    3119             :     return false;
    3120             :   }
    3121        7205 :   JSObject::MigrateToMap(object, new_map);
    3122        7205 :   if (FLAG_trace_migration && *original_map != object->map()) {
    3123           0 :     object->PrintInstanceMigration(stdout, *original_map, object->map());
    3124             :   }
    3125             : #if VERIFY_HEAP
    3126             :   if (FLAG_verify_heap) {
    3127             :     object->JSObjectVerify(isolate);
    3128             :   }
    3129             : #endif
    3130             :   return true;
    3131             : }
    3132             : 
    3133    19210523 : void JSObject::AddProperty(Isolate* isolate, Handle<JSObject> object,
    3134             :                            Handle<Name> name, Handle<Object> value,
    3135             :                            PropertyAttributes attributes) {
    3136             :   LookupIterator it(isolate, object, name, object,
    3137    19210523 :                     LookupIterator::OWN_SKIP_INTERCEPTOR);
    3138    19210539 :   CHECK_NE(LookupIterator::ACCESS_CHECK, it.state());
    3139             : #ifdef DEBUG
    3140             :   uint32_t index;
    3141             :   DCHECK(!object->IsJSProxy());
    3142             :   DCHECK(!name->AsArrayIndex(&index));
    3143             :   Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
    3144             :   DCHECK(maybe.IsJust());
    3145             :   DCHECK(!it.IsFound());
    3146             :   DCHECK(object->map()->is_extensible() || name->IsPrivate());
    3147             : #endif
    3148    38421064 :   CHECK(Object::AddDataProperty(&it, value, attributes,
    3149             :                                 Just(ShouldThrow::kThrowOnError),
    3150             :                                 StoreOrigin::kNamed)
    3151             :             .IsJust());
    3152    19210525 : }
    3153             : 
    3154      185221 : void JSObject::AddProperty(Isolate* isolate, Handle<JSObject> object,
    3155             :                            const char* name, Handle<Object> value,
    3156             :                            PropertyAttributes attributes) {
    3157      370442 :   JSObject::AddProperty(isolate, object,
    3158             :                         isolate->factory()->InternalizeUtf8String(name), value,
    3159      185221 :                         attributes);
    3160      185221 : }
    3161             : 
    3162             : // Reconfigures a property to a data property with attributes, even if it is not
    3163             : // reconfigurable.
    3164             : // Requires a LookupIterator that does not look at the prototype chain beyond
    3165             : // hidden prototypes.
    3166    10554052 : MaybeHandle<Object> JSObject::DefineOwnPropertyIgnoreAttributes(
    3167             :     LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
    3168             :     AccessorInfoHandling handling) {
    3169    21108111 :   MAYBE_RETURN_NULL(DefineOwnPropertyIgnoreAttributes(
    3170             :       it, value, attributes, Just(ShouldThrow::kThrowOnError), handling));
    3171    10554041 :   return value;
    3172             : }
    3173             : 
    3174    10887330 : Maybe<bool> JSObject::DefineOwnPropertyIgnoreAttributes(
    3175             :     LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
    3176             :     Maybe<ShouldThrow> should_throw, AccessorInfoHandling handling) {
    3177    10887330 :   it->UpdateProtector();
    3178             :   Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
    3179             : 
    3180    10888584 :   for (; it->IsFound(); it->Next()) {
    3181      560878 :     switch (it->state()) {
    3182             :       case LookupIterator::JSPROXY:
    3183             :       case LookupIterator::NOT_FOUND:
    3184             :       case LookupIterator::TRANSITION:
    3185           0 :         UNREACHABLE();
    3186             : 
    3187             :       case LookupIterator::ACCESS_CHECK:
    3188         421 :         if (!it->HasAccess()) {
    3189           0 :           it->isolate()->ReportFailedAccessCheck(it->GetHolder<JSObject>());
    3190           0 :           RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
    3191             :           return Just(true);
    3192             :         }
    3193             :         break;
    3194             : 
    3195             :       // If there's an interceptor, try to store the property with the
    3196             :       // interceptor.
    3197             :       // In case of success, the attributes will have been reset to the default
    3198             :       // attributes of the interceptor, rather than the incoming attributes.
    3199             :       //
    3200             :       // TODO(verwaest): JSProxy afterwards verify the attributes that the
    3201             :       // JSProxy claims it has, and verifies that they are compatible. If not,
    3202             :       // they throw. Here we should do the same.
    3203             :       case LookupIterator::INTERCEPTOR:
    3204         207 :         if (handling == DONT_FORCE_FIELD) {
    3205             :           Maybe<bool> result =
    3206             :               JSObject::SetPropertyWithInterceptor(it, should_throw, value);
    3207         414 :           if (result.IsNothing() || result.FromJust()) return result;
    3208             :         }
    3209             :         break;
    3210             : 
    3211             :       case LookupIterator::ACCESSOR: {
    3212        5331 :         Handle<Object> accessors = it->GetAccessors();
    3213             : 
    3214             :         // Special handling for AccessorInfo, which behaves like a data
    3215             :         // property.
    3216        5331 :         if (accessors->IsAccessorInfo() && handling == DONT_FORCE_FIELD) {
    3217             :           PropertyAttributes current_attributes = it->property_attributes();
    3218             :           // Ensure the context isn't changed after calling into accessors.
    3219             :           AssertNoContextChange ncc(it->isolate());
    3220             : 
    3221             :           // Update the attributes before calling the setter. The setter may
    3222             :           // later change the shape of the property.
    3223        4725 :           if (current_attributes != attributes) {
    3224        1169 :             it->TransitionToAccessorPair(accessors, attributes);
    3225             :           }
    3226             : 
    3227        4725 :           return Object::SetPropertyWithAccessor(it, value, should_throw);
    3228             :         }
    3229             : 
    3230         606 :         it->ReconfigureDataProperty(value, attributes);
    3231             :         return Just(true);
    3232             :       }
    3233             :       case LookupIterator::INTEGER_INDEXED_EXOTIC:
    3234             :         return Object::RedefineIncompatibleProperty(
    3235          18 :             it->isolate(), it->GetName(), value, should_throw);
    3236             : 
    3237             :       case LookupIterator::DATA: {
    3238             :         // Regular property update if the attributes match.
    3239      554910 :         if (it->property_attributes() == attributes) {
    3240      533553 :           return Object::SetDataProperty(it, value);
    3241             :         }
    3242             : 
    3243             :         // Special case: properties of typed arrays cannot be reconfigured to
    3244             :         // non-writable nor to non-enumerable.
    3245       40708 :         if (it->IsElement() && object->HasFixedTypedArrayElements()) {
    3246             :           return Object::RedefineIncompatibleProperty(
    3247           0 :               it->isolate(), it->GetName(), value, should_throw);
    3248             :         }
    3249             : 
    3250             :         // Reconfigure the data property if the attributes mismatch.
    3251       21357 :         it->ReconfigureDataProperty(value, attributes);
    3252             : 
    3253             :         return Just(true);
    3254             :       }
    3255             :     }
    3256             :   }
    3257             : 
    3258             :   return Object::AddDataProperty(it, value, attributes, should_throw,
    3259    10327084 :                                  StoreOrigin::kNamed);
    3260             : }
    3261             : 
    3262     3976111 : MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
    3263             :     Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
    3264             :     PropertyAttributes attributes) {
    3265             :   DCHECK(!value->IsTheHole());
    3266             :   LookupIterator it(object, name, object, LookupIterator::OWN);
    3267     3976110 :   return DefineOwnPropertyIgnoreAttributes(&it, value, attributes);
    3268             : }
    3269             : 
    3270     2472230 : MaybeHandle<Object> JSObject::SetOwnElementIgnoreAttributes(
    3271             :     Handle<JSObject> object, uint32_t index, Handle<Object> value,
    3272             :     PropertyAttributes attributes) {
    3273             :   Isolate* isolate = object->GetIsolate();
    3274             :   LookupIterator it(isolate, object, index, object, LookupIterator::OWN);
    3275     2472230 :   return DefineOwnPropertyIgnoreAttributes(&it, value, attributes);
    3276             : }
    3277             : 
    3278      433635 : MaybeHandle<Object> JSObject::DefinePropertyOrElementIgnoreAttributes(
    3279             :     Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
    3280             :     PropertyAttributes attributes) {
    3281             :   Isolate* isolate = object->GetIsolate();
    3282             :   LookupIterator it = LookupIterator::PropertyOrElement(
    3283      433635 :       isolate, object, name, object, LookupIterator::OWN);
    3284      433635 :   return DefineOwnPropertyIgnoreAttributes(&it, value, attributes);
    3285             : }
    3286             : 
    3287      249502 : Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor(
    3288             :     LookupIterator* it) {
    3289      292441 :   return GetPropertyAttributesWithInterceptorInternal(it, it->GetInterceptor());
    3290             : }
    3291             : 
    3292      682142 : void JSObject::NormalizeProperties(Handle<JSObject> object,
    3293             :                                    PropertyNormalizationMode mode,
    3294             :                                    int expected_additional_properties,
    3295             :                                    const char* reason) {
    3296      936492 :   if (!object->HasFastProperties()) return;
    3297             : 
    3298             :   Handle<Map> map(object->map(), object->GetIsolate());
    3299      427793 :   Handle<Map> new_map = Map::Normalize(object->GetIsolate(), map, mode, reason);
    3300             : 
    3301      427794 :   MigrateToMap(object, new_map, expected_additional_properties);
    3302             : }
    3303             : 
    3304     1103164 : void JSObject::MigrateSlowToFast(Handle<JSObject> object,
    3305             :                                  int unused_property_fields,
    3306             :                                  const char* reason) {
    3307     1933259 :   if (object->HasFastProperties()) return;
    3308             :   DCHECK(!object->IsJSGlobalObject());
    3309             :   Isolate* isolate = object->GetIsolate();
    3310             :   Factory* factory = isolate->factory();
    3311      675924 :   Handle<NameDictionary> dictionary(object->property_dictionary(), isolate);
    3312             : 
    3313             :   // Make sure we preserve dictionary representation if there are too many
    3314             :   // descriptors.
    3315             :   int number_of_elements = dictionary->NumberOfElements();
    3316      337962 :   if (number_of_elements > kMaxNumberOfDescriptors) return;
    3317             : 
    3318             :   Handle<FixedArray> iteration_order =
    3319      337367 :       NameDictionary::IterationIndices(isolate, dictionary);
    3320             : 
    3321             :   int instance_descriptor_length = iteration_order->length();
    3322             :   int number_of_fields = 0;
    3323             : 
    3324             :   // Compute the length of the instance descriptor.
    3325             :   ReadOnlyRoots roots(isolate);
    3326     3877404 :   for (int i = 0; i < instance_descriptor_length; i++) {
    3327             :     int index = Smi::ToInt(iteration_order->get(i));
    3328             :     DCHECK(dictionary->IsKey(roots, dictionary->KeyAt(index)));
    3329             : 
    3330     3540038 :     PropertyKind kind = dictionary->DetailsAt(index).kind();
    3331     1770019 :     if (kind == kData) {
    3332             :       if (FLAG_track_constant_fields) {
    3333     1359106 :         number_of_fields += 1;
    3334             :       } else {
    3335             :         Object value = dictionary->ValueAt(index);
    3336             :         if (!value->IsJSFunction()) {
    3337             :           number_of_fields += 1;
    3338             :         }
    3339             :       }
    3340             :     }
    3341             :   }
    3342             : 
    3343             :   Handle<Map> old_map(object->map(), isolate);
    3344             : 
    3345      337366 :   int inobject_props = old_map->GetInObjectProperties();
    3346             : 
    3347             :   // Allocate new map.
    3348      337366 :   Handle<Map> new_map = Map::CopyDropDescriptors(isolate, old_map);
    3349             :   // We should not only set this bit if we need to. We should not retain the
    3350             :   // old bit because turning a map into dictionary always sets this bit.
    3351     1011957 :   new_map->set_may_have_interesting_symbols(new_map->has_named_interceptor() ||
    3352      337368 :                                             new_map->is_access_check_needed());
    3353      337368 :   new_map->set_is_dictionary_map(false);
    3354             : 
    3355      337368 :   NotifyMapChange(old_map, new_map, isolate);
    3356             : 
    3357      337368 :   if (instance_descriptor_length == 0) {
    3358             :     DisallowHeapAllocation no_gc;
    3359             :     DCHECK_LE(unused_property_fields, inobject_props);
    3360             :     // Transform the object.
    3361       64297 :     new_map->SetInObjectUnusedPropertyFields(inobject_props);
    3362       64297 :     object->synchronized_set_map(*new_map);
    3363      128594 :     object->SetProperties(ReadOnlyRoots(isolate).empty_fixed_array());
    3364             :     // Check that it really works.
    3365             :     DCHECK(object->HasFastProperties());
    3366       64297 :     if (FLAG_trace_maps) {
    3367           0 :       LOG(isolate, MapEvent("SlowToFast", *old_map, *new_map, reason));
    3368             :     }
    3369             :     return;
    3370             :   }
    3371             : 
    3372             :   // Allocate the instance descriptor.
    3373             :   Handle<DescriptorArray> descriptors = DescriptorArray::Allocate(
    3374      273071 :       isolate, instance_descriptor_length, 0, AllocationType::kOld);
    3375             : 
    3376             :   int number_of_allocated_fields =
    3377      273068 :       number_of_fields + unused_property_fields - inobject_props;
    3378      273068 :   if (number_of_allocated_fields < 0) {
    3379             :     // There is enough inobject space for all fields (including unused).
    3380             :     number_of_allocated_fields = 0;
    3381       42493 :     unused_property_fields = inobject_props - number_of_fields;
    3382             :   }
    3383             : 
    3384             :   // Allocate the property array for the fields.
    3385             :   Handle<PropertyArray> fields =
    3386      273068 :       factory->NewPropertyArray(number_of_allocated_fields);
    3387             : 
    3388             :   bool is_transitionable_elements_kind =
    3389             :       IsTransitionableFastElementsKind(old_map->elements_kind());
    3390             : 
    3391             :   // Fill in the instance descriptor and the fields.
    3392             :   int current_offset = 0;
    3393     3813202 :   for (int i = 0; i < instance_descriptor_length; i++) {
    3394             :     int index = Smi::ToInt(iteration_order->get(i));
    3395             :     Name k = dictionary->NameAt(index);
    3396             :     // Dictionary keys are internalized upon insertion.
    3397             :     // TODO(jkummerow): Turn this into a DCHECK if it's not hit in the wild.
    3398     1770065 :     CHECK(k->IsUniqueName());
    3399             :     Handle<Name> key(k, isolate);
    3400             : 
    3401             :     // Properly mark the {new_map} if the {key} is an "interesting symbol".
    3402     1770066 :     if (key->IsInterestingSymbol()) {
    3403        1852 :       new_map->set_may_have_interesting_symbols(true);
    3404             :     }
    3405             : 
    3406             :     Object value = dictionary->ValueAt(index);
    3407             : 
    3408     1770066 :     PropertyDetails details = dictionary->DetailsAt(index);
    3409             :     DCHECK_EQ(kField, details.location());
    3410             :     DCHECK_EQ(PropertyConstness::kMutable, details.constness());
    3411             : 
    3412     1770066 :     Descriptor d;
    3413     1770064 :     if (details.kind() == kData) {
    3414             :       if (!FLAG_track_constant_fields && value->IsJSFunction()) {
    3415             :         d = Descriptor::DataConstant(key, handle(value, isolate),
    3416             :                                      details.attributes());
    3417             :       } else {
    3418             :         // Ensure that we make constant field only when elements kind is not
    3419             :         // transitionable.
    3420             :         PropertyConstness constness =
    3421             :             FLAG_track_constant_fields && !is_transitionable_elements_kind
    3422             :                 ? PropertyConstness::kConst
    3423     1359125 :                 : PropertyConstness::kMutable;
    3424     2718249 :         d = Descriptor::DataField(
    3425             :             key, current_offset, details.attributes(), constness,
    3426             :             // TODO(verwaest): value->OptimalRepresentation();
    3427             :             Representation::Tagged(),
    3428     4077375 :             MaybeObjectHandle(FieldType::Any(isolate)));
    3429             :       }
    3430             :     } else {
    3431             :       DCHECK_EQ(kAccessor, details.kind());
    3432      821878 :       d = Descriptor::AccessorConstant(key, handle(value, isolate),
    3433      410939 :                                        details.attributes());
    3434             :     }
    3435             :     details = d.GetDetails();
    3436     1770064 :     if (details.location() == kField) {
    3437     1359125 :       if (current_offset < inobject_props) {
    3438             :         object->InObjectPropertyAtPut(current_offset, value,
    3439       59658 :                                       UPDATE_WRITE_BARRIER);
    3440             :       } else {
    3441     1299467 :         int offset = current_offset - inobject_props;
    3442     1299467 :         fields->set(offset, value);
    3443             :       }
    3444     1359126 :       current_offset += details.field_width_in_words();
    3445             :     }
    3446     1770065 :     descriptors->Set(i, &d);
    3447             :   }
    3448             :   DCHECK(current_offset == number_of_fields);
    3449             : 
    3450      273071 :   descriptors->Sort();
    3451             : 
    3452             :   Handle<LayoutDescriptor> layout_descriptor = LayoutDescriptor::New(
    3453      273071 :       isolate, new_map, descriptors, descriptors->number_of_descriptors());
    3454             : 
    3455             :   DisallowHeapAllocation no_gc;
    3456      273071 :   new_map->InitializeDescriptors(isolate, *descriptors, *layout_descriptor);
    3457      273070 :   if (number_of_allocated_fields == 0) {
    3458       52054 :     new_map->SetInObjectUnusedPropertyFields(unused_property_fields);
    3459             :   } else {
    3460      221016 :     new_map->SetOutOfObjectUnusedPropertyFields(unused_property_fields);
    3461             :   }
    3462             : 
    3463      273070 :   if (FLAG_trace_maps) {
    3464         818 :     LOG(isolate, MapEvent("SlowToFast", *old_map, *new_map, reason));
    3465             :   }
    3466             :   // Transform the object.
    3467      273070 :   object->synchronized_set_map(*new_map);
    3468             : 
    3469      546142 :   object->SetProperties(*fields);
    3470             :   DCHECK(object->IsJSObject());
    3471             : 
    3472             :   // Check that it really works.
    3473             :   DCHECK(object->HasFastProperties());
    3474             : }
    3475             : 
    3476       72476 : void JSObject::RequireSlowElements(NumberDictionary dictionary) {
    3477       72476 :   if (dictionary->requires_slow_elements()) return;
    3478             :   dictionary->set_requires_slow_elements();
    3479       40065 :   if (map()->is_prototype_map()) {
    3480             :     // If this object is a prototype (the callee will check), invalidate any
    3481             :     // prototype chains involving it.
    3482             :     InvalidatePrototypeChains(map());
    3483             :   }
    3484             : }
    3485             : 
    3486      290847 : Handle<NumberDictionary> JSObject::NormalizeElements(Handle<JSObject> object) {
    3487             :   DCHECK(!object->HasFixedTypedArrayElements());
    3488             :   Isolate* isolate = object->GetIsolate();
    3489      290847 :   bool is_sloppy_arguments = object->HasSloppyArgumentsElements();
    3490             :   {
    3491             :     DisallowHeapAllocation no_gc;
    3492             :     FixedArrayBase elements = object->elements();
    3493             : 
    3494      290847 :     if (is_sloppy_arguments) {
    3495             :       elements = SloppyArgumentsElements::cast(elements)->arguments();
    3496             :     }
    3497             : 
    3498      290847 :     if (elements->IsNumberDictionary()) {
    3499             :       return handle(NumberDictionary::cast(elements), isolate);
    3500             :     }
    3501             :   }
    3502             : 
    3503             :   DCHECK(object->HasSmiOrObjectElements() || object->HasDoubleElements() ||
    3504             :          object->HasFastArgumentsElements() ||
    3505             :          object->HasFastStringWrapperElements());
    3506             : 
    3507             :   Handle<NumberDictionary> dictionary =
    3508      286567 :       object->GetElementsAccessor()->Normalize(object);
    3509             : 
    3510             :   // Switch to using the dictionary as the backing storage for elements.
    3511             :   ElementsKind target_kind = is_sloppy_arguments
    3512             :                                  ? SLOW_SLOPPY_ARGUMENTS_ELEMENTS
    3513      858223 :                                  : object->HasFastStringWrapperElements()
    3514             :                                        ? SLOW_STRING_WRAPPER_ELEMENTS
    3515      573134 :                                        : DICTIONARY_ELEMENTS;
    3516      286567 :   Handle<Map> new_map = JSObject::GetElementsTransitionMap(object, target_kind);
    3517             :   // Set the new map first to satify the elements type assert in set_elements().
    3518      286567 :   JSObject::MigrateToMap(object, new_map);
    3519             : 
    3520      286567 :   if (is_sloppy_arguments) {
    3521        1478 :     SloppyArgumentsElements::cast(object->elements())
    3522             :         ->set_arguments(*dictionary);
    3523             :   } else {
    3524      571656 :     object->set_elements(*dictionary);
    3525             :   }
    3526             : 
    3527      286567 :   isolate->counters()->elements_to_dictionary()->Increment();
    3528             : 
    3529             : #ifdef DEBUG
    3530             :   if (FLAG_trace_normalization) {
    3531             :     StdoutStream os;
    3532             :     os << "Object elements have been normalized:\n";
    3533             :     object->Print(os);
    3534             :   }
    3535             : #endif
    3536             : 
    3537             :   DCHECK(object->HasDictionaryElements() ||
    3538             :          object->HasSlowArgumentsElements() ||
    3539             :          object->HasSlowStringWrapperElements());
    3540      286567 :   return dictionary;
    3541             : }
    3542             : 
    3543         100 : Maybe<bool> JSObject::DeletePropertyWithInterceptor(LookupIterator* it,
    3544             :                                                     ShouldThrow should_throw) {
    3545             :   Isolate* isolate = it->isolate();
    3546             :   // Make sure that the top context does not change when doing callbacks or
    3547             :   // interceptor calls.
    3548             :   AssertNoContextChange ncc(isolate);
    3549             : 
    3550             :   DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
    3551         100 :   Handle<InterceptorInfo> interceptor(it->GetInterceptor());
    3552         100 :   if (interceptor->deleter()->IsUndefined(isolate)) return Nothing<bool>();
    3553             : 
    3554             :   Handle<JSObject> holder = it->GetHolder<JSObject>();
    3555             :   Handle<Object> receiver = it->GetReceiver();
    3556          58 :   if (!receiver->IsJSReceiver()) {
    3557           0 :     ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
    3558             :                                      Object::ConvertReceiver(isolate, receiver),
    3559             :                                      Nothing<bool>());
    3560             :   }
    3561             : 
    3562             :   PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
    3563          58 :                                  *holder, Just(should_throw));
    3564             :   Handle<Object> result;
    3565          58 :   if (it->IsElement()) {
    3566          23 :     result = args.CallIndexedDeleter(interceptor, it->index());
    3567             :   } else {
    3568          35 :     result = args.CallNamedDeleter(interceptor, it->name());
    3569             :   }
    3570             : 
    3571          58 :   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
    3572          58 :   if (result.is_null()) return Nothing<bool>();
    3573             : 
    3574             :   DCHECK(result->IsBoolean());
    3575             :   // Rebox CustomArguments::kReturnValueOffset before returning.
    3576             :   return Just(result->IsTrue(isolate));
    3577             : }
    3578             : 
    3579     1139784 : Maybe<bool> JSObject::CreateDataProperty(LookupIterator* it,
    3580             :                                          Handle<Object> value,
    3581             :                                          Maybe<ShouldThrow> should_throw) {
    3582             :   DCHECK(it->GetReceiver()->IsJSObject());
    3583     2279568 :   MAYBE_RETURN(JSReceiver::GetPropertyAttributes(it), Nothing<bool>());
    3584             :   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
    3585             :   Isolate* isolate = receiver->GetIsolate();
    3586             : 
    3587     1139779 :   if (it->IsFound()) {
    3588         405 :     Maybe<PropertyAttributes> attributes = GetPropertyAttributes(it);
    3589         442 :     MAYBE_RETURN(attributes, Nothing<bool>());
    3590         405 :     if ((attributes.FromJust() & DONT_DELETE) != 0) {
    3591         118 :       RETURN_FAILURE(
    3592             :           isolate, GetShouldThrow(isolate, should_throw),
    3593             :           NewTypeError(MessageTemplate::kRedefineDisallowed, it->GetName()));
    3594             :     }
    3595             :   } else {
    3596     1139374 :     if (!JSObject::IsExtensible(Handle<JSObject>::cast(it->GetReceiver()))) {
    3597         329 :       RETURN_FAILURE(
    3598             :           isolate, GetShouldThrow(isolate, should_throw),
    3599             :           NewTypeError(MessageTemplate::kDefineDisallowed, it->GetName()));
    3600             :     }
    3601             :   }
    3602             : 
    3603     2279312 :   RETURN_ON_EXCEPTION_VALUE(it->isolate(),
    3604             :                             DefineOwnPropertyIgnoreAttributes(it, value, NONE),
    3605             :                             Nothing<bool>());
    3606             : 
    3607             :   return Just(true);
    3608             : }
    3609             : 
    3610             : namespace {
    3611             : 
    3612             : template <typename Dictionary>
    3613    10214843 : bool TestDictionaryPropertiesIntegrityLevel(Dictionary dict,
    3614             :                                             ReadOnlyRoots roots,
    3615             :                                             PropertyAttributes level) {
    3616             :   DCHECK(level == SEALED || level == FROZEN);
    3617             : 
    3618    10214843 :   uint32_t capacity = dict->Capacity();
    3619    30655347 :   for (uint32_t i = 0; i < capacity; i++) {
    3620    10220572 :     Object key;
    3621    20437968 :     if (!dict->ToKey(roots, i, &key)) continue;
    3622        3194 :     if (key->FilterKey(ALL_PROPERTIES)) continue;
    3623        3176 :     PropertyDetails details = dict->DetailsAt(i);
    3624        3496 :     if (details.IsConfigurable()) return false;
    3625        7308 :     if (level == FROZEN && details.kind() == kData && !details.IsReadOnly()) {
    3626             :       return false;
    3627             :     }
    3628             :   }
    3629             :   return true;
    3630             : }
    3631             : 
    3632    10214524 : bool TestFastPropertiesIntegrityLevel(Map map, PropertyAttributes level) {
    3633             :   DCHECK(level == SEALED || level == FROZEN);
    3634             :   DCHECK(!map->IsCustomElementsReceiverMap());
    3635             :   DCHECK(!map->is_dictionary_map());
    3636             : 
    3637    10214524 :   DescriptorArray descriptors = map->instance_descriptors();
    3638             :   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
    3639    10218414 :   for (int i = 0; i < number_of_own_descriptors; i++) {
    3640        2144 :     if (descriptors->GetKey(i)->IsPrivate()) continue;
    3641        2126 :     PropertyDetails details = descriptors->GetDetails(i);
    3642        2126 :     if (details.IsConfigurable()) return false;
    3643        4457 :     if (level == FROZEN && details.kind() == kData && !details.IsReadOnly()) {
    3644             :       return false;
    3645             :     }
    3646             :   }
    3647             :   return true;
    3648             : }
    3649             : 
    3650    10214622 : bool TestPropertiesIntegrityLevel(JSObject object, PropertyAttributes level) {
    3651             :   DCHECK(!object->map()->IsCustomElementsReceiverMap());
    3652             : 
    3653    10214622 :   if (object->HasFastProperties()) {
    3654    10214524 :     return TestFastPropertiesIntegrityLevel(object->map(), level);
    3655             :   }
    3656             : 
    3657          98 :   return TestDictionaryPropertiesIntegrityLevel(
    3658          98 :       object->property_dictionary(), object->GetReadOnlyRoots(), level);
    3659             : }
    3660             : 
    3661    10214950 : bool TestElementsIntegrityLevel(JSObject object, PropertyAttributes level) {
    3662             :   DCHECK(!object->HasSloppyArgumentsElements());
    3663             : 
    3664             :   ElementsKind kind = object->GetElementsKind();
    3665             : 
    3666    10214950 :   if (IsDictionaryElementsKind(kind)) {
    3667             :     return TestDictionaryPropertiesIntegrityLevel(
    3668             :         NumberDictionary::cast(object->elements()), object->GetReadOnlyRoots(),
    3669    10214745 :         level);
    3670             :   }
    3671         205 :   if (IsFixedTypedArrayElementsKind(kind)) {
    3672          76 :     if (level == FROZEN && JSArrayBufferView::cast(object)->byte_length() > 0)
    3673             :       return false;  // TypedArrays with elements can't be frozen.
    3674          13 :     return TestPropertiesIntegrityLevel(object, level);
    3675             :   }
    3676         165 :   if (kind == PACKED_FROZEN_ELEMENTS) return true;
    3677          59 :   if (kind == PACKED_SEALED_ELEMENTS && level != FROZEN) return true;
    3678             : 
    3679             :   ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
    3680             :   // Only DICTIONARY_ELEMENTS and SLOW_SLOPPY_ARGUMENTS_ELEMENTS have
    3681             :   // PropertyAttributes so just test if empty
    3682          34 :   return accessor->NumberOfElements(object) == 0;
    3683             : }
    3684             : 
    3685    10450885 : bool FastTestIntegrityLevel(JSObject object, PropertyAttributes level) {
    3686             :   DCHECK(!object->map()->IsCustomElementsReceiverMap());
    3687             : 
    3688    10214950 :   return !object->map()->is_extensible() &&
    3689    20665494 :          TestElementsIntegrityLevel(object, level) &&
    3690    20665494 :          TestPropertiesIntegrityLevel(object, level);
    3691             : }
    3692             : 
    3693             : }  // namespace
    3694             : 
    3695    10451026 : Maybe<bool> JSObject::TestIntegrityLevel(Handle<JSObject> object,
    3696             :                                          IntegrityLevel level) {
    3697    31352966 :   if (!object->map()->IsCustomElementsReceiverMap() &&
    3698    20901936 :       !object->HasSloppyArgumentsElements()) {
    3699    10450885 :     return Just(FastTestIntegrityLevel(*object, level));
    3700             :   }
    3701         145 :   return GenericTestIntegrityLevel(Handle<JSReceiver>::cast(object), level);
    3702             : }
    3703             : 
    3704        6645 : Maybe<bool> JSObject::PreventExtensions(Handle<JSObject> object,
    3705             :                                         ShouldThrow should_throw) {
    3706             :   Isolate* isolate = object->GetIsolate();
    3707             : 
    3708        6645 :   if (!object->HasSloppyArgumentsElements()) {
    3709        6592 :     return PreventExtensionsWithTransition<NONE>(object, should_throw);
    3710             :   }
    3711             : 
    3712          53 :   if (object->IsAccessCheckNeeded() &&
    3713           0 :       !isolate->MayAccess(handle(isolate->context(), isolate), object)) {
    3714           0 :     isolate->ReportFailedAccessCheck(object);
    3715           0 :     RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
    3716           0 :     RETURN_FAILURE(isolate, should_throw,
    3717             :                    NewTypeError(MessageTemplate::kNoAccess));
    3718             :   }
    3719             : 
    3720          53 :   if (!object->map()->is_extensible()) return Just(true);
    3721             : 
    3722          53 :   if (object->IsJSGlobalProxy()) {
    3723           0 :     PrototypeIterator iter(isolate, object);
    3724           0 :     if (iter.IsAtEnd()) return Just(true);
    3725             :     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
    3726             :     return PreventExtensions(PrototypeIterator::GetCurrent<JSObject>(iter),
    3727           0 :                              should_throw);
    3728             :   }
    3729             : 
    3730         106 :   if (object->map()->has_named_interceptor() ||
    3731             :       object->map()->has_indexed_interceptor()) {
    3732           0 :     RETURN_FAILURE(isolate, should_throw,
    3733             :                    NewTypeError(MessageTemplate::kCannotPreventExt));
    3734             :   }
    3735             : 
    3736          53 :   if (!object->HasFixedTypedArrayElements()) {
    3737             :     // If there are fast elements we normalize.
    3738          53 :     Handle<NumberDictionary> dictionary = NormalizeElements(object);
    3739             :     DCHECK(object->HasDictionaryElements() ||
    3740             :            object->HasSlowArgumentsElements());
    3741             : 
    3742             :     // Make sure that we never go back to fast case.
    3743          53 :     object->RequireSlowElements(*dictionary);
    3744             :   }
    3745             : 
    3746             :   // Do a map transition, other objects with this map may still
    3747             :   // be extensible.
    3748             :   // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
    3749             :   Handle<Map> new_map =
    3750          53 :       Map::Copy(isolate, handle(object->map(), isolate), "PreventExtensions");
    3751             : 
    3752             :   new_map->set_is_extensible(false);
    3753          53 :   JSObject::MigrateToMap(object, new_map);
    3754             :   DCHECK(!object->map()->is_extensible());
    3755             : 
    3756             :   return Just(true);
    3757             : }
    3758             : 
    3759     2608216 : bool JSObject::IsExtensible(Handle<JSObject> object) {
    3760             :   Isolate* isolate = object->GetIsolate();
    3761     2608256 :   if (object->IsAccessCheckNeeded() &&
    3762          40 :       !isolate->MayAccess(handle(isolate->context(), isolate), object)) {
    3763             :     return true;
    3764             :   }
    3765     2608185 :   if (object->IsJSGlobalProxy()) {
    3766             :     PrototypeIterator iter(isolate, *object);
    3767        2802 :     if (iter.IsAtEnd()) return false;
    3768             :     DCHECK(iter.GetCurrent()->IsJSGlobalObject());
    3769             :     return iter.GetCurrent<JSObject>()->map()->is_extensible();
    3770             :   }
    3771             :   return object->map()->is_extensible();
    3772             : }
    3773             : 
    3774             : template <typename Dictionary>
    3775        2808 : void JSObject::ApplyAttributesToDictionary(
    3776             :     Isolate* isolate, ReadOnlyRoots roots, Handle<Dictionary> dictionary,
    3777             :     const PropertyAttributes attributes) {
    3778             :   int capacity = dictionary->Capacity();
    3779     1286552 :   for (int i = 0; i < capacity; i++) {
    3780      641872 :     Object k;
    3781      899289 :     if (!dictionary->ToKey(roots, i, &k)) continue;
    3782      384473 :     if (k->FilterKey(ALL_PROPERTIES)) continue;
    3783      375176 :     PropertyDetails details = dictionary->DetailsAt(i);
    3784      384455 :     int attrs = attributes;
    3785             :     // READ_ONLY is an invalid attribute for JS setters/getters.
    3786      584964 :     if ((attributes & READ_ONLY) && details.kind() == kAccessor) {
    3787           9 :       Object v = dictionary->ValueAt(i);
    3788          45 :       if (v->IsAccessorPair()) attrs &= ~READ_ONLY;
    3789             :     }
    3790             :     details = details.CopyAddAttributes(static_cast<PropertyAttributes>(attrs));
    3791        9279 :     dictionary->DetailsAtPut(isolate, i, details);
    3792             :   }
    3793        2808 : }
    3794             : 
    3795             : template <PropertyAttributes attrs>
    3796      242880 : Maybe<bool> JSObject::PreventExtensionsWithTransition(
    3797             :     Handle<JSObject> object, ShouldThrow should_throw) {
    3798             :   STATIC_ASSERT(attrs == NONE || attrs == SEALED || attrs == FROZEN);
    3799             : 
    3800             :   // Sealing/freezing sloppy arguments or namespace objects should be handled
    3801             :   // elsewhere.
    3802             :   DCHECK(!object->HasSloppyArgumentsElements());
    3803             :   DCHECK_IMPLIES(object->IsJSModuleNamespace(), attrs == NONE);
    3804             : 
    3805             :   Isolate* isolate = object->GetIsolate();
    3806      242907 :   if (object->IsAccessCheckNeeded() &&
    3807          25 :       !isolate->MayAccess(handle(isolate->context(), isolate), object)) {
    3808          20 :     isolate->ReportFailedAccessCheck(object);
    3809          20 :     RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
    3810           0 :     RETURN_FAILURE(isolate, should_throw,
    3811             :                    NewTypeError(MessageTemplate::kNoAccess));
    3812             :   }
    3813             : 
    3814        6591 :   if (attrs == NONE && !object->map()->is_extensible()) return Just(true);
    3815             :   ElementsKind old_elements_kind = object->map()->elements_kind();
    3816        9260 :   if (attrs != FROZEN && old_elements_kind == PACKED_SEALED_ELEMENTS)
    3817             :     return Just(true);
    3818      242781 :   if (old_elements_kind == PACKED_FROZEN_ELEMENTS) return Just(true);
    3819             : 
    3820      242781 :   if (object->IsJSGlobalProxy()) {
    3821          90 :     PrototypeIterator iter(isolate, object);
    3822          90 :     if (iter.IsAtEnd()) return Just(true);
    3823             :     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
    3824             :     return PreventExtensionsWithTransition<attrs>(
    3825          90 :         PrototypeIterator::GetCurrent<JSObject>(iter), should_throw);
    3826             :   }
    3827             : 
    3828      485380 :   if (object->map()->has_named_interceptor() ||
    3829             :       object->map()->has_indexed_interceptor()) {
    3830             :     MessageTemplate message = MessageTemplate::kNone;
    3831             :     switch (attrs) {
    3832             :       case NONE:
    3833             :         message = MessageTemplate::kCannotPreventExt;
    3834             :         break;
    3835             : 
    3836             :       case SEALED:
    3837             :         message = MessageTemplate::kCannotSeal;
    3838             :         break;
    3839             : 
    3840             :       case FROZEN:
    3841             :         message = MessageTemplate::kCannotFreeze;
    3842             :         break;
    3843             :     }
    3844           3 :     RETURN_FAILURE(isolate, should_throw, NewTypeError(message));
    3845             :   }
    3846             : 
    3847             :   Handle<NumberDictionary> new_element_dictionary;
    3848      970183 :   if (!object->HasFixedTypedArrayElements() &&
    3849      485296 :       !object->HasDictionaryElements() &&
    3850      484888 :       !object->HasSlowStringWrapperElements()) {
    3851             :     int length = object->IsJSArray()
    3852             :                      ? Smi::ToInt(Handle<JSArray>::cast(object)->length())
    3853      242198 :                      : object->elements()->length();
    3854      484396 :     new_element_dictionary =
    3855             :         length == 0 ? isolate->factory()->empty_slow_element_dictionary()
    3856      266078 :                     : object->GetElementsAccessor()->Normalize(object);
    3857             :   }
    3858             : 
    3859             :   Handle<Symbol> transition_marker;
    3860             :   if (attrs == NONE) {
    3861             :     transition_marker = isolate->factory()->nonextensible_symbol();
    3862             :   } else if (attrs == SEALED) {
    3863             :     transition_marker = isolate->factory()->sealed_symbol();
    3864             :   } else {
    3865             :     DCHECK(attrs == FROZEN);
    3866             :     transition_marker = isolate->factory()->frozen_symbol();
    3867             :   }
    3868             : 
    3869             :   Handle<Map> old_map(object->map(), isolate);
    3870             :   TransitionsAccessor transitions(isolate, old_map);
    3871      242693 :   Map transition = transitions.SearchSpecial(*transition_marker);
    3872      242693 :   if (!transition.is_null()) {
    3873             :     Handle<Map> transition_map(transition, isolate);
    3874             :     DCHECK(transition_map->has_dictionary_elements() ||
    3875             :            transition_map->has_fixed_typed_array_elements() ||
    3876             :            transition_map->elements_kind() == SLOW_STRING_WRAPPER_ELEMENTS ||
    3877             :            transition_map->is_frozen_or_sealed_elements());
    3878             :     DCHECK(!transition_map->is_extensible());
    3879      104954 :     JSObject::MigrateToMap(object, transition_map);
    3880      137739 :   } else if (transitions.CanHaveMoreTransitions()) {
    3881             :     // Create a new descriptor array with the appropriate property attributes
    3882             :     Handle<Map> new_map = Map::CopyForPreventExtensions(
    3883      136921 :         isolate, old_map, attrs, transition_marker, "CopyForPreventExtensions");
    3884      136919 :     JSObject::MigrateToMap(object, new_map);
    3885             :   } else {
    3886             :     DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map());
    3887             :     // Slow path: need to normalize properties for safety
    3888         818 :     NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0,
    3889             :                         "SlowPreventExtensions");
    3890             : 
    3891             :     // Create a new map, since other objects with this map may be extensible.
    3892             :     // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
    3893             :     Handle<Map> new_map = Map::Copy(isolate, handle(object->map(), isolate),
    3894         818 :                                     "SlowCopyForPreventExtensions");
    3895             :     new_map->set_is_extensible(false);
    3896         818 :     if (!new_element_dictionary.is_null()) {
    3897             :       ElementsKind new_kind =
    3898             :           IsStringWrapperElementsKind(old_map->elements_kind())
    3899             :               ? SLOW_STRING_WRAPPER_ELEMENTS
    3900         809 :               : DICTIONARY_ELEMENTS;
    3901        1618 :       new_map->set_elements_kind(new_kind);
    3902             :     }
    3903         818 :     JSObject::MigrateToMap(object, new_map);
    3904             : 
    3905             :     if (attrs != NONE) {
    3906             :       ReadOnlyRoots roots(isolate);
    3907         161 :       if (object->IsJSGlobalObject()) {
    3908             :         Handle<GlobalDictionary> dictionary(
    3909             :             JSGlobalObject::cast(*object)->global_dictionary(), isolate);
    3910          81 :         JSObject::ApplyAttributesToDictionary(isolate, roots, dictionary,
    3911             :                                               attrs);
    3912             :       } else {
    3913         160 :         Handle<NameDictionary> dictionary(object->property_dictionary(),
    3914          80 :                                           isolate);
    3915          80 :         JSObject::ApplyAttributesToDictionary(isolate, roots, dictionary,
    3916             :                                               attrs);
    3917             :       }
    3918             :     }
    3919             :   }
    3920             : 
    3921      242691 :   if (object->map()->is_frozen_or_sealed_elements()) {
    3922             :     return Just(true);
    3923             :   }
    3924             : 
    3925             :   // Both seal and preventExtensions always go through without modifications to
    3926             :   // typed array elements. Freeze works only if there are no actual elements.
    3927      235354 :   if (object->HasFixedTypedArrayElements()) {
    3928          63 :     if (attrs == FROZEN &&
    3929             :         JSArrayBufferView::cast(*object)->byte_length() > 0) {
    3930          90 :       isolate->Throw(*isolate->factory()->NewTypeError(
    3931             :           MessageTemplate::kCannotFreezeArrayBufferView));
    3932             :       return Nothing<bool>();
    3933             :     }
    3934             :     return Just(true);
    3935             :   }
    3936             : 
    3937             :   DCHECK(object->map()->has_dictionary_elements() ||
    3938             :          object->map()->elements_kind() == SLOW_STRING_WRAPPER_ELEMENTS);
    3939      235272 :   if (!new_element_dictionary.is_null()) {
    3940      469728 :     object->set_elements(*new_element_dictionary);
    3941             :   }
    3942             : 
    3943      235272 :   if (object->elements() !=
    3944             :       ReadOnlyRoots(isolate).empty_slow_element_dictionary()) {
    3945             :     Handle<NumberDictionary> dictionary(object->element_dictionary(), isolate);
    3946             :     // Make sure we never go back to the fast case
    3947        4940 :     object->RequireSlowElements(*dictionary);
    3948             :     if (attrs != NONE) {
    3949        2643 :       JSObject::ApplyAttributesToDictionary(isolate, ReadOnlyRoots(isolate),
    3950             :                                             dictionary, attrs);
    3951             :     }
    3952             :   }
    3953             : 
    3954             :   return Just(true);
    3955             : }
    3956             : 
    3957    11799950 : Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object,
    3958             :                                         Representation representation,
    3959             :                                         FieldIndex index) {
    3960             :   Isolate* isolate = object->GetIsolate();
    3961    11799950 :   if (object->IsUnboxedDoubleField(index)) {
    3962             :     double value = object->RawFastDoublePropertyAt(index);
    3963       19814 :     return isolate->factory()->NewHeapNumber(value);
    3964             :   }
    3965    23560254 :   Handle<Object> raw_value(object->RawFastPropertyAt(index), isolate);
    3966    11780125 :   return Object::WrapForRead(isolate, raw_value, representation);
    3967             : }
    3968             : 
    3969             : // TODO(cbruni/jkummerow): Consider moving this into elements.cc.
    3970      144818 : bool JSObject::HasEnumerableElements() {
    3971             :   // TODO(cbruni): cleanup
    3972      144818 :   JSObject object = *this;
    3973      144818 :   switch (object->GetElementsKind()) {
    3974             :     case PACKED_SMI_ELEMENTS:
    3975             :     case PACKED_ELEMENTS:
    3976             :     case PACKED_FROZEN_ELEMENTS:
    3977             :     case PACKED_SEALED_ELEMENTS:
    3978             :     case PACKED_DOUBLE_ELEMENTS: {
    3979             :       int length = object->IsJSArray()
    3980             :                        ? Smi::ToInt(JSArray::cast(object)->length())
    3981       29850 :                        : object->elements()->length();
    3982       29850 :       return length > 0;
    3983             :     }
    3984             :     case HOLEY_SMI_ELEMENTS:
    3985             :     case HOLEY_ELEMENTS: {
    3986             :       FixedArray elements = FixedArray::cast(object->elements());
    3987             :       int length = object->IsJSArray()
    3988             :                        ? Smi::ToInt(JSArray::cast(object)->length())
    3989      114491 :                        : elements->length();
    3990             :       Isolate* isolate = GetIsolate();
    3991     5019797 :       for (int i = 0; i < length; i++) {
    3992     2463813 :         if (!elements->is_the_hole(isolate, i)) return true;
    3993             :       }
    3994             :       return false;
    3995             :     }
    3996             :     case HOLEY_DOUBLE_ELEMENTS: {
    3997             :       int length = object->IsJSArray()
    3998             :                        ? Smi::ToInt(JSArray::cast(object)->length())
    3999          45 :                        : object->elements()->length();
    4000             :       // Zero-length arrays would use the empty FixedArray...
    4001          45 :       if (length == 0) return false;
    4002             :       // ...so only cast to FixedDoubleArray otherwise.
    4003             :       FixedDoubleArray elements = FixedDoubleArray::cast(object->elements());
    4004          45 :       for (int i = 0; i < length; i++) {
    4005          45 :         if (!elements->is_the_hole(i)) return true;
    4006             :       }
    4007             :       return false;
    4008             :     }
    4009             : #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) case TYPE##_ELEMENTS:
    4010             : 
    4011             :       TYPED_ARRAYS(TYPED_ARRAY_CASE)
    4012             : #undef TYPED_ARRAY_CASE
    4013             :       {
    4014             :         int length = object->elements()->length();
    4015           0 :         return length > 0;
    4016             :       }
    4017             :     case DICTIONARY_ELEMENTS: {
    4018         351 :       NumberDictionary elements = NumberDictionary::cast(object->elements());
    4019         351 :       return elements->NumberOfEnumerableProperties() > 0;
    4020             :     }
    4021             :     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
    4022             :     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
    4023             :       // We're approximating non-empty arguments objects here.
    4024             :       return true;
    4025             :     case FAST_STRING_WRAPPER_ELEMENTS:
    4026             :     case SLOW_STRING_WRAPPER_ELEMENTS:
    4027           0 :       if (String::cast(JSValue::cast(object)->value())->length() > 0) {
    4028             :         return true;
    4029             :       }
    4030           0 :       return object->elements()->length() > 0;
    4031             :     case NO_ELEMENTS:
    4032           0 :       return false;
    4033             :   }
    4034           0 :   UNREACHABLE();
    4035             : }
    4036             : 
    4037     1355517 : MaybeHandle<Object> JSObject::DefineAccessor(Handle<JSObject> object,
    4038             :                                              Handle<Name> name,
    4039             :                                              Handle<Object> getter,
    4040             :                                              Handle<Object> setter,
    4041             :                                              PropertyAttributes attributes) {
    4042             :   Isolate* isolate = object->GetIsolate();
    4043             : 
    4044             :   LookupIterator it = LookupIterator::PropertyOrElement(
    4045     1355517 :       isolate, object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
    4046     1355519 :   return DefineAccessor(&it, getter, setter, attributes);
    4047             : }
    4048             : 
    4049     1551794 : MaybeHandle<Object> JSObject::DefineAccessor(LookupIterator* it,
    4050             :                                              Handle<Object> getter,
    4051             :                                              Handle<Object> setter,
    4052             :                                              PropertyAttributes attributes) {
    4053             :   Isolate* isolate = it->isolate();
    4054             : 
    4055     1551794 :   it->UpdateProtector();
    4056             : 
    4057     1551795 :   if (it->state() == LookupIterator::ACCESS_CHECK) {
    4058        1738 :     if (!it->HasAccess()) {
    4059           5 :       isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>());
    4060           5 :       RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
    4061           0 :       return isolate->factory()->undefined_value();
    4062             :     }
    4063        1733 :     it->Next();
    4064             :   }
    4065             : 
    4066             :   Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
    4067             :   // Ignore accessors on typed arrays.
    4068     1579219 :   if (it->IsElement() && object->HasFixedTypedArrayElements()) {
    4069           0 :     return it->factory()->undefined_value();
    4070             :   }
    4071             : 
    4072             :   DCHECK(getter->IsCallable() || getter->IsUndefined(isolate) ||
    4073             :          getter->IsNull(isolate) || getter->IsFunctionTemplateInfo());
    4074             :   DCHECK(setter->IsCallable() || setter->IsUndefined(isolate) ||
    4075             :          setter->IsNull(isolate) || setter->IsFunctionTemplateInfo());
    4076     1551790 :   it->TransitionToAccessorProperty(getter, setter, attributes);
    4077             : 
    4078     1551789 :   return isolate->factory()->undefined_value();
    4079             : }
    4080             : 
    4081       62253 : MaybeHandle<Object> JSObject::SetAccessor(Handle<JSObject> object,
    4082             :                                           Handle<Name> name,
    4083             :                                           Handle<AccessorInfo> info,
    4084             :                                           PropertyAttributes attributes) {
    4085             :   Isolate* isolate = object->GetIsolate();
    4086             : 
    4087             :   LookupIterator it = LookupIterator::PropertyOrElement(
    4088       62253 :       isolate, object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
    4089             : 
    4090             :   // Duplicate ACCESS_CHECK outside of GetPropertyAttributes for the case that
    4091             :   // the FailedAccessCheckCallbackFunction doesn't throw an exception.
    4092             :   //
    4093             :   // TODO(verwaest): Force throw an exception if the callback doesn't, so we can
    4094             :   // remove reliance on default return values.
    4095       62253 :   if (it.state() == LookupIterator::ACCESS_CHECK) {
    4096        7780 :     if (!it.HasAccess()) {
    4097           5 :       isolate->ReportFailedAccessCheck(object);
    4098           5 :       RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
    4099           0 :       return it.factory()->undefined_value();
    4100             :     }
    4101        7775 :     it.Next();
    4102             :   }
    4103             : 
    4104             :   // Ignore accessors on typed arrays.
    4105       62260 :   if (it.IsElement() && object->HasFixedTypedArrayElements()) {
    4106           0 :     return it.factory()->undefined_value();
    4107             :   }
    4108             : 
    4109      124496 :   CHECK(GetPropertyAttributes(&it).IsJust());
    4110             : 
    4111             :   // ES5 forbids turning a property into an accessor if it's not
    4112             :   // configurable. See 8.6.1 (Table 5).
    4113       62309 :   if (it.IsFound() && !it.IsConfigurable()) {
    4114          25 :     return it.factory()->undefined_value();
    4115             :   }
    4116             : 
    4117       62223 :   it.TransitionToAccessorPair(info, attributes);
    4118             : 
    4119       62223 :   return object;
    4120             : }
    4121             : 
    4122         237 : Object JSObject::SlowReverseLookup(Object value) {
    4123         237 :   if (HasFastProperties()) {
    4124             :     int number_of_own_descriptors = map()->NumberOfOwnDescriptors();
    4125         180 :     DescriptorArray descs = map()->instance_descriptors();
    4126             :     bool value_is_number = value->IsNumber();
    4127        1806 :     for (int i = 0; i < number_of_own_descriptors; i++) {
    4128         822 :       PropertyDetails details = descs->GetDetails(i);
    4129         822 :       if (details.location() == kField) {
    4130             :         DCHECK_EQ(kData, details.kind());
    4131         765 :         FieldIndex field_index = FieldIndex::ForDescriptor(map(), i);
    4132         765 :         if (IsUnboxedDoubleField(field_index)) {
    4133           0 :           if (value_is_number) {
    4134             :             double property = RawFastDoublePropertyAt(field_index);
    4135           0 :             if (property == value->Number()) {
    4136           0 :               return descs->GetKey(i);
    4137             :             }
    4138             :           }
    4139             :         } else {
    4140         765 :           Object property = RawFastPropertyAt(field_index);
    4141         765 :           if (field_index.is_double()) {
    4142             :             DCHECK(property->IsMutableHeapNumber());
    4143           0 :             if (value_is_number && property->Number() == value->Number()) {
    4144           0 :               return descs->GetKey(i);
    4145             :             }
    4146         765 :           } else if (property == value) {
    4147           9 :             return descs->GetKey(i);
    4148             :           }
    4149             :         }
    4150             :       } else {
    4151             :         DCHECK_EQ(kDescriptor, details.location());
    4152          57 :         if (details.kind() == kData) {
    4153           0 :           if (descs->GetStrongValue(i) == value) {
    4154           0 :             return descs->GetKey(i);
    4155             :           }
    4156             :         }
    4157             :       }
    4158             :     }
    4159         171 :     return GetReadOnlyRoots().undefined_value();
    4160          57 :   } else if (IsJSGlobalObject()) {
    4161         114 :     return JSGlobalObject::cast(*this)->global_dictionary()->SlowReverseLookup(
    4162          57 :         value);
    4163             :   } else {
    4164           0 :     return property_dictionary()->SlowReverseLookup(value);
    4165             :   }
    4166             : }
    4167             : 
    4168           0 : void JSObject::PrototypeRegistryCompactionCallback(HeapObject value,
    4169             :                                                    int old_index,
    4170             :                                                    int new_index) {
    4171             :   DCHECK(value->IsMap() && Map::cast(value)->is_prototype_map());
    4172             :   Map map = Map::cast(value);
    4173             :   DCHECK(map->prototype_info()->IsPrototypeInfo());
    4174             :   PrototypeInfo proto_info = PrototypeInfo::cast(map->prototype_info());
    4175             :   DCHECK_EQ(old_index, proto_info->registry_slot());
    4176             :   proto_info->set_registry_slot(new_index);
    4177           0 : }
    4178             : 
    4179             : // static
    4180     4702865 : void JSObject::MakePrototypesFast(Handle<Object> receiver,
    4181             :                                   WhereToStart where_to_start,
    4182             :                                   Isolate* isolate) {
    4183     4702865 :   if (!receiver->IsJSReceiver()) return;
    4184    11765263 :   for (PrototypeIterator iter(isolate, Handle<JSReceiver>::cast(receiver),
    4185     4655414 :                               where_to_start);
    4186     3554893 :        !iter.IsAtEnd(); iter.Advance()) {
    4187             :     Handle<Object> current = PrototypeIterator::GetCurrent(iter);
    4188    12830883 :     if (!current->IsJSObject()) return;
    4189             :     Handle<JSObject> current_obj = Handle<JSObject>::cast(current);
    4190     8186375 :     Map current_map = current_obj->map();
    4191     8186375 :     if (current_map->is_prototype_map()) {
    4192             :       // If the map is already marked as should be fast, we're done. Its
    4193             :       // prototypes will have been marked already as well.
    4194     9721953 :       if (current_map->should_be_fast_prototype_map()) return;
    4195             :       Handle<Map> map(current_map, isolate);
    4196      458991 :       Map::SetShouldBeFastPrototypeMap(map, true, isolate);
    4197      458990 :       JSObject::OptimizeAsPrototype(current_obj);
    4198             :     }
    4199             :   }
    4200             : }
    4201             : 
    4202    26880280 : static bool PrototypeBenefitsFromNormalization(Handle<JSObject> object) {
    4203             :   DisallowHeapAllocation no_gc;
    4204    26880280 :   if (!object->HasFastProperties()) return false;
    4205    25655372 :   if (object->IsJSGlobalProxy()) return false;
    4206    25634078 :   if (object->GetIsolate()->bootstrapper()->IsActive()) return false;
    4207     9453773 :   return !object->map()->is_prototype_map() ||
    4208     9453773 :          !object->map()->should_be_fast_prototype_map();
    4209             : }
    4210             : 
    4211             : // static
    4212    26991612 : void JSObject::OptimizeAsPrototype(Handle<JSObject> object,
    4213             :                                    bool enable_setup_mode) {
    4214    26991612 :   if (object->IsJSGlobalObject()) return;
    4215    26893325 :   if (enable_setup_mode && PrototypeBenefitsFromNormalization(object)) {
    4216             :     // First normalize to ensure all JSFunctions are DATA_CONSTANT.
    4217             :     JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0,
    4218      331894 :                                   "NormalizeAsPrototype");
    4219             :   }
    4220    26893355 :   if (object->map()->is_prototype_map()) {
    4221    63631780 :     if (object->map()->should_be_fast_prototype_map() &&
    4222    41207187 :         !object->HasFastProperties()) {
    4223      283586 :       JSObject::MigrateSlowToFast(object, 0, "OptimizeAsPrototype");
    4224             :     }
    4225             :   } else {
    4226             :     Handle<Map> new_map = Map::Copy(object->GetIsolate(),
    4227             :                                     handle(object->map(), object->GetIsolate()),
    4228     4468756 :                                     "CopyAsPrototype");
    4229     4468757 :     JSObject::MigrateToMap(object, new_map);
    4230             :     object->map()->set_is_prototype_map(true);
    4231             : 
    4232             :     // Replace the pointer to the exact constructor with the Object function
    4233             :     // from the same context if undetectable from JS. This is to avoid keeping
    4234             :     // memory alive unnecessarily.
    4235     4468760 :     Object maybe_constructor = object->map()->GetConstructor();
    4236     4468761 :     if (maybe_constructor->IsJSFunction()) {
    4237             :       JSFunction constructor = JSFunction::cast(maybe_constructor);
    4238     4468070 :       if (!constructor->shared()->IsApiFunction()) {
    4239     4411352 :         Context context = constructor->context()->native_context();
    4240     4411352 :         JSFunction object_function = context->object_function();
    4241     4411352 :         object->map()->SetConstructor(object_function);
    4242             :       }
    4243             :     }
    4244             :   }
    4245             : }
    4246             : 
    4247             : // static
    4248      362527 : void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) {
    4249      362527 :   if (!object->map()->is_prototype_map()) return;
    4250       57534 :   if (!object->map()->should_be_fast_prototype_map()) return;
    4251       39489 :   OptimizeAsPrototype(object);
    4252             : }
    4253             : 
    4254             : // static
    4255     1797455 : void JSObject::LazyRegisterPrototypeUser(Handle<Map> user, Isolate* isolate) {
    4256             :   // Contract: In line with InvalidatePrototypeChains()'s requirements,
    4257             :   // leaf maps don't need to register as users, only prototypes do.
    4258             :   DCHECK(user->is_prototype_map());
    4259             : 
    4260     1797455 :   Handle<Map> current_user = user;
    4261             :   Handle<PrototypeInfo> current_user_info =
    4262     1797455 :       Map::GetOrCreatePrototypeInfo(user, isolate);
    4263     2303613 :   for (PrototypeIterator iter(isolate, user); !iter.IsAtEnd(); iter.Advance()) {
    4264             :     // Walk up the prototype chain as far as links haven't been registered yet.
    4265     1662215 :     if (current_user_info->registry_slot() != PrototypeInfo::UNREGISTERED) {
    4266             :       break;
    4267             :     }
    4268             :     Handle<Object> maybe_proto = PrototypeIterator::GetCurrent(iter);
    4269             :     // Proxies on the prototype chain are not supported. They make it
    4270             :     // impossible to make any assumptions about the prototype chain anyway.
    4271      506773 :     if (maybe_proto->IsJSProxy()) return;
    4272             :     Handle<JSObject> proto = Handle<JSObject>::cast(maybe_proto);
    4273             :     Handle<PrototypeInfo> proto_info =
    4274      506151 :         Map::GetOrCreatePrototypeInfo(proto, isolate);
    4275             :     Handle<Object> maybe_registry(proto_info->prototype_users(), isolate);
    4276             :     Handle<WeakArrayList> registry =
    4277             :         maybe_registry->IsSmi()
    4278             :             ? handle(ReadOnlyRoots(isolate->heap()).empty_weak_array_list(),
    4279             :                      isolate)
    4280      624712 :             : Handle<WeakArrayList>::cast(maybe_registry);
    4281      506148 :     int slot = 0;
    4282             :     Handle<WeakArrayList> new_array =
    4283      506148 :         PrototypeUsers::Add(isolate, registry, current_user, &slot);
    4284      506152 :     current_user_info->set_registry_slot(slot);
    4285      506152 :     if (!maybe_registry.is_identical_to(new_array)) {
    4286      268510 :       proto_info->set_prototype_users(*new_array);
    4287             :     }
    4288      506150 :     if (FLAG_trace_prototype_users) {
    4289           0 :       PrintF("Registering %p as a user of prototype %p (map=%p).\n",
    4290             :              reinterpret_cast<void*>(current_user->ptr()),
    4291             :              reinterpret_cast<void*>(proto->ptr()),
    4292           0 :              reinterpret_cast<void*>(proto->map()->ptr()));
    4293             :     }
    4294             : 
    4295             :     current_user = handle(proto->map(), isolate);
    4296             :     current_user_info = proto_info;
    4297             :   }
    4298             : }
    4299             : 
    4300             : // Can be called regardless of whether |user| was actually registered with
    4301             : // |prototype|. Returns true when there was a registration.
    4302             : // static
    4303     4426516 : bool JSObject::UnregisterPrototypeUser(Handle<Map> user, Isolate* isolate) {
    4304             :   DCHECK(user->is_prototype_map());
    4305             :   // If it doesn't have a PrototypeInfo, it was never registered.
    4306     4426516 :   if (!user->prototype_info()->IsPrototypeInfo()) return false;
    4307             :   // If it had no prototype before, see if it had users that might expect
    4308             :   // registration.
    4309     1853163 :   if (!user->prototype()->IsJSObject()) {
    4310             :     Object users =
    4311             :         PrototypeInfo::cast(user->prototype_info())->prototype_users();
    4312             :     return users->IsWeakArrayList();
    4313             :   }
    4314             :   Handle<JSObject> prototype(JSObject::cast(user->prototype()), isolate);
    4315             :   Handle<PrototypeInfo> user_info =
    4316     1783517 :       Map::GetOrCreatePrototypeInfo(user, isolate);
    4317             :   int slot = user_info->registry_slot();
    4318     1783518 :   if (slot == PrototypeInfo::UNREGISTERED) return false;
    4319             :   DCHECK(prototype->map()->is_prototype_map());
    4320             :   Object maybe_proto_info = prototype->map()->prototype_info();
    4321             :   // User knows its registry slot, prototype info and user registry must exist.
    4322             :   DCHECK(maybe_proto_info->IsPrototypeInfo());
    4323             :   Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(maybe_proto_info),
    4324             :                                    isolate);
    4325             :   Handle<WeakArrayList> prototype_users(
    4326             :       WeakArrayList::cast(proto_info->prototype_users()), isolate);
    4327             :   DCHECK_EQ(prototype_users->Get(slot), HeapObjectReference::Weak(*user));
    4328      126874 :   PrototypeUsers::MarkSlotEmpty(*prototype_users, slot);
    4329      126876 :   if (FLAG_trace_prototype_users) {
    4330           0 :     PrintF("Unregistering %p as a user of prototype %p.\n",
    4331             :            reinterpret_cast<void*>(user->ptr()),
    4332           0 :            reinterpret_cast<void*>(prototype->ptr()));
    4333             :   }
    4334             :   return true;
    4335             : }
    4336             : 
    4337             : namespace {
    4338             : 
    4339             : // This function must be kept in sync with
    4340             : // AccessorAssembler::InvalidateValidityCellIfPrototype() which does pre-checks
    4341             : // before jumping here.
    4342    16640823 : void InvalidateOnePrototypeValidityCellInternal(Map map) {
    4343             :   DCHECK(map->is_prototype_map());
    4344    16640823 :   if (FLAG_trace_prototype_users) {
    4345           0 :     PrintF("Invalidating prototype map %p 's cell\n",
    4346           0 :            reinterpret_cast<void*>(map.ptr()));
    4347             :   }
    4348             :   Object maybe_cell = map->prototype_validity_cell();
    4349    16640832 :   if (maybe_cell->IsCell()) {
    4350             :     // Just set the value; the cell will be replaced lazily.
    4351    16576138 :     Cell cell = Cell::cast(maybe_cell);
    4352    16576138 :     cell->set_value(Smi::FromInt(Map::kPrototypeChainInvalid));
    4353             :   }
    4354    16640832 : }
    4355             : 
    4356    15688579 : void InvalidatePrototypeChainsInternal(Map map) {
    4357    15688579 :   InvalidateOnePrototypeValidityCellInternal(map);
    4358             : 
    4359             :   Object maybe_proto_info = map->prototype_info();
    4360    15688587 :   if (!maybe_proto_info->IsPrototypeInfo()) return;
    4361             :   PrototypeInfo proto_info = PrototypeInfo::cast(maybe_proto_info);
    4362     4702866 :   if (!proto_info->prototype_users()->IsWeakArrayList()) {
    4363             :     return;
    4364             :   }
    4365             :   WeakArrayList prototype_users =
    4366             :       WeakArrayList::cast(proto_info->prototype_users());
    4367             :   // For now, only maps register themselves as users.
    4368    11973821 :   for (int i = PrototypeUsers::kFirstIndex; i < prototype_users->length();
    4369             :        ++i) {
    4370             :     HeapObject heap_object;
    4371     7183705 :     if (prototype_users->Get(i)->GetHeapObjectIfWeak(&heap_object) &&
    4372             :         heap_object->IsMap()) {
    4373             :       // Walk the prototype chain (backwards, towards leaf objects) if
    4374             :       // necessary.
    4375     2453823 :       InvalidatePrototypeChainsInternal(Map::cast(heap_object));
    4376             :     }
    4377             :   }
    4378             : }
    4379             : 
    4380             : }  // namespace
    4381             : 
    4382             : // static
    4383     8762672 : Map JSObject::InvalidatePrototypeChains(Map map) {
    4384             :   DisallowHeapAllocation no_gc;
    4385    13234760 :   InvalidatePrototypeChainsInternal(map);
    4386     8762678 :   return map;
    4387             : }
    4388             : 
    4389             : // We also invalidate global objects validity cell when a new lexical
    4390             : // environment variable is added. This is necessary to ensure that
    4391             : // Load/StoreGlobalIC handlers that load/store from global object's prototype
    4392             : // get properly invalidated.
    4393             : // Note, that the normal Load/StoreICs that load/store through the global object
    4394             : // in the prototype chain are not affected by appearance of a new lexical
    4395             : // variable and therefore we don't propagate invalidation down.
    4396             : // static
    4397      952248 : void JSObject::InvalidatePrototypeValidityCell(JSGlobalObject global) {
    4398             :   DisallowHeapAllocation no_gc;
    4399      952248 :   InvalidateOnePrototypeValidityCellInternal(global->map());
    4400      952248 : }
    4401             : 
    4402      210804 : Maybe<bool> JSObject::SetPrototype(Handle<JSObject> object,
    4403             :                                    Handle<Object> value, bool from_javascript,
    4404             :                                    ShouldThrow should_throw) {
    4405             :   Isolate* isolate = object->GetIsolate();
    4406             : 
    4407             : #ifdef DEBUG
    4408             :   int size = object->Size();
    4409             : #endif
    4410             : 
    4411      210804 :   if (from_javascript) {
    4412      190925 :     if (object->IsAccessCheckNeeded() &&
    4413          35 :         !isolate->MayAccess(handle(isolate->context(), isolate), object)) {
    4414           0 :       isolate->ReportFailedAccessCheck(object);
    4415           0 :       RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
    4416           0 :       RETURN_FAILURE(isolate, should_throw,
    4417             :                      NewTypeError(MessageTemplate::kNoAccess));
    4418             :     }
    4419             :   } else {
    4420             :     DCHECK(!object->IsAccessCheckNeeded());
    4421             :   }
    4422             : 
    4423             :   // Silently ignore the change if value is not a JSObject or null.
    4424             :   // SpiderMonkey behaves this way.
    4425      222511 :   if (!value->IsJSReceiver() && !value->IsNull(isolate)) return Just(true);
    4426             : 
    4427             :   bool all_extensible = object->map()->is_extensible();
    4428             :   Handle<JSObject> real_receiver = object;
    4429      210789 :   if (from_javascript) {
    4430             :     // Find the first object in the chain whose prototype object is not
    4431             :     // hidden.
    4432             :     PrototypeIterator iter(isolate, real_receiver, kStartAtPrototype,
    4433      190890 :                            PrototypeIterator::END_AT_NON_HIDDEN);
    4434      194064 :     while (!iter.IsAtEnd()) {
    4435             :       // Casting to JSObject is fine because hidden prototypes are never
    4436             :       // JSProxies.
    4437             :       real_receiver = PrototypeIterator::GetCurrent<JSObject>(iter);
    4438        3174 :       iter.Advance();
    4439        6348 :       all_extensible = all_extensible && real_receiver->map()->is_extensible();
    4440             :     }
    4441             :   }
    4442             :   Handle<Map> map(real_receiver->map(), isolate);
    4443             : 
    4444             :   // Nothing to do if prototype is already set.
    4445      210789 :   if (map->prototype() == *value) return Just(true);
    4446             : 
    4447             :   bool immutable_proto = map->is_immutable_proto();
    4448      185072 :   if (immutable_proto) {
    4449         171 :     RETURN_FAILURE(
    4450             :         isolate, should_throw,
    4451             :         NewTypeError(MessageTemplate::kImmutablePrototypeSet, object));
    4452             :   }
    4453             : 
    4454             :   // From 8.6.2 Object Internal Methods
    4455             :   // ...
    4456             :   // In addition, if [[Extensible]] is false the value of the [[Class]] and
    4457             :   // [[Prototype]] internal properties of the object may not be modified.
    4458             :   // ...
    4459             :   // Implementation specific extensions that modify [[Class]], [[Prototype]]
    4460             :   // or [[Extensible]] must not violate the invariants defined in the preceding
    4461             :   // paragraph.
    4462      185009 :   if (!all_extensible) {
    4463         495 :     RETURN_FAILURE(isolate, should_throw,
    4464             :                    NewTypeError(MessageTemplate::kNonExtensibleProto, object));
    4465             :   }
    4466             : 
    4467             :   // Before we can set the prototype we need to be sure prototype cycles are
    4468             :   // prevented.  It is sufficient to validate that the receiver is not in the
    4469             :   // new prototype chain.
    4470      184766 :   if (value->IsJSReceiver()) {
    4471      928525 :     for (PrototypeIterator iter(isolate, JSReceiver::cast(*value),
    4472             :                                 kStartAtReceiver);
    4473      377715 :          !iter.IsAtEnd(); iter.Advance()) {
    4474      377793 :       if (iter.GetCurrent<JSReceiver>() == *object) {
    4475             :         // Cycle detected.
    4476         198 :         RETURN_FAILURE(isolate, should_throw,
    4477             :                        NewTypeError(MessageTemplate::kCyclicProto));
    4478             :       }
    4479             :     }
    4480             :   }
    4481             : 
    4482             :   // Set the new prototype of the object.
    4483             : 
    4484             :   isolate->UpdateNoElementsProtectorOnSetPrototype(real_receiver);
    4485             : 
    4486             :   Handle<Map> new_map =
    4487      184688 :       Map::TransitionToPrototype(isolate, map, Handle<HeapObject>::cast(value));
    4488             :   DCHECK(new_map->prototype() == *value);
    4489      184688 :   JSObject::MigrateToMap(real_receiver, new_map);
    4490             : 
    4491             :   DCHECK(size == object->Size());
    4492             :   return Just(true);
    4493             : }
    4494             : 
    4495             : // static
    4496          24 : void JSObject::SetImmutableProto(Handle<JSObject> object) {
    4497             :   DCHECK(!object->IsAccessCheckNeeded());  // Never called from JS
    4498             :   Handle<Map> map(object->map(), object->GetIsolate());
    4499             : 
    4500             :   // Nothing to do if prototype is already set.
    4501          42 :   if (map->is_immutable_proto()) return;
    4502             : 
    4503             :   Handle<Map> new_map =
    4504           6 :       Map::TransitionToImmutableProto(object->GetIsolate(), map);
    4505           6 :   object->synchronized_set_map(*new_map);
    4506             : }
    4507             : 
    4508      442550 : void JSObject::EnsureCanContainElements(Handle<JSObject> object,
    4509             :                                         Arguments* args, uint32_t first_arg,
    4510             :                                         uint32_t arg_count,
    4511             :                                         EnsureElementsMode mode) {
    4512             :   // Elements in |Arguments| are ordered backwards (because they're on the
    4513             :   // stack), but the method that's called here iterates over them in forward
    4514             :   // direction.
    4515      442550 :   return EnsureCanContainElements(
    4516      885100 :       object, args->slot_at(first_arg + arg_count - 1), arg_count, mode);
    4517             : }
    4518             : 
    4519   247142551 : ElementsAccessor* JSObject::GetElementsAccessor() {
    4520   247142551 :   return ElementsAccessor::ForKind(GetElementsKind());
    4521             : }
    4522             : 
    4523     7084585 : void JSObject::ValidateElements(JSObject object) {
    4524             : #ifdef ENABLE_SLOW_DCHECKS
    4525             :   if (FLAG_enable_slow_asserts) {
    4526             :     object->GetElementsAccessor()->Validate(object);
    4527             :   }
    4528             : #endif
    4529     7084585 : }
    4530             : 
    4531      103647 : bool JSObject::WouldConvertToSlowElements(uint32_t index) {
    4532      103647 :   if (!HasFastElements()) return false;
    4533       13276 :   uint32_t capacity = static_cast<uint32_t>(elements()->length());
    4534             :   uint32_t new_capacity;
    4535       13276 :   return ShouldConvertToSlowElements(*this, capacity, index, &new_capacity);
    4536             : }
    4537             : 
    4538      878477 : static bool ShouldConvertToFastElements(JSObject object,
    4539             :                                         NumberDictionary dictionary,
    4540             :                                         uint32_t index,
    4541             :                                         uint32_t* new_capacity) {
    4542             :   // If properties with non-standard attributes or accessors were added, we
    4543             :   // cannot go back to fast elements.
    4544      878477 :   if (dictionary->requires_slow_elements()) return false;
    4545             : 
    4546             :   // Adding a property with this index will require slow elements.
    4547      855097 :   if (index >= static_cast<uint32_t>(Smi::kMaxValue)) return false;
    4548             : 
    4549      854974 :   if (object->IsJSArray()) {
    4550             :     Object length = JSArray::cast(object)->length();
    4551      569737 :     if (!length->IsSmi()) return false;
    4552      569719 :     *new_capacity = static_cast<uint32_t>(Smi::ToInt(length));
    4553      285237 :   } else if (object->IsJSSloppyArgumentsObject()) {
    4554             :     return false;
    4555             :   } else {
    4556      186111 :     *new_capacity = dictionary->max_number_key() + 1;
    4557             :   }
    4558     1511660 :   *new_capacity = Max(index + 1, *new_capacity);
    4559             : 
    4560      755830 :   uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) *
    4561      755830 :                              NumberDictionary::kEntrySize;
    4562             : 
    4563             :   // Turn fast if the dictionary only saves 50% space.
    4564      755830 :   return 2 * dictionary_size >= *new_capacity;
    4565             : }
    4566             : 
    4567         488 : static ElementsKind BestFittingFastElementsKind(JSObject object) {
    4568         488 :   if (!object->map()->CanHaveFastTransitionableElementsKind()) {
    4569             :     return HOLEY_ELEMENTS;
    4570             :   }
    4571         222 :   if (object->HasSloppyArgumentsElements()) {
    4572             :     return FAST_SLOPPY_ARGUMENTS_ELEMENTS;
    4573             :   }
    4574         222 :   if (object->HasStringWrapperElements()) {
    4575             :     return FAST_STRING_WRAPPER_ELEMENTS;
    4576             :   }
    4577             :   DCHECK(object->HasDictionaryElements());
    4578             :   NumberDictionary dictionary = object->element_dictionary();
    4579             :   ElementsKind kind = HOLEY_SMI_ELEMENTS;
    4580      435739 :   for (int i = 0; i < dictionary->Capacity(); i++) {
    4581             :     Object key = dictionary->KeyAt(i);
    4582      217808 :     if (key->IsNumber()) {
    4583             :       Object value = dictionary->ValueAt(i);
    4584       72427 :       if (!value->IsNumber()) return HOLEY_ELEMENTS;
    4585       72382 :       if (!value->IsSmi()) {
    4586        6838 :         if (!FLAG_unbox_double_arrays) return HOLEY_ELEMENTS;
    4587             :         kind = HOLEY_DOUBLE_ELEMENTS;
    4588             :       }
    4589             :     }
    4590             :   }
    4591             :   return kind;
    4592             : }
    4593             : 
    4594             : // static
    4595     5030105 : void JSObject::AddDataElement(Handle<JSObject> object, uint32_t index,
    4596             :                               Handle<Object> value,
    4597             :                               PropertyAttributes attributes) {
    4598             :   DCHECK(object->map()->is_extensible());
    4599             : 
    4600             :   Isolate* isolate = object->GetIsolate();
    4601             : 
    4602     5030105 :   uint32_t old_length = 0;
    4603     5030105 :   uint32_t new_capacity = 0;
    4604             : 
    4605     5030105 :   if (object->IsJSArray()) {
    4606     3372524 :     CHECK(JSArray::cast(*object)->length()->ToArrayLength(&old_length));
    4607             :   }
    4608             : 
    4609             :   ElementsKind kind = object->GetElementsKind();
    4610             :   FixedArrayBase elements = object->elements();
    4611             :   ElementsKind dictionary_kind = DICTIONARY_ELEMENTS;
    4612     5030105 :   if (IsSloppyArgumentsElementsKind(kind)) {
    4613             :     elements = SloppyArgumentsElements::cast(elements)->arguments();
    4614             :     dictionary_kind = SLOW_SLOPPY_ARGUMENTS_ELEMENTS;
    4615     4910483 :   } else if (IsStringWrapperElementsKind(kind)) {
    4616             :     dictionary_kind = SLOW_STRING_WRAPPER_ELEMENTS;
    4617             :   }
    4618             : 
    4619     5030105 :   if (attributes != NONE) {
    4620             :     kind = dictionary_kind;
    4621     5010870 :   } else if (elements->IsNumberDictionary()) {
    4622      878477 :     kind = ShouldConvertToFastElements(
    4623             :                *object, NumberDictionary::cast(elements), index, &new_capacity)
    4624             :                ? BestFittingFastElementsKind(*object)
    4625      878965 :                : dictionary_kind;
    4626     8264786 :   } else if (ShouldConvertToSlowElements(
    4627             :                  *object, static_cast<uint32_t>(elements->length()), index,
    4628             :                  &new_capacity)) {
    4629             :     kind = dictionary_kind;
    4630             :   }
    4631             : 
    4632     5030105 :   ElementsKind to = value->OptimalElementsKind();
    4633     6411189 :   if (IsHoleyElementsKind(kind) || !object->IsJSArray() || index > old_length) {
    4634             :     to = GetHoleyElementsKind(to);
    4635             :     kind = GetHoleyElementsKind(kind);
    4636             :   }
    4637             :   to = GetMoreGeneralElementsKind(kind, to);
    4638             :   ElementsAccessor* accessor = ElementsAccessor::ForKind(to);
    4639     5030105 :   accessor->Add(object, index, value, attributes, new_capacity);
    4640             : 
    4641     5030106 :   if (object->IsJSArray() && index >= old_length) {
    4642             :     Handle<Object> new_length =
    4643     1544721 :         isolate->factory()->NewNumberFromUint(index + 1);
    4644     1544721 :     JSArray::cast(*object)->set_length(*new_length);
    4645             :   }
    4646     5030106 : }
    4647             : 
    4648             : template <AllocationSiteUpdateMode update_or_check>
    4649      875165 : bool JSObject::UpdateAllocationSite(Handle<JSObject> object,
    4650             :                                     ElementsKind to_kind) {
    4651      875165 :   if (!object->IsJSArray()) return false;
    4652             : 
    4653      622900 :   if (!Heap::InYoungGeneration(*object)) return false;
    4654             : 
    4655      611160 :   if (Heap::IsLargeObject(*object)) return false;
    4656             : 
    4657             :   Handle<AllocationSite> site;
    4658             :   {
    4659             :     DisallowHeapAllocation no_allocation;
    4660             : 
    4661             :     Heap* heap = object->GetHeap();
    4662             :     AllocationMemento memento =
    4663     1222316 :         heap->FindAllocationMemento<Heap::kForRuntime>(object->map(), *object);
    4664      611160 :     if (memento.is_null()) return false;
    4665             : 
    4666             :     // Walk through to the Allocation Site
    4667      381890 :     site = handle(memento->GetAllocationSite(), heap->isolate());
    4668             :   }
    4669      381890 :   return AllocationSite::DigestTransitionFeedback<update_or_check>(site,
    4670      381890 :                                                                    to_kind);
    4671             : }
    4672             : 
    4673             : template bool
    4674             : JSObject::UpdateAllocationSite<AllocationSiteUpdateMode::kCheckOnly>(
    4675             :     Handle<JSObject> object, ElementsKind to_kind);
    4676             : 
    4677             : template bool JSObject::UpdateAllocationSite<AllocationSiteUpdateMode::kUpdate>(
    4678             :     Handle<JSObject> object, ElementsKind to_kind);
    4679             : 
    4680      141045 : void JSObject::TransitionElementsKind(Handle<JSObject> object,
    4681             :                                       ElementsKind to_kind) {
    4682             :   ElementsKind from_kind = object->GetElementsKind();
    4683             : 
    4684      141045 :   if (IsHoleyElementsKind(from_kind)) {
    4685             :     to_kind = GetHoleyElementsKind(to_kind);
    4686             :   }
    4687             : 
    4688      141045 :   if (from_kind == to_kind) return;
    4689             : 
    4690             :   // This method should never be called for any other case.
    4691             :   DCHECK(IsFastElementsKind(from_kind));
    4692             :   DCHECK(IsFastElementsKind(to_kind));
    4693             :   DCHECK_NE(TERMINAL_FAST_ELEMENTS_KIND, from_kind);
    4694             : 
    4695      140905 :   UpdateAllocationSite(object, to_kind);
    4696      278648 :   if (object->elements() == object->GetReadOnlyRoots().empty_fixed_array() ||
    4697             :       IsDoubleElementsKind(from_kind) == IsDoubleElementsKind(to_kind)) {
    4698             :     // No change is needed to the elements() buffer, the transition
    4699             :     // only requires a map change.
    4700      136261 :     Handle<Map> new_map = GetElementsTransitionMap(object, to_kind);
    4701      136261 :     MigrateToMap(object, new_map);
    4702             :     if (FLAG_trace_elements_transitions) {
    4703             :       Handle<FixedArrayBase> elms(object->elements(), object->GetIsolate());
    4704             :       PrintElementsTransition(stdout, object, from_kind, elms, to_kind, elms);
    4705             :     }
    4706             :   } else {
    4707             :     DCHECK((IsSmiElementsKind(from_kind) && IsDoubleElementsKind(to_kind)) ||
    4708             :            (IsDoubleElementsKind(from_kind) && IsObjectElementsKind(to_kind)));
    4709        4643 :     uint32_t c = static_cast<uint32_t>(object->elements()->length());
    4710        4643 :     ElementsAccessor::ForKind(to_kind)->GrowCapacityAndConvert(object, c);
    4711             :   }
    4712             : }
    4713             : 
    4714             : template <typename BackingStore>
    4715      284170 : static int HoleyElementsUsage(JSObject object, BackingStore store) {
    4716             :   Isolate* isolate = object->GetIsolate();
    4717             :   int limit = object->IsJSArray() ? Smi::ToInt(JSArray::cast(object)->length())
    4718      284170 :                                   : store->length();
    4719             :   int used = 0;
    4720  2060771844 :   for (int i = 0; i < limit; ++i) {
    4721  1030243837 :     if (!store->is_the_hole(isolate, i)) ++used;
    4722             :   }
    4723      284170 :   return used;
    4724             : }
    4725             : 
    4726      301047 : int JSObject::GetFastElementsUsage() {
    4727             :   FixedArrayBase store = elements();
    4728      301047 :   switch (GetElementsKind()) {
    4729             :     case PACKED_SMI_ELEMENTS:
    4730             :     case PACKED_DOUBLE_ELEMENTS:
    4731             :     case PACKED_ELEMENTS:
    4732             :     case PACKED_FROZEN_ELEMENTS:
    4733             :     case PACKED_SEALED_ELEMENTS:
    4734             :       return IsJSArray() ? Smi::ToInt(JSArray::cast(*this)->length())
    4735       16850 :                          : store->length();
    4736             :     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
    4737             :       store = SloppyArgumentsElements::cast(store)->arguments();
    4738             :       V8_FALLTHROUGH;
    4739             :     case HOLEY_SMI_ELEMENTS:
    4740             :     case HOLEY_ELEMENTS:
    4741             :     case FAST_STRING_WRAPPER_ELEMENTS:
    4742      283965 :       return HoleyElementsUsage(*this, FixedArray::cast(store));
    4743             :     case HOLEY_DOUBLE_ELEMENTS:
    4744         232 :       if (elements()->length() == 0) return 0;
    4745         205 :       return HoleyElementsUsage(*this, FixedDoubleArray::cast(store));
    4746             : 
    4747             :     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
    4748             :     case SLOW_STRING_WRAPPER_ELEMENTS:
    4749             :     case DICTIONARY_ELEMENTS:
    4750             :     case NO_ELEMENTS:
    4751             : #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) case TYPE##_ELEMENTS:
    4752             : 
    4753             :       TYPED_ARRAYS(TYPED_ARRAY_CASE)
    4754             : #undef TYPED_ARRAY_CASE
    4755           0 :       UNREACHABLE();
    4756             :   }
    4757             :   return 0;
    4758             : }
    4759             : 
    4760      134865 : MaybeHandle<Object> JSObject::GetPropertyWithInterceptor(LookupIterator* it,
    4761             :                                                          bool* done) {
    4762             :   DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
    4763      134895 :   return GetPropertyWithInterceptorInternal(it, it->GetInterceptor(), done);
    4764             : }
    4765             : 
    4766        5842 : Maybe<bool> JSObject::HasRealNamedProperty(Handle<JSObject> object,
    4767             :                                            Handle<Name> name) {
    4768             :   LookupIterator it = LookupIterator::PropertyOrElement(
    4769        5842 :       object->GetIsolate(), object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
    4770        5842 :   return HasProperty(&it);
    4771             : }
    4772             : 
    4773          17 : Maybe<bool> JSObject::HasRealElementProperty(Handle<JSObject> object,
    4774             :                                              uint32_t index) {
    4775             :   Isolate* isolate = object->GetIsolate();
    4776             :   LookupIterator it(isolate, object, index, object,
    4777             :                     LookupIterator::OWN_SKIP_INTERCEPTOR);
    4778          17 :   return HasProperty(&it);
    4779             : }
    4780             : 
    4781           5 : Maybe<bool> JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object,
    4782             :                                                    Handle<Name> name) {
    4783             :   LookupIterator it = LookupIterator::PropertyOrElement(
    4784           5 :       object->GetIsolate(), object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
    4785           5 :   Maybe<PropertyAttributes> maybe_result = GetPropertyAttributes(&it);
    4786           0 :   return maybe_result.IsJust() ? Just(it.state() == LookupIterator::ACCESSOR)
    4787          10 :                                : Nothing<bool>();
    4788             : }
    4789             : 
    4790           0 : bool JSObject::IsApiWrapper() {
    4791             :   // These object types can carry information relevant for embedders. The
    4792             :   // *_API_* types are generated through templates which can have embedder
    4793             :   // fields. The other types have their embedder fields added at compile time.
    4794             :   auto instance_type = map()->instance_type();
    4795           0 :   return instance_type == JS_API_OBJECT_TYPE ||
    4796           0 :          instance_type == JS_ARRAY_BUFFER_TYPE ||
    4797           0 :          instance_type == JS_DATA_VIEW_TYPE ||
    4798           0 :          instance_type == JS_SPECIAL_API_OBJECT_TYPE ||
    4799           0 :          instance_type == JS_TYPED_ARRAY_TYPE;
    4800             : }
    4801             : 
    4802       26384 : bool JSObject::IsDroppableApiWrapper() {
    4803             :   auto instance_type = map()->instance_type();
    4804       26384 :   return instance_type == JS_API_OBJECT_TYPE ||
    4805       26384 :          instance_type == JS_SPECIAL_API_OBJECT_TYPE;
    4806             : }
    4807             : 
    4808             : // static
    4809           9 : MaybeHandle<NativeContext> JSBoundFunction::GetFunctionRealm(
    4810             :     Handle<JSBoundFunction> function) {
    4811             :   DCHECK(function->map()->is_constructor());
    4812             :   return JSReceiver::GetFunctionRealm(
    4813           9 :       handle(function->bound_target_function(), function->GetIsolate()));
    4814             : }
    4815             : 
    4816             : // static
    4817          82 : MaybeHandle<String> JSBoundFunction::GetName(Isolate* isolate,
    4818             :                                              Handle<JSBoundFunction> function) {
    4819             :   Handle<String> prefix = isolate->factory()->bound__string();
    4820             :   Handle<String> target_name = prefix;
    4821             :   Factory* factory = isolate->factory();
    4822             :   // Concatenate the "bound " up to the last non-bound target.
    4823          82 :   while (function->bound_target_function()->IsJSBoundFunction()) {
    4824           0 :     ASSIGN_RETURN_ON_EXCEPTION(isolate, target_name,
    4825             :                                factory->NewConsString(prefix, target_name),
    4826             :                                String);
    4827             :     function = handle(JSBoundFunction::cast(function->bound_target_function()),
    4828             :                       isolate);
    4829             :   }
    4830          82 :   if (function->bound_target_function()->IsJSFunction()) {
    4831             :     Handle<JSFunction> target(
    4832             :         JSFunction::cast(function->bound_target_function()), isolate);
    4833          82 :     Handle<Object> name = JSFunction::GetName(isolate, target);
    4834          82 :     if (!name->IsString()) return target_name;
    4835          82 :     return factory->NewConsString(target_name, Handle<String>::cast(name));
    4836             :   }
    4837             :   // This will omit the proper target name for bound JSProxies.
    4838           0 :   return target_name;
    4839             : }
    4840             : 
    4841             : // static
    4842         316 : Maybe<int> JSBoundFunction::GetLength(Isolate* isolate,
    4843             :                                       Handle<JSBoundFunction> function) {
    4844             :   int nof_bound_arguments = function->bound_arguments()->length();
    4845         694 :   while (function->bound_target_function()->IsJSBoundFunction()) {
    4846             :     function = handle(JSBoundFunction::cast(function->bound_target_function()),
    4847             :                       isolate);
    4848             :     // Make sure we never overflow {nof_bound_arguments}, the number of
    4849             :     // arguments of a function is strictly limited by the max length of an
    4850             :     // JSAarray, Smi::kMaxValue is thus a reasonably good overestimate.
    4851             :     int length = function->bound_arguments()->length();
    4852         378 :     if (V8_LIKELY(Smi::kMaxValue - nof_bound_arguments > length)) {
    4853         378 :       nof_bound_arguments += length;
    4854             :     } else {
    4855             :       nof_bound_arguments = Smi::kMaxValue;
    4856             :     }
    4857             :   }
    4858             :   // All non JSFunction targets get a direct property and don't use this
    4859             :   // accessor.
    4860             :   Handle<JSFunction> target(JSFunction::cast(function->bound_target_function()),
    4861             :                             isolate);
    4862             :   int target_length = target->length();
    4863             : 
    4864         316 :   int length = Max(0, target_length - nof_bound_arguments);
    4865         316 :   return Just(length);
    4866             : }
    4867             : 
    4868             : // static
    4869          60 : Handle<String> JSBoundFunction::ToString(Handle<JSBoundFunction> function) {
    4870             :   Isolate* const isolate = function->GetIsolate();
    4871          60 :   return isolate->factory()->function_native_code_string();
    4872             : }
    4873             : 
    4874             : // static
    4875      131058 : Handle<Object> JSFunction::GetName(Isolate* isolate,
    4876             :                                    Handle<JSFunction> function) {
    4877      131058 :   if (function->shared()->name_should_print_as_anonymous()) {
    4878          20 :     return isolate->factory()->anonymous_string();
    4879             :   }
    4880      262076 :   return handle(function->shared()->Name(), isolate);
    4881             : }
    4882             : 
    4883             : // static
    4884        3707 : Handle<NativeContext> JSFunction::GetFunctionRealm(
    4885             :     Handle<JSFunction> function) {
    4886             :   DCHECK(function->map()->is_constructor());
    4887        3707 :   return handle(function->context()->native_context(), function->GetIsolate());
    4888             : }
    4889             : 
    4890      492995 : void JSFunction::MarkForOptimization(ConcurrencyMode mode) {
    4891             :   Isolate* isolate = GetIsolate();
    4892      492995 :   if (!isolate->concurrent_recompilation_enabled() ||
    4893             :       isolate->bootstrapper()->IsActive()) {
    4894             :     mode = ConcurrencyMode::kNotConcurrent;
    4895             :   }
    4896             : 
    4897             :   DCHECK(!is_compiled() || IsInterpreted());
    4898             :   DCHECK(shared()->IsInterpreted());
    4899             :   DCHECK(!IsOptimized());
    4900             :   DCHECK(!HasOptimizedCode());
    4901             :   DCHECK(shared()->allows_lazy_compilation() ||
    4902             :          !shared()->optimization_disabled());
    4903             : 
    4904      492995 :   if (mode == ConcurrencyMode::kConcurrent) {
    4905       28866 :     if (IsInOptimizationQueue()) {
    4906           0 :       if (FLAG_trace_concurrent_recompilation) {
    4907           0 :         PrintF("  ** Not marking ");
    4908           0 :         ShortPrint();
    4909           0 :         PrintF(" -- already in optimization queue.\n");
    4910             :       }
    4911             :       return;
    4912             :     }
    4913       28866 :     if (FLAG_trace_concurrent_recompilation) {
    4914           0 :       PrintF("  ** Marking ");
    4915           0 :       ShortPrint();
    4916           0 :       PrintF(" for concurrent recompilation.\n");
    4917             :     }
    4918             :   }
    4919             : 
    4920      492997 :   SetOptimizationMarker(mode == ConcurrencyMode::kConcurrent
    4921             :                             ? OptimizationMarker::kCompileOptimizedConcurrent
    4922             :                             : OptimizationMarker::kCompileOptimized);
    4923             : }
    4924             : 
    4925             : // static
    4926     3101363 : void JSFunction::EnsureClosureFeedbackCellArray(Handle<JSFunction> function) {
    4927             :   Isolate* const isolate = function->GetIsolate();
    4928             :   DCHECK(function->shared()->is_compiled());
    4929             :   DCHECK(function->shared()->HasFeedbackMetadata());
    4930     9304094 :   if (function->has_closure_feedback_cell_array() ||
    4931     6202734 :       function->has_feedback_vector()) {
    4932           0 :     return;
    4933             :   }
    4934     3101365 :   if (function->shared()->HasAsmWasmData()) return;
    4935             : 
    4936             :   Handle<SharedFunctionInfo> shared(function->shared(), isolate);
    4937             :   DCHECK(function->shared()->HasBytecodeArray());
    4938             :   Handle<HeapObject> feedback_cell_array =
    4939     3101367 :       ClosureFeedbackCellArray::New(isolate, shared);
    4940             :   // Many closure cell is used as a way to specify that there is no
    4941             :   // feedback cell for this function and a new feedback cell has to be
    4942             :   // allocated for this funciton. For ex: for eval functions, we have to create
    4943             :   // a feedback cell and cache it along with the code. It is safe to use
    4944             :   // many_closure_cell to indicate this because in regular cases, it should
    4945             :   // already have a feedback_vector / feedback cell array allocated.
    4946     3101364 :   if (function->raw_feedback_cell() == isolate->heap()->many_closures_cell()) {
    4947             :     Handle<FeedbackCell> feedback_cell =
    4948     1526109 :         isolate->factory()->NewOneClosureCell(feedback_cell_array);
    4949     1526103 :     function->set_raw_feedback_cell(*feedback_cell);
    4950             :   } else {
    4951     1575255 :     function->raw_feedback_cell()->set_value(*feedback_cell_array);
    4952             :   }
    4953             : }
    4954             : 
    4955             : // static
    4956     8715766 : void JSFunction::EnsureFeedbackVector(Handle<JSFunction> function) {
    4957             :   Isolate* const isolate = function->GetIsolate();
    4958             :   DCHECK(function->shared()->is_compiled());
    4959             :   DCHECK(function->shared()->HasFeedbackMetadata());
    4960    14330186 :   if (function->has_feedback_vector()) return;
    4961     3103169 :   if (function->shared()->HasAsmWasmData()) return;
    4962             : 
    4963             :   Handle<SharedFunctionInfo> shared(function->shared(), isolate);
    4964             :   DCHECK(function->shared()->HasBytecodeArray());
    4965             : 
    4966     3101369 :   EnsureClosureFeedbackCellArray(function);
    4967             :   Handle<ClosureFeedbackCellArray> closure_feedback_cell_array =
    4968     3101353 :       handle(function->closure_feedback_cell_array(), isolate);
    4969             :   Handle<HeapObject> feedback_vector =
    4970     3101353 :       FeedbackVector::New(isolate, shared, closure_feedback_cell_array);
    4971             :   // EnsureClosureFeedbackCellArray should handle the special case where we need
    4972             :   // to allocate a new feedback cell. Please look at comment in that function
    4973             :   // for more details.
    4974             :   DCHECK(function->raw_feedback_cell() !=
    4975             :          isolate->heap()->many_closures_cell());
    4976     3101351 :   function->raw_feedback_cell()->set_value(*feedback_vector);
    4977             : }
    4978             : 
    4979             : // static
    4980     8193852 : void JSFunction::InitializeFeedbackCell(Handle<JSFunction> function) {
    4981     8193852 :   if (FLAG_lazy_feedback_allocation) {
    4982           0 :     EnsureClosureFeedbackCellArray(function);
    4983             :   } else {
    4984     8193852 :     EnsureFeedbackVector(function);
    4985             :   }
    4986     8193860 : }
    4987             : 
    4988             : namespace {
    4989             : 
    4990      266214 : void SetInstancePrototype(Isolate* isolate, Handle<JSFunction> function,
    4991             :                           Handle<JSReceiver> value) {
    4992             :   // Now some logic for the maps of the objects that are created by using this
    4993             :   // function as a constructor.
    4994      266214 :   if (function->has_initial_map()) {
    4995             :     // If the function has allocated the initial map replace it with a
    4996             :     // copy containing the new prototype.  Also complete any in-object
    4997             :     // slack tracking that is in progress at this point because it is
    4998             :     // still tracking the old copy.
    4999      115518 :     function->CompleteInobjectSlackTrackingIfActive();
    5000             : 
    5001             :     Handle<Map> initial_map(function->initial_map(), isolate);
    5002             : 
    5003      230259 :     if (!isolate->bootstrapper()->IsActive() &&
    5004             :         initial_map->instance_type() == JS_OBJECT_TYPE) {
    5005             :       // Put the value in the initial map field until an initial map is needed.
    5006             :       // At that point, a new initial map is created and the prototype is put
    5007             :       // into the initial map where it belongs.
    5008      228748 :       function->set_prototype_or_initial_map(*value);
    5009             :     } else {
    5010             :       Handle<Map> new_map =
    5011        1144 :           Map::Copy(isolate, initial_map, "SetInstancePrototype");
    5012        1144 :       JSFunction::SetInitialMap(function, new_map, value);
    5013             : 
    5014             :       // If the function is used as the global Array function, cache the
    5015             :       // updated initial maps (and transitioned versions) in the native context.
    5016             :       Handle<Context> native_context(function->context()->native_context(),
    5017             :                                      isolate);
    5018             :       Handle<Object> array_function(
    5019             :           native_context->get(Context::ARRAY_FUNCTION_INDEX), isolate);
    5020        2177 :       if (array_function->IsJSFunction() &&
    5021             :           *function == JSFunction::cast(*array_function)) {
    5022         111 :         CacheInitialJSArrayMaps(native_context, new_map);
    5023             :       }
    5024             :     }
    5025             : 
    5026             :     // Deoptimize all code that embeds the previous initial map.
    5027      231036 :     initial_map->dependent_code()->DeoptimizeDependentCodeGroup(
    5028      115518 :         isolate, DependentCode::kInitialMapChangedGroup);
    5029             :   } else {
    5030             :     // Put the value in the initial map field until an initial map is
    5031             :     // needed.  At that point, a new initial map is created and the
    5032             :     // prototype is put into the initial map where it belongs.
    5033      301392 :     function->set_prototype_or_initial_map(*value);
    5034      150696 :     if (value->IsJSObject()) {
    5035             :       // Optimize as prototype to detach it from its transition tree.
    5036      150633 :       JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value));
    5037             :     }
    5038             :   }
    5039      266214 : }
    5040             : 
    5041             : }  // anonymous namespace
    5042             : 
    5043      266214 : void JSFunction::SetPrototype(Handle<JSFunction> function,
    5044             :                               Handle<Object> value) {
    5045             :   DCHECK(function->IsConstructor() ||
    5046             :          IsGeneratorFunction(function->shared()->kind()));
    5047             :   Isolate* isolate = function->GetIsolate();
    5048             :   Handle<JSReceiver> construct_prototype;
    5049             : 
    5050             :   // If the value is not a JSReceiver, store the value in the map's
    5051             :   // constructor field so it can be accessed.  Also, set the prototype
    5052             :   // used for constructing objects to the original object prototype.
    5053             :   // See ECMA-262 13.2.2.
    5054      266214 :   if (!value->IsJSReceiver()) {
    5055             :     // Copy the map so this does not affect unrelated functions.
    5056             :     // Remove map transitions because they point to maps with a
    5057             :     // different prototype.
    5058             :     Handle<Map> new_map =
    5059       94240 :         Map::Copy(isolate, handle(function->map(), isolate), "SetPrototype");
    5060             : 
    5061       94240 :     JSObject::MigrateToMap(function, new_map);
    5062       94240 :     new_map->SetConstructor(*value);
    5063       94240 :     new_map->set_has_non_instance_prototype(true);
    5064             : 
    5065             :     FunctionKind kind = function->shared()->kind();
    5066             :     Handle<Context> native_context(function->context()->native_context(),
    5067             :                                    isolate);
    5068             : 
    5069             :     construct_prototype = Handle<JSReceiver>(
    5070             :         IsGeneratorFunction(kind)
    5071             :             ? IsAsyncFunction(kind)
    5072       94258 :                   ? native_context->initial_async_generator_prototype()
    5073       94312 :                   : native_context->initial_generator_prototype()
    5074      188399 :             : native_context->initial_object_prototype(),
    5075      377032 :         isolate);
    5076             :   } else {
    5077      171974 :     construct_prototype = Handle<JSReceiver>::cast(value);
    5078      171974 :     function->map()->set_has_non_instance_prototype(false);
    5079             :   }
    5080             : 
    5081      266214 :   SetInstancePrototype(isolate, function, construct_prototype);
    5082      266214 : }
    5083             : 
    5084     4788040 : void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
    5085             :                                Handle<HeapObject> prototype) {
    5086     4788040 :   if (map->prototype() != *prototype)
    5087     4787479 :     Map::SetPrototype(function->GetIsolate(), map, prototype);
    5088     9576090 :   function->set_prototype_or_initial_map(*map);
    5089     9576084 :   map->SetConstructor(*function);
    5090     4788042 :   if (FLAG_trace_maps) {
    5091        3078 :     LOG(function->GetIsolate(), MapEvent("InitialMap", Map(), *map, "",
    5092             :                                          function->shared()->DebugName()));
    5093             :   }
    5094     4788042 : }
    5095             : 
    5096    18939724 : void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) {
    5097             :   DCHECK(function->has_prototype_slot());
    5098             :   DCHECK(function->IsConstructor() ||
    5099             :          IsResumableFunction(function->shared()->kind()));
    5100    37575872 :   if (function->has_initial_map()) return;
    5101             :   Isolate* isolate = function->GetIsolate();
    5102             : 
    5103             :   // First create a new map with the size and number of in-object properties
    5104             :   // suggested by the function.
    5105             :   InstanceType instance_type;
    5106      303586 :   if (IsResumableFunction(function->shared()->kind())) {
    5107             :     instance_type = IsAsyncGeneratorFunction(function->shared()->kind())
    5108             :                         ? JS_ASYNC_GENERATOR_OBJECT_TYPE
    5109        8712 :                         : JS_GENERATOR_OBJECT_TYPE;
    5110             :   } else {
    5111             :     instance_type = JS_OBJECT_TYPE;
    5112             :   }
    5113             : 
    5114             :   int instance_size;
    5115             :   int inobject_properties;
    5116             :   int expected_nof_properties =
    5117      303586 :       CalculateExpectedNofProperties(isolate, function);
    5118      303586 :   CalculateInstanceSizeHelper(instance_type, false, 0, expected_nof_properties,
    5119      303586 :                               &instance_size, &inobject_properties);
    5120             : 
    5121             :   Handle<Map> map = isolate->factory()->NewMap(instance_type, instance_size,
    5122             :                                                TERMINAL_FAST_ELEMENTS_KIND,
    5123      303586 :                                                inobject_properties);
    5124             : 
    5125             :   // Fetch or allocate prototype.
    5126             :   Handle<HeapObject> prototype;
    5127      303586 :   if (function->has_instance_prototype()) {
    5128      486372 :     prototype = handle(function->instance_prototype(), isolate);
    5129             :   } else {
    5130       60399 :     prototype = isolate->factory()->NewFunctionPrototype(function);
    5131             :   }
    5132             :   DCHECK(map->has_fast_object_elements());
    5133             : 
    5134             :   // Finally link initial map and constructor function.
    5135             :   DCHECK(prototype->IsJSReceiver());
    5136      303586 :   JSFunction::SetInitialMap(function, map, prototype);
    5137      303586 :   map->StartInobjectSlackTracking();
    5138             : }
    5139             : 
    5140             : #ifdef DEBUG
    5141             : namespace {
    5142             : 
    5143             : bool CanSubclassHaveInobjectProperties(InstanceType instance_type) {
    5144             :   switch (instance_type) {
    5145             :     case JS_API_OBJECT_TYPE:
    5146             :     case JS_ARRAY_BUFFER_TYPE:
    5147             :     case JS_ARRAY_TYPE:
    5148             :     case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
    5149             :     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
    5150             :     case JS_DATA_VIEW_TYPE:
    5151             :     case JS_DATE_TYPE:
    5152             :     case JS_FUNCTION_TYPE:
    5153             :     case JS_GENERATOR_OBJECT_TYPE:
    5154             : #ifdef V8_INTL_SUPPORT
    5155             :     case JS_INTL_COLLATOR_TYPE:
    5156             :     case JS_INTL_DATE_TIME_FORMAT_TYPE:
    5157             :     case JS_INTL_LIST_FORMAT_TYPE:
    5158             :     case JS_INTL_LOCALE_TYPE:
    5159             :     case JS_INTL_NUMBER_FORMAT_TYPE:
    5160             :     case JS_INTL_PLURAL_RULES_TYPE:
    5161             :     case JS_INTL_RELATIVE_TIME_FORMAT_TYPE:
    5162             :     case JS_INTL_SEGMENT_ITERATOR_TYPE:
    5163             :     case JS_INTL_SEGMENTER_TYPE:
    5164             :     case JS_INTL_V8_BREAK_ITERATOR_TYPE:
    5165             : #endif
    5166             :     case JS_ASYNC_FUNCTION_OBJECT_TYPE:
    5167             :     case JS_ASYNC_GENERATOR_OBJECT_TYPE:
    5168             :     case JS_MAP_TYPE:
    5169             :     case JS_MESSAGE_OBJECT_TYPE:
    5170             :     case JS_OBJECT_TYPE:
    5171             :     case JS_ERROR_TYPE:
    5172             :     case JS_ARGUMENTS_TYPE:
    5173             :     case JS_PROMISE_TYPE:
    5174             :     case JS_REGEXP_TYPE:
    5175             :     case JS_SET_TYPE:
    5176             :     case JS_SPECIAL_API_OBJECT_TYPE:
    5177             :     case JS_TYPED_ARRAY_TYPE:
    5178             :     case JS_VALUE_TYPE:
    5179             :     case JS_WEAK_MAP_TYPE:
    5180             :     case JS_WEAK_SET_TYPE:
    5181             :     case WASM_GLOBAL_TYPE:
    5182             :     case WASM_INSTANCE_TYPE:
    5183             :     case WASM_MEMORY_TYPE:
    5184             :     case WASM_MODULE_TYPE:
    5185             :     case WASM_TABLE_TYPE:
    5186             :       return true;
    5187             : 
    5188             :     case BIGINT_TYPE:
    5189             :     case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
    5190             :     case BYTECODE_ARRAY_TYPE:
    5191             :     case BYTE_ARRAY_TYPE:
    5192             :     case CELL_TYPE:
    5193             :     case CODE_TYPE:
    5194             :     case FILLER_TYPE:
    5195             :     case FIXED_ARRAY_TYPE:
    5196             :     case SCRIPT_CONTEXT_TABLE_TYPE:
    5197             :     case FIXED_DOUBLE_ARRAY_TYPE:
    5198             :     case FEEDBACK_METADATA_TYPE:
    5199             :     case FOREIGN_TYPE:
    5200             :     case FREE_SPACE_TYPE:
    5201             :     case HASH_TABLE_TYPE:
    5202             :     case ORDERED_HASH_MAP_TYPE:
    5203             :     case ORDERED_HASH_SET_TYPE:
    5204             :     case ORDERED_NAME_DICTIONARY_TYPE:
    5205             :     case NAME_DICTIONARY_TYPE:
    5206             :     case GLOBAL_DICTIONARY_TYPE:
    5207             :     case NUMBER_DICTIONARY_TYPE:
    5208             :     case SIMPLE_NUMBER_DICTIONARY_TYPE:
    5209             :     case STRING_TABLE_TYPE:
    5210             :     case HEAP_NUMBER_TYPE:
    5211             :     case JS_BOUND_FUNCTION_TYPE:
    5212             :     case JS_GLOBAL_OBJECT_TYPE:
    5213             :     case JS_GLOBAL_PROXY_TYPE:
    5214             :     case JS_PROXY_TYPE:
    5215             :     case MAP_TYPE:
    5216             :     case MUTABLE_HEAP_NUMBER_TYPE:
    5217             :     case ODDBALL_TYPE:
    5218             :     case PROPERTY_CELL_TYPE:
    5219             :     case SHARED_FUNCTION_INFO_TYPE:
    5220             :     case SYMBOL_TYPE:
    5221             :     case ALLOCATION_SITE_TYPE:
    5222             : 
    5223             : #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
    5224             :   case FIXED_##TYPE##_ARRAY_TYPE:
    5225             : #undef TYPED_ARRAY_CASE
    5226             : 
    5227             : #define MAKE_STRUCT_CASE(TYPE, Name, name) case TYPE:
    5228             :       STRUCT_LIST(MAKE_STRUCT_CASE)
    5229             : #undef MAKE_STRUCT_CASE
    5230             :       // We must not end up here for these instance types at all.
    5231             :       UNREACHABLE();
    5232             :     // Fall through.
    5233             :     default:
    5234             :       return false;
    5235             :   }
    5236             : }
    5237             : 
    5238             : }  // namespace
    5239             : #endif
    5240             : 
    5241             : namespace {
    5242             : 
    5243      312327 : bool FastInitializeDerivedMap(Isolate* isolate, Handle<JSFunction> new_target,
    5244             :                               Handle<JSFunction> constructor,
    5245             :                               Handle<Map> constructor_initial_map) {
    5246             :   // Use the default intrinsic prototype instead.
    5247      312327 :   if (!new_target->has_prototype_slot()) return false;
    5248             :   // Check that |function|'s initial map still in sync with the |constructor|,
    5249             :   // otherwise we must create a new initial map for |function|.
    5250      925985 :   if (new_target->has_initial_map() &&
    5251      613694 :       new_target->initial_map()->GetConstructor() == *constructor) {
    5252             :     DCHECK(new_target->instance_prototype()->IsJSReceiver());
    5253             :     return true;
    5254             :   }
    5255             :   InstanceType instance_type = constructor_initial_map->instance_type();
    5256             :   DCHECK(CanSubclassHaveInobjectProperties(instance_type));
    5257             :   // Create a new map with the size and number of in-object properties
    5258             :   // suggested by |function|.
    5259             : 
    5260             :   // Link initial map and constructor function if the new.target is actually a
    5261             :   // subclass constructor.
    5262      304456 :   if (!IsDerivedConstructor(new_target->shared()->kind())) return false;
    5263             : 
    5264             :   int instance_size;
    5265             :   int in_object_properties;
    5266             :   int embedder_fields =
    5267        9208 :       JSObject::GetEmbedderFieldCount(*constructor_initial_map);
    5268             :   int expected_nof_properties =
    5269        9208 :       JSFunction::CalculateExpectedNofProperties(isolate, new_target);
    5270        9208 :   JSFunction::CalculateInstanceSizeHelper(
    5271             :       instance_type, true, embedder_fields, expected_nof_properties,
    5272        9208 :       &instance_size, &in_object_properties);
    5273             : 
    5274       18416 :   int pre_allocated = constructor_initial_map->GetInObjectProperties() -
    5275        9208 :                       constructor_initial_map->UnusedPropertyFields();
    5276       18416 :   CHECK_LE(constructor_initial_map->UsedInstanceSize(), instance_size);
    5277        9208 :   int unused_property_fields = in_object_properties - pre_allocated;
    5278             :   Handle<Map> map =
    5279             :       Map::CopyInitialMap(isolate, constructor_initial_map, instance_size,
    5280        9208 :                           in_object_properties, unused_property_fields);
    5281        9208 :   map->set_new_target_is_base(false);
    5282       18416 :   Handle<HeapObject> prototype(new_target->instance_prototype(), isolate);
    5283        9208 :   JSFunction::SetInitialMap(new_target, map, prototype);
    5284             :   DCHECK(new_target->instance_prototype()->IsJSReceiver());
    5285       18416 :   map->SetConstructor(*constructor);
    5286        9208 :   map->set_construction_counter(Map::kNoSlackTracking);
    5287        9208 :   map->StartInobjectSlackTracking();
    5288        9208 :   return true;
    5289             : }
    5290             : 
    5291             : }  // namespace
    5292             : 
    5293             : // static
    5294     3255814 : MaybeHandle<Map> JSFunction::GetDerivedMap(Isolate* isolate,
    5295             :                                            Handle<JSFunction> constructor,
    5296             :                                            Handle<JSReceiver> new_target) {
    5297     3255814 :   EnsureHasInitialMap(constructor);
    5298             : 
    5299             :   Handle<Map> constructor_initial_map(constructor->initial_map(), isolate);
    5300     3255826 :   if (*new_target == *constructor) return constructor_initial_map;
    5301             : 
    5302             :   Handle<Map> result_map;
    5303             :   // Fast case, new.target is a subclass of constructor. The map is cacheable
    5304             :   // (and may already have been cached). new.target.prototype is guaranteed to
    5305             :   // be a JSReceiver.
    5306      313812 :   if (new_target->IsJSFunction()) {
    5307             :     Handle<JSFunction> function = Handle<JSFunction>::cast(new_target);
    5308      312327 :     if (FastInitializeDerivedMap(isolate, function, constructor,
    5309             :                                  constructor_initial_map)) {
    5310       17043 :       return handle(function->initial_map(), isolate);
    5311             :     }
    5312             :   }
    5313             : 
    5314             :   // Slow path, new.target is either a proxy or can't cache the map.
    5315             :   // new.target.prototype is not guaranteed to be a JSReceiver, and may need to
    5316             :   // fall back to the intrinsicDefaultProto.
    5317             :   Handle<Object> prototype;
    5318      296769 :   if (new_target->IsJSFunction()) {
    5319             :     Handle<JSFunction> function = Handle<JSFunction>::cast(new_target);
    5320      295284 :     if (function->has_prototype_slot()) {
    5321             :       // Make sure the new.target.prototype is cached.
    5322      295248 :       EnsureHasInitialMap(function);
    5323      590492 :       prototype = handle(function->prototype(), isolate);
    5324             :     } else {
    5325             :       // No prototype property, use the intrinsict default proto further down.
    5326             :       prototype = isolate->factory()->undefined_value();
    5327             :     }
    5328             :   } else {
    5329             :     Handle<String> prototype_string = isolate->factory()->prototype_string();
    5330        2970 :     ASSIGN_RETURN_ON_EXCEPTION(
    5331             :         isolate, prototype,
    5332             :         JSReceiver::GetProperty(isolate, new_target, prototype_string), Map);
    5333             :     // The above prototype lookup might change the constructor and its
    5334             :     // prototype, hence we have to reload the initial map.
    5335        1404 :     EnsureHasInitialMap(constructor);
    5336             :     constructor_initial_map = handle(constructor->initial_map(), isolate);
    5337             :   }
    5338             : 
    5339             :   // If prototype is not a JSReceiver, fetch the intrinsicDefaultProto from the
    5340             :   // correct realm. Rather than directly fetching the .prototype, we fetch the
    5341             :   // constructor that points to the .prototype. This relies on
    5342             :   // constructor.prototype being FROZEN for those constructors.
    5343      296688 :   if (!prototype->IsJSReceiver()) {
    5344             :     Handle<Context> context;
    5345        2754 :     ASSIGN_RETURN_ON_EXCEPTION(isolate, context,
    5346             :                                JSReceiver::GetFunctionRealm(new_target), Map);
    5347             :     DCHECK(context->IsNativeContext());
    5348             :     Handle<Object> maybe_index = JSReceiver::GetDataProperty(
    5349        1377 :         constructor, isolate->factory()->native_context_index_symbol());
    5350             :     int index = maybe_index->IsSmi() ? Smi::ToInt(*maybe_index)
    5351        1377 :                                      : Context::OBJECT_FUNCTION_INDEX;
    5352             :     Handle<JSFunction> realm_constructor(JSFunction::cast(context->get(index)),
    5353             :                                          isolate);
    5354        2754 :     prototype = handle(realm_constructor->prototype(), isolate);
    5355             :   }
    5356             : 
    5357      296688 :   Handle<Map> map = Map::CopyInitialMap(isolate, constructor_initial_map);
    5358      296686 :   map->set_new_target_is_base(false);
    5359      296687 :   CHECK(prototype->IsJSReceiver());
    5360      296687 :   if (map->prototype() != *prototype)
    5361      295905 :     Map::SetPrototype(isolate, map, Handle<HeapObject>::cast(prototype));
    5362      593372 :   map->SetConstructor(*constructor);
    5363      296686 :   return map;
    5364             : }
    5365             : 
    5366     3735729 : int JSFunction::ComputeInstanceSizeWithMinSlack(Isolate* isolate) {
    5367     3735729 :   CHECK(has_initial_map());
    5368     3735732 :   if (initial_map()->IsInobjectSlackTrackingInProgress()) {
    5369        6500 :     int slack = initial_map()->ComputeMinObjectSlack(isolate);
    5370             :     return initial_map()->InstanceSizeFromSlack(slack);
    5371             :   }
    5372             :   return initial_map()->instance_size();
    5373             : }
    5374             : 
    5375           0 : void JSFunction::PrintName(FILE* out) {
    5376           0 :   std::unique_ptr<char[]> name = shared()->DebugName()->ToCString();
    5377           0 :   PrintF(out, "%s", name.get());
    5378           0 : }
    5379             : 
    5380      519445 : Handle<String> JSFunction::GetName(Handle<JSFunction> function) {
    5381             :   Isolate* isolate = function->GetIsolate();
    5382             :   Handle<Object> name =
    5383      519445 :       JSReceiver::GetDataProperty(function, isolate->factory()->name_string());
    5384      519445 :   if (name->IsString()) return Handle<String>::cast(name);
    5385     1037504 :   return handle(function->shared()->DebugName(), isolate);
    5386             : }
    5387             : 
    5388      408409 : Handle<String> JSFunction::GetDebugName(Handle<JSFunction> function) {
    5389             :   Isolate* isolate = function->GetIsolate();
    5390             :   Handle<Object> name = JSReceiver::GetDataProperty(
    5391      408409 :       function, isolate->factory()->display_name_string());
    5392      408409 :   if (name->IsString()) return Handle<String>::cast(name);
    5393      408375 :   return JSFunction::GetName(function);
    5394             : }
    5395             : 
    5396        7084 : bool JSFunction::SetName(Handle<JSFunction> function, Handle<Name> name,
    5397             :                          Handle<String> prefix) {
    5398             :   Isolate* isolate = function->GetIsolate();
    5399             :   Handle<String> function_name;
    5400       14168 :   ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, function_name,
    5401             :                                    Name::ToFunctionName(isolate, name), false);
    5402        7075 :   if (prefix->length() > 0) {
    5403        3273 :     IncrementalStringBuilder builder(isolate);
    5404        3273 :     builder.AppendString(prefix);
    5405             :     builder.AppendCharacter(' ');
    5406        3273 :     builder.AppendString(function_name);
    5407        6546 :     ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, function_name, builder.Finish(),
    5408             :                                      false);
    5409             :   }
    5410       14114 :   RETURN_ON_EXCEPTION_VALUE(
    5411             :       isolate,
    5412             :       JSObject::DefinePropertyOrElementIgnoreAttributes(
    5413             :           function, isolate->factory()->name_string(), function_name,
    5414             :           static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY)),
    5415             :       false);
    5416        7057 :   return true;
    5417             : }
    5418             : 
    5419             : namespace {
    5420             : 
    5421     1082736 : Handle<String> NativeCodeFunctionSourceString(
    5422             :     Handle<SharedFunctionInfo> shared_info) {
    5423             :   Isolate* const isolate = shared_info->GetIsolate();
    5424     1082736 :   IncrementalStringBuilder builder(isolate);
    5425             :   builder.AppendCString("function ");
    5426     2165472 :   builder.AppendString(handle(shared_info->Name(), isolate));
    5427             :   builder.AppendCString("() { [native code] }");
    5428     2165472 :   return builder.Finish().ToHandleChecked();
    5429             : }
    5430             : 
    5431             : }  // namespace
    5432             : 
    5433             : // static
    5434     1892134 : Handle<String> JSFunction::ToString(Handle<JSFunction> function) {
    5435             :   Isolate* const isolate = function->GetIsolate();
    5436             :   Handle<SharedFunctionInfo> shared_info(function->shared(), isolate);
    5437             : 
    5438             :   // Check if {function} should hide its source code.
    5439     1892134 :   if (!shared_info->IsUserJavaScript()) {
    5440     1082664 :     return NativeCodeFunctionSourceString(shared_info);
    5441             :   }
    5442             : 
    5443             :   // Check if we should print {function} as a class.
    5444             :   Handle<Object> maybe_class_positions = JSReceiver::GetDataProperty(
    5445      809470 :       function, isolate->factory()->class_positions_symbol());
    5446      809470 :   if (maybe_class_positions->IsClassPositions()) {
    5447             :     ClassPositions class_positions =
    5448             :         ClassPositions::cast(*maybe_class_positions);
    5449             :     int start_position = class_positions->start();
    5450             :     int end_position = class_positions->end();
    5451             :     Handle<String> script_source(
    5452       43444 :         String::cast(Script::cast(shared_info->script())->source()), isolate);
    5453             :     return isolate->factory()->NewSubString(script_source, start_position,
    5454       21722 :                                             end_position);
    5455             :   }
    5456             : 
    5457             :   // Check if we have source code for the {function}.
    5458      787748 :   if (!shared_info->HasSourceCode()) {
    5459           0 :     return NativeCodeFunctionSourceString(shared_info);
    5460             :   }
    5461             : 
    5462     1575496 :   if (shared_info->function_token_position() == kNoSourcePosition) {
    5463             :     // If the function token position isn't valid, return [native code] to
    5464             :     // ensure calling eval on the returned source code throws rather than
    5465             :     // giving inconsistent call behaviour.
    5466             :     isolate->CountUsage(
    5467          72 :         v8::Isolate::UseCounterFeature::kFunctionTokenOffsetTooLongForToString);
    5468          72 :     return NativeCodeFunctionSourceString(shared_info);
    5469             :   }
    5470             :   return Handle<String>::cast(
    5471      787676 :       SharedFunctionInfo::GetSourceCodeHarmony(shared_info));
    5472             : }
    5473             : 
    5474             : // static
    5475      312792 : int JSFunction::CalculateExpectedNofProperties(Isolate* isolate,
    5476             :                                                Handle<JSFunction> function) {
    5477             :   int expected_nof_properties = 0;
    5478      639452 :   for (PrototypeIterator iter(isolate, function, kStartAtReceiver);
    5479      639452 :        !iter.IsAtEnd(); iter.Advance()) {
    5480             :     Handle<JSReceiver> current =
    5481             :         PrototypeIterator::GetCurrent<JSReceiver>(iter);
    5482      952234 :     if (!current->IsJSFunction()) break;
    5483             :     Handle<JSFunction> func = Handle<JSFunction>::cast(current);
    5484             :     // The super constructor should be compiled for the number of expected
    5485             :     // properties to be available.
    5486             :     Handle<SharedFunctionInfo> shared(func->shared(), isolate);
    5487      639664 :     IsCompiledScope is_compiled_scope(shared->is_compiled_scope());
    5488      668246 :     if (is_compiled_scope.is_compiled() ||
    5489       28580 :         Compiler::Compile(func, Compiler::CLEAR_EXCEPTION,
    5490             :                           &is_compiled_scope)) {
    5491             :       DCHECK(shared->is_compiled());
    5492      639657 :       int count = shared->expected_nof_properties();
    5493             :       // Check that the estimate is sane.
    5494      639657 :       if (expected_nof_properties <= JSObject::kMaxInObjectProperties - count) {
    5495      639452 :         expected_nof_properties += count;
    5496             :       } else {
    5497         205 :         return JSObject::kMaxInObjectProperties;
    5498             :       }
    5499             :     } else {
    5500             :       // In case there was a compilation error for the constructor we will
    5501             :       // throw an error during instantiation.
    5502             :       break;
    5503             :     }
    5504             :   }
    5505             :   // Inobject slack tracking will reclaim redundant inobject space
    5506             :   // later, so we can afford to adjust the estimate generously,
    5507             :   // meaning we over-allocate by at least 8 slots in the beginning.
    5508      312590 :   if (expected_nof_properties > 0) {
    5509      227732 :     expected_nof_properties += 8;
    5510      227732 :     if (expected_nof_properties > JSObject::kMaxInObjectProperties) {
    5511             :       expected_nof_properties = JSObject::kMaxInObjectProperties;
    5512             :     }
    5513             :   }
    5514             :   return expected_nof_properties;
    5515             : }
    5516             : 
    5517             : // static
    5518      312794 : void JSFunction::CalculateInstanceSizeHelper(InstanceType instance_type,
    5519             :                                              bool has_prototype_slot,
    5520             :                                              int requested_embedder_fields,
    5521             :                                              int requested_in_object_properties,
    5522             :                                              int* instance_size,
    5523             :                                              int* in_object_properties) {
    5524             :   DCHECK_LE(static_cast<unsigned>(requested_embedder_fields),
    5525             :             JSObject::kMaxEmbedderFields);
    5526      312794 :   int header_size = JSObject::GetHeaderSize(instance_type, has_prototype_slot);
    5527      312794 :   if (requested_embedder_fields) {
    5528             :     // If there are embedder fields, then the embedder fields start offset must
    5529             :     // be properly aligned (embedder fields are located between object header
    5530             :     // and inobject fields).
    5531             :     header_size = RoundUp<kSystemPointerSize>(header_size);
    5532             :     requested_embedder_fields *= kEmbedderDataSlotSizeInTaggedSlots;
    5533             :   }
    5534             :   int max_nof_fields =
    5535      312794 :       (JSObject::kMaxInstanceSize - header_size) >> kTaggedSizeLog2;
    5536      312794 :   CHECK_LE(max_nof_fields, JSObject::kMaxInObjectProperties);
    5537      312794 :   CHECK_LE(static_cast<unsigned>(requested_embedder_fields),
    5538             :            static_cast<unsigned>(max_nof_fields));
    5539      312794 :   *in_object_properties = Min(requested_in_object_properties,
    5540      312794 :                               max_nof_fields - requested_embedder_fields);
    5541             :   *instance_size =
    5542      312794 :       header_size +
    5543      625588 :       ((requested_embedder_fields + *in_object_properties) << kTaggedSizeLog2);
    5544      312794 :   CHECK_EQ(*in_object_properties,
    5545             :            ((*instance_size - header_size) >> kTaggedSizeLog2) -
    5546             :                requested_embedder_fields);
    5547      312794 :   CHECK_LE(static_cast<unsigned>(*instance_size),
    5548             :            static_cast<unsigned>(JSObject::kMaxInstanceSize));
    5549      312794 : }
    5550             : 
    5551       52398 : void JSFunction::ClearTypeFeedbackInfo() {
    5552       52398 :   ResetIfBytecodeFlushed();
    5553       52398 :   if (has_feedback_vector()) {
    5554       52352 :     FeedbackVector vector = feedback_vector();
    5555             :     Isolate* isolate = GetIsolate();
    5556       52352 :     if (vector->ClearSlots(isolate)) {
    5557             :       IC::OnFeedbackChanged(isolate, vector, FeedbackSlot::Invalid(), *this,
    5558       27636 :                             "ClearTypeFeedbackInfo");
    5559             :     }
    5560             :   }
    5561       52398 : }
    5562             : 
    5563      952248 : void JSGlobalObject::InvalidatePropertyCell(Handle<JSGlobalObject> global,
    5564             :                                             Handle<Name> name) {
    5565             :   // Regardless of whether the property is there or not invalidate
    5566             :   // Load/StoreGlobalICs that load/store through global object's prototype.
    5567      952248 :   JSObject::InvalidatePrototypeValidityCell(*global);
    5568             : 
    5569             :   DCHECK(!global->HasFastProperties());
    5570             :   auto dictionary = handle(global->global_dictionary(), global->GetIsolate());
    5571      952248 :   int entry = dictionary->FindEntry(global->GetIsolate(), name);
    5572      952248 :   if (entry == GlobalDictionary::kNotFound) return;
    5573          87 :   PropertyCell::InvalidateEntry(global->GetIsolate(), dictionary, entry);
    5574             : }
    5575             : 
    5576     8327719 : Handle<PropertyCell> JSGlobalObject::EnsureEmptyPropertyCell(
    5577             :     Handle<JSGlobalObject> global, Handle<Name> name,
    5578             :     PropertyCellType cell_type, int* entry_out) {
    5579             :   Isolate* isolate = global->GetIsolate();
    5580             :   DCHECK(!global->HasFastProperties());
    5581             :   Handle<GlobalDictionary> dictionary(global->global_dictionary(), isolate);
    5582     8327722 :   int entry = dictionary->FindEntry(isolate, name);
    5583             :   Handle<PropertyCell> cell;
    5584     8327720 :   if (entry != GlobalDictionary::kNotFound) {
    5585        3043 :     if (entry_out) *entry_out = entry;
    5586             :     cell = handle(dictionary->CellAt(entry), isolate);
    5587             :     PropertyCellType original_cell_type = cell->property_details().cell_type();
    5588             :     DCHECK(original_cell_type == PropertyCellType::kInvalidated ||
    5589             :            original_cell_type == PropertyCellType::kUninitialized);
    5590             :     DCHECK(cell->value()->IsTheHole(isolate));
    5591        3043 :     if (original_cell_type == PropertyCellType::kInvalidated) {
    5592         481 :       cell = PropertyCell::InvalidateEntry(isolate, dictionary, entry);
    5593             :     }
    5594             :     PropertyDetails details(kData, NONE, cell_type);
    5595        6086 :     cell->set_property_details(details);
    5596        3043 :     return cell;
    5597             :   }
    5598     8324677 :   cell = isolate->factory()->NewPropertyCell(name);
    5599             :   PropertyDetails details(kData, NONE, cell_type);
    5600             :   dictionary = GlobalDictionary::Add(isolate, dictionary, name, cell, details,
    5601     8324664 :                                      entry_out);
    5602             :   // {*entry_out} is initialized inside GlobalDictionary::Add().
    5603    16649334 :   global->SetProperties(*dictionary);
    5604     8324673 :   return cell;
    5605             : }
    5606             : 
    5607             : // static
    5608      150468 : MaybeHandle<JSDate> JSDate::New(Handle<JSFunction> constructor,
    5609             :                                 Handle<JSReceiver> new_target, double tv) {
    5610             :   Isolate* const isolate = constructor->GetIsolate();
    5611             :   Handle<JSObject> result;
    5612      300936 :   ASSIGN_RETURN_ON_EXCEPTION(
    5613             :       isolate, result,
    5614             :       JSObject::New(constructor, new_target, Handle<AllocationSite>::null()),
    5615             :       JSDate);
    5616      150468 :   if (-DateCache::kMaxTimeInMs <= tv && tv <= DateCache::kMaxTimeInMs) {
    5617      149964 :     tv = DoubleToInteger(tv) + 0.0;
    5618             :   } else {
    5619             :     tv = std::numeric_limits<double>::quiet_NaN();
    5620             :   }
    5621      150468 :   Handle<Object> value = isolate->factory()->NewNumber(tv);
    5622      300936 :   Handle<JSDate>::cast(result)->SetValue(*value, std::isnan(tv));
    5623      150468 :   return Handle<JSDate>::cast(result);
    5624             : }
    5625             : 
    5626             : // static
    5627     1178947 : double JSDate::CurrentTimeValue(Isolate* isolate) {
    5628     1178947 :   if (FLAG_log_internal_timer_events) LOG(isolate, CurrentTimeEvent());
    5629             : 
    5630             :   // According to ECMA-262, section 15.9.1, page 117, the precision of
    5631             :   // the number in a Date object representing a particular instant in
    5632             :   // time is milliseconds. Therefore, we floor the result of getting
    5633             :   // the OS time.
    5634     1178947 :   return std::floor(V8::GetCurrentPlatform()->CurrentClockTimeMillis());
    5635             : }
    5636             : 
    5637             : // static
    5638       11601 : Address JSDate::GetField(Address raw_object, Address smi_index) {
    5639             :   Object object(raw_object);
    5640             :   Smi index(smi_index);
    5641       23202 :   return JSDate::cast(object)
    5642       34803 :       ->DoGetField(static_cast<FieldIndex>(index->value()))
    5643       11601 :       ->ptr();
    5644             : }
    5645             : 
    5646       11601 : Object JSDate::DoGetField(FieldIndex index) {
    5647             :   DCHECK_NE(index, kDateValue);
    5648             : 
    5649             :   DateCache* date_cache = GetIsolate()->date_cache();
    5650             : 
    5651       11601 :   if (index < kFirstUncachedField) {
    5652             :     Object stamp = cache_stamp();
    5653       11232 :     if (stamp != date_cache->stamp() && stamp->IsSmi()) {
    5654             :       // Since the stamp is not NaN, the value is also not NaN.
    5655             :       int64_t local_time_ms =
    5656         567 :           date_cache->ToLocal(static_cast<int64_t>(value()->Number()));
    5657         567 :       SetCachedFields(local_time_ms, date_cache);
    5658             :     }
    5659        5616 :     switch (index) {
    5660             :       case kYear:
    5661             :         return year();
    5662             :       case kMonth:
    5663             :         return month();
    5664             :       case kDay:
    5665             :         return day();
    5666             :       case kWeekday:
    5667             :         return weekday();
    5668             :       case kHour:
    5669             :         return hour();
    5670             :       case kMinute:
    5671             :         return min();
    5672             :       case kSecond:
    5673             :         return sec();
    5674             :       default:
    5675           0 :         UNREACHABLE();
    5676             :     }
    5677             :   }
    5678             : 
    5679        5985 :   if (index >= kFirstUTCField) {
    5680        5796 :     return GetUTCField(index, value()->Number(), date_cache);
    5681             :   }
    5682             : 
    5683             :   double time = value()->Number();
    5684         243 :   if (std::isnan(time)) return GetReadOnlyRoots().nan_value();
    5685             : 
    5686         135 :   int64_t local_time_ms = date_cache->ToLocal(static_cast<int64_t>(time));
    5687             :   int days = DateCache::DaysFromTime(local_time_ms);
    5688             : 
    5689         135 :   if (index == kDays) return Smi::FromInt(days);
    5690             : 
    5691             :   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
    5692         270 :   if (index == kMillisecond) return Smi::FromInt(time_in_day_ms % 1000);
    5693             :   DCHECK_EQ(index, kTimeInDay);
    5694           0 :   return Smi::FromInt(time_in_day_ms);
    5695             : }
    5696             : 
    5697        5796 : Object JSDate::GetUTCField(FieldIndex index, double value,
    5698             :                            DateCache* date_cache) {
    5699             :   DCHECK_GE(index, kFirstUTCField);
    5700             : 
    5701       10899 :   if (std::isnan(value)) return GetReadOnlyRoots().nan_value();
    5702             : 
    5703         693 :   int64_t time_ms = static_cast<int64_t>(value);
    5704             : 
    5705         693 :   if (index == kTimezoneOffset) {
    5706         153 :     GetIsolate()->CountUsage(v8::Isolate::kDateGetTimezoneOffset);
    5707         153 :     return Smi::FromInt(date_cache->TimezoneOffset(time_ms));
    5708             :   }
    5709             : 
    5710             :   int days = DateCache::DaysFromTime(time_ms);
    5711             : 
    5712         576 :   if (index == kWeekdayUTC) return Smi::FromInt(date_cache->Weekday(days));
    5713             : 
    5714         504 :   if (index <= kDayUTC) {
    5715             :     int year, month, day;
    5716         198 :     date_cache->YearMonthDayFromDays(days, &year, &month, &day);
    5717         261 :     if (index == kYearUTC) return Smi::FromInt(year);
    5718         198 :     if (index == kMonthUTC) return Smi::FromInt(month);
    5719             :     DCHECK_EQ(index, kDayUTC);
    5720         144 :     return Smi::FromInt(day);
    5721             :   }
    5722             : 
    5723             :   int time_in_day_ms = DateCache::TimeInDay(time_ms, days);
    5724         306 :   switch (index) {
    5725             :     case kHourUTC:
    5726         234 :       return Smi::FromInt(time_in_day_ms / (60 * 60 * 1000));
    5727             :     case kMinuteUTC:
    5728         144 :       return Smi::FromInt((time_in_day_ms / (60 * 1000)) % 60);
    5729             :     case kSecondUTC:
    5730         126 :       return Smi::FromInt((time_in_day_ms / 1000) % 60);
    5731             :     case kMillisecondUTC:
    5732         108 :       return Smi::FromInt(time_in_day_ms % 1000);
    5733             :     case kDaysUTC:
    5734           0 :       return Smi::FromInt(days);
    5735             :     case kTimeInDayUTC:
    5736           0 :       return Smi::FromInt(time_in_day_ms);
    5737             :     default:
    5738           0 :       UNREACHABLE();
    5739             :   }
    5740             : 
    5741             :   UNREACHABLE();
    5742             : }
    5743             : 
    5744             : // static
    5745       11583 : Handle<Object> JSDate::SetValue(Handle<JSDate> date, double v) {
    5746             :   Isolate* const isolate = date->GetIsolate();
    5747       11583 :   Handle<Object> value = isolate->factory()->NewNumber(v);
    5748             :   bool value_is_nan = std::isnan(v);
    5749       23166 :   date->SetValue(*value, value_is_nan);
    5750       11583 :   return value;
    5751             : }
    5752             : 
    5753      162051 : void JSDate::SetValue(Object value, bool is_value_nan) {
    5754      162051 :   set_value(value);
    5755      162051 :   if (is_value_nan) {
    5756             :     HeapNumber nan = GetReadOnlyRoots().nan_value();
    5757             :     set_cache_stamp(nan, SKIP_WRITE_BARRIER);
    5758             :     set_year(nan, SKIP_WRITE_BARRIER);
    5759             :     set_month(nan, SKIP_WRITE_BARRIER);
    5760             :     set_day(nan, SKIP_WRITE_BARRIER);
    5761             :     set_hour(nan, SKIP_WRITE_BARRIER);
    5762             :     set_min(nan, SKIP_WRITE_BARRIER);
    5763             :     set_sec(nan, SKIP_WRITE_BARRIER);
    5764             :     set_weekday(nan, SKIP_WRITE_BARRIER);
    5765             :   } else {
    5766             :     set_cache_stamp(Smi::FromInt(DateCache::kInvalidStamp), SKIP_WRITE_BARRIER);
    5767             :   }
    5768      162051 : }
    5769             : 
    5770         567 : void JSDate::SetCachedFields(int64_t local_time_ms, DateCache* date_cache) {
    5771             :   int days = DateCache::DaysFromTime(local_time_ms);
    5772             :   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
    5773             :   int year, month, day;
    5774         567 :   date_cache->YearMonthDayFromDays(days, &year, &month, &day);
    5775             :   int weekday = date_cache->Weekday(days);
    5776         567 :   int hour = time_in_day_ms / (60 * 60 * 1000);
    5777         567 :   int min = (time_in_day_ms / (60 * 1000)) % 60;
    5778         567 :   int sec = (time_in_day_ms / 1000) % 60;
    5779         567 :   set_cache_stamp(date_cache->stamp());
    5780         567 :   set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
    5781         567 :   set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
    5782         567 :   set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
    5783             :   set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
    5784             :   set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
    5785             :   set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
    5786             :   set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
    5787         567 : }
    5788             : 
    5789        9197 : int JSMessageObject::GetLineNumber() const {
    5790        9197 :   if (start_position() == -1) return Message::kNoLineNumberInfo;
    5791             : 
    5792             :   Handle<Script> the_script(script(), GetIsolate());
    5793             : 
    5794             :   Script::PositionInfo info;
    5795             :   const Script::OffsetFlag offset_flag = Script::WITH_OFFSET;
    5796        9077 :   if (!Script::GetPositionInfo(the_script, start_position(), &info,
    5797             :                                offset_flag)) {
    5798             :     return Message::kNoLineNumberInfo;
    5799             :   }
    5800             : 
    5801        9077 :   return info.line + 1;
    5802             : }
    5803             : 
    5804       15321 : int JSMessageObject::GetColumnNumber() const {
    5805       15321 :   if (start_position() == -1) return -1;
    5806             : 
    5807             :   Handle<Script> the_script(script(), GetIsolate());
    5808             : 
    5809             :   Script::PositionInfo info;
    5810             :   const Script::OffsetFlag offset_flag = Script::WITH_OFFSET;
    5811       15146 :   if (!Script::GetPositionInfo(the_script, start_position(), &info,
    5812             :                                offset_flag)) {
    5813             :     return -1;
    5814             :   }
    5815             : 
    5816       15146 :   return info.column;  // Note: No '+1' in contrast to GetLineNumber.
    5817             : }
    5818             : 
    5819        6418 : Handle<String> JSMessageObject::GetSourceLine() const {
    5820             :   Isolate* isolate = GetIsolate();
    5821             :   Handle<Script> the_script(script(), isolate);
    5822             : 
    5823        6418 :   if (the_script->type() == Script::TYPE_WASM) {
    5824             :     return isolate->factory()->empty_string();
    5825             :   }
    5826             : 
    5827             :   Script::PositionInfo info;
    5828             :   const Script::OffsetFlag offset_flag = Script::WITH_OFFSET;
    5829        6418 :   if (!Script::GetPositionInfo(the_script, start_position(), &info,
    5830             :                                offset_flag)) {
    5831             :     return isolate->factory()->empty_string();
    5832             :   }
    5833             : 
    5834        6418 :   Handle<String> src = handle(String::cast(the_script->source()), isolate);
    5835        6418 :   return isolate->factory()->NewSubString(src, info.line_start, info.line_end);
    5836             : }
    5837             : 
    5838             : }  // namespace internal
    5839      121996 : }  // namespace v8

Generated by: LCOV version 1.10