Commit 37c861a7 authored by Jaroslav Sevcik's avatar Jaroslav Sevcik Committed by Commit Bot

[turbofan] Fix receiver != holder case for constant loads.

Bug: chromium:945187
Change-Id: If6f36a4767ffda5f23873c79775116514dd0a2b6
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1539582
Commit-Queue: Jaroslav Sevcik <jarin@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60464}
parent 04088798
......@@ -197,51 +197,60 @@ Node* PropertyAccessBuilder::ResolveHolder(
Node* PropertyAccessBuilder::TryBuildLoadConstantDataField(
Handle<Name> name, PropertyAccessInfo const& access_info, Node* receiver) {
// Optimize immutable property loads.
HeapObjectMatcher m(receiver);
if (m.HasValue() && m.Value()->IsJSObject()) {
// Make sure the actual map of the receiver is among the maps in
// {access_info}.
// First, determine if we have a constant holder to load from.
Handle<JSObject> holder;
// If {access_info} has a holder, just use it.
if (!access_info.holder().ToHandle(&holder)) {
// Otherwise, try to match the {receiver} as a constant.
HeapObjectMatcher m(receiver);
if (!m.HasValue() || !m.Value()->IsJSObject()) return nullptr;
// Let us make sure the actual map of the constant receiver is among
// the maps in {access_info}.
Handle<Map> receiver_map = handle(m.Value()->map(), isolate());
if (std::find_if(access_info.receiver_maps().begin(),
access_info.receiver_maps().end(), [&](Handle<Map> map) {
return map.address() == receiver_map.address();
}) == access_info.receiver_maps().end()) {
// The map of the receiver is not in the feedback, let us bail out.
return nullptr;
}
// TODO(ishell): Use something simpler like
//
// Handle<Object> value =
// JSObject::FastPropertyAt(Handle<JSObject>::cast(m.Value()),
// Representation::Tagged(), field_index);
//
// here, once we have the immutable bit in the access_info.
holder = Handle<JSObject>::cast(m.Value());
}
// TODO(ishell): Use something simpler like
//
// Handle<Object> value =
// JSObject::FastPropertyAt(Handle<JSObject>::cast(m.Value()),
// Representation::Tagged(), field_index);
//
// here, once we have the immutable bit in the access_info.
// TODO(turbofan): Given that we already have the field_index here, we
// might be smarter in the future and not rely on the LookupIterator.
LookupIterator it(isolate(), m.Value(), name,
LookupIterator::OWN_SKIP_INTERCEPTOR);
if (it.state() == LookupIterator::DATA) {
bool is_readonly_non_configurable =
it.IsReadOnly() && !it.IsConfigurable();
if (is_readonly_non_configurable ||
(FLAG_track_constant_fields && access_info.IsDataConstantField())) {
Node* value = jsgraph()->Constant(JSReceiver::GetDataProperty(&it));
if (!is_readonly_non_configurable) {
// It's necessary to add dependency on the map that introduced
// the field.
DCHECK(access_info.IsDataConstantField());
DCHECK(!it.is_dictionary_holder());
MapRef map(broker(),
handle(it.GetHolder<HeapObject>()->map(), isolate()));
map.SerializeOwnDescriptors(); // TODO(neis): Remove later.
if (dependencies()->DependOnFieldConstness(
map, it.GetFieldDescriptorIndex()) !=
PropertyConstness::kConst) {
return nullptr;
}
// TODO(turbofan): Given that we already have the field_index here, we
// might be smarter in the future and not rely on the LookupIterator.
LookupIterator it(isolate(), holder, name,
LookupIterator::OWN_SKIP_INTERCEPTOR);
if (it.state() == LookupIterator::DATA) {
bool is_readonly_non_configurable = it.IsReadOnly() && !it.IsConfigurable();
if (is_readonly_non_configurable ||
(FLAG_track_constant_fields && access_info.IsDataConstantField())) {
Node* value = jsgraph()->Constant(JSReceiver::GetDataProperty(&it));
if (!is_readonly_non_configurable) {
// It's necessary to add dependency on the map that introduced
// the field.
DCHECK(access_info.IsDataConstantField());
DCHECK(!it.is_dictionary_holder());
MapRef map(broker(),
handle(it.GetHolder<HeapObject>()->map(), isolate()));
map.SerializeOwnDescriptors(); // TODO(neis): Remove later.
if (dependencies()->DependOnFieldConstness(
map, it.GetFieldDescriptorIndex()) !=
PropertyConstness::kConst) {
return nullptr;
}
return value;
}
return value;
}
}
return nullptr;
......@@ -251,7 +260,6 @@ Node* PropertyAccessBuilder::BuildLoadDataField(
Handle<Name> name, PropertyAccessInfo const& access_info, Node* receiver,
Node** effect, Node** control) {
DCHECK(access_info.IsDataField() || access_info.IsDataConstantField());
receiver = ResolveHolder(access_info, receiver);
if (Node* value =
TryBuildLoadConstantDataField(name, access_info, receiver)) {
return value;
......@@ -261,7 +269,7 @@ Node* PropertyAccessBuilder::BuildLoadDataField(
Type const field_type = access_info.field_type();
MachineRepresentation const field_representation =
access_info.field_representation();
Node* storage = receiver;
Node* storage = ResolveHolder(access_info, receiver);
if (!field_index.is_inobject()) {
storage = *effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForJSObjectPropertiesOrHash()),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment