[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:
Leszek Swirski 2017-07-31 16:01:44 +01:00 committed by Commit Bot
parent 2d79d2c3a7
commit b34d2ec6a8
10 changed files with 24 additions and 30 deletions

View File

@ -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) {

View File

@ -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;

View File

@ -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();

View File

@ -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)

View File

@ -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;

View File

@ -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) {

View File

@ -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;

View File

@ -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, _)

View File

@ -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) {

View File

@ -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());
}