Reviewers: mvstanton,

Description:
Serializer: cache hashmaps on the isolate.

This speeds up multiple uses of the serializer quite a bit.

[email protected]

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

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

Affected files (+68, -21 lines):
  M src/heap/heap.cc
  M src/isolate.h
  M src/isolate.cc
  M src/serialize.h
  M src/serialize.cc
  M src/snapshot-source-sink.cc
  M test/cctest/test-serialize.cc


Index: src/heap/heap.cc
diff --git a/src/heap/heap.cc b/src/heap/heap.cc
index 66f98ced9816c26714e874e22b99d0232c87c53b..19b0fa8f3537d8d1c26ad73e5cc240996933973c 100644
--- a/src/heap/heap.cc
+++ b/src/heap/heap.cc
@@ -784,6 +784,7 @@ void Heap::CollectAllAvailableGarbage(const char* gc_reason) {
     DisallowHeapAllocation no_recursive_gc;
     isolate()->optimizing_compiler_thread()->Flush();
   }
+  isolate()->ClearSerializerData();
   mark_compact_collector()->SetFlags(kMakeHeapIterableMask |
                                      kReduceMemoryFootprintMask);
   isolate_->compilation_cache()->Clear();
Index: src/isolate.cc
diff --git a/src/isolate.cc b/src/isolate.cc
index 62dad8df706c2b265eab7e43f24e72c07c22c1c0..cc114c977cf5af69db3e1013f339fcc6c90f2059 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -1816,6 +1816,16 @@ void Isolate::GlobalTearDown() {
 }


+void Isolate::ClearSerializerData() {
+  delete external_reference_table_;
+  external_reference_table_ = NULL;
+  delete external_reference_map_;
+  external_reference_map_ = NULL;
+  delete root_index_map_;
+  root_index_map_ = NULL;
+}
+
+
 void Isolate::Deinit() {
   TRACE_ISOLATE(deinit);

@@ -1863,6 +1873,8 @@ void Isolate::Deinit() {
   heap_profiler_ = NULL;
   delete cpu_profiler_;
   cpu_profiler_ = NULL;
+
+  ClearSerializerData();
 }


@@ -1951,9 +1963,6 @@ Isolate::~Isolate() {
   delete string_stream_debug_object_cache_;
   string_stream_debug_object_cache_ = NULL;

-  delete external_reference_table_;
-  external_reference_table_ = NULL;
-
   delete random_number_generator_;
   random_number_generator_ = NULL;

Index: src/isolate.h
diff --git a/src/isolate.h b/src/isolate.h
index e13409c536a11d7531b5785c9cce6faea3c588db..2b34b73555dc2a8bf0ae7c95aca664c23744a747 100644
--- a/src/isolate.h
+++ b/src/isolate.h
@@ -376,8 +376,9 @@ typedef List<HeapObject*> DebugObjectCache;
V(Relocatable*, relocatable_top, NULL) \ V(DebugObjectCache*, string_stream_debug_object_cache, NULL) \ V(Object*, string_stream_current_security_token, NULL) \ - /* Serializer state. */ \ V(ExternalReferenceTable*, external_reference_table, NULL) \ + V(HashMap*, external_reference_map, NULL) \ + V(HashMap*, root_index_map, NULL) \ V(int, pending_microtask_count, 0) \ V(bool, autorun_microtasks, true) \ V(HStatistics*, hstatistics, NULL) \
@@ -527,6 +528,8 @@ class Isolate {

   static void GlobalTearDown();

+  void ClearSerializerData();
+
   // Find the PerThread for this particular (isolate, thread) combination
   // If one does not yet exist, return null.
   PerIsolateThreadData* FindPerThreadDataForThisThread();
Index: src/serialize.cc
diff --git a/src/serialize.cc b/src/serialize.cc
index 1d33f4f0623e3a38f2f46247b06a6e64eb93f60b..7d28f18caa43dc838ecec8aaabcb1bc54c0bcd01 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -330,23 +330,26 @@ ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) {
 }


-ExternalReferenceEncoder::ExternalReferenceEncoder(Isolate* isolate)
-    : map_(HashMap::PointersMatch) {
+ExternalReferenceEncoder::ExternalReferenceEncoder(Isolate* isolate) {
+  map_ = isolate->external_reference_map();
+  if (map_ != NULL) return;
+  map_ = new HashMap(HashMap::PointersMatch);
ExternalReferenceTable* table = ExternalReferenceTable::instance(isolate);
   for (int i = 0; i < table->size(); ++i) {
     Address addr = table->address(i);
     if (addr == ExternalReferenceTable::NotAvailable()) continue;
     // We expect no duplicate external references entries in the table.
-    DCHECK_NULL(map_.Lookup(addr, Hash(addr), false));
- map_.Lookup(addr, Hash(addr), true)->value = reinterpret_cast<void*>(i);
+    DCHECK_NULL(map_->Lookup(addr, Hash(addr), false));
+ map_->Lookup(addr, Hash(addr), true)->value = reinterpret_cast<void*>(i);
   }
+  isolate->set_external_reference_map(map_);
 }


 uint32_t ExternalReferenceEncoder::Encode(Address address) const {
   DCHECK_NOT_NULL(address);
   HashMap::Entry* entry =
-      const_cast<HashMap&>(map_).Lookup(address, Hash(address), false);
+      const_cast<HashMap*>(map_)->Lookup(address, Hash(address), false);
   DCHECK_NOT_NULL(entry);
   return static_cast<uint32_t>(reinterpret_cast<intptr_t>(entry->value));
 }
@@ -355,14 +358,17 @@ uint32_t ExternalReferenceEncoder::Encode(Address address) const {
 const char* ExternalReferenceEncoder::NameOfAddress(Isolate* isolate,
Address address) const {
   HashMap::Entry* entry =
-      const_cast<HashMap&>(map_).Lookup(address, Hash(address), false);
+      const_cast<HashMap*>(map_)->Lookup(address, Hash(address), false);
   if (entry == NULL) return "<unknown>";
uint32_t i = static_cast<uint32_t>(reinterpret_cast<intptr_t>(entry->value));
   return ExternalReferenceTable::instance(isolate)->name(i);
 }


-RootIndexMap::RootIndexMap(Isolate* isolate) : map_(HashMap::PointersMatch) {
+RootIndexMap::RootIndexMap(Isolate* isolate) {
+  map_ = isolate->root_index_map();
+  if (map_ != NULL) return;
+  map_ = new HashMap(HashMap::PointersMatch);
   Object** root_array = isolate->heap()->roots_array_start();
   for (uint32_t i = 0; i < Heap::kStrongRootListLength; i++) {
     Heap::RootListIndex root_index = static_cast<Heap::RootListIndex>(i);
@@ -372,15 +378,16 @@ RootIndexMap::RootIndexMap(Isolate* isolate) : map_(HashMap::PointersMatch) {
     if (root->IsHeapObject() &&
         isolate->heap()->RootCanBeTreatedAsConstant(root_index)) {
       HeapObject* heap_object = HeapObject::cast(root);
-      HashMap::Entry* entry = LookupEntry(&map_, heap_object, false);
+      HashMap::Entry* entry = LookupEntry(map_, heap_object, false);
       if (entry != NULL) {
         // Some are initialized to a previous value in the root list.
         DCHECK_LT(GetValue(entry), i);
       } else {
-        SetValue(LookupEntry(&map_, heap_object, true), i);
+        SetValue(LookupEntry(map_, heap_object, true), i);
       }
     }
   }
+  isolate->set_root_index_map(map_);
 }


@@ -1192,7 +1199,7 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
 Serializer::Serializer(Isolate* isolate, SnapshotByteSink* sink)
     : isolate_(isolate),
       sink_(sink),
-      external_reference_encoder_(new ExternalReferenceEncoder(isolate)),
+      external_reference_encoder_(isolate),
       root_index_map_(isolate),
       code_address_map_(NULL),
       large_objects_total_size_(0),
@@ -1208,7 +1215,6 @@ Serializer::Serializer(Isolate* isolate, SnapshotByteSink* sink)


 Serializer::~Serializer() {
-  delete external_reference_encoder_;
   if (code_address_map_ != NULL) delete code_address_map_;
 }

Index: src/serialize.h
diff --git a/src/serialize.h b/src/serialize.h
index 1614ecd45459099ad78de707895cacd0492b75b4..3f56c53b9878120aa1664ded41c173fa156f1d52 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -63,7 +63,7 @@ class ExternalReferenceEncoder {
                                  kPointerSizeLog2);
   }

-  HashMap map_;
+  HashMap* map_;

   DISALLOW_COPY_AND_ASSIGN(ExternalReferenceEncoder);
 };
@@ -102,13 +102,13 @@ class RootIndexMap : public AddressMapBase {
   static const int kInvalidRootIndex = -1;

   int Lookup(HeapObject* obj) {
-    HashMap::Entry* entry = LookupEntry(&map_, obj, false);
+    HashMap::Entry* entry = LookupEntry(map_, obj, false);
     if (entry) return GetValue(entry);
     return kInvalidRootIndex;
   }

  private:
-  HashMap map_;
+  HashMap* map_;

   DISALLOW_COPY_AND_ASSIGN(RootIndexMap);
 };
@@ -687,7 +687,7 @@ class Serializer : public SerializerDeserializer {
   BackReference AllocateLargeObject(int size);
   BackReference Allocate(AllocationSpace space, int size);
   int EncodeExternalReference(Address addr) {
-    return external_reference_encoder_->Encode(addr);
+    return external_reference_encoder_.Encode(addr);
   }

   // GetInt reads 4 bytes at once, requiring padding at the end.
@@ -714,7 +714,7 @@ class Serializer : public SerializerDeserializer {
   Isolate* isolate_;

   SnapshotByteSink* sink_;
-  ExternalReferenceEncoder* external_reference_encoder_;
+  ExternalReferenceEncoder external_reference_encoder_;

   BackReferenceMap back_reference_map_;
   RootIndexMap root_index_map_;
Index: src/snapshot-source-sink.cc
diff --git a/src/snapshot-source-sink.cc b/src/snapshot-source-sink.cc
index 0054aec27c154afd795199361ef28a2d24e2a51c..eedcee6a9cebc52beea08338e7f9152eafd0b6c1 100644
--- a/src/snapshot-source-sink.cc
+++ b/src/snapshot-source-sink.cc
@@ -14,7 +14,7 @@ namespace v8 {
 namespace internal {

 void SnapshotByteSource::CopyRaw(byte* to, int number_of_bytes) {
-  MemCopy(to, data_ + position_, number_of_bytes);
+  memcpy(to, data_ + position_, number_of_bytes);
   position_ += number_of_bytes;
 }

Index: test/cctest/test-serialize.cc
diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc
index 9fadddf4c27a199564430b786307cc4f4a3aee77..2849e7262db199f7b1b26776dddbf13b3c5b3cbd 100644
--- a/test/cctest/test-serialize.cc
+++ b/test/cctest/test-serialize.cc
@@ -1549,3 +1549,31 @@ TEST(SerializeInternalReference) {
   }
   isolate->Dispose();
 }
+
+
+TEST(DeserializePerf) {
+  FLAG_serialize_toplevel = true;
+
+  const char* source = "function f() { return 'abc'; }; f() + 'def'";
+  v8::ScriptCompiler::CachedData* cache = ProduceCache(source);
+
+  v8::Isolate* isolate2 = v8::Isolate::New();
+  {
+    v8::Isolate::Scope iscope(isolate2);
+    v8::HandleScope scope(isolate2);
+    v8::Local<v8::Context> context = v8::Context::New(isolate2);
+    reinterpret_cast<Isolate*>(isolate2)->compilation_cache()->Disable();
+    v8::Context::Scope context_scope(context);
+
+    v8::Local<v8::String> source_str = v8_str(source);
+    v8::ScriptOrigin origin(v8_str("test"));
+    v8::ScriptCompiler::Source source(source_str, origin, cache);
+    v8::Local<v8::UnboundScript> script;
+    for (int i = 0; i < 100000; i++) {
+      DisallowCompilation no_compile(reinterpret_cast<Isolate*>(isolate2));
+      script = v8::ScriptCompiler::CompileUnbound(
+          isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache);
+    }
+  }
+  isolate2->Dispose();
+}


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