Skip to content
This repository has been archived by the owner on Mar 25, 2018. It is now read-only.

Commit

Permalink
[serializer] small fixes for blink snapshot.
Browse files Browse the repository at this point in the history
Changes include:
 - Adding V8_EXPORT macro for SnapshotCreator
 - Removing outdated DCHECKs.
 - Allow nullptr as external reference. This required a...
 - Refactoring of hashmaps used by the serializer.
 - Remove external references for counters. These are not used
   anywhere for isolates that are being serialized.
 - Put template infos into the partial snapshot cache.
 - Remove unnecessary presubmit check for external references.
   mksnapshot crashes if external references are missing.

R=jochen@chromium.org, vogelheim@chromium.org
BUG=chromium:617892

Review-Url: https://codereview.chromium.org/2490783004
Cr-Commit-Position: refs/heads/master@{#40949}
  • Loading branch information
hashseed authored and Commit bot committed Nov 14, 2016
1 parent a9f553b commit c759a3d
Show file tree
Hide file tree
Showing 17 changed files with 98 additions and 171 deletions.
4 changes: 0 additions & 4 deletions PRESUBMIT.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ def _V8PresubmitChecks(input_api, output_api):
input_api.PresubmitLocalPath(), 'tools'))
from presubmit import CppLintProcessor
from presubmit import SourceProcessor
from presubmit import CheckExternalReferenceRegistration
from presubmit import CheckAuthorizedAuthor
from presubmit import CheckStatusFiles

Expand All @@ -78,9 +77,6 @@ def _V8PresubmitChecks(input_api, output_api):
results.append(output_api.PresubmitError(
"Copyright header, trailing whitespaces and two empty lines " \
"between declarations check failed"))
if not CheckExternalReferenceRegistration(input_api.PresubmitLocalPath()):
results.append(output_api.PresubmitError(
"External references registration check failed"))
if not CheckStatusFiles(input_api.PresubmitLocalPath()):
results.append(output_api.PresubmitError("Status file check failed"))
results.extend(CheckAuthorizedAuthor(input_api, output_api))
Expand Down
2 changes: 1 addition & 1 deletion include/v8.h
Original file line number Diff line number Diff line change
Expand Up @@ -7575,7 +7575,7 @@ class V8_EXPORT V8 {
/**
* Helper class to create a snapshot data blob.
*/
class SnapshotCreator {
class V8_EXPORT SnapshotCreator {
public:
enum class FunctionCodeHandling { kClear, kKeep };

Expand Down
10 changes: 5 additions & 5 deletions src/address-map.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace internal {
RootIndexMap::RootIndexMap(Isolate* isolate) {
map_ = isolate->root_index_map();
if (map_ != NULL) return;
map_ = new base::HashMap();
map_ = new HeapObjectToIndexHashMap();
for (uint32_t i = 0; i < Heap::kStrongRootListLength; i++) {
Heap::RootListIndex root_index = static_cast<Heap::RootListIndex>(i);
Object* root = isolate->heap()->root(root_index);
Expand All @@ -22,12 +22,12 @@ RootIndexMap::RootIndexMap(Isolate* isolate) {
// not be referenced through the root list in the snapshot.
if (isolate->heap()->RootCanBeTreatedAsConstant(root_index)) {
HeapObject* heap_object = HeapObject::cast(root);
base::HashMap::Entry* entry = LookupEntry(map_, heap_object, false);
if (entry != NULL) {
Maybe<uint32_t> maybe_index = map_->Get(heap_object);
if (maybe_index.IsJust()) {
// Some are initialized to a previous value in the root list.
DCHECK_LT(GetValue(entry), i);
DCHECK_LT(maybe_index.FromJust(), i);
} else {
SetValue(LookupEntry(map_, heap_object, true), i);
map_->Set(heap_object, i);
}
} else {
// Immortal immovable root objects are constant and allocated on the first
Expand Down
64 changes: 34 additions & 30 deletions src/address-map.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,56 +5,60 @@
#ifndef V8_ADDRESS_MAP_H_
#define V8_ADDRESS_MAP_H_

#include "include/v8.h"
#include "src/assert-scope.h"
#include "src/base/hashmap.h"
#include "src/objects.h"

namespace v8 {
namespace internal {

class AddressMapBase {
protected:
static void SetValue(base::HashMap::Entry* entry, uint32_t v) {
entry->value = reinterpret_cast<void*>(v);
}
template <typename Type>
class PointerToIndexHashMap
: public base::TemplateHashMapImpl<uintptr_t, uint32_t,
base::KeyEqualityMatcher<intptr_t>,
base::DefaultAllocationPolicy> {
public:
typedef base::TemplateHashMapEntry<uintptr_t, uint32_t> Entry;

static uint32_t GetValue(base::HashMap::Entry* entry) {
return static_cast<uint32_t>(reinterpret_cast<intptr_t>(entry->value));
inline void Set(Type value, uint32_t index) {
uintptr_t key = Key(value);
LookupOrInsert(key, Hash(key))->value = index;
}

inline static base::HashMap::Entry* LookupEntry(base::HashMap* map,
HeapObject* obj,
bool insert) {
if (insert) {
map->LookupOrInsert(Key(obj), Hash(obj));
}
return map->Lookup(Key(obj), Hash(obj));
inline Maybe<uint32_t> Get(Type value) const {
uintptr_t key = Key(value);
Entry* entry = Lookup(key, Hash(key));
if (entry == nullptr) return Nothing<uint32_t>();
return Just(entry->value);
}

private:
static uint32_t Hash(HeapObject* obj) {
return static_cast<int32_t>(reinterpret_cast<intptr_t>(obj->address()));
static uintptr_t Key(Type value) {
return reinterpret_cast<uintptr_t>(value);
}

static void* Key(HeapObject* obj) {
return reinterpret_cast<void*>(obj->address());
static uint32_t Hash(uintptr_t key) {
return static_cast<uint32_t>(key >> kPointerSizeLog2);
}
};

class RootIndexMap : public AddressMapBase {
class AddressToIndexHashMap : public PointerToIndexHashMap<Address> {};
class HeapObjectToIndexHashMap : public PointerToIndexHashMap<HeapObject*> {};

class RootIndexMap {
public:
explicit RootIndexMap(Isolate* isolate);

static const int kInvalidRootIndex = -1;

int Lookup(HeapObject* obj) {
base::HashMap::Entry* entry = LookupEntry(map_, obj, false);
if (entry) return GetValue(entry);
return kInvalidRootIndex;
Maybe<uint32_t> maybe_index = map_->Get(obj);
return maybe_index.IsJust() ? maybe_index.FromJust() : kInvalidRootIndex;
}

private:
base::HashMap* map_;
HeapObjectToIndexHashMap* map_;

DISALLOW_COPY_AND_ASSIGN(RootIndexMap);
};
Expand Down Expand Up @@ -186,21 +190,21 @@ class SerializerReference {

// Mapping objects to their location after deserialization.
// This is used during building, but not at runtime by V8.
class SerializerReferenceMap : public AddressMapBase {
class SerializerReferenceMap {
public:
SerializerReferenceMap()
: no_allocation_(), map_(), attached_reference_index_(0) {}

SerializerReference Lookup(HeapObject* obj) {
base::HashMap::Entry* entry = LookupEntry(&map_, obj, false);
return entry ? SerializerReference(GetValue(entry)) : SerializerReference();
Maybe<uint32_t> maybe_index = map_.Get(obj);
return maybe_index.IsJust() ? SerializerReference(maybe_index.FromJust())
: SerializerReference();
}

void Add(HeapObject* obj, SerializerReference b) {
DCHECK(b.is_valid());
DCHECK_NULL(LookupEntry(&map_, obj, false));
base::HashMap::Entry* entry = LookupEntry(&map_, obj, true);
SetValue(entry, b.bitfield_);
DCHECK(map_.Get(obj).IsNothing());
map_.Set(obj, b.bitfield_);
}

SerializerReference AddAttachedReference(HeapObject* attached_reference) {
Expand All @@ -212,7 +216,7 @@ class SerializerReferenceMap : public AddressMapBase {

private:
DisallowHeapAllocation no_allocation_;
base::HashMap map_;
HeapObjectToIndexHashMap map_;
int attached_reference_index_;
DISALLOW_COPY_AND_ASSIGN(SerializerReferenceMap);
};
Expand Down
2 changes: 0 additions & 2 deletions src/api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1240,7 +1240,6 @@ Local<FunctionTemplate> FunctionTemplate::NewWithFastHandler(
experimental::FastAccessorBuilder* fast_handler, v8::Local<Value> data,
v8::Local<Signature> signature, int length) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
DCHECK(!i_isolate->serializer_enabled());
LOG_API(i_isolate, FunctionTemplate, NewWithFastHandler);
ENTER_V8(i_isolate);
return FunctionTemplateNew(i_isolate, callback, fast_handler, data, signature,
Expand All @@ -1251,7 +1250,6 @@ Local<FunctionTemplate> FunctionTemplate::NewWithCache(
Isolate* isolate, FunctionCallback callback, Local<Private> cache_property,
Local<Value> data, Local<Signature> signature, int length) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
DCHECK(!i_isolate->serializer_enabled());
LOG_API(i_isolate, FunctionTemplate, NewWithFastHandler);
ENTER_V8(i_isolate);
return FunctionTemplateNew(i_isolate, callback, nullptr, data, signature,
Expand Down
31 changes: 2 additions & 29 deletions src/external-reference-table.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@ ExternalReferenceTable* ExternalReferenceTable::instance(Isolate* isolate) {
}

ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) {
// nullptr is preserved through serialization/deserialization.
Add(nullptr, "nullptr");
AddReferences(isolate);
AddBuiltins(isolate);
AddRuntimeFunctions(isolate);
AddStatCounters(isolate);
AddIsolateAddresses(isolate);
AddAccessors(isolate);
AddStubCache(isolate);
Expand Down Expand Up @@ -73,8 +74,6 @@ void ExternalReferenceTable::AddReferences(Isolate* isolate) {
Add(ExternalReference::isolate_address(isolate).address(), "isolate");
Add(ExternalReference::interpreter_dispatch_table_address(isolate).address(),
"Interpreter::dispatch_table_address");
Add(ExternalReference::interpreter_dispatch_counters(isolate).address(),
"Interpreter::interpreter_dispatch_counters");
Add(ExternalReference::address_of_negative_infinity().address(),
"LDoubleConstant::negative_infinity");
Add(ExternalReference::power_double_double_function(isolate).address(),
Expand Down Expand Up @@ -315,32 +314,6 @@ void ExternalReferenceTable::AddRuntimeFunctions(Isolate* isolate) {
}
}

void ExternalReferenceTable::AddStatCounters(Isolate* isolate) {
// Stat counters
struct StatsRefTableEntry {
StatsCounter* (Counters::*counter)();
const char* name;
};

static const StatsRefTableEntry stats_ref_table[] = {
#define COUNTER_ENTRY(name, caption) {&Counters::name, "Counters::" #name},
STATS_COUNTER_LIST_1(COUNTER_ENTRY) STATS_COUNTER_LIST_2(COUNTER_ENTRY)
#undef COUNTER_ENTRY
};

Counters* counters = isolate->counters();
for (unsigned i = 0; i < arraysize(stats_ref_table); ++i) {
// To make sure the indices are not dependent on whether counters are
// enabled, use a dummy address as filler.
Address address = NotAvailable();
StatsCounter* counter = (counters->*(stats_ref_table[i].counter))();
if (counter->Enabled()) {
address = reinterpret_cast<Address>(counter->GetInternalPointer());
}
Add(address, stats_ref_table[i].name);
}
}

void ExternalReferenceTable::AddIsolateAddresses(Isolate* isolate) {
// Top addresses
static const char* address_names[] = {
Expand Down
9 changes: 3 additions & 6 deletions src/external-reference-table.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,9 @@ class ExternalReferenceTable {
public:
static ExternalReferenceTable* instance(Isolate* isolate);

int size() const { return refs_.length(); }
Address address(int i) { return refs_[i].address; }
const char* name(int i) { return refs_[i].name; }

inline static Address NotAvailable() { return NULL; }
uint32_t size() const { return static_cast<uint32_t>(refs_.length()); }
Address address(uint32_t i) { return refs_[i].address; }
const char* name(uint32_t i) { return refs_[i].name; }

static const int kDeoptTableSerializeEntryCount = 64;

Expand All @@ -43,7 +41,6 @@ class ExternalReferenceTable {
void AddReferences(Isolate* isolate);
void AddBuiltins(Isolate* isolate);
void AddRuntimeFunctions(Isolate* isolate);
void AddStatCounters(Isolate* isolate);
void AddIsolateAddresses(Isolate* isolate);
void AddAccessors(Isolate* isolate);
void AddStubCache(Isolate* isolate);
Expand Down
6 changes: 4 additions & 2 deletions src/isolate.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class RandomNumberGenerator;
namespace internal {

class AccessCompilerData;
class AddressToIndexHashMap;
class BasicBlockProfiler;
class Bootstrapper;
class CancelableTaskManager;
Expand All @@ -59,6 +60,7 @@ class ExternalCallbackScope;
class ExternalReferenceTable;
class Factory;
class HandleScopeImplementer;
class HeapObjectToIndexHashMap;
class HeapProfiler;
class HStatistics;
class HTracer;
Expand Down Expand Up @@ -400,8 +402,8 @@ typedef List<HeapObject*> DebugObjectCache;
V(Object*, string_stream_current_security_token, nullptr) \
V(ExternalReferenceTable*, external_reference_table, nullptr) \
V(intptr_t*, api_external_references, nullptr) \
V(base::HashMap*, external_reference_map, nullptr) \
V(base::HashMap*, root_index_map, nullptr) \
V(AddressToIndexHashMap*, external_reference_map, nullptr) \
V(HeapObjectToIndexHashMap*, root_index_map, nullptr) \
V(v8::DeserializeInternalFieldsCallback, \
deserialize_internal_fields_callback, nullptr) \
V(int, pending_microtask_count, 0) \
Expand Down
2 changes: 1 addition & 1 deletion src/snapshot/deserializer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,7 @@ bool Deserializer::ReadData(Object** current, Object** limit, int source_space,
int skip = source_.GetInt(); \
current = reinterpret_cast<Object**>( \
reinterpret_cast<Address>(current) + skip); \
int reference_id = source_.GetInt(); \
uint32_t reference_id = static_cast<uint32_t>(source_.GetInt()); \
Address address = external_reference_table_->address(reference_id); \
new_object = reinterpret_cast<Object*>(address); \
} else if (where == kAttachedReference) { \
Expand Down
1 change: 1 addition & 0 deletions src/snapshot/partial-serializer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ bool PartialSerializer::ShouldBeInThePartialSnapshotCache(HeapObject* o) {
DCHECK(!o->IsScript());
return o->IsName() || o->IsSharedFunctionInfo() || o->IsHeapNumber() ||
o->IsCode() || o->IsScopeInfo() || o->IsAccessorInfo() ||
o->IsTemplateInfo() ||
o->map() ==
startup_serializer_->isolate()->heap()->fixed_cow_array_map();
}
Expand Down
30 changes: 13 additions & 17 deletions src/snapshot/serializer-common.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,44 +18,40 @@ namespace internal {

ExternalReferenceEncoder::ExternalReferenceEncoder(Isolate* isolate) {
map_ = isolate->external_reference_map();
if (map_ != NULL) return;
map_ = new base::HashMap();
if (map_ != nullptr) return;
map_ = new AddressToIndexHashMap();
ExternalReferenceTable* table = ExternalReferenceTable::instance(isolate);
for (int i = 0; i < table->size(); ++i) {
for (uint32_t i = 0; i < table->size(); ++i) {
Address addr = table->address(i);
if (addr == ExternalReferenceTable::NotAvailable()) continue;
// We expect no duplicate external references entries in the table.
// AccessorRefTable getter may have duplicates, indicated by an empty string
// as name.
DCHECK(table->name(i)[0] == '\0' ||
map_->Lookup(addr, Hash(addr)) == nullptr);
map_->LookupOrInsert(addr, Hash(addr))->value = reinterpret_cast<void*>(i);
DCHECK(table->name(i)[0] == '\0' || map_->Get(addr).IsNothing());
map_->Set(addr, i);
DCHECK(map_->Get(addr).IsJust());
}
isolate->set_external_reference_map(map_);
}

uint32_t ExternalReferenceEncoder::Encode(Address address) const {
DCHECK_NOT_NULL(address);
base::HashMap::Entry* entry =
const_cast<base::HashMap*>(map_)->Lookup(address, Hash(address));
if (entry == nullptr) {
Maybe<uint32_t> maybe_index = map_->Get(address);
if (maybe_index.IsNothing()) {
void* function_addr = address;
v8::base::OS::PrintError("Unknown external reference %p.\n", function_addr);
#ifdef SYMBOLIZE_FUNCTION
v8::base::OS::PrintError("%s\n", backtrace_symbols(&function_addr, 1)[0]);
#endif // SYMBOLIZE_FUNCTION
v8::base::OS::Abort();
}
return static_cast<uint32_t>(reinterpret_cast<intptr_t>(entry->value));
return maybe_index.FromJust();
}

const char* ExternalReferenceEncoder::NameOfAddress(Isolate* isolate,
Address address) const {
base::HashMap::Entry* entry =
const_cast<base::HashMap*>(map_)->Lookup(address, Hash(address));
if (entry == NULL) return "<unknown>";
uint32_t i = static_cast<uint32_t>(reinterpret_cast<intptr_t>(entry->value));
return ExternalReferenceTable::instance(isolate)->name(i);
Maybe<uint32_t> maybe_index = map_->Get(address);
if (maybe_index.IsNothing()) return "<unknown>";
return ExternalReferenceTable::instance(isolate)->name(
maybe_index.FromJust());
}

void SerializedData::AllocateData(int size) {
Expand Down
7 changes: 1 addition & 6 deletions src/snapshot/serializer-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,7 @@ class ExternalReferenceEncoder {
const char* NameOfAddress(Isolate* isolate, Address address) const;

private:
static uint32_t Hash(Address key) {
return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key) >>
kPointerSizeLog2);
}

base::HashMap* map_;
AddressToIndexHashMap* map_;

DISALLOW_COPY_AND_ASSIGN(ExternalReferenceEncoder);
};
Expand Down
1 change: 1 addition & 0 deletions src/snapshot/serializer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,7 @@ void Serializer::ObjectSerializer::VisitExternalReference(RelocInfo* rinfo) {
sink_->Put(kExternalReference + how_to_code + kStartOfObject, "ExternalRef");
sink_->PutInt(skip, "SkipB4ExternalRef");
Address target = rinfo->target_external_reference();
DCHECK_NOT_NULL(target); // Code does not reference null.
sink_->PutInt(serializer_->EncodeExternalReference(target), "reference id");
bytes_processed_so_far_ += rinfo->target_address_size();
}
Expand Down
Loading

0 comments on commit c759a3d

Please sign in to comment.