[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: Georg Neis <neis@chromium.org> Cr-Commit-Position: refs/heads/master@{#60464}
This commit is contained in:
parent
040887988a
commit
37c861a7d6
@ -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(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(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(), 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()),
|
||||
|
Loading…
Reference in New Issue
Block a user