[objects] Move deopt_count to FeedbackVector
Since any deopt-count-based heuristics should be native context dependent, it belongs in the feedback vector rather than the SFI. Bug: v8:6402 Change-Id: I30804d58bc1dec9150558e6ee21ee5b4dbd36c8d Reviewed-on: https://chromium-review.googlesource.com/593661 Commit-Queue: Leszek Swirski <leszeks@chromium.org> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Cr-Commit-Position: refs/heads/master@{#47014}
This commit is contained in:
parent
2d79d2c3a7
commit
b34d2ec6a8
@ -243,13 +243,12 @@ void Deoptimizer::DeoptimizeMarkedCodeForContext(Context* context) {
|
||||
if (!code->marked_for_deoptimization()) return;
|
||||
|
||||
// Unlink this function.
|
||||
SharedFunctionInfo* shared = function->shared();
|
||||
if (!code->deopt_already_counted()) {
|
||||
shared->increment_deopt_count();
|
||||
function->feedback_vector()->increment_deopt_count();
|
||||
code->set_deopt_already_counted(true);
|
||||
}
|
||||
|
||||
function->set_code(shared->code());
|
||||
function->set_code(function->shared()->code());
|
||||
|
||||
if (FLAG_trace_deopt) {
|
||||
CodeTracer::Scope scope(code->GetHeap()->isolate()->GetCodeTracer());
|
||||
@ -535,7 +534,7 @@ Deoptimizer::Deoptimizer(Isolate* isolate, JSFunction* function,
|
||||
// that can eventually lead to disabling optimization for a function.
|
||||
isolate->counters()->soft_deopts_executed()->Increment();
|
||||
} else if (function != nullptr) {
|
||||
function->shared()->increment_deopt_count();
|
||||
function->feedback_vector()->increment_deopt_count();
|
||||
}
|
||||
}
|
||||
if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) {
|
||||
|
@ -100,6 +100,7 @@ ACCESSORS(FeedbackVector, optimized_code_cell, Object, kOptimizedCodeOffset)
|
||||
INT32_ACCESSORS(FeedbackVector, length, kLengthOffset)
|
||||
INT32_ACCESSORS(FeedbackVector, invocation_count, kInvocationCountOffset)
|
||||
INT32_ACCESSORS(FeedbackVector, profiler_ticks, kProfilerTicksOffset)
|
||||
INT32_ACCESSORS(FeedbackVector, deopt_count, kDeoptCountOffset)
|
||||
|
||||
bool FeedbackVector::is_empty() const { return length() == 0; }
|
||||
|
||||
@ -109,6 +110,13 @@ FeedbackMetadata* FeedbackVector::metadata() const {
|
||||
|
||||
void FeedbackVector::clear_invocation_count() { set_invocation_count(0); }
|
||||
|
||||
void FeedbackVector::increment_deopt_count() {
|
||||
int count = deopt_count();
|
||||
if (count < std::numeric_limits<int32_t>::max()) {
|
||||
set_deopt_count(count + 1);
|
||||
}
|
||||
}
|
||||
|
||||
Code* FeedbackVector::optimized_code() const {
|
||||
Object* slot = optimized_code_cell();
|
||||
if (slot->IsSmi()) return nullptr;
|
||||
|
@ -206,6 +206,7 @@ Handle<FeedbackVector> FeedbackVector::New(Isolate* isolate,
|
||||
Smi::FromEnum(OptimizationMarker::kNone));
|
||||
DCHECK_EQ(vector->invocation_count(), 0);
|
||||
DCHECK_EQ(vector->profiler_ticks(), 0);
|
||||
DCHECK_EQ(vector->deopt_count(), 0);
|
||||
|
||||
// Ensure we can skip the write barrier
|
||||
Handle<Object> uninitialized_sentinel = UninitializedSentinel(isolate);
|
||||
@ -334,7 +335,7 @@ void FeedbackVector::EvictOptimizedCodeMarkedForDeoptimization(
|
||||
PrintF("]\n");
|
||||
}
|
||||
if (!code->deopt_already_counted()) {
|
||||
shared->increment_deopt_count();
|
||||
increment_deopt_count();
|
||||
code->set_deopt_already_counted(true);
|
||||
}
|
||||
ClearOptimizedCode();
|
||||
|
@ -148,7 +148,11 @@ class FeedbackVector : public HeapObject {
|
||||
// runtime profiler.
|
||||
DECL_INT32_ACCESSORS(profiler_ticks)
|
||||
|
||||
// [deopt_count]: The number of times this function has deoptimized.
|
||||
DECL_INT32_ACCESSORS(deopt_count)
|
||||
|
||||
inline void clear_invocation_count();
|
||||
inline void increment_deopt_count();
|
||||
|
||||
inline Code* optimized_code() const;
|
||||
inline OptimizationMarker optimization_marker() const;
|
||||
@ -243,6 +247,7 @@ class FeedbackVector : public HeapObject {
|
||||
V(kLengthOffset, kInt32Size) \
|
||||
V(kInvocationCountOffset, kInt32Size) \
|
||||
V(kProfilerTicksOffset, kInt32Size) \
|
||||
V(kDeoptCountOffset, kInt32Size) \
|
||||
V(kUnalignedHeaderSize, 0)
|
||||
|
||||
DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, FEEDBACK_VECTOR_FIELDS)
|
||||
|
@ -4228,9 +4228,10 @@ AllocationResult Heap::CopyFeedbackVector(FeedbackVector* src) {
|
||||
|
||||
// Slow case: Just copy the content one-by-one.
|
||||
result->set_shared_function_info(src->shared_function_info());
|
||||
result->set_optimized_code_cell(src->optimized_code_cell());
|
||||
result->set_invocation_count(src->invocation_count());
|
||||
result->set_profiler_ticks(src->profiler_ticks());
|
||||
result->set_optimized_code_cell(src->optimized_code_cell());
|
||||
result->set_deopt_count(src->deopt_count());
|
||||
for (int i = 0; i < len; i++) result->set(i, src->get(i), mode);
|
||||
return result;
|
||||
}
|
||||
@ -4373,6 +4374,7 @@ AllocationResult Heap::AllocateFeedbackVector(SharedFunctionInfo* shared,
|
||||
vector->set_length(length);
|
||||
vector->set_invocation_count(0);
|
||||
vector->set_profiler_ticks(0);
|
||||
vector->set_deopt_count(0);
|
||||
// TODO(leszeks): Initialize based on the feedback metadata.
|
||||
MemsetPointer(vector->slots_start(), undefined_value(), length);
|
||||
return vector;
|
||||
|
@ -13852,7 +13852,6 @@ void Map::StartInobjectSlackTracking() {
|
||||
|
||||
void SharedFunctionInfo::ResetForNewContext(int new_ic_age) {
|
||||
set_ic_age(new_ic_age);
|
||||
set_deopt_count(0);
|
||||
}
|
||||
|
||||
void ObjectVisitor::VisitCodeTarget(Code* host, RelocInfo* rinfo) {
|
||||
|
@ -358,23 +358,10 @@ void SharedFunctionInfo::set_inferred_name(String* inferred_name) {
|
||||
BIT_FIELD_ACCESSORS(SharedFunctionInfo, counters_and_bailout_reason, ic_age,
|
||||
SharedFunctionInfo::ICAgeBits)
|
||||
|
||||
BIT_FIELD_ACCESSORS(SharedFunctionInfo, counters_and_bailout_reason,
|
||||
deopt_count, SharedFunctionInfo::DeoptCountBits)
|
||||
|
||||
BIT_FIELD_ACCESSORS(SharedFunctionInfo, counters_and_bailout_reason,
|
||||
disable_optimization_reason,
|
||||
SharedFunctionInfo::DisabledOptimizationReasonBits)
|
||||
|
||||
void SharedFunctionInfo::increment_deopt_count() {
|
||||
int value = counters_and_bailout_reason();
|
||||
int deopt_count = DeoptCountBits::decode(value);
|
||||
// Saturate the deopt count when incrementing, rather than overflowing.
|
||||
if (deopt_count < DeoptCountBits::kMax) {
|
||||
set_counters_and_bailout_reason(
|
||||
DeoptCountBits::update(value, deopt_count + 1));
|
||||
}
|
||||
}
|
||||
|
||||
bool SharedFunctionInfo::IsUserJavaScript() {
|
||||
Object* script_obj = script();
|
||||
if (script_obj->IsUndefined(GetIsolate())) return false;
|
||||
|
@ -337,10 +337,6 @@ class SharedFunctionInfo : public HeapObject {
|
||||
Handle<Object> GetSourceCode();
|
||||
Handle<Object> GetSourceCodeHarmony();
|
||||
|
||||
// Number of times the function was deoptimized.
|
||||
DECL_INT_ACCESSORS(deopt_count)
|
||||
inline void increment_deopt_count();
|
||||
|
||||
// Stores deopt_count, ic_age and bailout_reason as bit-fields.
|
||||
DECL_INT_ACCESSORS(counters_and_bailout_reason)
|
||||
|
||||
@ -515,7 +511,6 @@ class SharedFunctionInfo : public HeapObject {
|
||||
|
||||
// Bit fields in |counters_and_bailout_reason|.
|
||||
#define COUNTERS_AND_BAILOUT_REASON_BIT_FIELDS(V, _) \
|
||||
V(DeoptCountBits, int, 4, _) \
|
||||
V(ICAgeBits, int, 8, _) \
|
||||
V(DisabledOptimizationReasonBits, BailoutReason, 8, _)
|
||||
|
||||
|
@ -417,7 +417,9 @@ RUNTIME_FUNCTION(Runtime_GetDeoptCount) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(1, args.length());
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
|
||||
return Smi::FromInt(function->shared()->deopt_count());
|
||||
// Functions without a feedback vector have never deoptimized.
|
||||
if (!function->has_feedback_vector()) return Smi::kZero;
|
||||
return Smi::FromInt(function->feedback_vector()->deopt_count());
|
||||
}
|
||||
|
||||
static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
|
@ -2265,8 +2265,6 @@ TEST(ResetSharedFunctionInfoCountersDuringIncrementalMarking) {
|
||||
CcTest::CollectAllGarbage();
|
||||
|
||||
CHECK_EQ(CcTest::heap()->global_ic_age(), f->shared()->ic_age());
|
||||
CHECK_EQ(0, f->shared()->deopt_count());
|
||||
CHECK_EQ(0, f->feedback_vector()->profiler_ticks());
|
||||
}
|
||||
|
||||
|
||||
@ -2308,8 +2306,6 @@ TEST(ResetSharedFunctionInfoCountersDuringMarkSweep) {
|
||||
CcTest::CollectAllGarbage();
|
||||
|
||||
CHECK_EQ(CcTest::heap()->global_ic_age(), f->shared()->ic_age());
|
||||
CHECK_EQ(0, f->shared()->deopt_count());
|
||||
CHECK_EQ(0, f->feedback_vector()->profiler_ticks());
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user