Commit a8e82da6 authored by yangguo's avatar yangguo Committed by Commit bot

Serializer: simplify external reference encoding.

External references are encoded as a tuple of type and ID. This
requires both the external reference encode and the decoder to
create a mapping between the encoding and the external reference
table index.

Instead, we simply use the external reference table index as
encoding.

We now also assume that there are no duplicate entries. Existing
duplicates have been removed in this change.

R=vogelheim@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#27033}
parent d67f4818
...@@ -861,7 +861,8 @@ void RelocInfo::Print(Isolate* isolate, std::ostream& os) { // NOLINT ...@@ -861,7 +861,8 @@ void RelocInfo::Print(Isolate* isolate, std::ostream& os) { // NOLINT
os << " (" << Brief(target_object()) << ")"; os << " (" << Brief(target_object()) << ")";
} else if (rmode_ == EXTERNAL_REFERENCE) { } else if (rmode_ == EXTERNAL_REFERENCE) {
ExternalReferenceEncoder ref_encoder(isolate); ExternalReferenceEncoder ref_encoder(isolate);
os << " (" << ref_encoder.NameOfAddress(target_external_reference()) os << " ("
<< ref_encoder.NameOfAddress(isolate, target_external_reference())
<< ") (" << static_cast<const void*>(target_external_reference()) << ") (" << static_cast<const void*>(target_external_reference())
<< ")"; << ")";
} else if (IsCodeTarget(rmode_)) { } else if (IsCodeTarget(rmode_)) {
......
...@@ -185,8 +185,8 @@ static int DecodeIt(Isolate* isolate, std::ostream* os, ...@@ -185,8 +185,8 @@ static int DecodeIt(Isolate* isolate, std::ostream* os,
SmartArrayPointer<const char> obj_name = accumulator.ToCString(); SmartArrayPointer<const char> obj_name = accumulator.ToCString();
out.AddFormatted(" ;; object: %s", obj_name.get()); out.AddFormatted(" ;; object: %s", obj_name.get());
} else if (rmode == RelocInfo::EXTERNAL_REFERENCE) { } else if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
const char* reference_name = const char* reference_name = ref_encoder.NameOfAddress(
ref_encoder.NameOfAddress(relocinfo.target_external_reference()); isolate, relocinfo.target_external_reference());
out.AddFormatted(" ;; external reference (%s)", reference_name); out.AddFormatted(" ;; external reference (%s)", reference_name);
} else if (RelocInfo::IsCodeTarget(rmode)) { } else if (RelocInfo::IsCodeTarget(rmode)) {
out.AddFormatted(" ;; code:"); out.AddFormatted(" ;; code:");
......
...@@ -32,20 +32,6 @@ namespace internal { ...@@ -32,20 +32,6 @@ namespace internal {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Coding of external references. // Coding of external references.
// The encoding of an external reference. The type is in the high word.
// The id is in the low word.
static uint32_t EncodeExternal(TypeCode type, uint16_t id) {
return static_cast<uint32_t>(type) << 16 | id;
}
static int* GetInternalPointer(StatsCounter* counter) {
// All counters refer to dummy_counter, if deserializing happens without
// setting up counters.
static int dummy_counter = 0;
return counter->Enabled() ? counter->GetInternalPointer() : &dummy_counter;
}
ExternalReferenceTable* ExternalReferenceTable::instance(Isolate* isolate) { ExternalReferenceTable* ExternalReferenceTable::instance(Isolate* isolate) {
ExternalReferenceTable* external_reference_table = ExternalReferenceTable* external_reference_table =
...@@ -58,63 +44,7 @@ ExternalReferenceTable* ExternalReferenceTable::instance(Isolate* isolate) { ...@@ -58,63 +44,7 @@ ExternalReferenceTable* ExternalReferenceTable::instance(Isolate* isolate) {
} }
void ExternalReferenceTable::AddFromId(TypeCode type, ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) {
uint16_t id,
const char* name,
Isolate* isolate) {
Address address;
switch (type) {
case C_BUILTIN: {
ExternalReference ref(static_cast<Builtins::CFunctionId>(id), isolate);
address = ref.address();
break;
}
case BUILTIN: {
ExternalReference ref(static_cast<Builtins::Name>(id), isolate);
address = ref.address();
break;
}
case RUNTIME_FUNCTION: {
ExternalReference ref(static_cast<Runtime::FunctionId>(id), isolate);
address = ref.address();
break;
}
case IC_UTILITY: {
ExternalReference ref(IC_Utility(static_cast<IC::UtilityId>(id)),
isolate);
address = ref.address();
break;
}
default:
UNREACHABLE();
return;
}
Add(address, type, id, name);
}
void ExternalReferenceTable::Add(Address address,
TypeCode type,
uint16_t id,
const char* name) {
DCHECK_NOT_NULL(address);
ExternalReferenceEntry entry;
entry.address = address;
entry.code = EncodeExternal(type, id);
entry.name = name;
DCHECK_NE(0u, entry.code);
// Assert that the code is added in ascending order to rule out duplicates.
DCHECK((size() == 0) || (code(size() - 1) < entry.code));
refs_.Add(entry);
if (id > max_id_[type]) max_id_[type] = id;
}
void ExternalReferenceTable::PopulateTable(Isolate* isolate) {
for (int type_code = 0; type_code < kTypeCodeCount; type_code++) {
max_id_[type_code] = 0;
}
// Miscellaneous // Miscellaneous
Add(ExternalReference::roots_array_start(isolate).address(), Add(ExternalReference::roots_array_start(isolate).address(),
"Heap::roots_array_start()"); "Heap::roots_array_start()");
...@@ -179,10 +109,6 @@ void ExternalReferenceTable::PopulateTable(Isolate* isolate) { ...@@ -179,10 +109,6 @@ void ExternalReferenceTable::PopulateTable(Isolate* isolate) {
Add(ExternalReference::get_make_code_young_function(isolate).address(), Add(ExternalReference::get_make_code_young_function(isolate).address(),
"Code::MakeCodeYoung"); "Code::MakeCodeYoung");
Add(ExternalReference::cpu_features().address(), "cpu_features"); Add(ExternalReference::cpu_features().address(), "cpu_features");
Add(ExternalReference(Runtime::kAllocateInNewSpace, isolate).address(),
"Runtime::AllocateInNewSpace");
Add(ExternalReference(Runtime::kAllocateInTargetSpace, isolate).address(),
"Runtime::AllocateInTargetSpace");
Add(ExternalReference::old_pointer_space_allocation_top_address(isolate) Add(ExternalReference::old_pointer_space_allocation_top_address(isolate)
.address(), .address(),
"Heap::OldPointerSpaceAllocationTopAddress"); "Heap::OldPointerSpaceAllocationTopAddress");
...@@ -218,9 +144,6 @@ void ExternalReferenceTable::PopulateTable(Isolate* isolate) { ...@@ -218,9 +144,6 @@ void ExternalReferenceTable::PopulateTable(Isolate* isolate) {
"double_constants.minus_one_half"); "double_constants.minus_one_half");
Add(ExternalReference::stress_deopt_count(isolate).address(), Add(ExternalReference::stress_deopt_count(isolate).address(),
"Isolate::stress_deopt_count_address()"); "Isolate::stress_deopt_count_address()");
Add(ExternalReference::incremental_marking_record_write_function(isolate)
.address(),
"IncrementalMarking::RecordWriteFromCode");
// Debug addresses // Debug addresses
Add(ExternalReference::debug_after_break_target_address(isolate).address(), Add(ExternalReference::debug_after_break_target_address(isolate).address(),
...@@ -260,143 +183,151 @@ void ExternalReferenceTable::PopulateTable(Isolate* isolate) { ...@@ -260,143 +183,151 @@ void ExternalReferenceTable::PopulateTable(Isolate* isolate) {
// new references. // new references.
struct RefTableEntry { struct RefTableEntry {
TypeCode type;
uint16_t id; uint16_t id;
const char* name; const char* name;
}; };
static const RefTableEntry ref_table[] = { static const RefTableEntry c_builtins[] = {
// Builtins #define DEF_ENTRY_C(name, ignored) \
#define DEF_ENTRY_C(name, ignored) \ { Builtins::c_##name, "Builtins::" #name } \
{ C_BUILTIN, \ ,
Builtins::c_##name, \ BUILTIN_LIST_C(DEF_ENTRY_C)
"Builtins::" #name },
BUILTIN_LIST_C(DEF_ENTRY_C)
#undef DEF_ENTRY_C #undef DEF_ENTRY_C
};
#define DEF_ENTRY_C(name, ignored) \ for (unsigned i = 0; i < arraysize(c_builtins); ++i) {
{ BUILTIN, \ ExternalReference ref(static_cast<Builtins::CFunctionId>(c_builtins[i].id),
Builtins::k##name, \ isolate);
"Builtins::" #name }, Add(ref.address(), c_builtins[i].name);
#define DEF_ENTRY_A(name, kind, state, extra) DEF_ENTRY_C(name, ignored) }
BUILTIN_LIST_C(DEF_ENTRY_C) static const RefTableEntry builtins[] = {
BUILTIN_LIST_A(DEF_ENTRY_A) #define DEF_ENTRY_C(name, ignored) \
BUILTIN_LIST_DEBUG_A(DEF_ENTRY_A) { Builtins::k##name, "Builtins::" #name } \
,
#define DEF_ENTRY_A(name, i1, i2, i3) \
{ Builtins::k##name, "Builtins::" #name } \
,
BUILTIN_LIST_C(DEF_ENTRY_C) BUILTIN_LIST_A(DEF_ENTRY_A)
BUILTIN_LIST_DEBUG_A(DEF_ENTRY_A)
#undef DEF_ENTRY_C #undef DEF_ENTRY_C
#undef DEF_ENTRY_A #undef DEF_ENTRY_A
};
// Runtime functions for (unsigned i = 0; i < arraysize(builtins); ++i) {
#define RUNTIME_ENTRY(name, nargs, ressize) \ ExternalReference ref(static_cast<Builtins::Name>(builtins[i].id), isolate);
{ RUNTIME_FUNCTION, \ Add(ref.address(), builtins[i].name);
Runtime::k##name, \ }
"Runtime::" #name },
RUNTIME_FUNCTION_LIST(RUNTIME_ENTRY) static const RefTableEntry runtime_functions[] = {
INLINE_OPTIMIZED_FUNCTION_LIST(RUNTIME_ENTRY) #define RUNTIME_ENTRY(name, i1, i2) \
{ Runtime::k##name, "Runtime::" #name } \
,
RUNTIME_FUNCTION_LIST(RUNTIME_ENTRY)
INLINE_OPTIMIZED_FUNCTION_LIST(RUNTIME_ENTRY)
#undef RUNTIME_ENTRY #undef RUNTIME_ENTRY
};
#define INLINE_OPTIMIZED_ENTRY(name, nargs, ressize) \ for (unsigned i = 0; i < arraysize(runtime_functions); ++i) {
{ RUNTIME_FUNCTION, \ ExternalReference ref(
Runtime::kInlineOptimized##name, \ static_cast<Runtime::FunctionId>(runtime_functions[i].id), isolate);
"Runtime::" #name }, Add(ref.address(), runtime_functions[i].name);
}
INLINE_OPTIMIZED_FUNCTION_LIST(INLINE_OPTIMIZED_ENTRY)
#undef INLINE_OPTIMIZED_ENTRY
// IC utilities
#define IC_ENTRY(name) \
{ IC_UTILITY, \
IC::k##name, \
"IC::" #name },
IC_UTIL_LIST(IC_ENTRY) static const RefTableEntry inline_caches[] = {
#define IC_ENTRY(name) \
{ IC::k##name, "IC::" #name } \
,
IC_UTIL_LIST(IC_ENTRY)
#undef IC_ENTRY #undef IC_ENTRY
}; // end of ref_table[]. };
for (size_t i = 0; i < arraysize(ref_table); ++i) { for (unsigned i = 0; i < arraysize(inline_caches); ++i) {
AddFromId(ref_table[i].type, ExternalReference ref(
ref_table[i].id, IC_Utility(static_cast<IC::UtilityId>(inline_caches[i].id)), isolate);
ref_table[i].name, Add(ref.address(), runtime_functions[i].name);
isolate);
} }
// Stat counters // Stat counters
struct StatsRefTableEntry { struct StatsRefTableEntry {
StatsCounter* (Counters::*counter)(); StatsCounter* (Counters::*counter)();
uint16_t id;
const char* name; const char* name;
}; };
const StatsRefTableEntry stats_ref_table[] = { static const StatsRefTableEntry stats_ref_table[] = {
#define COUNTER_ENTRY(name, caption) \ #define COUNTER_ENTRY(name, caption) \
{ &Counters::name, \ { &Counters::name, "Counters::" #name } \
Counters::k_##name, \ ,
"Counters::" #name }, STATS_COUNTER_LIST_1(COUNTER_ENTRY) STATS_COUNTER_LIST_2(COUNTER_ENTRY)
STATS_COUNTER_LIST_1(COUNTER_ENTRY)
STATS_COUNTER_LIST_2(COUNTER_ENTRY)
#undef COUNTER_ENTRY #undef COUNTER_ENTRY
}; // end of stats_ref_table[]. };
Counters* counters = isolate->counters(); Counters* counters = isolate->counters();
for (size_t i = 0; i < arraysize(stats_ref_table); ++i) { for (unsigned i = 0; i < arraysize(stats_ref_table); ++i) {
Add(reinterpret_cast<Address>(GetInternalPointer( // To make sure the indices are not dependent on whether counters are
(counters->*(stats_ref_table[i].counter))())), // enabled, use a dummy address as filler.
STATS_COUNTER, Address address = NotAvailable();
stats_ref_table[i].id, StatsCounter* counter = (counters->*(stats_ref_table[i].counter))();
stats_ref_table[i].name); if (counter->Enabled()) {
address = reinterpret_cast<Address>(counter->GetInternalPointer());
}
Add(address, stats_ref_table[i].name);
} }
// Top addresses // Top addresses
static const char* address_names[] = {
const char* AddressNames[] = { #define BUILD_NAME_LITERAL(Name, name) "Isolate::" #name "_address",
#define BUILD_NAME_LITERAL(CamelName, hacker_name) \ FOR_EACH_ISOLATE_ADDRESS_NAME(BUILD_NAME_LITERAL) NULL
"Isolate::" #hacker_name "_address",
FOR_EACH_ISOLATE_ADDRESS_NAME(BUILD_NAME_LITERAL)
NULL
#undef BUILD_NAME_LITERAL #undef BUILD_NAME_LITERAL
}; };
for (uint16_t i = 0; i < Isolate::kIsolateAddressCount; ++i) { for (int i = 0; i < Isolate::kIsolateAddressCount; ++i) {
Add(isolate->get_address_from_id((Isolate::AddressId)i), Add(isolate->get_address_from_id(static_cast<Isolate::AddressId>(i)),
TOP_ADDRESS, i, AddressNames[i]); address_names[i]);
} }
// Accessors // Accessors
#define ACCESSOR_INFO_DECLARATION(name) \ struct AccessorRefTable {
Add(FUNCTION_ADDR(&Accessors::name##Getter), ACCESSOR_CODE, \ Address address;
Accessors::k##name##Getter, "Accessors::" #name "Getter"); \ const char* name;
Add(FUNCTION_ADDR(&Accessors::name##Setter), ACCESSOR_CODE, \ };
Accessors::k##name##Setter, "Accessors::" #name "Setter");
ACCESSOR_INFO_LIST(ACCESSOR_INFO_DECLARATION) static const AccessorRefTable accessors[] = {
#define ACCESSOR_INFO_DECLARATION(name) \
{ FUNCTION_ADDR(&Accessors::name##Getter), "Accessors::" #name "Getter" } \
, {FUNCTION_ADDR(&Accessors::name##Setter), "Accessors::" #name "Setter"},
ACCESSOR_INFO_LIST(ACCESSOR_INFO_DECLARATION)
#undef ACCESSOR_INFO_DECLARATION #undef ACCESSOR_INFO_DECLARATION
};
for (unsigned i = 0; i < arraysize(accessors); ++i) {
Add(accessors[i].address, accessors[i].name);
}
StubCache* stub_cache = isolate->stub_cache(); StubCache* stub_cache = isolate->stub_cache();
// Stub cache tables // Stub cache tables
Add(stub_cache->key_reference(StubCache::kPrimary).address(), Add(stub_cache->key_reference(StubCache::kPrimary).address(),
STUB_CACHE_TABLE, 1, "StubCache::primary_->key"); "StubCache::primary_->key");
Add(stub_cache->value_reference(StubCache::kPrimary).address(), Add(stub_cache->value_reference(StubCache::kPrimary).address(),
STUB_CACHE_TABLE, 2, "StubCache::primary_->value"); "StubCache::primary_->value");
Add(stub_cache->map_reference(StubCache::kPrimary).address(), Add(stub_cache->map_reference(StubCache::kPrimary).address(),
STUB_CACHE_TABLE, 3, "StubCache::primary_->map"); "StubCache::primary_->map");
Add(stub_cache->key_reference(StubCache::kSecondary).address(), Add(stub_cache->key_reference(StubCache::kSecondary).address(),
STUB_CACHE_TABLE, 4, "StubCache::secondary_->key"); "StubCache::secondary_->key");
Add(stub_cache->value_reference(StubCache::kSecondary).address(), Add(stub_cache->value_reference(StubCache::kSecondary).address(),
STUB_CACHE_TABLE, 5, "StubCache::secondary_->value"); "StubCache::secondary_->value");
Add(stub_cache->map_reference(StubCache::kSecondary).address(), Add(stub_cache->map_reference(StubCache::kSecondary).address(),
STUB_CACHE_TABLE, 6, "StubCache::secondary_->map"); "StubCache::secondary_->map");
// Runtime entries // Runtime entries
Add(ExternalReference::delete_handle_scope_extensions(isolate).address(), Add(ExternalReference::delete_handle_scope_extensions(isolate).address(),
RUNTIME_ENTRY, 1, "HandleScope::DeleteExtensions"); "HandleScope::DeleteExtensions");
Add(ExternalReference::incremental_marking_record_write_function(isolate) Add(ExternalReference::incremental_marking_record_write_function(isolate)
.address(), .address(),
RUNTIME_ENTRY, 2, "IncrementalMarking::RecordWrite"); "IncrementalMarking::RecordWrite");
Add(ExternalReference::store_buffer_overflow_function(isolate).address(), Add(ExternalReference::store_buffer_overflow_function(isolate).address(),
RUNTIME_ENTRY, 3, "StoreBuffer::StoreBufferOverflow"); "StoreBuffer::StoreBufferOverflow");
// Add a small set of deopt entry addresses to encoder without generating the // Add a small set of deopt entry addresses to encoder without generating the
// deopt table code, which isn't possible at deserialization time. // deopt table code, which isn't possible at deserialization time.
...@@ -407,78 +338,44 @@ void ExternalReferenceTable::PopulateTable(Isolate* isolate) { ...@@ -407,78 +338,44 @@ void ExternalReferenceTable::PopulateTable(Isolate* isolate) {
entry, entry,
Deoptimizer::LAZY, Deoptimizer::LAZY,
Deoptimizer::CALCULATE_ENTRY_ADDRESS); Deoptimizer::CALCULATE_ENTRY_ADDRESS);
Add(address, LAZY_DEOPTIMIZATION, entry, "lazy_deopt"); Add(address, "lazy_deopt");
} }
} }
ExternalReferenceEncoder::ExternalReferenceEncoder(Isolate* isolate) ExternalReferenceEncoder::ExternalReferenceEncoder(Isolate* isolate)
: encodings_(HashMap::PointersMatch), : map_(HashMap::PointersMatch) {
isolate_(isolate) { ExternalReferenceTable* table = ExternalReferenceTable::instance(isolate);
ExternalReferenceTable* external_references = for (int i = 0; i < table->size(); ++i) {
ExternalReferenceTable::instance(isolate_); Address addr = table->address(i);
for (int i = 0; i < external_references->size(); ++i) { if (addr == ExternalReferenceTable::NotAvailable()) continue;
Put(external_references->address(i), i); // We expect no duplicate external references entries in the table.
DCHECK_NULL(map_.Lookup(addr, Hash(addr), false));
map_.Lookup(addr, Hash(addr), true)->value = reinterpret_cast<void*>(i);
} }
} }
uint32_t ExternalReferenceEncoder::Encode(Address key) const { uint32_t ExternalReferenceEncoder::Encode(Address address) const {
int index = IndexOf(key); DCHECK_NOT_NULL(address);
DCHECK(key == NULL || index >= 0);
return index >= 0 ?
ExternalReferenceTable::instance(isolate_)->code(index) : 0;
}
const char* ExternalReferenceEncoder::NameOfAddress(Address key) const {
int index = IndexOf(key);
return index >= 0 ? ExternalReferenceTable::instance(isolate_)->name(index)
: "<unknown>";
}
int ExternalReferenceEncoder::IndexOf(Address key) const {
if (key == NULL) return -1;
HashMap::Entry* entry = HashMap::Entry* entry =
const_cast<HashMap&>(encodings_).Lookup(key, Hash(key), false); const_cast<HashMap&>(map_).Lookup(address, Hash(address), false);
return entry == NULL DCHECK_NOT_NULL(entry);
? -1 return static_cast<uint32_t>(reinterpret_cast<intptr_t>(entry->value));
: static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
} }
void ExternalReferenceEncoder::Put(Address key, int index) { const char* ExternalReferenceEncoder::NameOfAddress(Isolate* isolate,
HashMap::Entry* entry = encodings_.Lookup(key, Hash(key), true); Address address) const {
entry->value = reinterpret_cast<void*>(index); HashMap::Entry* entry =
} const_cast<HashMap&>(map_).Lookup(address, Hash(address), false);
if (entry == NULL) return "<unknown>";
uint32_t i = static_cast<uint32_t>(reinterpret_cast<intptr_t>(entry->value));
ExternalReferenceDecoder::ExternalReferenceDecoder(Isolate* isolate) return ExternalReferenceTable::instance(isolate)->name(i);
: encodings_(NewArray<Address*>(kTypeCodeCount)),
isolate_(isolate) {
ExternalReferenceTable* external_references =
ExternalReferenceTable::instance(isolate_);
for (int type = kFirstTypeCode; type < kTypeCodeCount; ++type) {
int max = external_references->max_id(type) + 1;
encodings_[type] = NewArray<Address>(max + 1);
}
for (int i = 0; i < external_references->size(); ++i) {
Put(external_references->code(i), external_references->address(i));
}
}
ExternalReferenceDecoder::~ExternalReferenceDecoder() {
for (int type = kFirstTypeCode; type < kTypeCodeCount; ++type) {
DeleteArray(encodings_[type]);
}
DeleteArray(encodings_);
} }
RootIndexMap::RootIndexMap(Isolate* isolate) { RootIndexMap::RootIndexMap(Isolate* isolate) : map_(HashMap::PointersMatch) {
map_ = new HashMap(HashMap::PointersMatch);
Object** root_array = isolate->heap()->roots_array_start(); Object** root_array = isolate->heap()->roots_array_start();
for (uint32_t i = 0; i < Heap::kStrongRootListLength; i++) { for (uint32_t i = 0; i < Heap::kStrongRootListLength; i++) {
Heap::RootListIndex root_index = static_cast<Heap::RootListIndex>(i); Heap::RootListIndex root_index = static_cast<Heap::RootListIndex>(i);
...@@ -488,12 +385,12 @@ RootIndexMap::RootIndexMap(Isolate* isolate) { ...@@ -488,12 +385,12 @@ RootIndexMap::RootIndexMap(Isolate* isolate) {
if (root->IsHeapObject() && if (root->IsHeapObject() &&
isolate->heap()->RootCanBeTreatedAsConstant(root_index)) { isolate->heap()->RootCanBeTreatedAsConstant(root_index)) {
HeapObject* heap_object = HeapObject::cast(root); HeapObject* heap_object = HeapObject::cast(root);
HashMap::Entry* entry = LookupEntry(map_, heap_object, false); HashMap::Entry* entry = LookupEntry(&map_, heap_object, false);
if (entry != NULL) { if (entry != NULL) {
// Some are initialized to a previous value in the root list. // Some are initialized to a previous value in the root list.
DCHECK_LT(GetValue(entry), i); DCHECK_LT(GetValue(entry), i);
} else { } else {
SetValue(LookupEntry(map_, heap_object, true), i); SetValue(LookupEntry(&map_, heap_object, true), i);
} }
} }
} }
...@@ -654,8 +551,10 @@ void Deserializer::Initialize(Isolate* isolate) { ...@@ -654,8 +551,10 @@ void Deserializer::Initialize(Isolate* isolate) {
DCHECK_NULL(isolate_); DCHECK_NULL(isolate_);
DCHECK_NOT_NULL(isolate); DCHECK_NOT_NULL(isolate);
isolate_ = isolate; isolate_ = isolate;
DCHECK_NULL(external_reference_decoder_); DCHECK_NULL(external_reference_table_);
external_reference_decoder_ = new ExternalReferenceDecoder(isolate); external_reference_table_ = ExternalReferenceTable::instance(isolate);
CHECK_EQ(magic_number_,
SerializedData::ComputeMagicNumber(external_reference_table_));
} }
...@@ -751,10 +650,6 @@ MaybeHandle<SharedFunctionInfo> Deserializer::DeserializeCode( ...@@ -751,10 +650,6 @@ MaybeHandle<SharedFunctionInfo> Deserializer::DeserializeCode(
Deserializer::~Deserializer() { Deserializer::~Deserializer() {
// TODO(svenpanne) Re-enable this assertion when v8 initialization is fixed. // TODO(svenpanne) Re-enable this assertion when v8 initialization is fixed.
// DCHECK(source_.AtEOF()); // DCHECK(source_.AtEOF());
if (external_reference_decoder_) {
delete external_reference_decoder_;
external_reference_decoder_ = NULL;
}
attached_objects_.Dispose(); attached_objects_.Dispose();
} }
...@@ -1004,7 +899,7 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space, ...@@ -1004,7 +899,7 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
current = reinterpret_cast<Object**>( \ current = reinterpret_cast<Object**>( \
reinterpret_cast<Address>(current) + skip); \ reinterpret_cast<Address>(current) + skip); \
int reference_id = source_.GetInt(); \ int reference_id = source_.GetInt(); \
Address address = external_reference_decoder_->Decode(reference_id); \ Address address = external_reference_table_->address(reference_id); \
new_object = reinterpret_cast<Object*>(address); \ new_object = reinterpret_cast<Object*>(address); \
} else if (where == kBackref) { \ } else if (where == kBackref) { \
emit_write_barrier = (space_number == NEW_SPACE); \ emit_write_barrier = (space_number == NEW_SPACE); \
...@@ -2387,7 +2282,7 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize( ...@@ -2387,7 +2282,7 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
HandleScope scope(isolate); HandleScope scope(isolate);
SmartPointer<SerializedCodeData> scd( SmartPointer<SerializedCodeData> scd(
SerializedCodeData::FromCachedData(cached_data, *source)); SerializedCodeData::FromCachedData(isolate, cached_data, *source));
if (scd.is_empty()) { if (scd.is_empty()) {
if (FLAG_profile_deserialization) PrintF("[Cached code failed check]\n"); if (FLAG_profile_deserialization) PrintF("[Cached code failed check]\n");
DCHECK(cached_data->rejected()); DCHECK(cached_data->rejected());
...@@ -2465,6 +2360,7 @@ SnapshotData::SnapshotData(const Serializer& ser) { ...@@ -2465,6 +2360,7 @@ SnapshotData::SnapshotData(const Serializer& ser) {
AllocateData(size); AllocateData(size);
// Set header values. // Set header values.
SetMagicNumber(ser.isolate());
SetHeaderValue(kCheckSumOffset, Version::Hash()); SetHeaderValue(kCheckSumOffset, Version::Hash());
SetHeaderValue(kNumReservationsOffset, reservations.length()); SetHeaderValue(kNumReservationsOffset, reservations.length());
SetHeaderValue(kPayloadLengthOffset, payload.length()); SetHeaderValue(kPayloadLengthOffset, payload.length());
...@@ -2555,7 +2451,7 @@ SerializedCodeData::SerializedCodeData(const List<byte>& payload, ...@@ -2555,7 +2451,7 @@ SerializedCodeData::SerializedCodeData(const List<byte>& payload,
AllocateData(size); AllocateData(size);
// Set header values. // Set header values.
SetHeaderValue(kMagicNumberOffset, kMagicNumber); SetMagicNumber(cs.isolate());
SetHeaderValue(kVersionHashOffset, Version::Hash()); SetHeaderValue(kVersionHashOffset, Version::Hash());
SetHeaderValue(kSourceHashOffset, SourceHash(cs.source())); SetHeaderValue(kSourceHashOffset, SourceHash(cs.source()));
SetHeaderValue(kCpuFeaturesOffset, SetHeaderValue(kCpuFeaturesOffset,
...@@ -2587,15 +2483,15 @@ SerializedCodeData::SerializedCodeData(const List<byte>& payload, ...@@ -2587,15 +2483,15 @@ SerializedCodeData::SerializedCodeData(const List<byte>& payload,
SerializedCodeData::SanityCheckResult SerializedCodeData::SanityCheck( SerializedCodeData::SanityCheckResult SerializedCodeData::SanityCheck(
String* source) const { Isolate* isolate, String* source) const {
uint32_t magic_number = GetHeaderValue(kMagicNumberOffset); uint32_t magic_number = GetMagicNumber();
uint32_t version_hash = GetHeaderValue(kVersionHashOffset); uint32_t version_hash = GetHeaderValue(kVersionHashOffset);
uint32_t source_hash = GetHeaderValue(kSourceHashOffset); uint32_t source_hash = GetHeaderValue(kSourceHashOffset);
uint32_t cpu_features = GetHeaderValue(kCpuFeaturesOffset); uint32_t cpu_features = GetHeaderValue(kCpuFeaturesOffset);
uint32_t flags_hash = GetHeaderValue(kFlagHashOffset); uint32_t flags_hash = GetHeaderValue(kFlagHashOffset);
uint32_t c1 = GetHeaderValue(kChecksum1Offset); uint32_t c1 = GetHeaderValue(kChecksum1Offset);
uint32_t c2 = GetHeaderValue(kChecksum2Offset); uint32_t c2 = GetHeaderValue(kChecksum2Offset);
if (magic_number != kMagicNumber) return MAGIC_NUMBER_MISMATCH; if (magic_number != ComputeMagicNumber(isolate)) return MAGIC_NUMBER_MISMATCH;
if (version_hash != Version::Hash()) return VERSION_MISMATCH; if (version_hash != Version::Hash()) return VERSION_MISMATCH;
if (source_hash != SourceHash(source)) return SOURCE_MISMATCH; if (source_hash != SourceHash(source)) return SOURCE_MISMATCH;
if (cpu_features != static_cast<uint32_t>(CpuFeatures::SupportedFeatures())) { if (cpu_features != static_cast<uint32_t>(CpuFeatures::SupportedFeatures())) {
...@@ -2655,11 +2551,12 @@ SerializedCodeData::SerializedCodeData(ScriptData* data) ...@@ -2655,11 +2551,12 @@ SerializedCodeData::SerializedCodeData(ScriptData* data)
: SerializedData(const_cast<byte*>(data->data()), data->length()) {} : SerializedData(const_cast<byte*>(data->data()), data->length()) {}
SerializedCodeData* SerializedCodeData::FromCachedData(ScriptData* cached_data, SerializedCodeData* SerializedCodeData::FromCachedData(Isolate* isolate,
ScriptData* cached_data,
String* source) { String* source) {
DisallowHeapAllocation no_gc; DisallowHeapAllocation no_gc;
SerializedCodeData* scd = new SerializedCodeData(cached_data); SerializedCodeData* scd = new SerializedCodeData(cached_data);
SanityCheckResult r = scd->SanityCheck(source); SanityCheckResult r = scd->SanityCheck(isolate, source);
if (r == CHECK_SUCCESS) return scd; if (r == CHECK_SUCCESS) return scd;
cached_data->Reject(); cached_data->Reject();
source->GetIsolate()->counters()->code_cache_reject_reason()->AddSample(r); source->GetIsolate()->counters()->code_cache_reject_reason()->AddSample(r);
......
...@@ -15,30 +15,7 @@ namespace internal { ...@@ -15,30 +15,7 @@ namespace internal {
class ScriptData; class ScriptData;
// A TypeCode is used to distinguish different kinds of external reference. static const int kDeoptTableSerializeEntryCount = 64;
// It is a single bit to make testing for types easy.
enum TypeCode {
UNCLASSIFIED, // One-of-a-kind references.
C_BUILTIN,
BUILTIN,
RUNTIME_FUNCTION,
IC_UTILITY,
STATS_COUNTER,
TOP_ADDRESS,
ACCESSOR_CODE,
STUB_CACHE_TABLE,
RUNTIME_ENTRY,
LAZY_DEOPTIMIZATION
};
const int kTypeCodeCount = LAZY_DEOPTIMIZATION + 1;
const int kFirstTypeCode = UNCLASSIFIED;
const int kReferenceIdBits = 16;
const int kReferenceIdMask = (1 << kReferenceIdBits) - 1;
const int kReferenceTypeShift = kReferenceIdBits;
const int kDeoptTableSerializeEntryCount = 64;
// ExternalReferenceTable is a helper class that defines the relationship // ExternalReferenceTable is a helper class that defines the relationship
// between external references and their encodings. It is used to build // between external references and their encodings. It is used to build
...@@ -47,46 +24,28 @@ class ExternalReferenceTable { ...@@ -47,46 +24,28 @@ class ExternalReferenceTable {
public: public:
static ExternalReferenceTable* instance(Isolate* isolate); static ExternalReferenceTable* instance(Isolate* isolate);
~ExternalReferenceTable() { }
int size() const { return refs_.length(); } int size() const { return refs_.length(); }
Address address(int i) { return refs_[i].address; } Address address(int i) { return refs_[i].address; }
uint32_t code(int i) { return refs_[i].code; }
const char* name(int i) { return refs_[i].name; } const char* name(int i) { return refs_[i].name; }
int max_id(int code) { return max_id_[code]; } inline static Address NotAvailable() { return NULL; }
private: private:
explicit ExternalReferenceTable(Isolate* isolate) : refs_(64) {
PopulateTable(isolate);
}
struct ExternalReferenceEntry { struct ExternalReferenceEntry {
Address address; Address address;
uint32_t code;
const char* name; const char* name;
}; };
void PopulateTable(Isolate* isolate); explicit ExternalReferenceTable(Isolate* isolate);
// For a few types of references, we can get their address from their id.
void AddFromId(TypeCode type,
uint16_t id,
const char* name,
Isolate* isolate);
// For other types of references, the caller will figure out the address.
void Add(Address address, TypeCode type, uint16_t id, const char* name);
void Add(Address address, const char* name) { void Add(Address address, const char* name) {
Add(address, UNCLASSIFIED, ++max_id_[UNCLASSIFIED], name); ExternalReferenceEntry entry = {address, name};
refs_.Add(entry);
} }
List<ExternalReferenceEntry> refs_; List<ExternalReferenceEntry> refs_;
uint16_t max_id_[kTypeCodeCount];
DISALLOW_COPY_AND_ASSIGN(ExternalReferenceTable);
}; };
...@@ -96,47 +55,17 @@ class ExternalReferenceEncoder { ...@@ -96,47 +55,17 @@ class ExternalReferenceEncoder {
uint32_t Encode(Address key) const; uint32_t Encode(Address key) const;
const char* NameOfAddress(Address key) const; const char* NameOfAddress(Isolate* isolate, Address address) const;
private: private:
HashMap encodings_;
static uint32_t Hash(Address key) { static uint32_t Hash(Address key) {
return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key) >> 2); return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key) >>
kPointerSizeLog2);
} }
int IndexOf(Address key) const; HashMap map_;
void Put(Address key, int index);
Isolate* isolate_;
};
class ExternalReferenceDecoder {
public:
explicit ExternalReferenceDecoder(Isolate* isolate);
~ExternalReferenceDecoder();
Address Decode(uint32_t key) const {
if (key == 0) return NULL;
return *Lookup(key);
}
private:
Address** encodings_;
Address* Lookup(uint32_t key) const {
int type = key >> kReferenceTypeShift;
DCHECK(kFirstTypeCode <= type && type < kTypeCodeCount);
int id = key & kReferenceIdMask;
return &encodings_[type][id];
}
void Put(uint32_t key, Address value) {
*Lookup(key) = value;
}
Isolate* isolate_; DISALLOW_COPY_AND_ASSIGN(ExternalReferenceEncoder);
}; };
...@@ -170,17 +99,16 @@ class RootIndexMap : public AddressMapBase { ...@@ -170,17 +99,16 @@ class RootIndexMap : public AddressMapBase {
public: public:
explicit RootIndexMap(Isolate* isolate); explicit RootIndexMap(Isolate* isolate);
~RootIndexMap() { delete map_; }
static const int kInvalidRootIndex = -1; static const int kInvalidRootIndex = -1;
int Lookup(HeapObject* obj) { int Lookup(HeapObject* obj) {
HashMap::Entry* entry = LookupEntry(map_, obj, false); HashMap::Entry* entry = LookupEntry(&map_, obj, false);
if (entry) return GetValue(entry); if (entry) return GetValue(entry);
return kInvalidRootIndex; return kInvalidRootIndex;
} }
private: private:
HashMap* map_; HashMap map_;
DISALLOW_COPY_AND_ASSIGN(RootIndexMap); DISALLOW_COPY_AND_ASSIGN(RootIndexMap);
}; };
...@@ -519,9 +447,16 @@ class SerializedData { ...@@ -519,9 +447,16 @@ class SerializedData {
if (owns_data_) DeleteArray<byte>(data_); if (owns_data_) DeleteArray<byte>(data_);
} }
uint32_t GetMagicNumber() const { return GetHeaderValue(kMagicNumberOffset); }
class ChunkSizeBits : public BitField<uint32_t, 0, 31> {}; class ChunkSizeBits : public BitField<uint32_t, 0, 31> {};
class IsLastChunkBits : public BitField<bool, 31, 1> {}; class IsLastChunkBits : public BitField<bool, 31, 1> {};
static uint32_t ComputeMagicNumber(ExternalReferenceTable* table) {
uint32_t external_refs = table->size();
return 0xC0DE0000 ^ external_refs;
}
protected: protected:
void SetHeaderValue(int offset, uint32_t value) { void SetHeaderValue(int offset, uint32_t value) {
uint32_t* address = reinterpret_cast<uint32_t*>(data_ + offset); uint32_t* address = reinterpret_cast<uint32_t*>(data_ + offset);
...@@ -536,6 +471,16 @@ class SerializedData { ...@@ -536,6 +471,16 @@ class SerializedData {
void AllocateData(int size); void AllocateData(int size);
static uint32_t ComputeMagicNumber(Isolate* isolate) {
return ComputeMagicNumber(ExternalReferenceTable::instance(isolate));
}
void SetMagicNumber(Isolate* isolate) {
SetHeaderValue(kMagicNumberOffset, ComputeMagicNumber(isolate));
}
static const int kMagicNumberOffset = 0;
byte* data_; byte* data_;
int size_; int size_;
bool owns_data_; bool owns_data_;
...@@ -550,7 +495,8 @@ class Deserializer: public SerializerDeserializer { ...@@ -550,7 +495,8 @@ class Deserializer: public SerializerDeserializer {
explicit Deserializer(Data* data) explicit Deserializer(Data* data)
: isolate_(NULL), : isolate_(NULL),
source_(data->Payload()), source_(data->Payload()),
external_reference_decoder_(NULL), magic_number_(data->GetMagicNumber()),
external_reference_table_(NULL),
deserialized_large_objects_(0), deserialized_large_objects_(0),
deserializing_user_code_(false) { deserializing_user_code_(false) {
DecodeReservation(data->Reservations()); DecodeReservation(data->Reservations());
...@@ -624,6 +570,8 @@ class Deserializer: public SerializerDeserializer { ...@@ -624,6 +570,8 @@ class Deserializer: public SerializerDeserializer {
Vector<Handle<Object> > attached_objects_; Vector<Handle<Object> > attached_objects_;
SnapshotByteSource source_; SnapshotByteSource source_;
uint32_t magic_number_;
// The address of the next object that will be allocated in each space. // The address of the next object that will be allocated in each space.
// Each space has a number of chunks reserved by the GC, with each chunk // Each space has a number of chunks reserved by the GC, with each chunk
// fitting into a page. Deserialized objects are allocated into the // fitting into a page. Deserialized objects are allocated into the
...@@ -632,7 +580,7 @@ class Deserializer: public SerializerDeserializer { ...@@ -632,7 +580,7 @@ class Deserializer: public SerializerDeserializer {
uint32_t current_chunk_[kNumberOfPreallocatedSpaces]; uint32_t current_chunk_[kNumberOfPreallocatedSpaces];
Address high_water_[kNumberOfPreallocatedSpaces]; Address high_water_[kNumberOfPreallocatedSpaces];
ExternalReferenceDecoder* external_reference_decoder_; ExternalReferenceTable* external_reference_table_;
List<HeapObject*> deserialized_large_objects_; List<HeapObject*> deserialized_large_objects_;
...@@ -945,13 +893,15 @@ class SnapshotData : public SerializedData { ...@@ -945,13 +893,15 @@ class SnapshotData : public SerializedData {
private: private:
bool IsSane(); bool IsSane();
// The data header consists of uint32_t-sized entries: // The data header consists of uint32_t-sized entries:
// [0] version hash // [0] magic number and external reference count
// [1] number of reservation size entries // [1] version hash
// [2] payload length // [2] number of reservation size entries
// [3] payload length
// ... reservations // ... reservations
// ... serialized payload // ... serialized payload
static const int kCheckSumOffset = 0; static const int kCheckSumOffset = kMagicNumberOffset + kInt32Size;
static const int kNumReservationsOffset = kCheckSumOffset + kInt32Size; static const int kNumReservationsOffset = kCheckSumOffset + kInt32Size;
static const int kPayloadLengthOffset = kNumReservationsOffset + kInt32Size; static const int kPayloadLengthOffset = kNumReservationsOffset + kInt32Size;
static const int kHeaderSize = kPayloadLengthOffset + kInt32Size; static const int kHeaderSize = kPayloadLengthOffset + kInt32Size;
...@@ -962,7 +912,8 @@ class SnapshotData : public SerializedData { ...@@ -962,7 +912,8 @@ class SnapshotData : public SerializedData {
class SerializedCodeData : public SerializedData { class SerializedCodeData : public SerializedData {
public: public:
// Used when consuming. // Used when consuming.
static SerializedCodeData* FromCachedData(ScriptData* cached_data, static SerializedCodeData* FromCachedData(Isolate* isolate,
ScriptData* cached_data,
String* source); String* source);
// Used when producing. // Used when producing.
...@@ -990,14 +941,12 @@ class SerializedCodeData : public SerializedData { ...@@ -990,14 +941,12 @@ class SerializedCodeData : public SerializedData {
CHECKSUM_MISMATCH = 6 CHECKSUM_MISMATCH = 6
}; };
SanityCheckResult SanityCheck(String* source) const; SanityCheckResult SanityCheck(Isolate* isolate, String* source) const;
uint32_t SourceHash(String* source) const { return source->length(); } uint32_t SourceHash(String* source) const { return source->length(); }
static const uint32_t kMagicNumber = 0xC0D1F1ED;
// The data header consists of uint32_t-sized entries: // The data header consists of uint32_t-sized entries:
// [ 0] magic number // [ 0] magic number and external reference count
// [ 1] version hash // [ 1] version hash
// [ 2] source hash // [ 2] source hash
// [ 3] cpu features // [ 3] cpu features
...@@ -1011,7 +960,6 @@ class SerializedCodeData : public SerializedData { ...@@ -1011,7 +960,6 @@ class SerializedCodeData : public SerializedData {
// ... reservations // ... reservations
// ... code stub keys // ... code stub keys
// ... serialized payload // ... serialized payload
static const int kMagicNumberOffset = 0;
static const int kVersionHashOffset = kMagicNumberOffset + kInt32Size; static const int kVersionHashOffset = kMagicNumberOffset + kInt32Size;
static const int kSourceHashOffset = kVersionHashOffset + kInt32Size; static const int kSourceHashOffset = kVersionHashOffset + kInt32Size;
static const int kCpuFeaturesOffset = kSourceHashOffset + kInt32Size; static const int kCpuFeaturesOffset = kSourceHashOffset + kInt32Size;
......
...@@ -71,74 +71,6 @@ class TestIsolate : public Isolate { ...@@ -71,74 +71,6 @@ class TestIsolate : public Isolate {
}; };
template <class T>
static Address AddressOf(T id) {
return ExternalReference(id, CcTest::i_isolate()).address();
}
template <class T>
static uint32_t Encode(const ExternalReferenceEncoder& encoder, T id) {
return encoder.Encode(AddressOf(id));
}
static uint32_t make_code(TypeCode type, int id) {
return static_cast<uint32_t>(type) << kReferenceTypeShift | id;
}
TEST(ExternalReferenceEncoder) {
Isolate* isolate = CcTest::i_isolate();
v8::V8::Initialize();
ExternalReferenceEncoder encoder(isolate);
CHECK_EQ(make_code(BUILTIN, Builtins::kArrayCode),
Encode(encoder, Builtins::kArrayCode));
CHECK_EQ(make_code(v8::internal::RUNTIME_FUNCTION, Runtime::kAbort),
Encode(encoder, Runtime::kAbort));
ExternalReference stack_limit_address =
ExternalReference::address_of_stack_limit(isolate);
CHECK_EQ(make_code(UNCLASSIFIED, 2),
encoder.Encode(stack_limit_address.address()));
ExternalReference real_stack_limit_address =
ExternalReference::address_of_real_stack_limit(isolate);
CHECK_EQ(make_code(UNCLASSIFIED, 3),
encoder.Encode(real_stack_limit_address.address()));
CHECK_EQ(make_code(UNCLASSIFIED, 8),
encoder.Encode(ExternalReference::debug_break(isolate).address()));
CHECK_EQ(
make_code(UNCLASSIFIED, 4),
encoder.Encode(ExternalReference::new_space_start(isolate).address()));
CHECK_EQ(
make_code(UNCLASSIFIED, 1),
encoder.Encode(ExternalReference::roots_array_start(isolate).address()));
CHECK_EQ(make_code(UNCLASSIFIED, 33),
encoder.Encode(ExternalReference::cpu_features().address()));
}
TEST(ExternalReferenceDecoder) {
Isolate* isolate = CcTest::i_isolate();
v8::V8::Initialize();
ExternalReferenceDecoder decoder(isolate);
CHECK_EQ(AddressOf(Builtins::kArrayCode),
decoder.Decode(make_code(BUILTIN, Builtins::kArrayCode)));
CHECK_EQ(AddressOf(Runtime::kAbort),
decoder.Decode(make_code(v8::internal::RUNTIME_FUNCTION,
Runtime::kAbort)));
CHECK_EQ(ExternalReference::address_of_stack_limit(isolate).address(),
decoder.Decode(make_code(UNCLASSIFIED, 2)));
CHECK_EQ(ExternalReference::address_of_real_stack_limit(isolate).address(),
decoder.Decode(make_code(UNCLASSIFIED, 3)));
CHECK_EQ(ExternalReference::debug_break(isolate).address(),
decoder.Decode(make_code(UNCLASSIFIED, 8)));
CHECK_EQ(ExternalReference::new_space_start(isolate).address(),
decoder.Decode(make_code(UNCLASSIFIED, 4)));
}
void WritePayload(const Vector<const byte>& payload, const char* file_name) { void WritePayload(const Vector<const byte>& payload, const char* file_name) {
FILE* file = v8::base::OS::FOpen(file_name, "wb"); FILE* file = v8::base::OS::FOpen(file_name, "wb");
if (file == NULL) { if (file == NULL) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment