Age inline caches after context disposal.

Review URL: https://chromiumcodereview.appspot.com/9837005

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11122 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
ulan@chromium.org 2012-03-23 13:33:11 +00:00
parent 148f1c1701
commit 0b6a617779
10 changed files with 67 additions and 20 deletions

View File

@ -1436,6 +1436,11 @@ int Shell::RunMain(int argc, char* argv[]) {
}
if (!options.last_run) {
context.Dispose();
if (i::FLAG_send_idle_notification) {
const int kLongIdlePauseInMs = 1000;
V8::ContextDisposedNotification();
V8::IdleNotification(kLongIdlePauseInMs);
}
}
#ifndef V8_SHARED
@ -1490,6 +1495,7 @@ int Shell::Main(int argc, char* argv[]) {
int stress_runs = i::FLAG_stress_runs;
for (int i = 0; i < stress_runs && result == 0; i++) {
printf("============ Run %d/%d ============\n", i + 1, stress_runs);
options.last_run = (i == stress_runs - 1);
result = RunMain(argc, argv);
}
#endif

View File

@ -350,6 +350,9 @@ DEFINE_bool(trace_incremental_marking, false,
// v8.cc
DEFINE_bool(use_idle_notification, true,
"Use idle notification to reduce memory footprint.")
DEFINE_bool(send_idle_notification, false,
"Send idle notifcation between stress runs.")
// ic.cc
DEFINE_bool(use_ic, true, "use inline caching")

View File

@ -92,6 +92,7 @@ Heap::Heap()
always_allocate_scope_depth_(0),
linear_allocation_scope_depth_(0),
contexts_disposed_(0),
global_ic_age_(0),
scan_on_scavenge_pages_(0),
new_space_(this),
old_pointer_space_(NULL),
@ -3393,6 +3394,7 @@ MaybeObject* Heap::CreateCode(const CodeDesc& desc,
code->set_type_feedback_info(undefined_value(), SKIP_WRITE_BARRIER);
code->set_handler_table(empty_fixed_array(), SKIP_WRITE_BARRIER);
code->set_gc_metadata(Smi::FromInt(0));
code->set_ic_age(global_ic_age_);
// Allow self references to created code object by patching the handle to
// point to the newly allocated Code object.
if (!self_reference.is_null()) {
@ -4838,13 +4840,21 @@ void Heap::AdvanceIdleIncrementalMarking(intptr_t step_size) {
bool Heap::IdleNotification(int hint) {
intptr_t size_factor = Min(Max(hint, 30), 1000) / 10;
const int kMaxHint = 1000;
intptr_t size_factor = Min(Max(hint, 30), kMaxHint) / 10;
// The size factor is in range [3..100].
intptr_t step_size = size_factor * IncrementalMarking::kAllocatedThreshold;
if (contexts_disposed_ > 0) {
if (hint >= kMaxHint) {
// The embedder is requesting a lot of GC work after context disposal,
// we age inline caches so that they don't keep objects from
// the old context alive.
AgeInlineCaches();
}
int mark_sweep_time = Min(TimeMarkSweepWouldTakeInMs(), 1000);
if (hint >= mark_sweep_time && !FLAG_expose_gc) {
if (hint >= mark_sweep_time && !FLAG_expose_gc &&
incremental_marking()->IsStopped()) {
HistogramTimerScope scope(isolate_->counters()->gc_context());
CollectAllGarbage(kReduceMemoryFootprintMask,
"idle notification: contexts disposed");
@ -4859,7 +4869,7 @@ bool Heap::IdleNotification(int hint) {
return false;
}
if (hint >= 1000 || !FLAG_incremental_marking ||
if (hint >= kMaxHint || !FLAG_incremental_marking ||
FLAG_expose_gc || Serializer::enabled()) {
return IdleGlobalGC();
}

View File

@ -1480,6 +1480,13 @@ class Heap {
void ClearNormalizedMapCaches();
// Clears the cache of ICs related to this map.
void ClearCacheOnMap(Map* map) {
if (FLAG_cleanup_code_caches_at_gc) {
map->ClearCodeCache(this);
}
}
GCTracer* tracer() { return tracer_; }
// Returns the size of objects residing in non new spaces.
@ -1585,6 +1592,16 @@ class Heap {
// For post mortem debugging.
void RememberUnmappedPage(Address page, bool compacted);
// Global inline caching age: it is incremented on some GCs after context
// disposal. We use it to flush inline caches.
int global_ic_age() {
return global_ic_age_;
}
void AgeInlineCaches() {
++global_ic_age_;
}
private:
Heap();
@ -1612,6 +1629,8 @@ class Heap {
// For keeping track of context disposals.
int contexts_disposed_;
int global_ic_age_;
int scan_on_scavenge_pages_;
#if defined(V8_TARGET_ARCH_X64)

View File

@ -178,7 +178,12 @@ class IncrementalMarkingMarkingVisitor : public ObjectVisitor {
void VisitCodeTarget(RelocInfo* rinfo) {
ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
if (FLAG_cleanup_code_caches_at_gc && target->is_inline_cache_stub()
&& (target->ic_age() != heap_->global_ic_age())) {
IC::Clear(rinfo->pc());
target = Code::GetCodeFromTargetAddress(rinfo->target_address());
}
heap_->mark_compact_collector()->RecordRelocSlot(rinfo, Code::cast(target));
MarkObject(target);
}
@ -795,6 +800,12 @@ void IncrementalMarking::Step(intptr_t allocated_bytes) {
Map* map = obj->map();
if (map == filler_map) continue;
if (obj->IsMap()) {
Map* map = Map::cast(obj);
heap_->ClearCacheOnMap(map);
}
int size = obj->SizeFromMap(map);
bytes_to_process -= size;
MarkBit map_mark_bit = Marking::MarkBitFrom(map);

View File

@ -52,13 +52,6 @@ void MarkCompactCollector::SetFlags(int flags) {
}
void MarkCompactCollector::ClearCacheOnMap(Map* map) {
if (FLAG_cleanup_code_caches_at_gc) {
map->ClearCodeCache(heap());
}
}
void MarkCompactCollector::MarkObject(HeapObject* obj, MarkBit mark_bit) {
ASSERT(Marking::MarkBitFrom(obj) == mark_bit);
if (!mark_bit.Get()) {
@ -88,7 +81,7 @@ void MarkCompactCollector::SetMark(HeapObject* obj, MarkBit mark_bit) {
mark_bit.Set();
MemoryChunk::IncrementLiveBytesFromGC(obj->address(), obj->Size());
if (obj->IsMap()) {
ClearCacheOnMap(Map::cast(obj));
heap_->ClearCacheOnMap(Map::cast(obj));
}
}

View File

@ -1049,7 +1049,8 @@ class StaticMarkingVisitor : public StaticVisitorBase {
Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
if (FLAG_cleanup_code_caches_at_gc && target->is_inline_cache_stub()
&& (target->ic_state() == MEGAMORPHIC ||
heap->mark_compact_collector()->flush_monomorphic_ics_)) {
heap->mark_compact_collector()->flush_monomorphic_ics_ ||
target->ic_age() != heap->global_ic_age())) {
IC::Clear(rinfo->pc());
target = Code::GetCodeFromTargetAddress(rinfo->target_address());
}
@ -1797,7 +1798,7 @@ void MarkCompactCollector::ProcessNewlyMarkedObject(HeapObject* object) {
ASSERT(HEAP->Contains(object));
if (object->IsMap()) {
Map* map = Map::cast(object);
ClearCacheOnMap(map);
heap_->ClearCacheOnMap(map);
// When map collection is enabled we have to mark through map's transitions
// in a special way to make transition links weak.

View File

@ -638,9 +638,6 @@ class MarkCompactCollector {
// Marks the object black. This is for non-incremental marking.
INLINE(void SetMark(HeapObject* obj, MarkBit mark_bit));
// Clears the cache of ICs related to this map.
INLINE(void ClearCacheOnMap(Map* map));
void ProcessNewlyMarkedObject(HeapObject* obj);
// Creates back pointers for all map transitions, stores them in

View File

@ -4130,7 +4130,7 @@ ACCESSORS(Code, handler_table, FixedArray, kHandlerTableOffset)
ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset)
ACCESSORS(Code, type_feedback_info, Object, kTypeFeedbackInfoOffset)
ACCESSORS(Code, gc_metadata, Object, kGCMetadataOffset)
INT_ACCESSORS(Code, ic_age, kICAgeOffset)
byte* Code::instruction_start() {
return FIELD_ADDR(this, kHeaderSize);
@ -4713,6 +4713,7 @@ void Map::ClearCodeCache(Heap* heap) {
// No write barrier is needed since empty_fixed_array is not in new space.
// Please note this function is used during marking:
// - MarkCompactCollector::MarkUnmarkedObject
// - IncrementalMarking::Step
ASSERT(!heap->InNewSpace(heap->raw_unchecked_empty_fixed_array()));
WRITE_FIELD(this, kCodeCacheOffset, heap->raw_unchecked_empty_fixed_array());
}

View File

@ -4180,6 +4180,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();
// Unchecked accessors to be used during GC.
inline ByteArray* unchecked_relocation_info();
inline FixedArray* unchecked_deoptimization_data();
@ -4432,8 +4437,9 @@ class Code: public HeapObject {
static const int kTypeFeedbackInfoOffset =
kDeoptimizationDataOffset + kPointerSize;
static const int kGCMetadataOffset = kTypeFeedbackInfoOffset + kPointerSize;
static const int kFlagsOffset = kGCMetadataOffset + kPointerSize;
static const int kICAgeOffset =
kGCMetadataOffset + kPointerSize;
static const int kFlagsOffset = kICAgeOffset + kIntSize;
static const int kKindSpecificFlagsOffset = kFlagsOffset + kIntSize;
static const int kKindSpecificFlagsSize = 2 * kIntSize;