Commit 8ef5d8dd authored by Jakob Linke's avatar Jakob Linke Committed by V8 LUCI CQ

[maglev] Use PropertyAccessInfo to create deps for property loads

Missing deps were causing correctness issues due to missed deopts. In
this CL, we reuse PropertyAccessInfo creation to create appropriate
dependencies.

Bug: v8:7700
Change-Id: Ic6c20df01fa8a36f677aed80791fcea1ccc4b512
Fixed: v8:13289
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3904603Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Auto-Submit: Jakob Linke <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/main@{#83304}
parent 2b7d58d1
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "src/builtins/builtins-constructor.h" #include "src/builtins/builtins-constructor.h"
#include "src/codegen/interface-descriptors-inl.h" #include "src/codegen/interface-descriptors-inl.h"
#include "src/common/globals.h" #include "src/common/globals.h"
#include "src/compiler/access-info.h"
#include "src/compiler/compilation-dependencies.h" #include "src/compiler/compilation-dependencies.h"
#include "src/compiler/feedback-source.h" #include "src/compiler/feedback-source.h"
#include "src/compiler/heap-refs.h" #include "src/compiler/heap-refs.h"
...@@ -994,6 +995,7 @@ void MaglevGraphBuilder::BuildMapCheck(ValueNode* object, ...@@ -994,6 +995,7 @@ void MaglevGraphBuilder::BuildMapCheck(ValueNode* object,
bool MaglevGraphBuilder::TryBuildMonomorphicLoad(ValueNode* receiver, bool MaglevGraphBuilder::TryBuildMonomorphicLoad(ValueNode* receiver,
ValueNode* lookup_start_object, ValueNode* lookup_start_object,
const compiler::NameRef& name,
const compiler::MapRef& map, const compiler::MapRef& map,
MaybeObjectHandle handler) { MaybeObjectHandle handler) {
if (handler.is_null()) return false; if (handler.is_null()) return false;
...@@ -1013,7 +1015,8 @@ bool MaglevGraphBuilder::TryBuildMonomorphicLoad(ValueNode* receiver, ...@@ -1013,7 +1015,8 @@ bool MaglevGraphBuilder::TryBuildMonomorphicLoad(ValueNode* receiver,
return false; return false;
} else { } else {
return TryBuildMonomorphicLoadFromLoadHandler( return TryBuildMonomorphicLoadFromLoadHandler(
receiver, lookup_start_object, map, LoadHandler::cast(ho_handler)); receiver, lookup_start_object, name, map,
LoadHandler::cast(ho_handler));
} }
} }
...@@ -1060,7 +1063,8 @@ bool MaglevGraphBuilder::TryBuildMonomorphicLoadFromSmiHandler( ...@@ -1060,7 +1063,8 @@ bool MaglevGraphBuilder::TryBuildMonomorphicLoadFromSmiHandler(
bool MaglevGraphBuilder::TryBuildMonomorphicLoadFromLoadHandler( bool MaglevGraphBuilder::TryBuildMonomorphicLoadFromLoadHandler(
ValueNode* receiver, ValueNode* lookup_start_object, ValueNode* receiver, ValueNode* lookup_start_object,
const compiler::MapRef& map, LoadHandler handler) { const compiler::NameRef& name, const compiler::MapRef& map,
LoadHandler handler) {
Object maybe_smi_handler = handler.smi_handler(local_isolate_); Object maybe_smi_handler = handler.smi_handler(local_isolate_);
if (!maybe_smi_handler.IsSmi()) return false; if (!maybe_smi_handler.IsSmi()) return false;
...@@ -1101,27 +1105,18 @@ bool MaglevGraphBuilder::TryBuildMonomorphicLoadFromLoadHandler( ...@@ -1101,27 +1105,18 @@ bool MaglevGraphBuilder::TryBuildMonomorphicLoadFromLoadHandler(
BuildMapCheck(lookup_start_object, map); BuildMapCheck(lookup_start_object, map);
} }
Object validity_cell = handler.validity_cell(local_isolate_); // Create compilation dependencies as needed.
if (validity_cell.IsCell(local_isolate_)) { // TODO(v8:7700): We only use the PropertyAccessInfo in order to create the
compiler::MapRef receiver_map = map; // proper dependencies. We should consider either using more of the PAI
if (receiver_map.IsPrimitiveMap()) { // (instead of relying on handlers), or duplicate dependency creation logic
// Perform the implicit ToObject for primitives here. // here (which is a bit involved since it requires e.g. a prototype walk).
// Implemented according to ES6 section 7.3.2 GetV (V, P). {
// Note: Keep sync'd with AccessInfoFactory::ComputePropertyAccessInfo. compiler::PropertyAccessInfo info = broker()->GetPropertyAccessInfo(
base::Optional<compiler::JSFunctionRef> constructor = map, name, compiler::AccessMode::kLoad, broker()->dependencies());
broker()->target_native_context().GetConstructorFunction( if (!info.IsInvalid()) {
receiver_map); DCHECK(!info.HasDictionaryHolder());
receiver_map = constructor.value().initial_map(broker()->dependencies()); info.RecordDependencies(broker()->dependencies());
} }
compiler::MapRef proto_map = receiver_map.prototype().map();
while (proto_map.object()->prototype_validity_cell(
local_isolate_, kRelaxedLoad) == validity_cell) {
broker()->dependencies()->DependOnStableMap(proto_map);
proto_map = proto_map.prototype().map();
}
} else {
DCHECK_EQ(Smi::ToInt(validity_cell), Map::kPrototypeChainValid);
} }
switch (kind) { switch (kind) {
...@@ -1260,8 +1255,12 @@ void MaglevGraphBuilder::VisitGetNamedProperty() { ...@@ -1260,8 +1255,12 @@ void MaglevGraphBuilder::VisitGetNamedProperty() {
MaybeObjectHandle handler = MaybeObjectHandle handler =
FeedbackNexusForSlot(slot).FindHandlerForMap(map.object()); FeedbackNexusForSlot(slot).FindHandlerForMap(map.object());
if (TryBuildMonomorphicLoad(object, object, map, handler)) return; if (TryBuildMonomorphicLoad(object, object, name, map, handler)) {
} break; return;
}
break;
}
default: default:
break; break;
...@@ -1308,9 +1307,13 @@ void MaglevGraphBuilder::VisitGetNamedPropertyFromSuper() { ...@@ -1308,9 +1307,13 @@ void MaglevGraphBuilder::VisitGetNamedPropertyFromSuper() {
MaybeObjectHandle handler = MaybeObjectHandle handler =
FeedbackNexusForSlot(slot).FindHandlerForMap(map.object()); FeedbackNexusForSlot(slot).FindHandlerForMap(map.object());
if (TryBuildMonomorphicLoad(receiver, lookup_start_object, map, handler)) if (TryBuildMonomorphicLoad(receiver, lookup_start_object, name, map,
handler)) {
return; return;
} break; }
break;
}
default: default:
break; break;
...@@ -1559,7 +1562,9 @@ void MaglevGraphBuilder::VisitSetNamedProperty() { ...@@ -1559,7 +1562,9 @@ void MaglevGraphBuilder::VisitSetNamedProperty() {
FeedbackNexusForSlot(slot).FindHandlerForMap(map.object()); FeedbackNexusForSlot(slot).FindHandlerForMap(map.object());
if (TryBuildMonomorphicStore(object, map, handler)) return; if (TryBuildMonomorphicStore(object, map, handler)) return;
} break;
break;
}
default: default:
break; break;
...@@ -1601,7 +1606,9 @@ void MaglevGraphBuilder::VisitDefineNamedOwnProperty() { ...@@ -1601,7 +1606,9 @@ void MaglevGraphBuilder::VisitDefineNamedOwnProperty() {
FeedbackNexusForSlot(slot).FindHandlerForMap(map.object()); FeedbackNexusForSlot(slot).FindHandlerForMap(map.object());
if (TryBuildMonomorphicStore(object, map, handler)) return; if (TryBuildMonomorphicStore(object, map, handler)) return;
} break;
break;
}
default: default:
break; break;
......
...@@ -968,6 +968,7 @@ class MaglevGraphBuilder { ...@@ -968,6 +968,7 @@ class MaglevGraphBuilder {
bool TryBuildMonomorphicLoad(ValueNode* receiver, bool TryBuildMonomorphicLoad(ValueNode* receiver,
ValueNode* lookup_start_object, ValueNode* lookup_start_object,
const compiler::NameRef& name,
const compiler::MapRef& map, const compiler::MapRef& map,
MaybeObjectHandle handler); MaybeObjectHandle handler);
bool TryBuildMonomorphicLoadFromSmiHandler(ValueNode* receiver, bool TryBuildMonomorphicLoadFromSmiHandler(ValueNode* receiver,
...@@ -976,6 +977,7 @@ class MaglevGraphBuilder { ...@@ -976,6 +977,7 @@ class MaglevGraphBuilder {
int32_t handler); int32_t handler);
bool TryBuildMonomorphicLoadFromLoadHandler(ValueNode* receiver, bool TryBuildMonomorphicLoadFromLoadHandler(ValueNode* receiver,
ValueNode* lookup_start_object, ValueNode* lookup_start_object,
const compiler::NameRef& name,
const compiler::MapRef& map, const compiler::MapRef& map,
LoadHandler handler); LoadHandler handler);
......
// Copyright 2022 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Flags: --allow-natives-syntax
function Thingy() {}
Thingy.prototype = {
foo: function() { return 42; }
};
const x = new Thingy();
function f(o) {
return o.foo();
}
%PrepareFunctionForOptimization(f);
assertEquals(42, f(x));
%OptimizeMaglevOnNextCall(f);
assertEquals(42, f(x));
Thingy.prototype.foo = function() { return 56; }
assertEquals(56, f(x));
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