Commit cb8105e2 authored by jochen@chromium.org's avatar jochen@chromium.org

Move gc notifications from V8 to Isolate and make idle hint mandatory

Embedders should use e.g. isolate->IdleNotification(1000) instead
of v8::V8::IdleNotification()

BUG=397026
R=hpayer@chromium.org, ernstm@chromium.org
LOG=y

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22584 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 464d45fc
......@@ -4459,6 +4459,34 @@ class V8_EXPORT Isolate {
void SetCreateHistogramFunction(CreateHistogramCallback);
void SetAddHistogramSampleFunction(AddHistogramSampleCallback);
/**
* Optional notification that the embedder is idle.
* V8 uses the notification to reduce memory footprint.
* This call can be used repeatedly if the embedder remains idle.
* Returns true if the embedder should stop calling IdleNotification
* until real work has been done. This indicates that V8 has done
* as much cleanup as it will be able to do.
*
* The idle_time_in_ms argument specifies the time V8 has to do reduce
* the memory footprint. There is no guarantee that the actual work will be
* done within the time limit.
*/
bool IdleNotification(int idle_time_in_ms);
/**
* Optional notification that the system is running low on memory.
* V8 uses these notifications to attempt to free memory.
*/
void LowMemoryNotification();
/**
* Optional notification that a context has been disposed. V8 uses
* these notifications to guide the GC heuristic. Returns the number
* of context disposals - including this one - since the last time
* V8 had a chance to clean up.
*/
int ContextDisposedNotification();
private:
template<class K, class V, class Traits> friend class PersistentValueMap;
......@@ -4969,12 +4997,16 @@ class V8_EXPORT V8 {
* The hint argument specifies the amount of work to be done in the function
* on scale from 1 to 1000. There is no guarantee that the actual work will
* match the hint.
*
* Deprecated, please use Isolate::IdleNotification.
*/
static bool IdleNotification(int hint = 1000);
/**
* Optional notification that the system is running low on memory.
* V8 uses these notifications to attempt to free memory.
*
* Deprecated, please use Isolate::LowMemoryNotification.
*/
static void LowMemoryNotification();
......@@ -4983,6 +5015,8 @@ class V8_EXPORT V8 {
* these notifications to guide the GC heuristic. Returns the number
* of context disposals - including this one - since the last time
* V8 had a chance to clean up.
*
* Deprecated, please use Isolate::ContextDisposedNotification.
*/
static int ContextDisposedNotification();
......
......@@ -6712,6 +6712,27 @@ void Isolate::SetAddHistogramSampleFunction(
}
bool v8::Isolate::IdleNotification(int idle_time_in_ms) {
// Returning true tells the caller that it need not
// continue to call IdleNotification.
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
if (!i::FLAG_use_idle_notification) return true;
return isolate->heap()->IdleNotification(idle_time_in_ms);
}
void v8::Isolate::LowMemoryNotification() {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
isolate->heap()->CollectAllAvailableGarbage("low memory notification");
}
int v8::Isolate::ContextDisposedNotification() {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
return isolate->heap()->NotifyContextDisposed();
}
String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj)
: str_(NULL), length_(0) {
i::Isolate* isolate = i::Isolate::Current();
......
......@@ -1251,14 +1251,14 @@ void SourceGroup::ExecuteInThread() {
}
if (Shell::options.send_idle_notification) {
const int kLongIdlePauseInMs = 1000;
V8::ContextDisposedNotification();
V8::IdleNotification(kLongIdlePauseInMs);
isolate->ContextDisposedNotification();
isolate->IdleNotification(kLongIdlePauseInMs);
}
if (Shell::options.invoke_weak_callbacks) {
// By sending a low memory notifications, we will try hard to collect
// all garbage and will therefore also invoke all weak callbacks of
// actually unreachable persistent handles.
V8::LowMemoryNotification();
isolate->LowMemoryNotification();
}
}
done_semaphore_.Signal();
......@@ -1440,14 +1440,14 @@ int Shell::RunMain(Isolate* isolate, int argc, char* argv[]) {
}
if (options.send_idle_notification) {
const int kLongIdlePauseInMs = 1000;
V8::ContextDisposedNotification();
V8::IdleNotification(kLongIdlePauseInMs);
isolate->ContextDisposedNotification();
isolate->IdleNotification(kLongIdlePauseInMs);
}
if (options.invoke_weak_callbacks) {
// By sending a low memory notifications, we will try hard to collect all
// garbage and will therefore also invoke all weak callbacks of actually
// unreachable persistent handles.
V8::LowMemoryNotification();
isolate->LowMemoryNotification();
}
#ifndef V8_SHARED
......
......@@ -13498,21 +13498,21 @@ TEST(DontLeakGlobalObjects) {
{ v8::HandleScope scope(CcTest::isolate());
LocalContext context;
}
v8::V8::ContextDisposedNotification();
CcTest::isolate()->ContextDisposedNotification();
CheckSurvivingGlobalObjectsCount(0);
{ v8::HandleScope scope(CcTest::isolate());
LocalContext context;
v8_compile("Date")->Run();
}
v8::V8::ContextDisposedNotification();
CcTest::isolate()->ContextDisposedNotification();
CheckSurvivingGlobalObjectsCount(0);
{ v8::HandleScope scope(CcTest::isolate());
LocalContext context;
v8_compile("/aaa/")->Run();
}
v8::V8::ContextDisposedNotification();
CcTest::isolate()->ContextDisposedNotification();
CheckSurvivingGlobalObjectsCount(0);
{ v8::HandleScope scope(CcTest::isolate());
......@@ -13521,7 +13521,7 @@ TEST(DontLeakGlobalObjects) {
LocalContext context(&extensions);
v8_compile("gc();")->Run();
}
v8::V8::ContextDisposedNotification();
CcTest::isolate()->ContextDisposedNotification();
CheckSurvivingGlobalObjectsCount(0);
}
}
......@@ -17600,6 +17600,7 @@ static void CreateGarbageInOldSpace() {
// Test that idle notification can be handled and eventually returns true.
TEST(IdleNotification) {
const intptr_t MB = 1024 * 1024;
const int IdlePauseInMs = 1000;
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
intptr_t initial_size = CcTest::heap()->SizeOfObjects();
......@@ -17608,7 +17609,7 @@ TEST(IdleNotification) {
CHECK_GT(size_with_garbage, initial_size + MB);
bool finished = false;
for (int i = 0; i < 200 && !finished; i++) {
finished = v8::V8::IdleNotification();
finished = env->GetIsolate()->IdleNotification(IdlePauseInMs);
}
intptr_t final_size = CcTest::heap()->SizeOfObjects();
CHECK(finished);
......@@ -17628,7 +17629,7 @@ TEST(IdleNotificationWithSmallHint) {
CHECK_GT(size_with_garbage, initial_size + MB);
bool finished = false;
for (int i = 0; i < 200 && !finished; i++) {
finished = v8::V8::IdleNotification(IdlePauseInMs);
finished = env->GetIsolate()->IdleNotification(IdlePauseInMs);
}
intptr_t final_size = CcTest::heap()->SizeOfObjects();
CHECK(finished);
......@@ -17648,7 +17649,7 @@ TEST(IdleNotificationWithLargeHint) {
CHECK_GT(size_with_garbage, initial_size + MB);
bool finished = false;
for (int i = 0; i < 200 && !finished; i++) {
finished = v8::V8::IdleNotification(IdlePauseInMs);
finished = env->GetIsolate()->IdleNotification(IdlePauseInMs);
}
intptr_t final_size = CcTest::heap()->SizeOfObjects();
CHECK(finished);
......@@ -17665,7 +17666,7 @@ TEST(Regress2107) {
v8::HandleScope scope(env->GetIsolate());
intptr_t initial_size = CcTest::heap()->SizeOfObjects();
// Send idle notification to start a round of incremental GCs.
v8::V8::IdleNotification(kShortIdlePauseInMs);
env->GetIsolate()->IdleNotification(kShortIdlePauseInMs);
// Emulate 7 page reloads.
for (int i = 0; i < 7; i++) {
{
......@@ -17675,8 +17676,8 @@ TEST(Regress2107) {
CreateGarbageInOldSpace();
ctx->Exit();
}
v8::V8::ContextDisposedNotification();
v8::V8::IdleNotification(kLongIdlePauseInMs);
env->GetIsolate()->ContextDisposedNotification();
env->GetIsolate()->IdleNotification(kLongIdlePauseInMs);
}
// Create garbage and check that idle notification still collects it.
CreateGarbageInOldSpace();
......@@ -17684,7 +17685,7 @@ TEST(Regress2107) {
CHECK_GT(size_with_garbage, initial_size + MB);
bool finished = false;
for (int i = 0; i < 200 && !finished; i++) {
finished = v8::V8::IdleNotification(kShortIdlePauseInMs);
finished = env->GetIsolate()->IdleNotification(kShortIdlePauseInMs);
}
intptr_t final_size = CcTest::heap()->SizeOfObjects();
CHECK_LT(final_size, initial_size + 1);
......@@ -18160,7 +18161,7 @@ TEST(Regress528) {
CompileRun(source_simple);
context->Exit();
}
v8::V8::ContextDisposedNotification();
isolate->ContextDisposedNotification();
for (gc_count = 1; gc_count < 10; gc_count++) {
other_context->Enter();
CompileRun(source_simple);
......@@ -18182,7 +18183,7 @@ TEST(Regress528) {
CompileRun(source_eval);
context->Exit();
}
v8::V8::ContextDisposedNotification();
isolate->ContextDisposedNotification();
for (gc_count = 1; gc_count < 10; gc_count++) {
other_context->Enter();
CompileRun(source_eval);
......@@ -18209,7 +18210,7 @@ TEST(Regress528) {
CHECK_EQ(1, message->GetLineNumber());
context->Exit();
}
v8::V8::ContextDisposedNotification();
isolate->ContextDisposedNotification();
for (gc_count = 1; gc_count < 10; gc_count++) {
other_context->Enter();
CompileRun(source_exception);
......@@ -18220,7 +18221,7 @@ TEST(Regress528) {
CHECK_GE(2, gc_count);
CHECK_EQ(1, GetGlobalObjectsCount());
v8::V8::ContextDisposedNotification();
isolate->ContextDisposedNotification();
}
......
......@@ -1797,7 +1797,7 @@ TEST(LeakNativeContextViaMap) {
ctx2->Exit();
v8::Local<v8::Context>::New(isolate, ctx1)->Exit();
ctx1p.Reset();
v8::V8::ContextDisposedNotification();
isolate->ContextDisposedNotification();
}
CcTest::heap()->CollectAllAvailableGarbage();
CHECK_EQ(2, NumberOfGlobalObjects());
......@@ -1843,7 +1843,7 @@ TEST(LeakNativeContextViaFunction) {
ctx2->Exit();
ctx1->Exit();
ctx1p.Reset();
v8::V8::ContextDisposedNotification();
isolate->ContextDisposedNotification();
}
CcTest::heap()->CollectAllAvailableGarbage();
CHECK_EQ(2, NumberOfGlobalObjects());
......@@ -1887,7 +1887,7 @@ TEST(LeakNativeContextViaMapKeyed) {
ctx2->Exit();
ctx1->Exit();
ctx1p.Reset();
v8::V8::ContextDisposedNotification();
isolate->ContextDisposedNotification();
}
CcTest::heap()->CollectAllAvailableGarbage();
CHECK_EQ(2, NumberOfGlobalObjects());
......@@ -1935,7 +1935,7 @@ TEST(LeakNativeContextViaMapProto) {
ctx2->Exit();
ctx1->Exit();
ctx1p.Reset();
v8::V8::ContextDisposedNotification();
isolate->ContextDisposedNotification();
}
CcTest::heap()->CollectAllAvailableGarbage();
CHECK_EQ(2, NumberOfGlobalObjects());
......@@ -2096,8 +2096,8 @@ TEST(ResetSharedFunctionInfoCountersDuringIncrementalMarking) {
// The following two calls will increment CcTest::heap()->global_ic_age().
const int kLongIdlePauseInMs = 1000;
v8::V8::ContextDisposedNotification();
v8::V8::IdleNotification(kLongIdlePauseInMs);
CcTest::isolate()->ContextDisposedNotification();
CcTest::isolate()->IdleNotification(kLongIdlePauseInMs);
while (!marking->IsStopped() && !marking->IsComplete()) {
marking->Step(1 * MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD);
......@@ -2152,8 +2152,8 @@ TEST(ResetSharedFunctionInfoCountersDuringMarkSweep) {
// The following two calls will increment CcTest::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);
CcTest::isolate()->ContextDisposedNotification();
CcTest::isolate()->IdleNotification(kLongIdlePauseInMs);
CHECK_EQ(CcTest::heap()->global_ic_age(), f->shared()->ic_age());
CHECK_EQ(0, f->shared()->opt_count());
......@@ -3207,7 +3207,7 @@ TEST(IncrementalMarkingClearsMonomorphicIC) {
CHECK(ic_before->ic_state() == MONOMORPHIC);
// Fire context dispose notification.
v8::V8::ContextDisposedNotification();
CcTest::isolate()->ContextDisposedNotification();
SimulateIncrementalMarking();
CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags);
......@@ -3248,7 +3248,7 @@ TEST(IncrementalMarkingClearsPolymorphicIC) {
CHECK(ic_before->ic_state() == POLYMORPHIC);
// Fire context dispose notification.
v8::V8::ContextDisposedNotification();
CcTest::isolate()->ContextDisposedNotification();
SimulateIncrementalMarking();
CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags);
......
......@@ -658,7 +658,7 @@ TEST(DontLeakContextOnObserve) {
"Object.unobserve(obj, observer);");
}
v8::V8::ContextDisposedNotification();
CcTest::isolate()->ContextDisposedNotification();
CheckSurvivingGlobalObjectsCount(1);
}
......@@ -679,7 +679,7 @@ TEST(DontLeakContextOnGetNotifier) {
CompileRun("Object.getNotifier(obj);");
}
v8::V8::ContextDisposedNotification();
CcTest::isolate()->ContextDisposedNotification();
CheckSurvivingGlobalObjectsCount(1);
}
......@@ -706,6 +706,6 @@ TEST(DontLeakContextOnNotifierPerformChange) {
"notifier, 'foo', function(){})");
}
v8::V8::ContextDisposedNotification();
CcTest::isolate()->ContextDisposedNotification();
CheckSurvivingGlobalObjectsCount(1);
}
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