summaryrefslogtreecommitdiff
path: root/deps/v8/src/serialize.h
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/serialize.h')
-rw-r--r--deps/v8/src/serialize.h301
1 files changed, 164 insertions, 137 deletions
diff --git a/deps/v8/src/serialize.h b/deps/v8/src/serialize.h
index 958f20e24..e4e6c3ad8 100644
--- a/deps/v8/src/serialize.h
+++ b/deps/v8/src/serialize.h
@@ -5,7 +5,11 @@
#ifndef V8_SERIALIZE_H_
#define V8_SERIALIZE_H_
-#include "hashmap.h"
+#include "src/compiler.h"
+#include "src/hashmap.h"
+#include "src/heap-profiler.h"
+#include "src/isolate.h"
+#include "src/snapshot-source-sink.h"
namespace v8 {
namespace internal {
@@ -13,18 +17,16 @@ namespace internal {
// A TypeCode is used to distinguish different kinds of external reference.
// It is a single bit to make testing for types easy.
enum TypeCode {
- UNCLASSIFIED, // One-of-a-kind references.
+ UNCLASSIFIED, // One-of-a-kind references.
+ C_BUILTIN,
BUILTIN,
RUNTIME_FUNCTION,
IC_UTILITY,
- DEBUG_ADDRESS,
STATS_COUNTER,
TOP_ADDRESS,
- C_BUILTIN,
- EXTENSION,
ACCESSOR,
- RUNTIME_ENTRY,
STUB_CACHE_TABLE,
+ RUNTIME_ENTRY,
LAZY_DEOPTIMIZATION
};
@@ -34,10 +36,8 @@ const int kFirstTypeCode = UNCLASSIFIED;
const int kReferenceIdBits = 16;
const int kReferenceIdMask = (1 << kReferenceIdBits) - 1;
const int kReferenceTypeShift = kReferenceIdBits;
-const int kDebugRegisterBits = 4;
-const int kDebugIdShift = kDebugRegisterBits;
-const int kDeoptTableSerializeEntryCount = 12;
+const int kDeoptTableSerializeEntryCount = 64;
// ExternalReferenceTable is a helper class that defines the relationship
// between external references and their encodings. It is used to build
@@ -60,7 +60,7 @@ class ExternalReferenceTable {
private:
explicit ExternalReferenceTable(Isolate* isolate) : refs_(64) {
- PopulateTable(isolate);
+ PopulateTable(isolate);
}
struct ExternalReferenceEntry {
@@ -80,8 +80,12 @@ class ExternalReferenceTable {
// 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) {
+ Add(address, UNCLASSIFIED, ++max_id_[UNCLASSIFIED], name);
+ }
+
List<ExternalReferenceEntry> refs_;
- int max_id_[kTypeCodeCount];
+ uint16_t max_id_[kTypeCodeCount];
};
@@ -122,7 +126,7 @@ class ExternalReferenceDecoder {
Address* Lookup(uint32_t key) const {
int type = key >> kReferenceTypeShift;
- ASSERT(kFirstTypeCode <= type && type < kTypeCodeCount);
+ DCHECK(kFirstTypeCode <= type && type < kTypeCodeCount);
int id = key & kReferenceIdMask;
return &encodings_[type][id];
}
@@ -135,49 +139,6 @@ class ExternalReferenceDecoder {
};
-class SnapshotByteSource {
- public:
- SnapshotByteSource(const byte* array, int length)
- : data_(array), length_(length), position_(0) { }
-
- bool HasMore() { return position_ < length_; }
-
- int Get() {
- ASSERT(position_ < length_);
- return data_[position_++];
- }
-
- int32_t GetUnalignedInt() {
-#if defined(V8_HOST_CAN_READ_UNALIGNED) && __BYTE_ORDER == __LITTLE_ENDIAN
- int32_t answer;
- ASSERT(position_ + sizeof(answer) <= length_ + 0u);
- answer = *reinterpret_cast<const int32_t*>(data_ + position_);
-#else
- int32_t answer = data_[position_];
- answer |= data_[position_ + 1] << 8;
- answer |= data_[position_ + 2] << 16;
- answer |= data_[position_ + 3] << 24;
-#endif
- return answer;
- }
-
- void Advance(int by) { position_ += by; }
-
- inline void CopyRaw(byte* to, int number_of_bytes);
-
- inline int GetInt();
-
- bool AtEOF();
-
- int position() { return position_; }
-
- private:
- const byte* data_;
- int length_;
- int position_;
-};
-
-
// The Serializer/Deserializer class is a common superclass for Serializer and
// Deserializer which is used to store common constants and methods used by
// both.
@@ -190,17 +151,18 @@ class SerializerDeserializer: public ObjectVisitor {
protected:
// Where the pointed-to object can be found:
enum Where {
- kNewObject = 0, // Object is next in snapshot.
+ kNewObject = 0, // Object is next in snapshot.
// 1-6 One per space.
- kRootArray = 0x9, // Object is found in root array.
- kPartialSnapshotCache = 0xa, // Object is in the cache.
- kExternalReference = 0xb, // Pointer to an external reference.
- kSkip = 0xc, // Skip n bytes.
- kNop = 0xd, // Does nothing, used to pad.
- // 0xe-0xf Free.
- kBackref = 0x10, // Object is described relative to end.
+ kRootArray = 0x9, // Object is found in root array.
+ kPartialSnapshotCache = 0xa, // Object is in the cache.
+ kExternalReference = 0xb, // Pointer to an external reference.
+ kSkip = 0xc, // Skip n bytes.
+ kBuiltin = 0xd, // Builtin code object.
+ kAttachedReference = 0xe, // Object is described in an attached list.
+ kNop = 0xf, // Does nothing, used to pad.
+ kBackref = 0x10, // Object is described relative to end.
// 0x11-0x16 One per space.
- kBackrefWithSkip = 0x18, // Object is described relative to end.
+ kBackrefWithSkip = 0x18, // Object is described relative to end.
// 0x19-0x1e One per space.
// 0x20-0x3f Used by misc. tags below.
kPointedToMask = 0x3f
@@ -249,11 +211,11 @@ class SerializerDeserializer: public ObjectVisitor {
// 0x73-0x7f Repeat last word (subtract 0x72 to get the count).
static const int kMaxRepeats = 0x7f - 0x72;
static int CodeForRepeats(int repeats) {
- ASSERT(repeats >= 1 && repeats <= kMaxRepeats);
+ DCHECK(repeats >= 1 && repeats <= kMaxRepeats);
return 0x72 + repeats;
}
static int RepeatsForCode(int byte_code) {
- ASSERT(byte_code >= kConstantRepeat && byte_code <= 0x7f);
+ DCHECK(byte_code >= kConstantRepeat && byte_code <= 0x7f);
return byte_code - 0x72;
}
static const int kRootArrayConstants = 0xa0;
@@ -271,26 +233,6 @@ class SerializerDeserializer: public ObjectVisitor {
};
-int SnapshotByteSource::GetInt() {
- // This way of variable-length encoding integers does not suffer from branch
- // mispredictions.
- uint32_t answer = GetUnalignedInt();
- int bytes = answer & 3;
- Advance(bytes);
- uint32_t mask = 0xffffffffu;
- mask >>= 32 - (bytes << 3);
- answer &= mask;
- answer >>= 2;
- return answer;
-}
-
-
-void SnapshotByteSource::CopyRaw(byte* to, int number_of_bytes) {
- OS::MemCopy(to, data_ + position_, number_of_bytes);
- position_ += number_of_bytes;
-}
-
-
// A Deserializer reads a snapshot and reconstructs the Object graph it defines.
class Deserializer: public SerializerDeserializer {
public:
@@ -306,11 +248,21 @@ class Deserializer: public SerializerDeserializer {
void DeserializePartial(Isolate* isolate, Object** root);
void set_reservation(int space_number, int reservation) {
- ASSERT(space_number >= 0);
- ASSERT(space_number <= LAST_SPACE);
+ DCHECK(space_number >= 0);
+ DCHECK(space_number <= LAST_SPACE);
reservations_[space_number] = reservation;
}
+ void FlushICacheForNewCodeObjects();
+
+ // Serialized user code reference certain objects that are provided in a list
+ // By calling this method, we assume that we are deserializing user code.
+ void SetAttachedObjects(Vector<Object*>* attached_objects) {
+ attached_objects_ = attached_objects;
+ }
+
+ bool deserializing_user_code() { return attached_objects_ != NULL; }
+
private:
virtual void VisitPointers(Object** start, Object** end);
@@ -331,16 +283,16 @@ class Deserializer: public SerializerDeserializer {
Object** start, Object** end, int space, Address object_address);
void ReadObject(int space_number, Object** write_back);
+ // Special handling for serialized code like hooking up internalized strings.
+ HeapObject* ProcessNewObjectFromSerializedCode(HeapObject* obj);
+ Object* ProcessBackRefInSerializedCode(Object* obj);
+
// This routine both allocates a new object, and also keeps
// track of where objects have been allocated so that we can
// fix back references when deserializing.
Address Allocate(int space_index, int size) {
Address address = high_water_[space_index];
high_water_[space_index] = address + size;
- HeapProfiler* profiler = isolate_->heap_profiler();
- if (profiler->is_tracking_allocations()) {
- profiler->AllocationEvent(address, size);
- }
return address;
}
@@ -352,11 +304,12 @@ class Deserializer: public SerializerDeserializer {
return HeapObject::FromAddress(high_water_[space] - offset);
}
- void FlushICacheForNewCodeObjects();
-
// Cached current isolate.
Isolate* isolate_;
+ // Objects from the attached object descriptions in the serialized user code.
+ Vector<Object*>* attached_objects_;
+
SnapshotByteSource* source_;
// This is the address of the next object that will be allocated in each
// space. It is used to calculate the addresses of back-references.
@@ -371,18 +324,6 @@ class Deserializer: public SerializerDeserializer {
};
-class SnapshotByteSink {
- public:
- virtual ~SnapshotByteSink() { }
- virtual void Put(int byte, const char* description) = 0;
- virtual void PutSection(int byte, const char* description) {
- Put(byte, description);
- }
- void PutInt(uintptr_t integer, const char* description);
- virtual int Position() = 0;
-};
-
-
// Mapping objects to their location after deserialization.
// This is used during building, but not at runtime by V8.
class SerializationAddressMapper {
@@ -400,13 +341,13 @@ class SerializationAddressMapper {
}
int MappedTo(HeapObject* obj) {
- ASSERT(IsMapped(obj));
+ DCHECK(IsMapped(obj));
return static_cast<int>(reinterpret_cast<intptr_t>(
serialization_map_->Lookup(Key(obj), Hash(obj), false)->value));
}
void AddMapping(HeapObject* obj, int to) {
- ASSERT(!IsMapped(obj));
+ DCHECK(!IsMapped(obj));
HashMap::Entry* entry =
serialization_map_->Lookup(Key(obj), Hash(obj), true);
entry->value = Value(to);
@@ -442,21 +383,12 @@ class Serializer : public SerializerDeserializer {
// You can call this after serialization to find out how much space was used
// in each space.
int CurrentAllocationAddress(int space) const {
- ASSERT(space < kNumberOfSpaces);
+ DCHECK(space < kNumberOfSpaces);
return fullness_[space];
}
Isolate* isolate() const { return isolate_; }
- static void RequestEnable(Isolate* isolate);
- static void InitializeOncePerProcess();
- static void TearDown();
- static bool enabled(Isolate* isolate) {
- SerializationState state = static_cast<SerializationState>(
- NoBarrier_Load(&serialization_state_));
- ASSERT(state != SERIALIZER_STATE_UNINITIALIZED);
- return state == SERIALIZER_STATE_ENABLED;
- }
SerializationAddressMapper* address_mapper() { return &address_mapper_; }
void PutRoot(int index,
HeapObject* object,
@@ -468,10 +400,9 @@ class Serializer : public SerializerDeserializer {
static const int kInvalidRootIndex = -1;
int RootIndex(HeapObject* heap_object, HowToCode from);
- virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) = 0;
intptr_t root_index_wave_front() { return root_index_wave_front_; }
void set_root_index_wave_front(intptr_t value) {
- ASSERT(value >= root_index_wave_front_);
+ DCHECK(value >= root_index_wave_front_);
root_index_wave_front_ = value;
}
@@ -555,14 +486,6 @@ class Serializer : public SerializerDeserializer {
SnapshotByteSink* sink_;
ExternalReferenceEncoder* external_reference_encoder_;
- enum SerializationState {
- SERIALIZER_STATE_UNINITIALIZED = 0,
- SERIALIZER_STATE_DISABLED = 1,
- SERIALIZER_STATE_ENABLED = 2
- };
-
- static AtomicWord serialization_state_;
-
SerializationAddressMapper address_mapper_;
intptr_t root_index_wave_front_;
void Pad();
@@ -570,8 +493,12 @@ class Serializer : public SerializerDeserializer {
friend class ObjectSerializer;
friend class Deserializer;
+ // We may not need the code address map for logging for every instance
+ // of the serializer. Initialize it on demand.
+ void InitializeCodeAddressMap();
+
private:
- static CodeAddressMap* code_address_map_;
+ CodeAddressMap* code_address_map_;
DISALLOW_COPY_AND_ASSIGN(Serializer);
};
@@ -584,23 +511,24 @@ class PartialSerializer : public Serializer {
: Serializer(isolate, sink),
startup_serializer_(startup_snapshot_serializer) {
set_root_index_wave_front(Heap::kStrongRootListLength);
+ InitializeCodeAddressMap();
}
// Serialize the objects reachable from a single object pointer.
- virtual void Serialize(Object** o);
+ void Serialize(Object** o);
virtual void SerializeObject(Object* o,
HowToCode how_to_code,
WhereToPoint where_to_point,
int skip);
- protected:
- virtual int PartialSnapshotCacheIndex(HeapObject* o);
- virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) {
+ private:
+ int PartialSnapshotCacheIndex(HeapObject* o);
+ bool ShouldBeInThePartialSnapshotCache(HeapObject* o) {
// Scripts should be referred only through shared function infos. We can't
// allow them to be part of the partial snapshot because they contain a
// unique ID, and deserializing several partial snapshots containing script
// would cause dupes.
- ASSERT(!o->IsScript());
+ DCHECK(!o->IsScript());
return o->IsName() || o->IsSharedFunctionInfo() ||
o->IsHeapNumber() || o->IsCode() ||
o->IsScopeInfo() ||
@@ -608,7 +536,7 @@ class PartialSerializer : public Serializer {
startup_serializer_->isolate()->heap()->fixed_cow_array_map();
}
- private:
+
Serializer* startup_serializer_;
DISALLOW_COPY_AND_ASSIGN(PartialSerializer);
};
@@ -623,6 +551,7 @@ class StartupSerializer : public Serializer {
// which will repopulate the cache with objects needed by that partial
// snapshot.
isolate->set_serialize_partial_snapshot_cache_length(0);
+ InitializeCodeAddressMap();
}
// Serialize the current state of the heap. The order is:
// 1) Strong references.
@@ -641,12 +570,110 @@ class StartupSerializer : public Serializer {
}
private:
- virtual bool ShouldBeInThePartialSnapshotCache(HeapObject* o) {
- return false;
+ DISALLOW_COPY_AND_ASSIGN(StartupSerializer);
+};
+
+
+class CodeSerializer : public Serializer {
+ public:
+ CodeSerializer(Isolate* isolate, SnapshotByteSink* sink, String* source)
+ : Serializer(isolate, sink), source_(source) {
+ set_root_index_wave_front(Heap::kStrongRootListLength);
+ InitializeCodeAddressMap();
}
+
+ static ScriptData* Serialize(Isolate* isolate,
+ Handle<SharedFunctionInfo> info,
+ Handle<String> source);
+
+ virtual void SerializeObject(Object* o, HowToCode how_to_code,
+ WhereToPoint where_to_point, int skip);
+
+ static Handle<SharedFunctionInfo> Deserialize(Isolate* isolate,
+ ScriptData* data,
+ Handle<String> source);
+
+ static const int kSourceObjectIndex = 0;
+
+ String* source() {
+ DCHECK(!AllowHeapAllocation::IsAllowed());
+ return source_;
+ }
+
+ private:
+ void SerializeBuiltin(Code* builtin, HowToCode how_to_code,
+ WhereToPoint where_to_point, int skip);
+ void SerializeSourceObject(HowToCode how_to_code, WhereToPoint where_to_point,
+ int skip);
+
+ DisallowHeapAllocation no_gc_;
+ String* source_;
+ DISALLOW_COPY_AND_ASSIGN(CodeSerializer);
};
+// Wrapper around ScriptData to provide code-serializer-specific functionality.
+class SerializedCodeData {
+ public:
+ // Used by when consuming.
+ explicit SerializedCodeData(ScriptData* data, String* source)
+ : script_data_(data), owns_script_data_(false) {
+ DisallowHeapAllocation no_gc;
+ CHECK(IsSane(source));
+ }
+
+ // Used when producing.
+ SerializedCodeData(List<byte>* payload, CodeSerializer* cs);
+
+ ~SerializedCodeData() {
+ if (owns_script_data_) delete script_data_;
+ }
+
+ // Return ScriptData object and relinquish ownership over it to the caller.
+ ScriptData* GetScriptData() {
+ ScriptData* result = script_data_;
+ script_data_ = NULL;
+ DCHECK(owns_script_data_);
+ owns_script_data_ = false;
+ return result;
+ }
+
+ const byte* Payload() const {
+ return script_data_->data() + kHeaderEntries * kIntSize;
+ }
+
+ int PayloadLength() const {
+ return script_data_->length() - kHeaderEntries * kIntSize;
+ }
+
+ int GetReservation(int space) const {
+ return GetHeaderValue(kReservationsOffset + space);
+ }
+
+ private:
+ void SetHeaderValue(int offset, int value) {
+ reinterpret_cast<int*>(const_cast<byte*>(script_data_->data()))[offset] =
+ value;
+ }
+
+ int GetHeaderValue(int offset) const {
+ return reinterpret_cast<const int*>(script_data_->data())[offset];
+ }
+
+ bool IsSane(String* source);
+
+ int CheckSum(String* source);
+
+ // The data header consists of int-sized entries:
+ // [0] version hash
+ // [1..7] reservation sizes for spaces from NEW_SPACE to PROPERTY_CELL_SPACE.
+ static const int kCheckSumOffset = 0;
+ static const int kReservationsOffset = 1;
+ static const int kHeaderEntries = 8;
+
+ ScriptData* script_data_;
+ bool owns_script_data_;
+};
} } // namespace v8::internal
#endif // V8_SERIALIZE_H_