[ic] Clarify lookup start object vs holder more

This CL also allows reusing slow case for API callbacks.

Bug: chromium:1201781
Change-Id: Ib5f81c510404060c888ba30c82357d6ed1a95cf5
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2882809
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Marja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/master@{#74470}
This commit is contained in:
Igor Sheludko 2021-05-10 14:07:41 +02:00 committed by V8 LUCI CQ
parent d0c5b343da
commit 0e9a480fa5
4 changed files with 45 additions and 45 deletions

View File

@ -696,8 +696,9 @@ void AccessorAssembler::HandleLoadICSmiHandlerLoadNamedCase(
p->name(), p->slot(), p->vector()); p->name(), p->slot(), p->vector());
} else { } else {
exit_point->ReturnCallRuntime(Runtime::kGetProperty, p->context(), holder, exit_point->ReturnCallRuntime(Runtime::kGetProperty, p->context(),
p->name(), p->receiver()); p->lookup_start_object(), p->name(),
p->receiver());
} }
} }

View File

@ -774,23 +774,20 @@ void IC::SetCache(Handle<Name> name, const MaybeObjectHandle& handler) {
} }
void LoadIC::UpdateCaches(LookupIterator* lookup) { void LoadIC::UpdateCaches(LookupIterator* lookup) {
Handle<Object> code; Handle<Object> handler;
if (lookup->state() == LookupIterator::ACCESS_CHECK) { if (lookup->state() == LookupIterator::ACCESS_CHECK) {
code = LoadHandler::LoadSlow(isolate()); handler = LoadHandler::LoadSlow(isolate());
} else if (!lookup->IsFound()) { } else if (!lookup->IsFound()) {
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNonexistentDH); TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNonexistentDH);
Handle<Smi> smi_handler = LoadHandler::LoadNonExistent(isolate()); Handle<Smi> smi_handler = LoadHandler::LoadNonExistent(isolate());
code = LoadHandler::LoadFullChain( handler = LoadHandler::LoadFullChain(
isolate(), lookup_start_object_map(), isolate(), lookup_start_object_map(),
MaybeObjectHandle(isolate()->factory()->null_value()), smi_handler); MaybeObjectHandle(isolate()->factory()->null_value()), smi_handler);
} else if (IsLoadGlobalIC() && lookup->state() == LookupIterator::JSPROXY) { } else if (IsLoadGlobalIC() && lookup->state() == LookupIterator::JSPROXY) {
// If there is proxy just install the slow stub since we need to call the // If there is proxy just install the slow stub since we need to call the
// HasProperty trap for global loads. The ProxyGetProperty builtin doesn't // HasProperty trap for global loads. The ProxyGetProperty builtin doesn't
// handle this case. // handle this case.
Handle<Smi> slow_handler = LoadHandler::LoadSlow(isolate()); handler = LoadHandler::LoadSlow(isolate());
Handle<JSProxy> holder = lookup->GetHolder<JSProxy>();
code = LoadHandler::LoadFromPrototype(isolate(), lookup_start_object_map(),
holder, slow_handler);
} else { } else {
if (IsLoadGlobalIC()) { if (IsLoadGlobalIC()) {
if (lookup->TryLookupCachedProperty()) { if (lookup->TryLookupCachedProperty()) {
@ -805,12 +802,12 @@ void LoadIC::UpdateCaches(LookupIterator* lookup) {
return; return;
} }
} }
code = ComputeHandler(lookup); handler = ComputeHandler(lookup);
} }
// Can't use {lookup->name()} because the LookupIterator might be in // Can't use {lookup->name()} because the LookupIterator might be in
// "elements" mode for keys that are strings representing integers above // "elements" mode for keys that are strings representing integers above
// JSArray::kMaxIndex. // JSArray::kMaxIndex.
SetCache(lookup->GetName(), code); SetCache(lookup->GetName(), handler);
TraceIC("LoadIC", lookup->GetName()); TraceIC("LoadIC", lookup->GetName());
} }

View File

@ -27,23 +27,22 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate, MaybeHandle<Object> Runtime::GetObjectProperty(
Handle<Object> holder, Isolate* isolate, Handle<Object> lookup_start_object, Handle<Object> key,
Handle<Object> key, Handle<Object> receiver, bool* is_found) {
Handle<Object> receiver,
bool* is_found) {
if (receiver.is_null()) { if (receiver.is_null()) {
receiver = holder; receiver = lookup_start_object;
} }
if (holder->IsNullOrUndefined(isolate)) { if (lookup_start_object->IsNullOrUndefined(isolate)) {
ErrorUtils::ThrowLoadFromNullOrUndefined(isolate, holder, key); ErrorUtils::ThrowLoadFromNullOrUndefined(isolate, lookup_start_object, key);
return MaybeHandle<Object>(); return MaybeHandle<Object>();
} }
bool success = false; bool success = false;
LookupIterator::Key lookup_key(isolate, key, &success); LookupIterator::Key lookup_key(isolate, key, &success);
if (!success) return MaybeHandle<Object>(); if (!success) return MaybeHandle<Object>();
LookupIterator it = LookupIterator(isolate, receiver, lookup_key, holder); LookupIterator it =
LookupIterator(isolate, receiver, lookup_key, lookup_start_object);
MaybeHandle<Object> result = Object::GetProperty(&it); MaybeHandle<Object> result = Object::GetProperty(&it);
if (is_found) *is_found = it.IsFound(); if (is_found) *is_found = it.IsFound();
@ -60,12 +59,12 @@ MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate,
: name_string; : name_string;
THROW_NEW_ERROR(isolate, THROW_NEW_ERROR(isolate,
NewTypeError(MessageTemplate::kInvalidPrivateBrand, NewTypeError(MessageTemplate::kInvalidPrivateBrand,
class_name, holder), class_name, lookup_start_object),
Object); Object);
} }
THROW_NEW_ERROR(isolate, THROW_NEW_ERROR(isolate,
NewTypeError(MessageTemplate::kInvalidPrivateMemberRead, NewTypeError(MessageTemplate::kInvalidPrivateMemberRead,
name_string, holder), name_string, lookup_start_object),
Object); Object);
} }
return result; return result;
@ -707,15 +706,15 @@ RUNTIME_FUNCTION(Runtime_JSReceiverSetPrototypeOfDontThrow) {
RUNTIME_FUNCTION(Runtime_GetProperty) { RUNTIME_FUNCTION(Runtime_GetProperty) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK(args.length() == 3 || args.length() == 2); DCHECK(args.length() == 3 || args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(Object, holder_obj, 0); CONVERT_ARG_HANDLE_CHECKED(Object, lookup_start_obj, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1); CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1);
Handle<Object> receiver_obj = holder_obj; Handle<Object> receiver_obj = lookup_start_obj;
if (args.length() == 3) { if (args.length() == 3) {
CHECK(args[2].IsObject()); CHECK(args[2].IsObject());
receiver_obj = args.at<Object>(2); receiver_obj = args.at<Object>(2);
} }
// Fast cases for getting named properties of the holder JSObject // Fast cases for getting named properties of the lookup_start_obj JSObject
// itself. // itself.
// //
// The global proxy objects has to be excluded since LookupOwn on // The global proxy objects has to be excluded since LookupOwn on
@ -733,18 +732,19 @@ RUNTIME_FUNCTION(Runtime_GetProperty) {
if (key_obj->IsString() && String::cast(*key_obj).AsArrayIndex(&index)) { if (key_obj->IsString() && String::cast(*key_obj).AsArrayIndex(&index)) {
key_obj = isolate->factory()->NewNumberFromUint(index); key_obj = isolate->factory()->NewNumberFromUint(index);
} }
if (holder_obj->IsJSObject()) { if (lookup_start_obj->IsJSObject()) {
if (!holder_obj->IsJSGlobalProxy() && !holder_obj->IsAccessCheckNeeded() && Handle<JSObject> lookup_start_object =
key_obj->IsName()) { Handle<JSObject>::cast(lookup_start_obj);
Handle<JSObject> holder = Handle<JSObject>::cast(holder_obj); if (!lookup_start_object->IsJSGlobalProxy() &&
!lookup_start_object->IsAccessCheckNeeded() && key_obj->IsName()) {
Handle<Name> key = Handle<Name>::cast(key_obj); Handle<Name> key = Handle<Name>::cast(key_obj);
key_obj = key = isolate->factory()->InternalizeName(key); key_obj = key = isolate->factory()->InternalizeName(key);
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
if (holder->IsJSGlobalObject()) { if (lookup_start_object->IsJSGlobalObject()) {
// Attempt dictionary lookup. // Attempt dictionary lookup.
GlobalDictionary dictionary = GlobalDictionary dictionary = JSGlobalObject::cast(*lookup_start_object)
JSGlobalObject::cast(*holder).global_dictionary(kAcquireLoad); .global_dictionary(kAcquireLoad);
InternalIndex entry = dictionary.FindEntry(isolate, key); InternalIndex entry = dictionary.FindEntry(isolate, key);
if (entry.is_found()) { if (entry.is_found()) {
PropertyCell cell = dictionary.CellAt(entry); PropertyCell cell = dictionary.CellAt(entry);
@ -754,17 +754,19 @@ RUNTIME_FUNCTION(Runtime_GetProperty) {
// If value is the hole (meaning, absent) do the general lookup. // If value is the hole (meaning, absent) do the general lookup.
} }
} }
} else if (!holder->HasFastProperties()) { } else if (!lookup_start_object->HasFastProperties()) {
// Attempt dictionary lookup. // Attempt dictionary lookup.
if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) {
SwissNameDictionary dictionary = holder->property_dictionary_swiss(); SwissNameDictionary dictionary =
lookup_start_object->property_dictionary_swiss();
InternalIndex entry = dictionary.FindEntry(isolate, *key); InternalIndex entry = dictionary.FindEntry(isolate, *key);
if (entry.is_found() && if (entry.is_found() &&
(dictionary.DetailsAt(entry).kind() == kData)) { (dictionary.DetailsAt(entry).kind() == kData)) {
return dictionary.ValueAt(entry); return dictionary.ValueAt(entry);
} }
} else { } else {
NameDictionary dictionary = holder->property_dictionary(); NameDictionary dictionary =
lookup_start_object->property_dictionary();
InternalIndex entry = dictionary.FindEntry(isolate, key); InternalIndex entry = dictionary.FindEntry(isolate, key);
if ((entry.is_found()) && if ((entry.is_found()) &&
(dictionary.DetailsAt(entry).kind() == kData)) { (dictionary.DetailsAt(entry).kind() == kData)) {
@ -779,22 +781,21 @@ RUNTIME_FUNCTION(Runtime_GetProperty) {
// transition elements to FAST_*_ELEMENTS to avoid excessive boxing of // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
// doubles for those future calls in the case that the elements would // doubles for those future calls in the case that the elements would
// become PACKED_DOUBLE_ELEMENTS. // become PACKED_DOUBLE_ELEMENTS.
Handle<JSObject> js_object = Handle<JSObject>::cast(holder_obj); ElementsKind elements_kind = lookup_start_object->GetElementsKind();
ElementsKind elements_kind = js_object->GetElementsKind();
if (IsDoubleElementsKind(elements_kind)) { if (IsDoubleElementsKind(elements_kind)) {
if (Smi::ToInt(*key_obj) >= js_object->elements().length()) { if (Smi::ToInt(*key_obj) >= lookup_start_object->elements().length()) {
elements_kind = IsHoleyElementsKind(elements_kind) ? HOLEY_ELEMENTS elements_kind = IsHoleyElementsKind(elements_kind) ? HOLEY_ELEMENTS
: PACKED_ELEMENTS; : PACKED_ELEMENTS;
JSObject::TransitionElementsKind(js_object, elements_kind); JSObject::TransitionElementsKind(lookup_start_object, elements_kind);
} }
} else { } else {
DCHECK(IsSmiOrObjectElementsKind(elements_kind) || DCHECK(IsSmiOrObjectElementsKind(elements_kind) ||
!IsFastElementsKind(elements_kind)); !IsFastElementsKind(elements_kind));
} }
} }
} else if (holder_obj->IsString() && key_obj->IsSmi()) { } else if (lookup_start_obj->IsString() && key_obj->IsSmi()) {
// Fast case for string indexing using [] with a smi index. // Fast case for string indexing using [] with a smi index.
Handle<String> str = Handle<String>::cast(holder_obj); Handle<String> str = Handle<String>::cast(lookup_start_obj);
int index = Handle<Smi>::cast(key_obj)->value(); int index = Handle<Smi>::cast(key_obj)->value();
if (index >= 0 && index < str->length()) { if (index >= 0 && index < str->length()) {
Factory* factory = isolate->factory(); Factory* factory = isolate->factory();
@ -805,8 +806,8 @@ RUNTIME_FUNCTION(Runtime_GetProperty) {
// Fall back to GetObjectProperty. // Fall back to GetObjectProperty.
RETURN_RESULT_OR_FAILURE( RETURN_RESULT_OR_FAILURE(
isolate, isolate, Runtime::GetObjectProperty(isolate, lookup_start_obj, key_obj,
Runtime::GetObjectProperty(isolate, holder_obj, key_obj, receiver_obj)); receiver_obj));
} }
RUNTIME_FUNCTION(Runtime_SetKeyedProperty) { RUNTIME_FUNCTION(Runtime_SetKeyedProperty) {

View File

@ -788,9 +788,10 @@ class Runtime : public AllStatic {
Handle<Object> value, StoreOrigin store_origin, Handle<Object> value, StoreOrigin store_origin,
Maybe<ShouldThrow> should_throw = Nothing<ShouldThrow>()); Maybe<ShouldThrow> should_throw = Nothing<ShouldThrow>());
// When "receiver" is not passed, it defaults to "holder". // When "receiver" is not passed, it defaults to "lookup_start_object".
V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static MaybeHandle<Object> V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static MaybeHandle<Object>
GetObjectProperty(Isolate* isolate, Handle<Object> holder, Handle<Object> key, GetObjectProperty(Isolate* isolate, Handle<Object> lookup_start_object,
Handle<Object> key,
Handle<Object> receiver = Handle<Object>(), Handle<Object> receiver = Handle<Object>(),
bool* is_found = nullptr); bool* is_found = nullptr);