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:
parent
148f1c1701
commit
0b6a617779
@ -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
|
||||
|
@ -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")
|
||||
|
||||
|
16
src/heap.cc
16
src/heap.cc
@ -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();
|
||||
}
|
||||
|
19
src/heap.h
19
src/heap.h
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user