Do not serialize non-lazy compiled function literals.
authoryangguo@chromium.org <yangguo@chromium.org>
Mon, 29 Sep 2014 07:53:22 +0000 (07:53 +0000)
committeryangguo@chromium.org <yangguo@chromium.org>
Mon, 29 Sep 2014 07:53:22 +0000 (07:53 +0000)
... and some small refactorings.

R=mvstanton@chromium.org

Review URL: https://codereview.chromium.org/594513002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24266 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/compiler.cc
src/compiler.h
src/serialize.cc
src/serialize.h

index 13a1ec8..d8467e5 100644 (file)
@@ -995,6 +995,8 @@ static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
 
   DCHECK(info->is_eval() || info->is_global());
 
+  info->MarkAsToplevel();
+
   Handle<SharedFunctionInfo> result;
 
   { VMState<COMPILER> state(info->isolate());
@@ -1264,6 +1266,13 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(
   bool allow_lazy = literal->AllowsLazyCompilation() &&
       !DebuggerWantsEagerCompilation(&info, allow_lazy_without_ctx);
 
+
+  if (outer_info->is_toplevel() && outer_info->will_serialize()) {
+    // Make sure that if the toplevel code (possibly to be serialized),
+    // the inner unction must be allowed to be compiled lazily.
+    DCHECK(allow_lazy);
+  }
+
   // Generate code
   Handle<ScopeInfo> scope_info;
   if (FLAG_lazy && allow_lazy && !literal->is_parenthesized()) {
index 9617afc..e9176d3 100644 (file)
@@ -85,7 +85,8 @@ class CompilationInfo {
     kInliningEnabled = 1 << 17,
     kTypingEnabled = 1 << 18,
     kDisableFutureOptimization = 1 << 19,
-    kAbortedDueToDependency = 1 << 20
+    kAbortedDueToDependency = 1 << 20,
+    kToplevel = 1 << 21
   };
 
   CompilationInfo(Handle<JSFunction> closure, Zone* zone);
@@ -208,6 +209,10 @@ class CompilationInfo {
 
   bool is_typing_enabled() const { return GetFlag(kTypingEnabled); }
 
+  void MarkAsToplevel() { SetFlag(kToplevel); }
+
+  bool is_toplevel() const { return GetFlag(kToplevel); }
+
   bool IsCodePreAgingActive() const {
     return FLAG_optimize_for_size && FLAG_age_code && !will_serialize() &&
            !is_debug();
index a2dde9b..9d59b6f 100644 (file)
@@ -1846,7 +1846,7 @@ ScriptData* CodeSerializer::Serialize(Isolate* isolate,
   SnapshotByteSink* sink = FLAG_trace_code_serializer
                                ? static_cast<SnapshotByteSink*>(&debug_sink)
                                : static_cast<SnapshotByteSink*>(&list_sink);
-  CodeSerializer cs(isolate, sink, *source);
+  CodeSerializer cs(isolate, sink, *source, info->code());
   DisallowHeapAllocation no_gc;
   Object** location = Handle<Object>::cast(info).location();
   cs.VisitPointer(location);
@@ -1867,31 +1867,25 @@ ScriptData* CodeSerializer::Serialize(Isolate* isolate,
 
 void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code,
                                      WhereToPoint where_to_point, int skip) {
-  CHECK(o->IsHeapObject());
   HeapObject* heap_object = HeapObject::cast(o);
 
-  // The code-caches link to context-specific code objects, which
-  // the startup and context serializes cannot currently handle.
-  DCHECK(!heap_object->IsMap() ||
-         Map::cast(heap_object)->code_cache() ==
-             heap_object->GetHeap()->empty_fixed_array());
-
   int root_index;
   if ((root_index = RootIndex(heap_object, how_to_code)) != kInvalidRootIndex) {
     PutRoot(root_index, heap_object, how_to_code, where_to_point, skip);
     return;
   }
 
-  // TODO(yangguo) wire up global object.
-  // TODO(yangguo) We cannot deal with different hash seeds yet.
-  DCHECK(!heap_object->IsHashTable());
-
   if (address_mapper_.IsMapped(heap_object)) {
     SerializeReferenceToPreviousObject(heap_object, how_to_code, where_to_point,
                                        skip);
     return;
   }
 
+  if (skip != 0) {
+    sink_->Put(kSkip, "SkipFromSerializeObject");
+    sink_->PutInt(skip, "SkipDistanceFromSerializeObject");
+  }
+
   if (heap_object->IsCode()) {
     Code* code_object = Code::cast(heap_object);
     switch (code_object->kind()) {
@@ -1901,34 +1895,50 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code,
       case Code::NUMBER_OF_KINDS:     // Pseudo enum value.
         CHECK(false);
       case Code::BUILTIN:
-        SerializeBuiltin(code_object, how_to_code, where_to_point, skip);
+        SerializeBuiltin(code_object, how_to_code, where_to_point);
         return;
       case Code::STUB:
-        SerializeCodeStub(code_object, how_to_code, where_to_point, skip);
+        SerializeCodeStub(code_object, how_to_code, where_to_point);
         return;
 #define IC_KIND_CASE(KIND) case Code::KIND:
         IC_KIND_LIST(IC_KIND_CASE)
 #undef IC_KIND_CASE
+        SerializeHeapObject(code_object, how_to_code, where_to_point);
+        return;
       // TODO(yangguo): add special handling to canonicalize ICs.
       case Code::FUNCTION:
-        SerializeHeapObject(code_object, how_to_code, where_to_point, skip);
+        // Only serialize the code for the toplevel function. Replace code
+        // of included function literals by the lazy compile builtin.
+        // This is safe, as checked in Compiler::BuildFunctionInfo.
+        if (code_object != main_code_) {
+          Code* lazy = *isolate()->builtins()->CompileLazy();
+          SerializeBuiltin(lazy, how_to_code, where_to_point);
+        } else {
+          SerializeHeapObject(code_object, how_to_code, where_to_point);
+        }
         return;
     }
   }
 
   if (heap_object == source_) {
-    SerializeSourceObject(how_to_code, where_to_point, skip);
+    SerializeSourceObject(how_to_code, where_to_point);
     return;
   }
 
-  SerializeHeapObject(heap_object, how_to_code, where_to_point, skip);
+  // Past this point we should not see any (context-specific) maps anymore.
+  CHECK(!heap_object->IsMap());
+  // There should be no references to the global object embedded.
+  CHECK(!heap_object->IsJSGlobalProxy() && !heap_object->IsGlobalObject());
+  // There should be no hash table embedded. They would require rehashing.
+  CHECK(!heap_object->IsHashTable());
+
+  SerializeHeapObject(heap_object, how_to_code, where_to_point);
 }
 
 
 void CodeSerializer::SerializeHeapObject(HeapObject* heap_object,
                                          HowToCode how_to_code,
-                                         WhereToPoint where_to_point,
-                                         int skip) {
+                                         WhereToPoint where_to_point) {
   if (heap_object->IsScript()) {
     // The wrapper cache uses a Foreign object to point to a global handle.
     // However, the object visitor expects foreign objects to point to external
@@ -1936,11 +1946,6 @@ void CodeSerializer::SerializeHeapObject(HeapObject* heap_object,
     Script::cast(heap_object)->ClearWrapperCache();
   }
 
-  if (skip != 0) {
-    sink_->Put(kSkip, "SkipFromSerializeObject");
-    sink_->PutInt(skip, "SkipDistanceFromSerializeObject");
-  }
-
   if (FLAG_trace_code_serializer) {
     PrintF("Encoding heap object: ");
     heap_object->ShortPrint();
@@ -1955,12 +1960,7 @@ void CodeSerializer::SerializeHeapObject(HeapObject* heap_object,
 
 
 void CodeSerializer::SerializeBuiltin(Code* builtin, HowToCode how_to_code,
-                                      WhereToPoint where_to_point, int skip) {
-  if (skip != 0) {
-    sink_->Put(kSkip, "SkipFromSerializeBuiltin");
-    sink_->PutInt(skip, "SkipDistanceFromSerializeBuiltin");
-  }
-
+                                      WhereToPoint where_to_point) {
   DCHECK((how_to_code == kPlain && where_to_point == kStartOfObject) ||
          (how_to_code == kPlain && where_to_point == kInnerPointer) ||
          (how_to_code == kFromCode && where_to_point == kInnerPointer));
@@ -1979,18 +1979,13 @@ void CodeSerializer::SerializeBuiltin(Code* builtin, HowToCode how_to_code,
 
 
 void CodeSerializer::SerializeCodeStub(Code* stub, HowToCode how_to_code,
-                                       WhereToPoint where_to_point, int skip) {
+                                       WhereToPoint where_to_point) {
   DCHECK((how_to_code == kPlain && where_to_point == kStartOfObject) ||
          (how_to_code == kPlain && where_to_point == kInnerPointer) ||
          (how_to_code == kFromCode && where_to_point == kInnerPointer));
   uint32_t stub_key = stub->stub_key();
   DCHECK(CodeStub::MajorKeyFromKey(stub_key) != CodeStub::NoCache);
 
-  if (skip != 0) {
-    sink_->Put(kSkip, "SkipFromSerializeCodeStub");
-    sink_->PutInt(skip, "SkipDistanceFromSerializeCodeStub");
-  }
-
   int index = AddCodeStubKey(stub_key) + kCodeStubsBaseIndex;
 
   if (FLAG_trace_code_serializer) {
@@ -2017,16 +2012,8 @@ int CodeSerializer::AddCodeStubKey(uint32_t stub_key) {
 
 
 void CodeSerializer::SerializeSourceObject(HowToCode how_to_code,
-                                           WhereToPoint where_to_point,
-                                           int skip) {
-  if (skip != 0) {
-    sink_->Put(kSkip, "SkipFromSerializeSourceObject");
-    sink_->PutInt(skip, "SkipDistanceFromSerializeSourceObject");
-  }
-
-  if (FLAG_trace_code_serializer) {
-    PrintF("Encoding source object\n");
-  }
+                                           WhereToPoint where_to_point) {
+  if (FLAG_trace_code_serializer) PrintF("Encoding source object\n");
 
   DCHECK(how_to_code == kPlain && where_to_point == kStartOfObject);
   sink_->Put(kAttachedReference + how_to_code + where_to_point, "Source");
index b6ad82c..616f8f1 100644 (file)
@@ -577,19 +577,10 @@ class StartupSerializer : public Serializer {
 
 class CodeSerializer : public Serializer {
  public:
-  CodeSerializer(Isolate* isolate, SnapshotByteSink* sink, String* source)
-      : Serializer(isolate, sink), source_(source) {
-    set_root_index_wave_front(Heap::kStrongRootListLength);
-    InitializeCodeAddressMap();
-  }
-
   static ScriptData* Serialize(Isolate* isolate,
                                Handle<SharedFunctionInfo> info,
                                Handle<String> source);
 
-  virtual void SerializeObject(Object* o, HowToCode how_to_code,
-                               WhereToPoint where_to_point, int skip);
-
   static Handle<SharedFunctionInfo> Deserialize(Isolate* isolate,
                                                 ScriptData* data,
                                                 Handle<String> source);
@@ -605,18 +596,29 @@ class CodeSerializer : public Serializer {
   List<uint32_t>* stub_keys() { return &stub_keys_; }
 
  private:
+  CodeSerializer(Isolate* isolate, SnapshotByteSink* sink, String* source,
+                 Code* main_code)
+      : Serializer(isolate, sink), source_(source), main_code_(main_code) {
+    set_root_index_wave_front(Heap::kStrongRootListLength);
+    InitializeCodeAddressMap();
+  }
+
+  virtual void SerializeObject(Object* o, HowToCode how_to_code,
+                               WhereToPoint where_to_point, int skip);
+
   void SerializeBuiltin(Code* builtin, HowToCode how_to_code,
-                        WhereToPoint where_to_point, int skip);
+                        WhereToPoint where_to_point);
   void SerializeCodeStub(Code* stub, HowToCode how_to_code,
-                         WhereToPoint where_to_point, int skip);
-  void SerializeSourceObject(HowToCode how_to_code, WhereToPoint where_to_point,
-                             int skip);
+                         WhereToPoint where_to_point);
+  void SerializeSourceObject(HowToCode how_to_code,
+                             WhereToPoint where_to_point);
   void SerializeHeapObject(HeapObject* heap_object, HowToCode how_to_code,
-                           WhereToPoint where_to_point, int skip);
+                           WhereToPoint where_to_point);
   int AddCodeStubKey(uint32_t stub_key);
 
   DisallowHeapAllocation no_gc_;
   String* source_;
+  Code* main_code_;
   List<uint32_t> stub_keys_;
   DISALLOW_COPY_AND_ASSIGN(CodeSerializer);
 };