Update the Idle collector to do a full GC

after being idle for some time.

Remove the default argument from CollectAllGarbage.

Review URL: http://codereview.chromium.org/174302

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2748 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
mike@belshe.com 2009-08-25 02:54:39 +00:00
parent 050d1297fa
commit 6f3c50460a
11 changed files with 59 additions and 22 deletions

View File

@ -2280,9 +2280,13 @@ class V8EXPORT V8 {
/**
* 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.
* \param is_high_priority tells whether the embedder is high priority.
* 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.
*/
static void IdleNotification(bool is_high_priority);
static bool IdleNotification(bool is_high_priority);
/**
* Optional notification that the system is running low on memory.

View File

@ -2604,8 +2604,8 @@ bool v8::V8::Dispose() {
}
void v8::V8::IdleNotification(bool is_high_priority) {
i::V8::IdleNotification(is_high_priority);
bool v8::V8::IdleNotification(bool is_high_priority) {
return i::V8::IdleNotification(is_high_priority);
}
@ -3335,7 +3335,7 @@ void V8::ResumeProfilerEx(int flags) {
flags &= ~(PROFILER_MODULE_HEAP_SNAPSHOT | PROFILER_MODULE_CPU);
const int current_flags = i::Logger::GetActiveProfilerModules();
i::Logger::ResumeProfiler(flags);
i::Heap::CollectAllGarbage();
i::Heap::CollectAllGarbage(false);
i::Logger::PauseProfiler(~current_flags & flags);
} else {
i::Logger::ResumeProfiler(flags);

View File

@ -1548,8 +1548,8 @@ void Debug::CreateScriptCache() {
// Perform two GCs to get rid of all unreferenced scripts. The first GC gets
// rid of all the cached script wrappers and the second gets rid of the
// scripts which is no longer referenced.
Heap::CollectAllGarbage();
Heap::CollectAllGarbage();
Heap::CollectAllGarbage(false);
Heap::CollectAllGarbage(false);
ASSERT(script_cache_ == NULL);
script_cache_ = new ScriptCache();
@ -1599,7 +1599,7 @@ Handle<FixedArray> Debug::GetLoadedScripts() {
// Perform GC to get unreferenced scripts evicted from the cache before
// returning the content.
Heap::CollectAllGarbage();
Heap::CollectAllGarbage(false);
// Get the scripts from the cache.
return script_cache_->GetScripts();

View File

@ -677,7 +677,7 @@ v8::Handle<v8::FunctionTemplate> GCExtension::GetNativeFunction(
v8::Handle<v8::Value> GCExtension::GC(const v8::Arguments& args) {
// All allocation spaces other than NEW_SPACE have the same effect.
Heap::CollectAllGarbage();
Heap::CollectAllGarbage(false);
return v8::Undefined();
}

View File

@ -238,7 +238,7 @@ int Heap::AdjustAmountOfExternalAllocatedMemory(int change_in_bytes) {
amount_of_external_allocated_memory_ -
amount_of_external_allocated_memory_at_last_global_gc_;
if (amount_since_last_global_gc > external_allocation_limit_) {
CollectAllGarbage();
CollectAllGarbage(false);
}
} else {
// Avoid underflow.
@ -285,7 +285,7 @@ void Heap::SetLastScriptId(Object* last_script_id) {
} \
if (!__object__->IsRetryAfterGC()) RETURN_EMPTY; \
Counters::gc_last_resort_from_handles.Increment(); \
Heap::CollectAllGarbage(); \
Heap::CollectAllGarbage(false); \
{ \
AlwaysAllocateScope __scope__; \
__object__ = FUNCTION_CALL; \

View File

@ -332,7 +332,7 @@ void Heap::CollectAllGarbageIfContextDisposed() {
// informed decisions about when to force a collection.
if (!FLAG_expose_gc && context_disposed_pending_) {
HistogramTimerScope scope(&Counters::gc_context);
CollectAllGarbage();
CollectAllGarbage(false);
}
context_disposed_pending_ = false;
}

View File

@ -629,7 +629,7 @@ class Heap : public AllStatic {
// Performs a full garbage collection. Force compaction if the
// parameter is true.
static void CollectAllGarbage(bool force_compaction = false);
static void CollectAllGarbage(bool force_compaction);
// Performs a full garbage collection if a context has been disposed
// since the last time the check was performed.
@ -842,6 +842,39 @@ class Heap : public AllStatic {
> old_gen_allocation_limit_;
}
// Can be called when the embedding application is idle.
static bool IdleNotification() {
static const int kIdlesBeforeCollection = 7;
static int number_idle_notifications = 0;
static int last_gc_count = gc_count_;
bool finished = false;
if (last_gc_count == gc_count_) {
number_idle_notifications++;
} else {
number_idle_notifications = 0;
last_gc_count = gc_count_;
}
if (number_idle_notifications >= kIdlesBeforeCollection) {
// The first time through we collect without forcing compaction.
// The second time through we force compaction and quit.
bool force_compaction =
number_idle_notifications > kIdlesBeforeCollection;
CollectAllGarbage(force_compaction);
last_gc_count = gc_count_;
if (force_compaction) {
number_idle_notifications = 0;
finished = true;
}
}
// Uncommit unused memory in new space.
Heap::UncommitFromSpace();
return finished;
}
// Declare all the root indices.
enum RootListIndex {
#define ROOT_INDEX_DECLARATION(type, name, camel_name) k##camel_name##RootIndex,

View File

@ -171,7 +171,7 @@ int main(int argc, char** argv) {
}
}
// Get rid of unreferenced scripts with a global GC.
i::Heap::CollectAllGarbage();
i::Heap::CollectAllGarbage(false);
i::Serializer ser;
ser.Serialize();
v8::internal::byte* bytes;

View File

@ -7263,7 +7263,7 @@ static Object* Runtime_DebugReferencedBy(Arguments args) {
ASSERT(args.length() == 3);
// First perform a full GC in order to avoid references from dead objects.
Heap::CollectAllGarbage();
Heap::CollectAllGarbage(false);
// Check parameters.
CONVERT_CHECKED(JSObject, target, args[0]);
@ -7339,7 +7339,7 @@ static Object* Runtime_DebugConstructedBy(Arguments args) {
ASSERT(args.length() == 2);
// First perform a full GC in order to avoid dead objects.
Heap::CollectAllGarbage();
Heap::CollectAllGarbage(false);
// Check parameters.
CONVERT_CHECKED(JSFunction, constructor, args[0]);
@ -7633,7 +7633,7 @@ void Runtime::PerformGC(Object* result) {
// Handle last resort GC and make sure to allow future allocations
// to grow the heap without causing GCs (if possible).
Counters::gc_last_resort_from_js.Increment();
Heap::CollectAllGarbage();
Heap::CollectAllGarbage(false);
}
}

View File

@ -157,13 +157,13 @@ uint32_t V8::Random() {
}
void V8::IdleNotification(bool is_high_priority) {
if (!FLAG_use_idle_notification) return;
bool V8::IdleNotification(bool is_high_priority) {
if (!FLAG_use_idle_notification) return false;
// Ignore high priority instances of V8.
if (is_high_priority) return;
if (is_high_priority) return false;
// Uncommit unused memory in new space.
Heap::UncommitFromSpace();
// Tell the heap that it may want to adjust.
return Heap::IdleNotification();
}

View File

@ -100,7 +100,7 @@ class V8 : public AllStatic {
static Smi* RandomPositiveSmi();
// Idle notification directly from the API.
static void IdleNotification(bool is_high_priority);
static bool IdleNotification(bool is_high_priority);
private:
// True if engine is currently running