[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:
parent
d0c5b343da
commit
0e9a480fa5
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
15
src/ic/ic.cc
15
src/ic/ic.cc
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user