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
-~----------~----~----~----~------~----~------~--~---

Reply via email to