Commit 92df7d10 authored by Mythri A's avatar Mythri A Committed by Commit Bot

Only flush feedback vector on bytecode flush

When bytecode is flushed we also want to flush the feedback vectors to
save memory. There was a bug in this code and we flushed
ClosureFeedbackCellArray too. Flushing ClosureFeedbackCellArrays causes
the closures created by this function before and after the bytecode
flush to have different feedback cells and hence different feedback
vectors. This cl fixes it so we only flush feedback vectors on a
bytecode flush.

Also this cl pretenures ClosureFeedbackCellArrays. Only FeedbackCells
and FeedbackVectors can contain ClosureFeedbackCellArrays which are
pretenured, so it is better to pretenure ClosureFeedbackCellArrays as
well.


Bug: chromium:1031479
Change-Id: I7831441a95420b9e5711f4143461f1eb7fa1616a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1980582
Commit-Queue: Mythri Alle <mythria@chromium.org>
Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarMichael Stanton <mvstanton@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65866}
parent 4f033b1e
...@@ -509,7 +509,7 @@ Handle<ClosureFeedbackCellArray> Factory::NewClosureFeedbackCellArray( ...@@ -509,7 +509,7 @@ Handle<ClosureFeedbackCellArray> Factory::NewClosureFeedbackCellArray(
Handle<ClosureFeedbackCellArray> feedback_cell_array = Handle<ClosureFeedbackCellArray> feedback_cell_array =
NewFixedArrayWithMap<ClosureFeedbackCellArray>( NewFixedArrayWithMap<ClosureFeedbackCellArray>(
RootIndex::kClosureFeedbackCellArrayMap, length, RootIndex::kClosureFeedbackCellArrayMap, length,
AllocationType::kYoung); AllocationType::kOld);
return feedback_cell_array; return feedback_cell_array;
} }
......
...@@ -2292,7 +2292,11 @@ void MarkCompactCollector::ClearFlushedJsFunctions() { ...@@ -2292,7 +2292,11 @@ void MarkCompactCollector::ClearFlushedJsFunctions() {
JSFunction flushed_js_function; JSFunction flushed_js_function;
while (weak_objects_.flushed_js_functions.Pop(kMainThreadTask, while (weak_objects_.flushed_js_functions.Pop(kMainThreadTask,
&flushed_js_function)) { &flushed_js_function)) {
flushed_js_function.ResetIfBytecodeFlushed(); auto gc_notify_updated_slot = [](HeapObject object, ObjectSlot slot,
Object target) {
RecordSlot(object, slot, HeapObject::cast(target));
};
flushed_js_function.ResetIfBytecodeFlushed(gc_notify_updated_slot);
} }
} }
......
...@@ -26,9 +26,21 @@ void FeedbackCell::clear_padding() { ...@@ -26,9 +26,21 @@ void FeedbackCell::clear_padding() {
FeedbackCell::kAlignedSize - FeedbackCell::kUnalignedSize); FeedbackCell::kAlignedSize - FeedbackCell::kUnalignedSize);
} }
void FeedbackCell::reset() { void FeedbackCell::reset_feedback_vector(
set_value(GetReadOnlyRoots().undefined_value()); base::Optional<std::function<void(HeapObject object, ObjectSlot slot,
HeapObject target)>>
gc_notify_updated_slot) {
set_interrupt_budget(FeedbackCell::GetInitialInterruptBudget()); set_interrupt_budget(FeedbackCell::GetInitialInterruptBudget());
if (value().IsUndefined() || value().IsClosureFeedbackCellArray()) return;
CHECK(value().IsFeedbackVector());
ClosureFeedbackCellArray closure_feedback_cell_array =
FeedbackVector::cast(value()).closure_feedback_cell_array();
set_value(closure_feedback_cell_array);
if (gc_notify_updated_slot) {
(*gc_notify_updated_slot)(*this, RawField(FeedbackCell::kValueOffset),
closure_feedback_cell_array);
}
} }
} // namespace internal } // namespace internal
......
...@@ -34,7 +34,10 @@ class FeedbackCell : public TorqueGeneratedFeedbackCell<FeedbackCell, Struct> { ...@@ -34,7 +34,10 @@ class FeedbackCell : public TorqueGeneratedFeedbackCell<FeedbackCell, Struct> {
static const int kAlignedSize = RoundUp<kObjectAlignment>(int{kSize}); static const int kAlignedSize = RoundUp<kObjectAlignment>(int{kSize});
inline void clear_padding(); inline void clear_padding();
inline void reset(); inline void reset_feedback_vector(
base::Optional<std::function<void(HeapObject object, ObjectSlot slot,
HeapObject target)>>
gc_notify_updated_slot = base::nullopt);
using BodyDescriptor = using BodyDescriptor =
FixedBodyDescriptor<kValueOffset, kInterruptBudgetOffset, kAlignedSize>; FixedBodyDescriptor<kValueOffset, kInterruptBudgetOffset, kAlignedSize>;
......
...@@ -705,12 +705,15 @@ bool JSFunction::NeedsResetDueToFlushedBytecode() { ...@@ -705,12 +705,15 @@ bool JSFunction::NeedsResetDueToFlushedBytecode() {
code.builtin_index() != Builtins::kCompileLazy; code.builtin_index() != Builtins::kCompileLazy;
} }
void JSFunction::ResetIfBytecodeFlushed() { void JSFunction::ResetIfBytecodeFlushed(
base::Optional<std::function<void(HeapObject object, ObjectSlot slot,
HeapObject target)>>
gc_notify_updated_slot) {
if (FLAG_flush_bytecode && NeedsResetDueToFlushedBytecode()) { if (FLAG_flush_bytecode && NeedsResetDueToFlushedBytecode()) {
// Bytecode was flushed and function is now uncompiled, reset JSFunction // Bytecode was flushed and function is now uncompiled, reset JSFunction
// by setting code to CompileLazy and clearing the feedback vector. // by setting code to CompileLazy and clearing the feedback vector.
set_code(GetIsolate()->builtins()->builtin(i::Builtins::kCompileLazy)); set_code(GetIsolate()->builtins()->builtin(i::Builtins::kCompileLazy));
raw_feedback_cell().reset(); raw_feedback_cell().reset_feedback_vector(gc_notify_updated_slot);
} }
} }
......
...@@ -1081,7 +1081,10 @@ class JSFunction : public JSFunctionOrBoundFunction { ...@@ -1081,7 +1081,10 @@ class JSFunction : public JSFunctionOrBoundFunction {
// Resets function to clear compiled data after bytecode has been flushed. // Resets function to clear compiled data after bytecode has been flushed.
inline bool NeedsResetDueToFlushedBytecode(); inline bool NeedsResetDueToFlushedBytecode();
inline void ResetIfBytecodeFlushed(); inline void ResetIfBytecodeFlushed(
base::Optional<std::function<void(HeapObject object, ObjectSlot slot,
HeapObject target)>>
gc_notify_updated_slot = base::nullopt);
DECL_GETTER(has_prototype_slot, bool) DECL_GETTER(has_prototype_slot, bool)
......
...@@ -188,18 +188,11 @@ static bool IsSuitableForOnStackReplacement(Isolate* isolate, ...@@ -188,18 +188,11 @@ static bool IsSuitableForOnStackReplacement(Isolate* isolate,
Handle<JSFunction> function) { Handle<JSFunction> function) {
// Keep track of whether we've succeeded in optimizing. // Keep track of whether we've succeeded in optimizing.
if (function->shared().optimization_disabled()) return false; if (function->shared().optimization_disabled()) return false;
// TODO(chromium:1031479): When we flush the bytecode we also reset the // TODO(chromium:1031479): Currently, OSR triggering mechanism is tied to the
// feedback_cell that holds feedback vector / closure feedback cell array. // bytecode array. So, it might be possible to mark closure in one native
// Closure feedback cell array holds the feedback cells that should be used // context and optimize a closure from a different native context. So check if
// when creating closures from the given function. If we happen to execute the // there is a feedback vector before OSRing. We don't expect this to happen
// function again, we re-compile and re-intialize this array. So, the closures // often.
// created by this function after the flush would have different feedback
// cells when compared to the corresponding closures created before the flush.
// Currently, OSR triggering mechanism is tied to the bytecode array. So, it
// is possible to mark one closure for OSR but optimize a different one.
// These two factors could cause us to OSR functions that don't have feedback
// vector. This is a temporary fix and we should fix one (or both) of the two
// causes.
if (!function->has_feedback_vector()) return false; if (!function->has_feedback_vector()) return false;
// If we are trying to do OSR when there are already optimized // If we are trying to do OSR when there are already optimized
// activations of the function, it means (a) the function is directly or // activations of the function, it means (a) the function is directly or
......
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