From 232d990545556dc27adeb40c442d751e3cb4bd97 Mon Sep 17 00:00:00 2001 From: "ulan@chromium.org" Date: Tue, 3 Apr 2012 17:22:05 +0000 Subject: [PATCH] Reset function info counters after context disposal in incremental marking step. R=mstarzinger@chromium.org BUG=117767,V8:1902 TEST=test/cctest/test-heap/ResetSharedFunctionInfoCountersDuringIncrementalMarking Review URL: https://chromiumcodereview.appspot.com/9903019 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11222 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/incremental-marking.cc | 6 ++++ src/objects.cc | 13 +++++-- src/objects.h | 4 +++ test/cctest/test-heap.cc | 87 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 107 insertions(+), 3 deletions(-) diff --git a/src/incremental-marking.cc b/src/incremental-marking.cc index f3255e2..7bbd521 100644 --- a/src/incremental-marking.cc +++ b/src/incremental-marking.cc @@ -205,6 +205,12 @@ class IncrementalMarkingMarkingVisitor : public ObjectVisitor { MarkObject(target); } + void VisitSharedFunctionInfo(SharedFunctionInfo* shared) { + if (shared->ic_age() != heap_->global_ic_age()) { + shared->ResetForNewContext(heap_->global_ic_age()); + } + } + void VisitPointer(Object** p) { Object* obj = *p; if (obj->NonFailureIsHeapObject()) { diff --git a/src/objects.cc b/src/objects.cc index d99338c..a4f63a1 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -1390,9 +1390,11 @@ void HeapObject::IterateBody(InstanceType type, int object_size, case EXTERNAL_FLOAT_ARRAY_TYPE: case EXTERNAL_DOUBLE_ARRAY_TYPE: break; - case SHARED_FUNCTION_INFO_TYPE: - SharedFunctionInfo::BodyDescriptor::IterateBody(this, v); + case SHARED_FUNCTION_INFO_TYPE: { + SharedFunctionInfo* shared = reinterpret_cast(this); + shared->SharedFunctionInfoIterateBody(v); break; + } #define MAKE_STRUCT_CASE(NAME, Name, name) \ case NAME##_TYPE: @@ -7926,6 +7928,12 @@ void SharedFunctionInfo::CompleteInobjectSlackTracking() { } +void SharedFunctionInfo::SharedFunctionInfoIterateBody(ObjectVisitor* v) { + v->VisitSharedFunctionInfo(this); + SharedFunctionInfo::BodyDescriptor::IterateBody(this, v); +} + + #define DECLARE_TAG(ignore1, name, ignore2) name, const char* const VisitorSynchronization::kTags[ VisitorSynchronization::kNumberOfSyncTags] = { @@ -7983,7 +7991,6 @@ void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) { CHECK_EQ(target, old_target); // VisitPointer doesn't change Code* *target. } - void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) { ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); VisitPointer(rinfo->target_object_address()); diff --git a/src/objects.h b/src/objects.h index ca6acf5..76d8351 100644 --- a/src/objects.h +++ b/src/objects.h @@ -5490,6 +5490,8 @@ class SharedFunctionInfo: public HeapObject { static bool CompileLazy(Handle shared, ClearExceptionFlag flag); + void SharedFunctionInfoIterateBody(ObjectVisitor* v); + // Casting. static inline SharedFunctionInfo* cast(Object* obj); @@ -8538,6 +8540,8 @@ class ObjectVisitor BASE_EMBEDDED { // Visit pointer embedded into a code object. virtual void VisitEmbeddedPointer(RelocInfo* rinfo); + virtual void VisitSharedFunctionInfo(SharedFunctionInfo* shared) {} + // Visits a contiguous arrays of external references (references to the C++ // heap) in the half-open range [start, end). Any or all of the values // may be modified on return. diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc index d6f08c3..f97bf17 100644 --- a/test/cctest/test-heap.cc +++ b/test/cctest/test-heap.cc @@ -1593,3 +1593,90 @@ TEST(PrototypeTransitionClearing) { HEAP->CollectAllGarbage(Heap::kNoGCFlags); CHECK(map->GetPrototypeTransition(*prototype)->IsMap()); } + + +TEST(ResetSharedFunctionInfoCountersDuringIncrementalMarking) { + i::FLAG_allow_natives_syntax = true; +#ifdef DEBUG + i::FLAG_verify_heap = true; +#endif + InitializeVM(); + if (!i::V8::UseCrankshaft()) return; + v8::HandleScope outer_scope; + + { + v8::HandleScope scope; + CompileRun( + "function f () {" + " var s = 0;" + " for (var i = 0; i < 100; i++) s += i;" + " return s;" + "}" + "f(); f();" + "%OptimizeFunctionOnNextCall(f);" + "f();"); + } + Handle f = + v8::Utils::OpenHandle( + *v8::Handle::Cast( + v8::Context::GetCurrent()->Global()->Get(v8_str("f")))); + CHECK(f->IsOptimized()); + + IncrementalMarking* marking = HEAP->incremental_marking(); + marking->Abort(); + marking->Start(); + + // The following two calls will increment HEAP->global_ic_age(). + const int kLongIdlePauseInMs = 1000; + v8::V8::ContextDisposedNotification(); + v8::V8::IdleNotification(kLongIdlePauseInMs); + + while (!marking->IsStopped() && !marking->IsComplete()) { + marking->Step(1 * MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD); + } + + CHECK_EQ(HEAP->global_ic_age(), f->shared()->ic_age()); + CHECK_EQ(0, f->shared()->opt_count()); + CHECK_EQ(0, f->shared()->code()->profiler_ticks()); +} + + +TEST(ResetSharedFunctionInfoCountersDuringMarkSweep) { + i::FLAG_allow_natives_syntax = true; +#ifdef DEBUG + i::FLAG_verify_heap = true; +#endif + InitializeVM(); + if (!i::V8::UseCrankshaft()) return; + v8::HandleScope outer_scope; + + { + v8::HandleScope scope; + CompileRun( + "function f () {" + " var s = 0;" + " for (var i = 0; i < 100; i++) s += i;" + " return s;" + "}" + "f(); f();" + "%OptimizeFunctionOnNextCall(f);" + "f();"); + } + Handle f = + v8::Utils::OpenHandle( + *v8::Handle::Cast( + v8::Context::GetCurrent()->Global()->Get(v8_str("f")))); + CHECK(f->IsOptimized()); + + HEAP->incremental_marking()->Abort(); + + // The following two calls will increment HEAP->global_ic_age(). + // Since incremental marking is off, IdleNotification will do full GC. + const int kLongIdlePauseInMs = 1000; + v8::V8::ContextDisposedNotification(); + v8::V8::IdleNotification(kLongIdlePauseInMs); + + CHECK_EQ(HEAP->global_ic_age(), f->shared()->ic_age()); + CHECK_EQ(0, f->shared()->opt_count()); + CHECK_EQ(0, f->shared()->code()->profiler_ticks()); +} -- 2.7.4