Revision: 2519 Author: [email protected] Date: Wed Jul 22 03:01:25 2009 Log: Introduce a external allocation limit.
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 http://code.google.com/p/v8/source/detail?r=2519 Modified: /branches/bleeding_edge/src/heap-inl.h /branches/bleeding_edge/src/heap.cc /branches/bleeding_edge/src/heap.h /branches/bleeding_edge/test/cctest/test-api.cc ======================================= --- /branches/bleeding_edge/src/heap-inl.h Thu Jul 9 04:13:08 2009 +++ /branches/bleeding_edge/src/heap-inl.h Wed Jul 22 03:01:25 2009 @@ -226,6 +226,31 @@ // Call the slow part of scavenge object. return ScavengeObjectSlow(p, object); } + + +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) { ======================================= --- /branches/bleeding_edge/src/heap.cc Mon Jul 20 02:38:44 2009 +++ /branches/bleeding_edge/src/heap.cc Wed Jul 22 03:01:25 2009 @@ -85,8 +85,8 @@ // 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; @@ -2988,6 +2988,7 @@ 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); ======================================= --- /branches/bleeding_edge/src/heap.h Mon Jul 13 14:24:54 2009 +++ /branches/bleeding_edge/src/heap.h Wed Jul 22 03:01:25 2009 @@ -746,7 +746,7 @@ 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); @@ -802,22 +802,7 @@ // 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); @@ -901,6 +886,10 @@ // 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_; @@ -1230,7 +1219,7 @@ // 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; ======================================= --- /branches/bleeding_edge/test/cctest/test-api.cc Fri Jul 17 03:35:15 2009 +++ /branches/bleeding_edge/test/cctest/test-api.cc Wed Jul 22 03:01:25 2009 @@ -6216,6 +6216,7 @@ 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); --~--~---------~--~----~------------~-------~--~----~ v8-dev mailing list [email protected] http://groups.google.com/group/v8-dev -~----------~----~----~----~------~----~------~--~---
