Commit d90e873e authored by Georg Neis's avatar Georg Neis Committed by V8 LUCI CQ

[compiler] Fix two FeedbackCellRef uses

1) Code in JSCallReducer read a FeedbackCell twice and expected the
   result to be the same.

2) JSInliningHeuristics, in the CheckClosure case, assumed that the
   FeedbackCell contains a FeedbackVector.

Bug: chromium:1248743, v8:7790
Change-Id: I66d6dd5f7a879c2479572e1896dd78aeedd2fa27
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3160200Reviewed-by: 's avatarMichael Stanton <mvstanton@chromium.org>
Commit-Queue: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/main@{#76815}
parent e28f0cc4
...@@ -4368,13 +4368,13 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) { ...@@ -4368,13 +4368,13 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) {
return ReduceJSCall(node, p.shared_info(broker())); return ReduceJSCall(node, p.shared_info(broker()));
} else if (target->opcode() == IrOpcode::kCheckClosure) { } else if (target->opcode() == IrOpcode::kCheckClosure) {
FeedbackCellRef cell = MakeRef(broker(), FeedbackCellOf(target->op())); FeedbackCellRef cell = MakeRef(broker(), FeedbackCellOf(target->op()));
if (cell.shared_function_info().has_value()) { base::Optional<SharedFunctionInfoRef> shared = cell.shared_function_info();
return ReduceJSCall(node, *cell.shared_function_info()); if (!shared.has_value()) {
} else {
TRACE_BROKER_MISSING(broker(), "Unable to reduce JSCall. FeedbackCell " TRACE_BROKER_MISSING(broker(), "Unable to reduce JSCall. FeedbackCell "
<< cell << " has no FeedbackVector"); << cell << " has no FeedbackVector");
return NoChange(); return NoChange();
} }
return ReduceJSCall(node, *shared);
} }
// If {target} is the result of a JSCreateBoundFunction operation, // If {target} is the result of a JSCreateBoundFunction operation,
......
...@@ -27,8 +27,16 @@ bool IsSmall(int const size) { ...@@ -27,8 +27,16 @@ bool IsSmall(int const size) {
} }
bool CanConsiderForInlining(JSHeapBroker* broker, bool CanConsiderForInlining(JSHeapBroker* broker,
SharedFunctionInfoRef const& shared,
FeedbackCellRef const& feedback_cell) { FeedbackCellRef const& feedback_cell) {
base::Optional<FeedbackVectorRef> feedback_vector =
feedback_cell.feedback_vector();
if (!feedback_vector.has_value()) {
TRACE("Cannot consider " << feedback_cell
<< " for inlining (no feedback vector)");
return false;
}
SharedFunctionInfoRef shared = feedback_vector->shared_function_info();
if (!shared.HasBytecodeArray()) { if (!shared.HasBytecodeArray()) {
TRACE("Cannot consider " << shared << " for inlining (no bytecode)"); TRACE("Cannot consider " << shared << " for inlining (no bytecode)");
return false; return false;
...@@ -37,14 +45,21 @@ bool CanConsiderForInlining(JSHeapBroker* broker, ...@@ -37,14 +45,21 @@ bool CanConsiderForInlining(JSHeapBroker* broker,
// flushing it during the remaining compilation. // flushing it during the remaining compilation.
shared.GetBytecodeArray(); shared.GetBytecodeArray();
base::Optional<FeedbackVectorRef> feedback_vector = // Read feedback vector again in case it got flushed before we were able to
// prevent flushing above.
base::Optional<FeedbackVectorRef> feedback_vector_again =
feedback_cell.feedback_vector(); feedback_cell.feedback_vector();
if (!feedback_vector.has_value()) { if (!feedback_vector_again.has_value()) {
TRACE("Cannot consider " << shared << " for inlining (no feedback vector)"); TRACE("Cannot consider " << shared << " for inlining (no feedback vector)");
return false; return false;
} }
// Note that due to prevented bytecode flushing, this {feedback_cell} won't if (!feedback_vector_again->equals(*feedback_vector)) {
// change its value anymore during compilation. // The new feedback vector likely contains lots of uninitialized slots, so
// it doesn't make much sense to inline this function now.
TRACE("Not considering " << shared
<< " for inlining (feedback vector changed)");
return false;
}
SharedFunctionInfo::Inlineability inlineability = shared.GetInlineability(); SharedFunctionInfo::Inlineability inlineability = shared.GetInlineability();
if (inlineability != SharedFunctionInfo::kIsInlineable) { if (inlineability != SharedFunctionInfo::kIsInlineable) {
...@@ -59,9 +74,14 @@ bool CanConsiderForInlining(JSHeapBroker* broker, ...@@ -59,9 +74,14 @@ bool CanConsiderForInlining(JSHeapBroker* broker,
bool CanConsiderForInlining(JSHeapBroker* broker, bool CanConsiderForInlining(JSHeapBroker* broker,
JSFunctionRef const& function) { JSFunctionRef const& function) {
return CanConsiderForInlining( FeedbackCellRef feedback_cell =
broker, function.shared(), function.raw_feedback_cell(broker->dependencies());
function.raw_feedback_cell(broker->dependencies())); bool const result = CanConsiderForInlining(broker, feedback_cell);
if (result) {
CHECK(
function.shared().equals(feedback_cell.shared_function_info().value()));
}
return result;
} }
} // namespace } // namespace
...@@ -75,8 +95,8 @@ JSInliningHeuristic::Candidate JSInliningHeuristic::CollectFunctions( ...@@ -75,8 +95,8 @@ JSInliningHeuristic::Candidate JSInliningHeuristic::CollectFunctions(
HeapObjectMatcher m(callee); HeapObjectMatcher m(callee);
if (m.HasResolvedValue() && m.Ref(broker()).IsJSFunction()) { if (m.HasResolvedValue() && m.Ref(broker()).IsJSFunction()) {
out.functions[0] = m.Ref(broker()).AsJSFunction(); JSFunctionRef function = m.Ref(broker()).AsJSFunction();
JSFunctionRef function = out.functions[0].value(); out.functions[0] = function;
if (CanConsiderForInlining(broker(), function)) { if (CanConsiderForInlining(broker(), function)) {
out.bytecode[0] = function.shared().GetBytecodeArray(); out.bytecode[0] = function.shared().GetBytecodeArray();
out.num_functions = 1; out.num_functions = 1;
...@@ -108,11 +128,9 @@ JSInliningHeuristic::Candidate JSInliningHeuristic::CollectFunctions( ...@@ -108,11 +128,9 @@ JSInliningHeuristic::Candidate JSInliningHeuristic::CollectFunctions(
if (m.IsCheckClosure()) { if (m.IsCheckClosure()) {
DCHECK(!out.functions[0].has_value()); DCHECK(!out.functions[0].has_value());
FeedbackCellRef feedback_cell = MakeRef(broker(), FeedbackCellOf(m.op())); FeedbackCellRef feedback_cell = MakeRef(broker(), FeedbackCellOf(m.op()));
SharedFunctionInfoRef shared_info = if (CanConsiderForInlining(broker(), feedback_cell)) {
feedback_cell.shared_function_info().value(); out.shared_info = feedback_cell.shared_function_info().value();
out.shared_info = shared_info; out.bytecode[0] = out.shared_info->GetBytecodeArray();
if (CanConsiderForInlining(broker(), shared_info, feedback_cell)) {
out.bytecode[0] = shared_info.GetBytecodeArray();
} }
out.num_functions = 1; out.num_functions = 1;
return out; return out;
...@@ -120,12 +138,11 @@ JSInliningHeuristic::Candidate JSInliningHeuristic::CollectFunctions( ...@@ -120,12 +138,11 @@ JSInliningHeuristic::Candidate JSInliningHeuristic::CollectFunctions(
if (m.IsJSCreateClosure()) { if (m.IsJSCreateClosure()) {
DCHECK(!out.functions[0].has_value()); DCHECK(!out.functions[0].has_value());
JSCreateClosureNode n(callee); JSCreateClosureNode n(callee);
CreateClosureParameters const& p = n.Parameters();
FeedbackCellRef feedback_cell = n.GetFeedbackCellRefChecked(broker()); FeedbackCellRef feedback_cell = n.GetFeedbackCellRefChecked(broker());
SharedFunctionInfoRef shared_info = p.shared_info(broker()); if (CanConsiderForInlining(broker(), feedback_cell)) {
out.shared_info = shared_info; out.shared_info = feedback_cell.shared_function_info().value();
if (CanConsiderForInlining(broker(), shared_info, feedback_cell)) { out.bytecode[0] = out.shared_info->GetBytecodeArray();
out.bytecode[0] = shared_info.GetBytecodeArray(); CHECK(out.shared_info->equals(n.Parameters().shared_info(broker())));
} }
out.num_functions = 1; out.num_functions = 1;
return out; return out;
......
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