Special handling for inline caches in code serializer.
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
This commit is contained in:
parent
8325bfbfbf
commit
8cc5d418ee
@ -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());
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user