Index: src/heap.cc |
=================================================================== |
--- src/heap.cc (revision 5457) |
+++ src/heap.cc (working copy) |
@@ -1,4 +1,4 @@ |
-// Copyright 2009 the V8 project authors. All rights reserved. |
+// Copyright 2010 the V8 project authors. All rights reserved. |
// Redistribution and use in source and binary forms, with or without |
// modification, are permitted provided that the following conditions are |
// met: |
@@ -55,7 +55,6 @@ |
String* Heap::hidden_symbol_; |
Object* Heap::roots_[Heap::kRootListLength]; |
- |
NewSpace Heap::new_space_; |
OldSpace* Heap::old_pointer_space_ = NULL; |
OldSpace* Heap::old_data_space_ = NULL; |
@@ -64,9 +63,6 @@ |
CellSpace* Heap::cell_space_ = NULL; |
LargeObjectSpace* Heap::lo_space_ = NULL; |
-static const int kMinimumPromotionLimit = 2*MB; |
-static const int kMinimumAllocationLimit = 8*MB; |
- |
int Heap::old_gen_promotion_limit_ = kMinimumPromotionLimit; |
int Heap::old_gen_allocation_limit_ = kMinimumAllocationLimit; |
@@ -405,17 +401,26 @@ |
} |
-void Heap::CollectAllGarbage(bool force_compaction) { |
+void Heap::CollectAllGarbage(bool force_compaction, |
+ CollectionPolicy collectionPolicy) { |
// Since we are ignoring the return value, the exact choice of space does |
// not matter, so long as we do not specify NEW_SPACE, which would not |
// cause a full GC. |
MarkCompactCollector::SetForceCompaction(force_compaction); |
- CollectGarbage(0, OLD_POINTER_SPACE); |
+ CollectGarbage(0, OLD_POINTER_SPACE, collectionPolicy); |
MarkCompactCollector::SetForceCompaction(false); |
} |
-bool Heap::CollectGarbage(int requested_size, AllocationSpace space) { |
+void Heap::CollectAllAvailableGarbage() { |
+ CompilationCache::Clear(); |
+ CollectAllGarbage(true, AGGRESSIVE); |
+} |
+ |
+ |
+bool Heap::CollectGarbage(int requested_size, |
+ AllocationSpace space, |
+ CollectionPolicy collectionPolicy) { |
// The VM is in the GC state until exiting this function. |
VMState state(GC); |
@@ -442,7 +447,7 @@ |
? &Counters::gc_scavenger |
: &Counters::gc_compactor; |
rate->Start(); |
- PerformGarbageCollection(space, collector, &tracer); |
+ PerformGarbageCollection(collector, &tracer, collectionPolicy); |
rate->Stop(); |
GarbageCollectionEpilogue(); |
@@ -475,7 +480,7 @@ |
void Heap::PerformScavenge() { |
GCTracer tracer; |
- PerformGarbageCollection(NEW_SPACE, SCAVENGER, &tracer); |
+ PerformGarbageCollection(SCAVENGER, &tracer, NORMAL); |
} |
@@ -664,9 +669,9 @@ |
survival_rate_ = survival_rate; |
} |
-void Heap::PerformGarbageCollection(AllocationSpace space, |
- GarbageCollector collector, |
- GCTracer* tracer) { |
+void Heap::PerformGarbageCollection(GarbageCollector collector, |
+ GCTracer* tracer, |
+ CollectionPolicy collectionPolicy) { |
VerifySymbolTable(); |
if (collector == MARK_COMPACTOR && global_gc_prologue_callback_) { |
ASSERT(!allocation_allowed_); |
@@ -696,25 +701,45 @@ |
UpdateSurvivalRateTrend(start_new_space_size); |
- int old_gen_size = PromotedSpaceSize(); |
- old_gen_promotion_limit_ = |
- old_gen_size + Max(kMinimumPromotionLimit, old_gen_size / 3); |
- old_gen_allocation_limit_ = |
- old_gen_size + Max(kMinimumAllocationLimit, old_gen_size / 2); |
+ UpdateOldSpaceLimits(); |
- if (high_survival_rate_during_scavenges && |
- IsStableOrIncreasingSurvivalTrend()) { |
- // Stable high survival rates of young objects both during partial and |
- // full collection indicate that mutator is either building or modifying |
- // a structure with a long lifetime. |
- // In this case we aggressively raise old generation memory limits to |
- // postpone subsequent mark-sweep collection and thus trade memory |
- // space for the mutation speed. |
- old_gen_promotion_limit_ *= 2; |
- old_gen_allocation_limit_ *= 2; |
+ // Major GC would invoke weak handle callbacks on weakly reachable |
+ // handles, but won't collect weakly reachable objects until next |
+ // major GC. Therefore if we collect aggressively and weak handle callback |
+ // has been invoked, we rerun major GC to release objects which become |
+ // garbage. |
+ if (collectionPolicy == AGGRESSIVE) { |
+ // Note: as weak callbacks can execute arbitrary code, we cannot |
+ // hope that eventually there will be no weak callbacks invocations. |
+ // Therefore stop recollecting after several attempts. |
+ const int kMaxNumberOfAttempts = 7; |
+ for (int attempt = 0; attempt < kMaxNumberOfAttempts; attempt++) { |
+ { DisableAssertNoAllocation allow_allocation; |
+ GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); |
+ if (!GlobalHandles::PostGarbageCollectionProcessing()) break; |
+ } |
+ MarkCompact(tracer); |
+ // Weak handle callbacks can allocate data, so keep limits correct. |
+ UpdateOldSpaceLimits(); |
+ } |
+ } else { |
+ if (high_survival_rate_during_scavenges && |
+ IsStableOrIncreasingSurvivalTrend()) { |
+ // Stable high survival rates of young objects both during partial and |
+ // full collection indicate that mutator is either building or modifying |
+ // a structure with a long lifetime. |
+ // In this case we aggressively raise old generation memory limits to |
+ // postpone subsequent mark-sweep collection and thus trade memory |
+ // space for the mutation speed. |
+ old_gen_promotion_limit_ *= 2; |
+ old_gen_allocation_limit_ *= 2; |
+ } |
} |
- old_gen_exhausted_ = false; |
+ { DisableAssertNoAllocation allow_allocation; |
+ GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); |
+ GlobalHandles::PostGarbageCollectionProcessing(); |
+ } |
} else { |
tracer_ = tracer; |
Scavenge(); |
@@ -725,12 +750,6 @@ |
Counters::objs_since_last_young.Set(0); |
- if (collector == MARK_COMPACTOR) { |
- DisableAssertNoAllocation allow_allocation; |
- GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); |
- GlobalHandles::PostGarbageCollectionProcessing(); |
- } |
- |
// Update relocatables. |
Relocatable::PostGarbageCollectionProcessing(); |
@@ -1834,6 +1853,13 @@ |
CreateFixedStubs(); |
+ // Allocate the dictionary of intrinsic function names. |
+ obj = StringDictionary::Allocate(Runtime::kNumFunctions); |
+ if (obj->IsFailure()) return false; |
+ obj = Runtime::InitializeIntrinsicFunctionNames(obj); |
+ if (obj->IsFailure()) return false; |
+ set_intrinsic_function_names(StringDictionary::cast(obj)); |
+ |
if (InitializeNumberStringCache()->IsFailure()) return false; |
// Allocate cache for single character ASCII strings. |