diff --git a/src/builtins.cc b/src/builtins.cc index 8b385aae87..27d30545e3 100644 --- a/src/builtins.cc +++ b/src/builtins.cc @@ -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()); diff --git a/src/execution.cc b/src/execution.cc index d198c5a4b8..cfe61f963a 100644 --- a/src/execution.cc +++ b/src/execution.cc @@ -37,13 +37,9 @@ void StackGuard::reset_limits(const ExecutionAccess& lock) { static void PrintDeserializedCodeInfo(Handle 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"); } } diff --git a/src/flag-definitions.h b/src/flag-definitions.h index 2f291a4993..c2abd0f5a1 100644 --- a/src/flag-definitions.h +++ b/src/flag-definitions.h @@ -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, diff --git a/src/objects-inl.h b/src/objects-inl.h index 91bd009224..a5b46a454a 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -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); } diff --git a/src/objects.h b/src/objects.h index af6bb667e1..d944bee72a 100644 --- a/src/objects.h +++ b/src/objects.h @@ -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); diff --git a/src/serialize.cc b/src/serialize.cc index 4933a19f01..5e6de03f63 100644 --- a/src/serialize.cc +++ b/src/serialize.cc @@ -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 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 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(&debug_sink) : static_cast(&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(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"); diff --git a/src/serialize.h b/src/serialize.h index 482bc34e5c..47a244f7c5 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -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); diff --git a/test/mjsunit/serialize-ic.js b/test/mjsunit/serialize-ic.js index 8f20b2758f..8e5cd2fd50 100644 --- a/test/mjsunit/serialize-ic.js +++ b/test/mjsunit/serialize-ic.js @@ -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);