If V8 is holding on to a lot of external memory, we attempt to clean
it up even if we do not get an allocation failure. Since tiny V8
objects can hold on to a lot of external memory, we might run out of
external memory while waiting for a normal allocation failure.
Review URL: http://codereview.chromium.org/155916
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2519
ce2b1a6d-e550-0410-aec6-
3dcde31c8c00
}
+int Heap::AdjustAmountOfExternalAllocatedMemory(int change_in_bytes) {
+ ASSERT(HasBeenSetup());
+ int amount = amount_of_external_allocated_memory_ + change_in_bytes;
+ if (change_in_bytes >= 0) {
+ // Avoid overflow.
+ if (amount > amount_of_external_allocated_memory_) {
+ amount_of_external_allocated_memory_ = amount;
+ }
+ int amount_since_last_global_gc =
+ amount_of_external_allocated_memory_ -
+ amount_of_external_allocated_memory_at_last_global_gc_;
+ if (amount_since_last_global_gc > external_allocation_limit_) {
+ CollectAllGarbage();
+ }
+ } else {
+ // Avoid underflow.
+ if (amount >= 0) {
+ amount_of_external_allocated_memory_ = amount;
+ }
+ }
+ ASSERT(amount_of_external_allocated_memory_ >= 0);
+ return amount_of_external_allocated_memory_;
+}
+
+
void Heap::SetLastScriptId(Object* last_script_id) {
roots_[kLastScriptIdRootIndex] = last_script_id;
}
// Variables set based on semispace_size_ and old_generation_size_ in
// ConfigureHeap.
int Heap::young_generation_size_ = 0; // Will be 2 * semispace_size_.
-
int Heap::survived_since_last_expansion_ = 0;
+int Heap::external_allocation_limit_ = 0;
Heap::HeapState Heap::gc_state_ = NOT_IN_GC;
semispace_size_ = RoundUpToPowerOf2(semispace_size_);
initial_semispace_size_ = Min(initial_semispace_size_, semispace_size_);
young_generation_size_ = 2 * semispace_size_;
+ external_allocation_limit_ = 10 * semispace_size_;
// The old generation is paged.
old_generation_size_ = RoundUp(old_generation_size_, Page::kPageSize);
static Object* CreateSymbol(String* str);
// Write barrier support for address[offset] = o.
- inline static void RecordWrite(Address address, int offset);
+ static inline void RecordWrite(Address address, int offset);
// Given an address occupied by a live code object, return that object.
static Object* FindCodeObject(Address a);
// Adjusts the amount of registered external memory.
// Returns the adjusted value.
- static int AdjustAmountOfExternalAllocatedMemory(int change_in_bytes) {
- int amount = amount_of_external_allocated_memory_ + change_in_bytes;
- if (change_in_bytes >= 0) {
- // Avoid overflow.
- if (amount > amount_of_external_allocated_memory_) {
- amount_of_external_allocated_memory_ = amount;
- }
- } else {
- // Avoid underflow.
- if (amount >= 0) {
- amount_of_external_allocated_memory_ = amount;
- }
- }
- ASSERT(amount_of_external_allocated_memory_ >= 0);
- return amount_of_external_allocated_memory_;
- }
+ static inline int AdjustAmountOfExternalAllocatedMemory(int change_in_bytes);
// Allocate unitialized fixed array (pretenure == NON_TENURE).
static Object* AllocateRawFixedArray(int length);
// every allocation in large object space.
static int old_gen_allocation_limit_;
+ // Limit on the amount of externally allocated memory allowed
+ // between global GCs. If reached a global GC is forced.
+ static int external_allocation_limit_;
+
// The amount of external memory registered through the API kept alive
// by global handles
static int amount_of_external_allocated_memory_;
// Clear the cache.
static void Clear();
private:
- inline static int Hash(Map* map, String* name);
+ static inline int Hash(Map* map, String* name);
static const int kLength = 64;
struct Key {
Map* map;
THREADED_TEST(ExternalAllocatedMemory) {
v8::HandleScope outer;
+ v8::Persistent<Context> env = Context::New();
const int kSize = 1024*1024;
CHECK_EQ(v8::V8::AdjustAmountOfExternalAllocatedMemory(kSize), kSize);
CHECK_EQ(v8::V8::AdjustAmountOfExternalAllocatedMemory(-kSize), 0);