Reviewers: Jakob,

Description:
When optimizing deserialized code, make sure IC state is preserved.

[email protected]

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

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

Affected files (+46, -16 lines):
  M src/compiler.cc
  M src/flag-definitions.h
  M src/full-codegen.cc
  M src/objects.h
  M src/objects-inl.h
  M src/serialize.cc
  A + test/mjsunit/deserialize-optimize-inner.js


Index: src/compiler.cc
diff --git a/src/compiler.cc b/src/compiler.cc
index 3b612c1323dbf5874fb56cbe6959e699cb9112f0..33d88d75c0dac5429165543eae3188b199b8d7c5 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -938,16 +938,23 @@ bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) {
   DCHECK(info->function() != NULL);
   DCHECK(info->scope() != NULL);
   if (!info->shared_info()->has_deoptimization_support()) {
-    CompilationInfoWithZone unoptimized(info->shared_info());
+    Handle<SharedFunctionInfo> shared = info->shared_info();
+    CompilationInfoWithZone unoptimized(shared);
     // Note that we use the same AST that we will use for generating the
     // optimized code.
     unoptimized.SetFunction(info->function());
     unoptimized.PrepareForCompilation(info->scope());
     unoptimized.SetContext(info->context());
     unoptimized.EnableDeoptimizationSupport();
+    // If the current code has reloc info for serialization, also include
+    // reloc info for serialization for the new code, so that deopt support
+    // can be added without losing IC state.
+    if (shared->code()->kind() == Code::FUNCTION &&
+        shared->code()->has_reloc_info_for_serialization()) {
+      unoptimized.PrepareForSerializing();
+    }
     if (!FullCodeGenerator::MakeCode(&unoptimized)) return false;

-    Handle<SharedFunctionInfo> shared = info->shared_info();
     shared->EnableDeoptimizationSupport(*unoptimized.code());
     shared->set_feedback_vector(*unoptimized.feedback_vector());

@@ -1313,10 +1320,10 @@ 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 function must be allowed to be compiled lazily.
+ // This is necessary to serialize toplevel code without inner functions.
     DCHECK(allow_lazy);
   }

Index: src/flag-definitions.h
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 535dcd2d7baaff380ca6bd2832d39b84470f9e82..0d7363e8f52828e32617ba7f382325771226df7e 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -477,6 +477,7 @@ DEFINE_BOOL(trace_stub_failures, false,
             "trace deoptimization of generated code stubs")

 DEFINE_BOOL(serialize_toplevel, true, "enable caching of toplevel scripts")
+DEFINE_BOOL(serialize_inner, false, "enable caching of inner functions")
 DEFINE_BOOL(trace_code_serializer, false, "print code serializer trace")

 // compiler.cc
Index: src/full-codegen.cc
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index e32c59fc0746278c468de226c038445fc7aa2897..cb8f4aafcd9cd7274f032f14505f5dd028725252 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -338,6 +338,7 @@ bool FullCodeGenerator::MakeCode(CompilationInfo* info) {
   cgen.PopulateDeoptimizationData(code);
   cgen.PopulateTypeFeedbackInfo(code);
   code->set_has_deoptimization_support(info->HasDeoptimizationSupport());
+  code->set_has_reloc_info_for_serialization(info->will_serialize());
   code->set_handler_table(*cgen.handler_table());
   code->set_compiled_optimizable(info->IsOptimizable());
   code->set_allow_osr_at_loop_nesting_level(0);
Index: src/objects-inl.h
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 3dd6fed8a9ed0b17f187cbf3c94cb1cdf6711c20..108f9f62489ad62b492ce22a748826a81baee62f 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -4858,6 +4858,21 @@ void Code::set_compiled_optimizable(bool value) {
 }


+bool Code::has_reloc_info_for_serialization() {
+  DCHECK_EQ(FUNCTION, kind());
+  byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
+  return FullCodeFlagsHasRelocInfoForSerialization::decode(flags);
+}
+
+
+void Code::set_has_reloc_info_for_serialization(bool value) {
+  DCHECK_EQ(FUNCTION, kind());
+  byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
+  flags = FullCodeFlagsHasRelocInfoForSerialization::update(flags, value);
+  WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
+}
+
+
 int Code::allow_osr_at_loop_nesting_level() {
   DCHECK_EQ(FUNCTION, kind());
   int fields = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
Index: src/objects.h
diff --git a/src/objects.h b/src/objects.h
index 678dcb2ed5d48b6c233977513ff94bfe22a324b1..9569de97329d9316e684448e8478d32a4377cffa 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -5103,6 +5103,12 @@ class Code: public HeapObject {
   inline bool is_compiled_optimizable();
   inline void set_compiled_optimizable(bool value);

+  // [has_reloc_info_for_serialization]: For FUNCTION kind, tells if its
+  // reloc info includes runtime and external references to support
+  // serialization/deserialization.
+  inline bool has_reloc_info_for_serialization();
+  inline void set_has_reloc_info_for_serialization(bool value);
+
   // [allow_osr_at_loop_nesting_level]: For FUNCTION kind, tells for
   // how long the function has been marked for OSR and therefore which
   // level of loop nesting we are willing to do on-stack replacement
@@ -5387,6 +5393,8 @@ class Code: public HeapObject {
       public BitField<bool, 0, 1> {};  // NOLINT
class FullCodeFlagsHasDebugBreakSlotsField: public BitField<bool, 1, 1> {};
   class FullCodeFlagsIsCompiledOptimizable: public BitField<bool, 2, 1> {};
+  class FullCodeFlagsHasRelocInfoForSerialization
+      : public BitField<bool, 3, 1> {};

   static const int kProfilerTicksOffset = kFullCodeFlags + 1;

Index: src/serialize.cc
diff --git a/src/serialize.cc b/src/serialize.cc
index f492f5b6cc08c6ff91e15b77214bb3abd346d6af..e502c9559fce70b186d4a911936bf042239e8c71 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -2042,10 +2042,11 @@ void CodeSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
         SerializeIC(code_object, how_to_code, where_to_point);
         return;
       case Code::FUNCTION:
-        // Only serialize the code for the toplevel function. Replace code
-        // of included function literals by the lazy compile builtin.
+        DCHECK(code_object->has_reloc_info_for_serialization());
+ // Only serialize the code for the toplevel function unless specified + // by flag. Replace code of inner functions by the lazy compile builtin.
         // This is safe, as checked in Compiler::BuildFunctionInfo.
-        if (code_object != main_code_) {
+        if (code_object != main_code_ && !FLAG_serialize_inner) {
SerializeBuiltin(Builtins::kCompileLazy, how_to_code, where_to_point);
         } else {
           code_object->MakeYoung();
@@ -2062,6 +2063,8 @@ void CodeSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
   CHECK(!obj->IsJSGlobalProxy() && !obj->IsGlobalObject());
   // There should be no hash table embedded. They would require rehashing.
   CHECK(!obj->IsHashTable());
+  // We expect no instantiated function objects or contexts.
+  CHECK(!obj->IsJSFunction() && !obj->IsContext());

   SerializeGeneric(obj, how_to_code, where_to_point);
 }
Index: test/mjsunit/deserialize-optimize-inner.js
diff --git a/test/mjsunit/debug-compile-optimized.js b/test/mjsunit/deserialize-optimize-inner.js
similarity index 54%
copy from test/mjsunit/debug-compile-optimized.js
copy to test/mjsunit/deserialize-optimize-inner.js
index 468605abaab079d4b19250b90fed7048bec205aa..72df32018af497936ca870ed8901e993f614dcbf 100644
--- a/test/mjsunit/debug-compile-optimized.js
+++ b/test/mjsunit/deserialize-optimize-inner.js
@@ -2,17 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.

-// Flags: --expose-debug-as debug --allow-natives-syntax --crankshaft
+// Flags: --allow-natives-syntax --cache=code --no-lazy --serialize-inner

-Debug = debug.Debug;
+function f(x, y) { return x + y; }

-Debug.setListener(function() {});
-
-function f() {}
-f();
-f();
+assertEquals(1, f(0, 1));
+assertEquals(5, f(2, 3));
 %OptimizeFunctionOnNextCall(f);
-f();
+assertEquals(9, f(4, 5));
 assertOptimized(f);
-
-Debug.setListener(null);


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