Special handling for inline caches in code serializer.
authoryangguo@chromium.org <yangguo@chromium.org>
Mon, 20 Oct 2014 08:46:11 +0000 (08:46 +0000)
committeryangguo@chromium.org <yangguo@chromium.org>
Mon, 20 Oct 2014 08:46:11 +0000 (08:46 +0000)
R=mvstanton@chromium.org

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

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

src/builtins.cc
src/execution.cc
src/flag-definitions.h
src/objects-inl.h
src/objects.h
src/serialize.cc
src/serialize.h
test/mjsunit/serialize-ic.js

index 8b385aa..27d3054 100644 (file)
@@ -1574,7 +1574,7 @@ void Builtins::SetUp(Isolate* isolate, bool create_heap_objects) {
       PROFILE(isolate,
               CodeCreateEvent(Logger::BUILTIN_TAG, *code, functions[i].s_name));
       builtins_[i] = *code;
-      if (code->kind() == Code::BUILTIN) code->set_builtin_index(i);
+      code->set_builtin_index(i);
 #ifdef ENABLE_DISASSEMBLER
       if (FLAG_print_builtin_code) {
         CodeTracer::Scope trace_scope(isolate->GetCodeTracer());
index d198c5a..cfe61f9 100644 (file)
@@ -37,13 +37,9 @@ void StackGuard::reset_limits(const ExecutionAccess& lock) {
 static void PrintDeserializedCodeInfo(Handle<JSFunction> function) {
   if (function->code() == function->shared()->code() &&
       function->shared()->deserialized()) {
-    PrintF("Running deserialized script: ");
+    PrintF("Running deserialized script ");
     Object* script = function->shared()->script();
-    if (script->IsScript()) {
-      Script::cast(script)->name()->ShortPrint();
-    } else {
-      function->shared()->script()->ShortPrint();
-    }
+    if (script->IsScript()) Script::cast(script)->name()->ShortPrint();
     PrintF("\n");
   }
 }
index 2f291a4..c2abd0f 100644 (file)
@@ -445,7 +445,7 @@ DEFINE_BOOL(trace_stub_failures, false,
             "trace deoptimization of generated code stubs")
 
 DEFINE_BOOL(serialize_toplevel, false, "enable caching of toplevel scripts")
-DEFINE_BOOL(trace_code_serializer, false, "trace code serializer")
+DEFINE_INT(serializer_trace_level, 0, "trace code serializer (0 .. 2)")
 
 // compiler.cc
 DEFINE_INT(min_preparse_length, 1024,
index 91bd009..a5b46a4 100644 (file)
@@ -4833,13 +4833,11 @@ void Code::set_profiler_ticks(int ticks) {
 
 
 int Code::builtin_index() {
-  DCHECK_EQ(BUILTIN, kind());
   return READ_INT32_FIELD(this, kKindSpecificFlags1Offset);
 }
 
 
 void Code::set_builtin_index(int index) {
-  DCHECK_EQ(BUILTIN, kind());
   WRITE_INT32_FIELD(this, kKindSpecificFlags1Offset, index);
 }
 
index af6bb66..d944bee 100644 (file)
@@ -5150,6 +5150,10 @@ class Code: public HeapObject {
   inline void set_profiler_ticks(int ticks);
 
   // [builtin_index]: For BUILTIN kind, tells which builtin index it has.
+  // For builtins, tells which builtin index it has.
+  // Note that builtins can have a code kind other than BUILTIN, which means
+  // that for arbitrary code objects, this index value may be random garbage.
+  // To verify in that case, compare the code object to the indexed builtin.
   inline int builtin_index();
   inline void set_builtin_index(int id);
 
index 4933a19..5e6de03 100644 (file)
@@ -1184,13 +1184,8 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
       // Find a builtin and write a pointer to it to the current object.
       CASE_STATEMENT(kBuiltin, kPlain, kStartOfObject, 0)
       CASE_BODY(kBuiltin, kPlain, kStartOfObject, 0)
-#if V8_OOL_CONSTANT_POOL
-      // Find a builtin code entry and write a pointer to it to the current
-      // object.
       CASE_STATEMENT(kBuiltin, kPlain, kInnerPointer, 0)
       CASE_BODY(kBuiltin, kPlain, kInnerPointer, 0)
-#endif
-      // Find a builtin and write a pointer to it in the current code object.
       CASE_STATEMENT(kBuiltin, kFromCode, kInnerPointer, 0)
       CASE_BODY(kBuiltin, kFromCode, kInnerPointer, 0)
       // Find an object in the attached references and write a pointer to it to
@@ -1963,12 +1958,18 @@ ScriptData* CodeSerializer::Serialize(Isolate* isolate,
                                       Handle<String> source) {
   base::ElapsedTimer timer;
   if (FLAG_profile_deserialization) timer.Start();
+  if (FLAG_serializer_trace_level > 0) {
+    PrintF("[Serializing from");
+    Object* script = info->script();
+    if (script->IsScript()) Script::cast(script)->name()->ShortPrint();
+    PrintF("]\n");
+  }
 
   // Serialize code object.
   List<byte> payload;
   ListSnapshotSink list_sink(&payload);
   DebugSnapshotSink debug_sink(&list_sink);
-  SnapshotByteSink* sink = FLAG_trace_code_serializer
+  SnapshotByteSink* sink = FLAG_serializer_trace_level > 1
                                ? static_cast<SnapshotByteSink*>(&debug_sink)
                                : static_cast<SnapshotByteSink*>(&list_sink);
   CodeSerializer cs(isolate, sink, *source, info->code());
@@ -1997,13 +1998,16 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code,
 
   int root_index;
   if ((root_index = RootIndex(heap_object, how_to_code)) != kInvalidRootIndex) {
+    if (FLAG_serializer_trace_level > 0) {
+      PrintF(" Encoding root: %d\n", root_index);
+    }
     PutRoot(root_index, heap_object, how_to_code, where_to_point, skip);
     return;
   }
 
   if (address_mapper_.IsMapped(heap_object)) {
-    if (FLAG_trace_code_serializer) {
-      PrintF("Encoding back reference to: ");
+    if (FLAG_serializer_trace_level > 0) {
+      PrintF(" Encoding back reference to: ");
       heap_object->ShortPrint();
       PrintF("\n");
     }
@@ -2026,30 +2030,30 @@ 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);
+        SerializeBuiltin(code_object->builtin_index(), how_to_code,
+                         where_to_point);
         return;
       case Code::STUB:
-        SerializeCodeStub(code_object, how_to_code, where_to_point);
+        SerializeCodeStub(code_object->stub_key(), 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);
+        SerializeIC(code_object, how_to_code, where_to_point);
         return;
-      // TODO(yangguo): add special handling to canonicalize ICs.
       case Code::FUNCTION:
         // 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);
+          SerializeBuiltin(Builtins::kCompileLazy, how_to_code, where_to_point);
         } else {
           code_object->MakeYoung();
           SerializeHeapObject(code_object, how_to_code, where_to_point);
         }
         return;
     }
+    UNREACHABLE();
   }
 
   if (heap_object == source_) {
@@ -2071,8 +2075,8 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code,
 void CodeSerializer::SerializeHeapObject(HeapObject* heap_object,
                                          HowToCode how_to_code,
                                          WhereToPoint where_to_point) {
-  if (FLAG_trace_code_serializer) {
-    PrintF("Encoding heap object: ");
+  if (FLAG_serializer_trace_level > 0) {
+    PrintF(" Encoding heap object: ");
     heap_object->ShortPrint();
     PrintF("\n");
   }
@@ -2084,17 +2088,16 @@ void CodeSerializer::SerializeHeapObject(HeapObject* heap_object,
 }
 
 
-void CodeSerializer::SerializeBuiltin(Code* builtin, HowToCode how_to_code,
+void CodeSerializer::SerializeBuiltin(int builtin_index, HowToCode how_to_code,
                                       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));
-  int builtin_index = builtin->builtin_index();
   DCHECK_LT(builtin_index, Builtins::builtin_count);
   DCHECK_LE(0, builtin_index);
 
-  if (FLAG_trace_code_serializer) {
-    PrintF("Encoding builtin: %s\n",
+  if (FLAG_serializer_trace_level > 0) {
+    PrintF(" Encoding builtin: %s\n",
            isolate()->builtins()->name(builtin_index));
   }
 
@@ -2103,19 +2106,18 @@ void CodeSerializer::SerializeBuiltin(Code* builtin, HowToCode how_to_code,
 }
 
 
-void CodeSerializer::SerializeCodeStub(Code* stub, HowToCode how_to_code,
+void CodeSerializer::SerializeCodeStub(uint32_t stub_key, HowToCode how_to_code,
                                        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);
   DCHECK(!CodeStub::GetCode(isolate(), stub_key).is_null());
 
   int index = AddCodeStubKey(stub_key) + kCodeStubsBaseIndex;
 
-  if (FLAG_trace_code_serializer) {
-    PrintF("Encoding code stub %s as %d\n",
+  if (FLAG_serializer_trace_level > 0) {
+    PrintF(" Encoding code stub %s as %d\n",
            CodeStub::MajorName(CodeStub::MajorKeyFromKey(stub_key), false),
            index);
   }
@@ -2125,6 +2127,44 @@ void CodeSerializer::SerializeCodeStub(Code* stub, HowToCode how_to_code,
 }
 
 
+void CodeSerializer::SerializeIC(Code* ic, HowToCode how_to_code,
+                                 WhereToPoint where_to_point) {
+  // The IC may be implemented as a stub.
+  uint32_t stub_key = ic->stub_key();
+  if (stub_key != CodeStub::NoCacheKey()) {
+    if (FLAG_serializer_trace_level > 0) {
+      PrintF(" %s is a code stub\n", Code::Kind2String(ic->kind()));
+    }
+    SerializeCodeStub(stub_key, how_to_code, where_to_point);
+    return;
+  }
+  // The IC may be implemented as builtin. Only real builtins have an
+  // actual builtin_index value attached (otherwise it's just garbage).
+  // Compare to make sure we are really dealing with a builtin.
+  int builtin_index = ic->builtin_index();
+  if (builtin_index < Builtins::builtin_count) {
+    Builtins::Name name = static_cast<Builtins::Name>(builtin_index);
+    Code* builtin = isolate()->builtins()->builtin(name);
+    if (builtin == ic) {
+      if (FLAG_serializer_trace_level > 0) {
+        PrintF(" %s is a builtin\n", Code::Kind2String(ic->kind()));
+      }
+      DCHECK(ic->kind() == Code::KEYED_LOAD_IC ||
+             ic->kind() == Code::KEYED_STORE_IC);
+      SerializeBuiltin(builtin_index, how_to_code, where_to_point);
+      return;
+    }
+  }
+  // The IC may also just be a piece of code kept in the non_monomorphic_cache.
+  // In that case, just serialize as a normal code object.
+  if (FLAG_serializer_trace_level > 0) {
+    PrintF(" %s has no special handling\n", Code::Kind2String(ic->kind()));
+  }
+  DCHECK(ic->kind() == Code::LOAD_IC || ic->kind() == Code::STORE_IC);
+  SerializeHeapObject(ic, how_to_code, where_to_point);
+}
+
+
 int CodeSerializer::AddCodeStubKey(uint32_t stub_key) {
   // TODO(yangguo) Maybe we need a hash table for a faster lookup than O(n^2).
   int index = 0;
@@ -2139,7 +2179,7 @@ int CodeSerializer::AddCodeStubKey(uint32_t stub_key) {
 
 void CodeSerializer::SerializeSourceObject(HowToCode how_to_code,
                                            WhereToPoint where_to_point) {
-  if (FLAG_trace_code_serializer) PrintF("Encoding source object\n");
+  if (FLAG_serializer_trace_level > 0) 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 482bc34..47a244f 100644 (file)
@@ -637,9 +637,11 @@ class CodeSerializer : public Serializer {
   virtual void SerializeObject(Object* o, HowToCode how_to_code,
                                WhereToPoint where_to_point, int skip);
 
-  void SerializeBuiltin(Code* builtin, HowToCode how_to_code,
+  void SerializeBuiltin(int builtin_index, HowToCode how_to_code,
                         WhereToPoint where_to_point);
-  void SerializeCodeStub(Code* stub, HowToCode how_to_code,
+  void SerializeIC(Code* ic, HowToCode how_to_code,
+                   WhereToPoint where_to_point);
+  void SerializeCodeStub(uint32_t stub_key, HowToCode how_to_code,
                          WhereToPoint where_to_point);
   void SerializeSourceObject(HowToCode how_to_code,
                              WhereToPoint where_to_point);
index 8f20b27..8e5cd2f 100644 (file)
@@ -7,3 +7,12 @@
 var foo = [];
 foo[0] = "bar";
 assertEquals(["bar"], foo);
+
+var a;
+var b = 1;
+a = [2];               // STORE_IC
+a[0] = a[0] + 1;       // KEYED_STORE_IC, KEYED_LOAD_IC, BINARY_OP_IC
+assertTrue(a[0] > b);  // CALL_IC, COMPARE_IC
+b = b == null;         // COMPARE_NIL_IC
+b = b || Boolean('');  // TO_BOOLEAN_IC
+assertFalse(b);