Reviewers: jochen (slow),

Description:
Fix remaining issues in the custom snapshot.

Math functions:
Some Math functions require typed arrays for their implementation. The embedded script may call those Math functions. The serializer needs to deal with this. Added assertion to make sure no other typed array is created when snapshotting.

Number-string cache:
We assume that the initial snapshot does not expand the number-string cache.
This is no longer true for custom heap snapshots.

Bound functions:
Bound functions store the bound arguments in a COW fixed array, including the
bindee function. COW arrays are serialized into the startup snapshot and
referenced in the partial snapshot via partial snapshot cache. However, the
bindee function is context-dependent and must not be part of the startup
snapshot. There is no need for bound functions to use a COW array though.

[email protected]

Please review this at https://codereview.chromium.org/851073002/

Base URL: https://chromium.googlesource.com/v8/v8.git@master

Affected files (+31, -18 lines):
  M src/bootstrapper.cc
  M src/factory.cc
  M src/heap/heap.h
  M src/objects-inl.h
  M src/runtime/runtime-function.cc
  M src/runtime/runtime-typedarray.cc
  M src/serialize.cc
  M test/cctest/cctest.h
  M test/cctest/test-heap.cc
  M test/cctest/test-serialize.cc


Index: src/bootstrapper.cc
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 41833caef2b667549a5b9c0a581c4c5659151d6c..184bad7684e16ed356fe60d9763493f552fbdef2 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -2791,10 +2791,9 @@ Genesis::Genesis(Isolate* isolate,
   if (!InstallExperimentalNatives()) return;
   InitializeExperimentalGlobal();

- // We can't (de-)serialize typed arrays currently, but we are lucky: The state
-  // of the random number generator needs no initialization during snapshot
-  // creation time and we don't need trigonometric functions then.
-  if (!isolate->serializer_enabled()) {
+  // The serializer cannot serialize typed arrays. Reset those typed arrays
+  // for each new context.
+  {
     // Initially seed the per-context random number generator using the
     // per-isolate random number generator.
     const int num_elems = 2;
Index: src/factory.cc
diff --git a/src/factory.cc b/src/factory.cc
index 28526743341efef867af9977bc3f26b10e297897..96883052dad1a9105cd23dd0e641952821fbc730 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -2149,12 +2149,6 @@ void Factory::SetNumberStringCache(Handle<Object> number,
   if (number_string_cache()->get(hash * 2) != *undefined_value()) {
     int full_size = isolate()->heap()->FullSizeNumberStringCacheLength();
     if (number_string_cache()->length() != full_size) {
-      // The first time we have a hash collision, we move to the full sized
-      // number string cache.  The idea is to have a small number string
-      // cache in the snapshot to keep  boot-time memory usage down.
-      // If we expand the number string cache already while creating
-      // the snapshot then that didn't work out.
-      DCHECK(!isolate()->serializer_enabled());
       Handle<FixedArray> new_cache = NewFixedArray(full_size, TENURED);
       isolate()->heap()->set_number_string_cache(*new_cache);
       return;
Index: src/heap/heap.h
diff --git a/src/heap/heap.h b/src/heap/heap.h
index 6aeaff8069ff8d7adc8ebf390447758cbc3aca52..5fc3f07d75f54e406ecaa4ac5171d453b8c14f04 100644
--- a/src/heap/heap.h
+++ b/src/heap/heap.h
@@ -1486,6 +1486,10 @@ class Heap {
   MUST_USE_RESULT AllocationResult
AllocateFixedArray(int length, PretenureFlag pretenure = NOT_TENURED);

+  static const int kInitialStringTableSize = 2048;
+  static const int kInitialEvalCacheSize = 64;
+  static const int kInitialNumberStringCacheSize = 256;
+
  private:
   Heap();

@@ -2043,10 +2047,6 @@ class Heap {
   inline void UpdateAllocationsHash(uint32_t value);
   inline void PrintAlloctionsHash();

-  static const int kInitialStringTableSize = 2048;
-  static const int kInitialEvalCacheSize = 64;
-  static const int kInitialNumberStringCacheSize = 256;
-
   // Object counts and used memory by InstanceType
   size_t object_counts_[OBJECT_STATS_COUNT];
   size_t object_counts_last_time_[OBJECT_STATS_COUNT];
Index: src/objects-inl.h
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 7a00868ece963490f23dd3adce5387b0810453c7..076df3d932ec7309bb1aa0a792cc6efa91cece93 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -6186,7 +6186,7 @@ void JSFunction::set_function_bindings(FixedArray* bindings) {
   // Bound function literal may be initialized to the empty fixed array
   // before the bindings are set.
   DCHECK(bindings == GetHeap()->empty_fixed_array() ||
-         bindings->map() == GetHeap()->fixed_cow_array_map());
+         bindings->map() == GetHeap()->fixed_array_map());
   set_literals_or_bindings(bindings);
 }

Index: src/runtime/runtime-function.cc
diff --git a/src/runtime/runtime-function.cc b/src/runtime/runtime-function.cc index e25b6592e00130ffb52f7d5157af2048e487bde8..8fa813c3750923a45289de8b68520859280098f0 100644
--- a/src/runtime/runtime-function.cc
+++ b/src/runtime/runtime-function.cc
@@ -435,8 +435,7 @@ RUNTIME_FUNCTION(Runtime_FunctionBindArguments) {
   for (int j = 0; j < argc; j++, i++) {
     new_bindings->set(i, *arguments[j + 1]);
   }
-  new_bindings->set_map_no_write_barrier(
-      isolate->heap()->fixed_cow_array_map());
+ new_bindings->set_map_no_write_barrier(isolate->heap()->fixed_array_map());
   bound_function->set_function_bindings(*new_bindings);

// Update length. Have to remove the prototype first so that map migration
Index: src/runtime/runtime-typedarray.cc
diff --git a/src/runtime/runtime-typedarray.cc b/src/runtime/runtime-typedarray.cc index cd2c0eb9fa1a3b5ca90b85b0c949b7f383c92b25..82224bc9b3e8021d6b780e7af2343f75b9bb65c0 100644
--- a/src/runtime/runtime-typedarray.cc
+++ b/src/runtime/runtime-typedarray.cc
@@ -63,6 +63,8 @@ bool Runtime::SetupArrayBufferAllocatingData(Isolate* isolate,
                                              bool initialize) {
   void* data;
   CHECK(V8::ArrayBufferAllocator() != NULL);
+  // Prevent creating array buffers when serializing.
+  DCHECK(!isolate->serializer_enabled());
   if (allocated_length != 0) {
     if (initialize) {
       data = V8::ArrayBufferAllocator()->Allocate(allocated_length);
Index: src/serialize.cc
diff --git a/src/serialize.cc b/src/serialize.cc
index febb87b60c9bebed6cdcf0cefc3a683bbc94d16a..8d6d5508252450a24ef5810b414fa59f5c66fc84 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -1665,6 +1665,9 @@ void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, DCHECK(Map::cast(obj)->code_cache() == obj->GetHeap()->empty_fixed_array());
   }

+  // Replace typed arrays by undefined.
+  if (obj->IsJSTypedArray()) obj = isolate_->heap()->undefined_value();
+
   int root_index = root_index_map_.Lookup(obj);
   if (root_index != RootIndexMap::kInvalidRootIndex) {
     PutRoot(root_index, obj, how_to_code, where_to_point, skip);
@@ -1832,6 +1835,9 @@ void Serializer::ObjectSerializer::Serialize() {
     PrintF("\n");
   }

+  // We cannot serialize typed array objects correctly.
+  DCHECK(!object_->IsJSTypedArray());
+
   if (object_->IsScript()) {
     // Clear cached line ends.
     Object* undefined = serializer_->isolate()->heap()->undefined_value();
Index: test/cctest/cctest.h
diff --git a/test/cctest/cctest.h b/test/cctest/cctest.h
index a8239d26fb218e882755aca02e0bb0738a99e094..af0f666a89c1466d0fdcb2cdf97ad67c27b246d6 100644
--- a/test/cctest/cctest.h
+++ b/test/cctest/cctest.h
@@ -99,6 +99,7 @@ class TestHeap : public i::Heap {
   using i::Heap::AllocateJSObjectFromMap;
   using i::Heap::AllocateMap;
   using i::Heap::CopyCode;
+  using i::Heap::kInitialNumberStringCacheSize;
 };


Index: test/cctest/test-heap.cc
diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc
index f8a7df20c6a6fc178a6d8a25f8cf12afad2c9691..11aee2e36b69aa2be6966f54e481639282df49ea 100644
--- a/test/cctest/test-heap.cc
+++ b/test/cctest/test-heap.cc
@@ -5089,6 +5089,16 @@ TEST(Regress442710) {
 }


+TEST(NumberStringCacheSize) {
+  CcTest::InitializeVM();
+  Isolate* isolate = CcTest::i_isolate();
+  Heap* heap = isolate->heap();
+  // Test that the number-string cache has not been resized.
+  CHECK_EQ(TestHeap::kInitialNumberStringCacheSize * 2,
+           heap->number_string_cache()->length());
+}
+
+
 #ifdef DEBUG
 TEST(PathTracer) {
   CcTest::InitializeVM();
Index: test/cctest/test-serialize.cc
diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc
index a06cfbb8cd09dc0a51f9a7f3122b4aada65d58de..eb5977901b56e49689ecd02515370bb765d62bab 100644
--- a/test/cctest/test-serialize.cc
+++ b/test/cctest/test-serialize.cc
@@ -565,7 +565,9 @@ UNINITIALIZED_TEST(CustomContextSerialization) {
             "(function() {"
             "  e = function(s) { eval (s); }"
             "})();"
-            "var o = this;");
+            "var o = this;"
+            "var r = Math.random();"
+            "var f = (function(a, b) {}).bind(1, 2, 3);");
       }
       // Make sure all builtin scripts are cached.
       {


--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to