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}
This commit is contained in:
parent
64a2717529
commit
5242700da4
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user