Commit 5242700d authored by ulan's avatar ulan Committed by Commit bot

Revert "Remove IC age from Code."

This reverts commit 3cd889 for regressing Kraken benchmark

BUG=chromium:457174
LOG=N

Review URL: https://codereview.chromium.org/941503003

Cr-Commit-Position: refs/heads/master@{#26740}
parent 64a27175
......@@ -1457,6 +1457,7 @@ Handle<Code> Factory::NewCode(const CodeDesc& desc,
// fact that no allocation will happen from this point on.
DisallowHeapAllocation no_gc;
code->set_gc_metadata(Smi::FromInt(0));
code->set_ic_age(isolate()->heap()->global_ic_age());
code->set_instruction_size(desc.instr_size);
code->set_relocation_info(*reloc_info);
code->set_flags(flags);
......
......@@ -3691,6 +3691,7 @@ AllocationResult Heap::AllocateCode(int object_size, bool immovable) {
DCHECK(isolate_->code_range() == NULL || !isolate_->code_range()->valid() ||
isolate_->code_range()->contains(code->address()));
code->set_gc_metadata(Smi::FromInt(0));
code->set_ic_age(global_ic_age_);
return code;
}
......
......@@ -262,7 +262,8 @@ void StaticMarkingVisitor<StaticVisitor>::VisitCodeTarget(Heap* heap,
// when they might be keeping a Context alive, or when the heap is about
// to be serialized.
if (FLAG_cleanup_code_caches_at_gc && target->is_inline_cache_stub() &&
!target->is_call_stub() && heap->isolate()->serializer_enabled()) {
!target->is_call_stub() && (heap->isolate()->serializer_enabled() ||
target->ic_age() != heap->global_ic_age())) {
ICUtility::Clear(heap->isolate(), rinfo->pc(),
rinfo->host()->constant_pool());
target = Code::GetCodeFromTargetAddress(rinfo->target_address());
......
......@@ -6439,6 +6439,7 @@ void Code::set_stub_key(uint32_t key) {
ACCESSORS(Code, gc_metadata, Object, kGCMetadataOffset)
INT_ACCESSORS(Code, ic_age, kICAgeOffset)
byte* Code::instruction_start() {
......
......@@ -10657,6 +10657,10 @@ void JSFunction::StartInobjectSlackTracking() {
void SharedFunctionInfo::ResetForNewContext(int new_ic_age) {
code()->ClearInlineCaches();
// If we clear ICs, we need to clear the type feedback vector too, since
// CallICs are synced with a feedback vector slot.
ClearTypeFeedbackInfo();
set_ic_age(new_ic_age);
if (code()->kind() == Code::FUNCTION) {
code()->set_profiler_ticks(0);
......
......@@ -5057,6 +5057,11 @@ class Code: public HeapObject {
// it is only used by the garbage collector itself.
DECL_ACCESSORS(gc_metadata, Object)
// [ic_age]: Inline caching age: the value of the Heap::global_ic_age
// at the moment when this object was created.
inline void set_ic_age(int count);
inline int ic_age() const;
// [prologue_offset]: Offset of the function prologue, used for aging
// FUNCTIONs and OPTIMIZED_FUNCTIONs.
inline int prologue_offset() const;
......@@ -5412,15 +5417,17 @@ class Code: public HeapObject {
kDeoptimizationDataOffset + kPointerSize;
static const int kNextCodeLinkOffset = kTypeFeedbackInfoOffset + kPointerSize;
static const int kGCMetadataOffset = kNextCodeLinkOffset + kPointerSize;
static const int kConstantPoolOffset = kGCMetadataOffset + kPointerSize;
static const int kInstructionSizeOffset = kConstantPoolOffset + kPointerSize;
static const int kFlagsOffset = kInstructionSizeOffset + kIntSize;
static const int kInstructionSizeOffset = kGCMetadataOffset + kPointerSize;
static const int kICAgeOffset = kInstructionSizeOffset + kIntSize;
static const int kFlagsOffset = kICAgeOffset + kIntSize;
static const int kKindSpecificFlags1Offset = kFlagsOffset + kIntSize;
static const int kKindSpecificFlags2Offset =
kKindSpecificFlags1Offset + kIntSize;
// Note: We might be able to squeeze this into the flags above.
static const int kPrologueOffset = kKindSpecificFlags2Offset + kIntSize;
static const int kHeaderPaddingStart = kPrologueOffset + kIntSize;
static const int kConstantPoolOffset = kPrologueOffset + kIntSize;
static const int kHeaderPaddingStart = kConstantPoolOffset + kPointerSize;
// Add padding to align the instruction start following right after
// the Code object header.
......
......@@ -3393,6 +3393,15 @@ static void CheckVectorIC(Handle<JSFunction> f, int ic_slot_index,
}
static void CheckVectorICCleared(Handle<JSFunction> f, int ic_slot_index) {
Handle<TypeFeedbackVector> vector =
Handle<TypeFeedbackVector>(f->shared()->feedback_vector());
FeedbackVectorICSlot slot(ic_slot_index);
LoadICNexus nexus(vector, slot);
CHECK(IC::IsCleared(&nexus));
}
TEST(IncrementalMarkingPreservesMonomorphicIC) {
if (i::FLAG_always_opt) return;
CcTest::InitializeVM();
......@@ -3428,6 +3437,48 @@ TEST(IncrementalMarkingPreservesMonomorphicIC) {
}
TEST(IncrementalMarkingClearsMonomorphicIC) {
if (i::FLAG_always_opt) return;
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
v8::Local<v8::Value> obj1;
{
LocalContext env;
CompileRun("function fun() { this.x = 1; }; var obj = new fun();");
obj1 = env->Global()->Get(v8_str("obj"));
}
// Prepare function f that contains a monomorphic IC for object
// originating from a different native context.
CcTest::global()->Set(v8_str("obj1"), obj1);
CompileRun("function f(o) { return o.x; } f(obj1); f(obj1);");
Handle<JSFunction> f = v8::Utils::OpenHandle(
*v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f"))));
Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
if (FLAG_vector_ics) {
CheckVectorIC(f, 0, MONOMORPHIC);
CHECK(ic_before->ic_state() == DEFAULT);
} else {
CHECK(ic_before->ic_state() == MONOMORPHIC);
}
// Fire context dispose notification.
CcTest::isolate()->ContextDisposedNotification();
SimulateIncrementalMarking(CcTest::heap());
CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags);
Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
if (FLAG_vector_ics) {
CheckVectorICCleared(f, 0);
CHECK(ic_after->ic_state() == DEFAULT);
} else {
CHECK(IC::IsCleared(ic_after));
}
}
TEST(IncrementalMarkingPreservesPolymorphicIC) {
if (i::FLAG_always_opt) return;
CcTest::InitializeVM();
......@@ -3476,6 +3527,55 @@ TEST(IncrementalMarkingPreservesPolymorphicIC) {
}
TEST(IncrementalMarkingClearsPolymorphicIC) {
if (i::FLAG_always_opt) return;
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
v8::Local<v8::Value> obj1, obj2;
{
LocalContext env;
CompileRun("function fun() { this.x = 1; }; var obj = new fun();");
obj1 = env->Global()->Get(v8_str("obj"));
}
{
LocalContext env;
CompileRun("function fun() { this.x = 2; }; var obj = new fun();");
obj2 = env->Global()->Get(v8_str("obj"));
}
// Prepare function f that contains a polymorphic IC for objects
// originating from two different native contexts.
CcTest::global()->Set(v8_str("obj1"), obj1);
CcTest::global()->Set(v8_str("obj2"), obj2);
CompileRun("function f(o) { return o.x; } f(obj1); f(obj1); f(obj2);");
Handle<JSFunction> f = v8::Utils::OpenHandle(
*v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f"))));
Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
if (FLAG_vector_ics) {
CheckVectorIC(f, 0, POLYMORPHIC);
CHECK(ic_before->ic_state() == DEFAULT);
} else {
CHECK(ic_before->ic_state() == POLYMORPHIC);
}
// Fire context dispose notification.
CcTest::isolate()->ContextDisposedNotification();
SimulateIncrementalMarking(CcTest::heap());
CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags);
Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
if (FLAG_vector_ics) {
CheckVectorICCleared(f, 0);
CHECK(ic_before->ic_state() == DEFAULT);
} else {
CHECK(IC::IsCleared(ic_after));
}
}
class SourceResource : public v8::String::ExternalOneByteStringResource {
public:
explicit SourceResource(const char* data)
......
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