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

Serializer: clean up opcodes.

R=mvstanton@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#27292}
parent f289311c
...@@ -840,7 +840,7 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space, ...@@ -840,7 +840,7 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
switch (data) { switch (data) {
#define CASE_STATEMENT(where, how, within, space_number) \ #define CASE_STATEMENT(where, how, within, space_number) \
case where + how + within + space_number: \ case where + how + within + space_number: \
STATIC_ASSERT((where & ~kPointedToMask) == 0); \ STATIC_ASSERT((where & ~kWhereMask) == 0); \
STATIC_ASSERT((how & ~kHowToCodeMask) == 0); \ STATIC_ASSERT((how & ~kHowToCodeMask) == 0); \
STATIC_ASSERT((within & ~kWhereToPointMask) == 0); \ STATIC_ASSERT((within & ~kWhereToPointMask) == 0); \
STATIC_ASSERT((space_number & ~kSpaceMask) == 0); STATIC_ASSERT((space_number & ~kSpaceMask) == 0);
...@@ -859,6 +859,15 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space, ...@@ -859,6 +859,15 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
Object* new_object = NULL; /* May not be a real Object pointer. */ \ Object* new_object = NULL; /* May not be a real Object pointer. */ \
if (where == kNewObject) { \ if (where == kNewObject) { \
ReadObject(space_number, &new_object); \ ReadObject(space_number, &new_object); \
} else if (where == kBackref) { \
emit_write_barrier = (space_number == NEW_SPACE); \
new_object = GetBackReferencedObject(data & kSpaceMask); \
} else if (where == kBackrefWithSkip) { \
int skip = source_.GetInt(); \
current = reinterpret_cast<Object**>( \
reinterpret_cast<Address>(current) + skip); \
emit_write_barrier = (space_number == NEW_SPACE); \
new_object = GetBackReferencedObject(data & kSpaceMask); \
} else if (where == kRootArray) { \ } else if (where == kRootArray) { \
int root_id = source_.GetInt(); \ int root_id = source_.GetInt(); \
new_object = isolate->heap()->roots_array_start()[root_id]; \ new_object = isolate->heap()->roots_array_start()[root_id]; \
...@@ -874,10 +883,13 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space, ...@@ -874,10 +883,13 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
int reference_id = source_.GetInt(); \ int reference_id = source_.GetInt(); \
Address address = external_reference_table_->address(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 == kAttachedReference) { \
emit_write_barrier = (space_number == NEW_SPACE); \ int index = source_.GetInt(); \
new_object = GetBackReferencedObject(data & kSpaceMask); \ DCHECK(deserializing_user_code() || index == kGlobalProxyReference); \
} else if (where == kBuiltin) { \ new_object = *attached_objects_[index]; \
emit_write_barrier = isolate->heap()->InNewSpace(new_object); \
} else { \
DCHECK(where == kBuiltin); \
DCHECK(deserializing_user_code()); \ DCHECK(deserializing_user_code()); \
int builtin_id = source_.GetInt(); \ int builtin_id = source_.GetInt(); \
DCHECK_LE(0, builtin_id); \ DCHECK_LE(0, builtin_id); \
...@@ -885,18 +897,6 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space, ...@@ -885,18 +897,6 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
Builtins::Name name = static_cast<Builtins::Name>(builtin_id); \ Builtins::Name name = static_cast<Builtins::Name>(builtin_id); \
new_object = isolate->builtins()->builtin(name); \ new_object = isolate->builtins()->builtin(name); \
emit_write_barrier = false; \ emit_write_barrier = false; \
} else if (where == kAttachedReference) { \
int index = source_.GetInt(); \
DCHECK(deserializing_user_code() || index == kGlobalProxyReference); \
new_object = *attached_objects_[index]; \
emit_write_barrier = isolate->heap()->InNewSpace(new_object); \
} else { \
DCHECK(where == kBackrefWithSkip); \
int skip = source_.GetInt(); \
current = reinterpret_cast<Object**>( \
reinterpret_cast<Address>(current) + skip); \
emit_write_barrier = (space_number == NEW_SPACE); \
new_object = GetBackReferencedObject(data & kSpaceMask); \
} \ } \
if (within == kInnerPointer) { \ if (within == kInnerPointer) { \
if (space_number != CODE_SPACE || new_object->IsCode()) { \ if (space_number != CODE_SPACE || new_object->IsCode()) { \
...@@ -959,106 +959,6 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space, ...@@ -959,106 +959,6 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
FOUR_CASES(byte_code + 8) \ FOUR_CASES(byte_code + 8) \
FOUR_CASES(byte_code + 12) FOUR_CASES(byte_code + 12)
#define COMMON_RAW_LENGTHS(f) \
f(1) \
f(2) \
f(3) \
f(4) \
f(5) \
f(6) \
f(7) \
f(8) \
f(9) \
f(10) \
f(11) \
f(12) \
f(13) \
f(14) \
f(15) \
f(16) \
f(17) \
f(18) \
f(19) \
f(20) \
f(21) \
f(22) \
f(23) \
f(24) \
f(25) \
f(26) \
f(27) \
f(28) \
f(29) \
f(30) \
f(31)
// We generate 15 cases and bodies that process special tags that combine
// the raw data tag and the length into one byte.
#define RAW_CASE(index) \
case kRawData + index: { \
byte* raw_data_out = reinterpret_cast<byte*>(current); \
source_.CopyRaw(raw_data_out, index* kPointerSize); \
current = reinterpret_cast<Object**>(raw_data_out + index * kPointerSize); \
break; \
}
COMMON_RAW_LENGTHS(RAW_CASE)
#undef RAW_CASE
// Deserialize a chunk of raw data that doesn't have one of the popular
// lengths.
case kRawData: {
int size = source_.GetInt();
byte* raw_data_out = reinterpret_cast<byte*>(current);
source_.CopyRaw(raw_data_out, size);
break;
}
SIXTEEN_CASES(kRootArrayConstants + kNoSkipDistance)
SIXTEEN_CASES(kRootArrayConstants + kNoSkipDistance + 16) {
int root_id = RootArrayConstantFromByteCode(data);
Object* object = isolate->heap()->roots_array_start()[root_id];
DCHECK(!isolate->heap()->InNewSpace(object));
UnalignedCopy(current++, &object);
break;
}
SIXTEEN_CASES(kRootArrayConstants + kHasSkipDistance)
SIXTEEN_CASES(kRootArrayConstants + kHasSkipDistance + 16) {
int root_id = RootArrayConstantFromByteCode(data);
int skip = source_.GetInt();
current = reinterpret_cast<Object**>(
reinterpret_cast<intptr_t>(current) + skip);
Object* object = isolate->heap()->roots_array_start()[root_id];
DCHECK(!isolate->heap()->InNewSpace(object));
UnalignedCopy(current++, &object);
break;
}
case kVariableRepeat: {
int repeats = source_.GetInt();
Object* object = current[-1];
DCHECK(!isolate->heap()->InNewSpace(object));
for (int i = 0; i < repeats; i++) UnalignedCopy(current++, &object);
break;
}
STATIC_ASSERT(kRootArrayNumberOfConstantEncodings ==
Heap::kOldSpaceRoots);
STATIC_ASSERT(kMaxFixedRepeats == 15);
FOUR_CASES(kFixedRepeat)
FOUR_CASES(kFixedRepeat + 4)
FOUR_CASES(kFixedRepeat + 8)
case kFixedRepeat + 12:
case kFixedRepeat + 13:
case kFixedRepeat + 14: {
int repeats = RepeatsForCode(data);
Object* object;
UnalignedCopy(&object, current - 1);
DCHECK(!isolate->heap()->InNewSpace(object));
for (int i = 0; i < repeats; i++) UnalignedCopy(current++, &object);
break;
}
// Deserialize a new object and write a pointer to it to the current // Deserialize a new object and write a pointer to it to the current
// object. // object.
ALL_SPACES(kNewObject, kPlain, kStartOfObject) ALL_SPACES(kNewObject, kPlain, kStartOfObject)
...@@ -1108,38 +1008,19 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space, ...@@ -1108,38 +1008,19 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
// Find an object in the partial snapshots cache and write a pointer to it // Find an object in the partial snapshots cache and write a pointer to it
// to the current object. // to the current object.
CASE_STATEMENT(kPartialSnapshotCache, kPlain, kStartOfObject, 0) CASE_STATEMENT(kPartialSnapshotCache, kPlain, kStartOfObject, 0)
CASE_BODY(kPartialSnapshotCache, CASE_BODY(kPartialSnapshotCache, kPlain, kStartOfObject, 0)
kPlain,
kStartOfObject,
0)
// Find an code entry in the partial snapshots cache and // Find an code entry in the partial snapshots cache and
// write a pointer to it to the current object. // write a pointer to it to the current object.
CASE_STATEMENT(kPartialSnapshotCache, kPlain, kInnerPointer, 0) CASE_STATEMENT(kPartialSnapshotCache, kPlain, kInnerPointer, 0)
CASE_BODY(kPartialSnapshotCache, CASE_BODY(kPartialSnapshotCache, kPlain, kInnerPointer, 0)
kPlain,
kInnerPointer,
0)
// Find an external reference and write a pointer to it to the current // Find an external reference and write a pointer to it to the current
// object. // object.
CASE_STATEMENT(kExternalReference, kPlain, kStartOfObject, 0) CASE_STATEMENT(kExternalReference, kPlain, kStartOfObject, 0)
CASE_BODY(kExternalReference, CASE_BODY(kExternalReference, kPlain, kStartOfObject, 0)
kPlain,
kStartOfObject,
0)
// Find an external reference and write a pointer to it in the current // Find an external reference and write a pointer to it in the current
// code object. // code object.
CASE_STATEMENT(kExternalReference, kFromCode, kStartOfObject, 0) CASE_STATEMENT(kExternalReference, kFromCode, kStartOfObject, 0)
CASE_BODY(kExternalReference, CASE_BODY(kExternalReference, kFromCode, kStartOfObject, 0)
kFromCode,
kStartOfObject,
0)
// 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)
CASE_STATEMENT(kBuiltin, kPlain, kInnerPointer, 0)
CASE_BODY(kBuiltin, kPlain, kInnerPointer, 0)
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 // Find an object in the attached references and write a pointer to it to
// the current object. // the current object.
CASE_STATEMENT(kAttachedReference, kPlain, kStartOfObject, 0) CASE_STATEMENT(kAttachedReference, kPlain, kStartOfObject, 0)
...@@ -1148,6 +1029,13 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space, ...@@ -1148,6 +1029,13 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
CASE_BODY(kAttachedReference, kPlain, kInnerPointer, 0) CASE_BODY(kAttachedReference, kPlain, kInnerPointer, 0)
CASE_STATEMENT(kAttachedReference, kFromCode, kInnerPointer, 0) CASE_STATEMENT(kAttachedReference, kFromCode, kInnerPointer, 0)
CASE_BODY(kAttachedReference, kFromCode, kInnerPointer, 0) CASE_BODY(kAttachedReference, kFromCode, kInnerPointer, 0)
// 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)
CASE_STATEMENT(kBuiltin, kPlain, kInnerPointer, 0)
CASE_BODY(kBuiltin, kPlain, kInnerPointer, 0)
CASE_STATEMENT(kBuiltin, kFromCode, kInnerPointer, 0)
CASE_BODY(kBuiltin, kFromCode, kInnerPointer, 0)
#undef CASE_STATEMENT #undef CASE_STATEMENT
#undef CASE_BODY #undef CASE_BODY
...@@ -1175,17 +1063,8 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space, ...@@ -1175,17 +1063,8 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
break; break;
} }
case kNativesStringResource: { case kNop:
DCHECK(!isolate_->heap()->deserialization_complete());
int index = source_.Get();
Vector<const char> source_vector = Natives::GetScriptSource(index);
NativesExternalStringResource* resource =
new NativesExternalStringResource(source_vector.start(),
source_vector.length());
Object* resource_obj = reinterpret_cast<Object*>(resource);
UnalignedCopy(current++, &resource_obj);
break; break;
}
case kNextChunk: { case kNextChunk: {
int space = source_.Get(); int space = source_.Get();
...@@ -1201,6 +1080,60 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space, ...@@ -1201,6 +1080,60 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
break; break;
} }
case kSynchronize:
// If we get here then that indicates that you have a mismatch between
// the number of GC roots when serializing and deserializing.
CHECK(false);
break;
case kNativesStringResource: {
DCHECK(!isolate_->heap()->deserialization_complete());
int index = source_.Get();
Vector<const char> source_vector = Natives::GetScriptSource(index);
NativesExternalStringResource* resource =
new NativesExternalStringResource(source_vector.start(),
source_vector.length());
Object* resource_obj = reinterpret_cast<Object*>(resource);
UnalignedCopy(current++, &resource_obj);
break;
}
// Deserialize raw data of variable length.
case kVariableRawData: {
int size_in_bytes = source_.GetInt();
byte* raw_data_out = reinterpret_cast<byte*>(current);
source_.CopyRaw(raw_data_out, size_in_bytes);
break;
}
case kVariableRepeat: {
int repeats = source_.GetInt();
Object* object = current[-1];
DCHECK(!isolate->heap()->InNewSpace(object));
for (int i = 0; i < repeats; i++) UnalignedCopy(current++, &object);
break;
}
STATIC_ASSERT(kNumberOfRootArrayConstants == Heap::kOldSpaceRoots);
STATIC_ASSERT(kNumberOfRootArrayConstants == 32);
SIXTEEN_CASES(kRootArrayConstantsWithSkip)
SIXTEEN_CASES(kRootArrayConstantsWithSkip + 16) {
int skip = source_.GetInt();
current = reinterpret_cast<Object**>(
reinterpret_cast<intptr_t>(current) + skip);
// Fall through.
}
SIXTEEN_CASES(kRootArrayConstants)
SIXTEEN_CASES(kRootArrayConstants + 16) {
int root_id = data & kRootArrayConstantsMask;
Object* object = isolate->heap()->roots_array_start()[root_id];
DCHECK(!isolate->heap()->InNewSpace(object));
UnalignedCopy(current++, &object);
break;
}
STATIC_ASSERT(kNumberOfHotObjects == 8);
FOUR_CASES(kHotObjectWithSkip) FOUR_CASES(kHotObjectWithSkip)
FOUR_CASES(kHotObjectWithSkip + 4) { FOUR_CASES(kHotObjectWithSkip + 4) {
int skip = source_.GetInt(); int skip = source_.GetInt();
...@@ -1208,9 +1141,10 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space, ...@@ -1208,9 +1141,10 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
reinterpret_cast<Address>(current) + skip); reinterpret_cast<Address>(current) + skip);
// Fall through. // Fall through.
} }
FOUR_CASES(kHotObject) FOUR_CASES(kHotObject)
FOUR_CASES(kHotObject + 4) { FOUR_CASES(kHotObject + 4) {
int index = data & kHotObjectIndexMask; int index = data & kHotObjectMask;
Object* hot_object = hot_objects_.Get(index); Object* hot_object = hot_objects_.Get(index);
UnalignedCopy(current, &hot_object); UnalignedCopy(current, &hot_object);
if (write_barrier_needed && isolate->heap()->InNewSpace(hot_object)) { if (write_barrier_needed && isolate->heap()->InNewSpace(hot_object)) {
...@@ -1223,12 +1157,30 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space, ...@@ -1223,12 +1157,30 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
break; break;
} }
case kSynchronize: { // Deserialize raw data of fixed length from 1 to 32 words.
// If we get here then that indicates that you have a mismatch between STATIC_ASSERT(kNumberOfFixedRawData == 32);
// the number of GC roots when serializing and deserializing. SIXTEEN_CASES(kFixedRawData)
CHECK(false); SIXTEEN_CASES(kFixedRawData + 16) {
byte* raw_data_out = reinterpret_cast<byte*>(current);
int size_in_bytes = (data - kFixedRawDataStart) << kPointerSizeLog2;
source_.CopyRaw(raw_data_out, size_in_bytes);
current = reinterpret_cast<Object**>(raw_data_out + size_in_bytes);
break;
} }
STATIC_ASSERT(kNumberOfFixedRepeat == 16);
SIXTEEN_CASES(kFixedRepeat) {
int repeats = data - kFixedRepeatStart;
Object* object;
UnalignedCopy(&object, current - 1);
DCHECK(!isolate->heap()->InNewSpace(object));
for (int i = 0; i < repeats; i++) UnalignedCopy(current++, &object);
break;
}
#undef SIXTEEN_CASES
#undef FOUR_CASES
default: default:
CHECK(false); CHECK(false);
} }
...@@ -1446,7 +1398,7 @@ bool Serializer::SerializeKnownObject(HeapObject* obj, HowToCode how_to_code, ...@@ -1446,7 +1398,7 @@ bool Serializer::SerializeKnownObject(HeapObject* obj, HowToCode how_to_code,
// Encode a reference to a hot object by its index in the working set. // Encode a reference to a hot object by its index in the working set.
int index = hot_objects_.Find(obj); int index = hot_objects_.Find(obj);
if (index != HotObjectsList::kNotFound) { if (index != HotObjectsList::kNotFound) {
DCHECK(index >= 0 && index <= kMaxHotObjectIndex); DCHECK(index >= 0 && index < kNumberOfHotObjects);
if (FLAG_trace_serializer) { if (FLAG_trace_serializer) {
PrintF(" Encoding hot object %d:", index); PrintF(" Encoding hot object %d:", index);
obj->ShortPrint(); obj->ShortPrint();
...@@ -1557,16 +1509,13 @@ void Serializer::PutRoot(int root_index, ...@@ -1557,16 +1509,13 @@ void Serializer::PutRoot(int root_index,
PrintF("\n"); PrintF("\n");
} }
if (how_to_code == kPlain && if (how_to_code == kPlain && where_to_point == kStartOfObject &&
where_to_point == kStartOfObject && root_index < kNumberOfRootArrayConstants &&
root_index < kRootArrayNumberOfConstantEncodings &&
!isolate()->heap()->InNewSpace(object)) { !isolate()->heap()->InNewSpace(object)) {
if (skip == 0) { if (skip == 0) {
sink_->Put(kRootArrayConstants + kNoSkipDistance + root_index, sink_->Put(kRootArrayConstants + root_index, "RootConstant");
"RootConstant");
} else { } else {
sink_->Put(kRootArrayConstants + kHasSkipDistance + root_index, sink_->Put(kRootArrayConstantsWithSkip + root_index, "RootConstant");
"RootConstant");
sink_->PutInt(skip, "SkipInPutRoot"); sink_->PutInt(skip, "SkipInPutRoot");
} }
} else { } else {
...@@ -1717,7 +1666,7 @@ void Serializer::ObjectSerializer::SerializeExternalString() { ...@@ -1717,7 +1666,7 @@ void Serializer::ObjectSerializer::SerializeExternalString() {
int bytes_to_output = allocation_size - HeapObject::kHeaderSize; int bytes_to_output = allocation_size - HeapObject::kHeaderSize;
// Output raw data header. Do not bother with common raw length cases here. // Output raw data header. Do not bother with common raw length cases here.
sink_->Put(kRawData, "RawDataForString"); sink_->Put(kVariableRawData, "RawDataForString");
sink_->PutInt(bytes_to_output, "length"); sink_->PutInt(bytes_to_output, "length");
// Serialize string header (except for map). // Serialize string header (except for map).
...@@ -1808,11 +1757,11 @@ void Serializer::ObjectSerializer::VisitPointers(Object** start, ...@@ -1808,11 +1757,11 @@ void Serializer::ObjectSerializer::VisitPointers(Object** start,
} }
current += repeat_count; current += repeat_count;
bytes_processed_so_far_ += repeat_count * kPointerSize; bytes_processed_so_far_ += repeat_count * kPointerSize;
if (repeat_count > kMaxFixedRepeats) { if (repeat_count > kNumberOfFixedRepeat) {
sink_->Put(kVariableRepeat, "SerializeRepeats"); sink_->Put(kVariableRepeat, "VariableRepeat");
sink_->PutInt(repeat_count, "SerializeRepeats"); sink_->PutInt(repeat_count, "repeat count");
} else { } else {
sink_->Put(CodeForRepeats(repeat_count), "SerializeRepeats"); sink_->Put(kFixedRepeatStart + repeat_count, "FixedRepeat");
} }
} else { } else {
serializer_->SerializeObject( serializer_->SerializeObject(
...@@ -1997,17 +1946,15 @@ int Serializer::ObjectSerializer::OutputRawData( ...@@ -1997,17 +1946,15 @@ int Serializer::ObjectSerializer::OutputRawData(
code_has_been_output_ = true; code_has_been_output_ = true;
} }
if (bytes_to_output != 0 && (!is_code_object_ || outputting_code)) { if (bytes_to_output != 0 && (!is_code_object_ || outputting_code)) {
#define RAW_CASE(index) \ if (!outputting_code && bytes_to_output == to_skip &&
if (!outputting_code && bytes_to_output == index * kPointerSize && \ IsAligned(bytes_to_output, kPointerAlignment) &&
index * kPointerSize == to_skip) { \ bytes_to_output <= kNumberOfFixedRawData * kPointerSize) {
sink_->PutSection(kRawData + index, "RawDataFixed"); \ int size_in_words = bytes_to_output >> kPointerSizeLog2;
to_skip = 0; /* This insn already skips. */ \ sink_->PutSection(kFixedRawDataStart + size_in_words, "FixedRawData");
} else /* NOLINT */ to_skip = 0; // This instruction includes skip.
COMMON_RAW_LENGTHS(RAW_CASE) } else {
#undef RAW_CASE
{ /* NOLINT */
// We always end up here if we are outputting the code of a code object. // We always end up here if we are outputting the code of a code object.
sink_->Put(kRawData, "RawData"); sink_->Put(kVariableRawData, "VariableRawData");
sink_->PutInt(bytes_to_output, "length"); sink_->PutInt(bytes_to_output, "length");
} }
......
...@@ -303,121 +303,116 @@ class SerializerDeserializer: public ObjectVisitor { ...@@ -303,121 +303,116 @@ class SerializerDeserializer: public ObjectVisitor {
static const int kNumberOfSpaces = LAST_SPACE + 1; static const int kNumberOfSpaces = LAST_SPACE + 1;
protected: protected:
// ---------- byte code range 0x00..0x7f ----------
// Byte codes in this range represent Where, HowToCode and WhereToPoint.
// Where the pointed-to object can be found: // Where the pointed-to object can be found:
enum Where { enum Where {
kNewObject = 0, // Object is next in snapshot. // 0x00..0x05 Allocate new object, in specified space.
// 1-6 One per space. kNewObject = 0,
// 0x7, 0x8 Unused. // 0x06 Unused (including 0x26, 0x46, 0x66).
kRootArray = 0x9, // Object is found in root array. // 0x07 Unused (including 0x27, 0x47, 0x67).
kPartialSnapshotCache = 0xa, // Object is in the cache. // 0x08..0x0d Reference to previous object from space.
kExternalReference = 0xb, // Pointer to an external reference. kBackref = 0x08,
kSkip = 0xc, // Skip n bytes. // 0x0e Unused (including 0x2e, 0x4e, 0x6e).
kBuiltin = 0xd, // Builtin code object. // 0x0f Unused (including 0x2f, 0x4f, 0x6f).
kAttachedReference = 0xe, // Object is described in an attached list. // 0x10..0x15 Reference to previous object from space after skip.
// 0xf Used by misc. See below. kBackrefWithSkip = 0x10,
kBackref = 0x10, // Object is described relative to end. // 0x16 Unused (including 0x36, 0x56, 0x76).
// 0x11-0x16 One per space. // 0x17 Unused (including 0x37, 0x57, 0x77).
// 0x17 Unused. // 0x18 Root array item.
kBackrefWithSkip = 0x18, // Object is described relative to end. kRootArray = 0x18,
// 0x19-0x1e One per space. // 0x19 Object in the partial snapshot cache.
// 0x1f Unused. kPartialSnapshotCache = 0x19,
// 0x20-0x3f Used by misc. See below. // 0x1a External reference referenced by id.
kPointedToMask = 0x3f kExternalReference = 0x1a,
// 0x1b Object provided in the attached list.
kAttachedReference = 0x1b,
// 0x1c Builtin code referenced by index.
kBuiltin = 0x1c
// 0x1d..0x1e Misc (including 0x3d..0x3f, 0x5d..0x5f, 0x7d..0x7f)
// 0x1f Unused (including 0x3f, 0x5f, 0x7f).
}; };
static const int kWhereMask = 0x1f;
static const int kSpaceMask = 7;
STATIC_ASSERT(kNumberOfSpaces <= kSpaceMask + 1);
// How to code the pointer to the object. // How to code the pointer to the object.
enum HowToCode { enum HowToCode {
kPlain = 0, // Straight pointer. // Straight pointer.
// What this means depends on the architecture: kPlain = 0,
kFromCode = 0x40, // A pointer inlined in code. // A pointer inlined in code. What this means depends on the architecture.
kHowToCodeMask = 0x40 kFromCode = 0x20
}; };
// For kRootArrayConstants static const int kHowToCodeMask = 0x20;
enum WithSkip {
kNoSkipDistance = 0,
kHasSkipDistance = 0x40,
kWithSkipMask = 0x40
};
// Where to point within the object. // Where to point within the object.
enum WhereToPoint { enum WhereToPoint {
// Points to start of object
kStartOfObject = 0, kStartOfObject = 0,
kInnerPointer = 0x80, // First insn in code object or payload of cell. // Points to instruction in code object or payload of cell.
kWhereToPointMask = 0x80 kInnerPointer = 0x40
}; };
// Misc. static const int kWhereToPointMask = 0x40;
// 0x48, 0x88 and 0xc8 are unused.
// Raw data to be copied from the snapshot. This byte code does not advance
// the current pointer, which is used for code objects, where we write the
// entire code in one memcpy, then fix up stuff with kSkip and other byte
// codes that overwrite data.
static const int kRawData = 0x20;
// Some common raw lengths: 0x21-0x3f.
// These autoadvance the current pointer.
static const int kOnePointerRawData = 0x21;
// ---------- Misc ----------
// Skip.
static const int kSkip = 0x1d;
// Internal reference encoded as offsets of pc and target from code entry. // Internal reference encoded as offsets of pc and target from code entry.
static const int kInternalReference = 0x08; static const int kInternalReference = 0x1e;
static const int kVariableRepeat = 0x60;
// 0x61-0x6f Repeat last word
static const int kFixedRepeat = 0x61;
static const int kFixedRepeatBase = kFixedRepeat - 1;
static const int kLastFixedRepeat = 0x6f;
static const int kMaxFixedRepeats = kLastFixedRepeat - kFixedRepeatBase;
static int CodeForRepeats(int repeats) {
DCHECK(repeats >= 1 && repeats <= kMaxFixedRepeats);
return kFixedRepeatBase + repeats;
}
static int RepeatsForCode(int byte_code) {
DCHECK(byte_code > kFixedRepeatBase && byte_code <= kLastFixedRepeat);
return byte_code - kFixedRepeatBase;
}
// Hot objects are a small set of recently seen or back-referenced objects.
// They are represented by a single opcode to save space.
// We use 0x70..0x77 for 8 hot objects, and 0x78..0x7f to add skip.
static const int kHotObject = 0x70;
static const int kMaxHotObjectIndex = 0x77 - kHotObject;
static const int kHotObjectWithSkip = 0x78;
STATIC_ASSERT(HotObjectsList::kSize == kMaxHotObjectIndex + 1);
STATIC_ASSERT(0x7f - kHotObjectWithSkip == kMaxHotObjectIndex);
static const int kHotObjectIndexMask = 0x7;
static const int kRootArrayConstants = 0xa0;
// 0xa0-0xbf Things from the first 32 elements of the root array.
static const int kRootArrayNumberOfConstantEncodings = 0x20;
static int RootArrayConstantFromByteCode(int byte_code) {
return byte_code & 0x1f;
}
// Do nothing, used for padding. // Do nothing, used for padding.
static const int kNop = 0xf; static const int kNop = 0x3d;
// Move to next reserved chunk. // Move to next reserved chunk.
static const int kNextChunk = 0x4f; static const int kNextChunk = 0x3e;
// A tag emitted at strategic points in the snapshot to delineate sections. // A tag emitted at strategic points in the snapshot to delineate sections.
// If the deserializer does not find these at the expected moments then it // If the deserializer does not find these at the expected moments then it
// is an indication that the snapshot and the VM do not fit together. // is an indication that the snapshot and the VM do not fit together.
// Examine the build process for architecture, version or configuration // Examine the build process for architecture, version or configuration
// mismatches. // mismatches.
static const int kSynchronize = 0x8f; static const int kSynchronize = 0x5d;
// Used for the source code of the natives, which is in the executable, but // Used for the source code of the natives, which is in the executable, but
// is referred to from external strings in the snapshot. // is referred to from external strings in the snapshot.
static const int kNativesStringResource = 0xcf; static const int kNativesStringResource = 0x5e;
// Raw data of variable length.
static const int kVariableRawData = 0x7d;
// Repeats of variable length.
static const int kVariableRepeat = 0x7e;
// ---------- byte code range 0x80..0xff ----------
// First 32 root array items.
static const int kNumberOfRootArrayConstants = 0x20;
// 0x80..0x9f
static const int kRootArrayConstants = 0x80;
// 0xa0..0xbf
static const int kRootArrayConstantsWithSkip = 0xa0;
static const int kRootArrayConstantsMask = 0x1f;
// 8 hot (recently seen or back-referenced) objects with optional skip.
static const int kNumberOfHotObjects = 0x08;
// 0xc0..0xc7
static const int kHotObject = 0xc0;
// 0xc8..0xcf
static const int kHotObjectWithSkip = 0xc8;
static const int kHotObjectMask = 0x07;
// 32 common raw data lengths.
static const int kNumberOfFixedRawData = 0x20;
// 0xd0..0xef
static const int kFixedRawData = 0xd0;
static const int kOnePointerRawData = kFixedRawData;
static const int kFixedRawDataStart = kFixedRawData - 1;
// 16 repeats lengths.
static const int kNumberOfFixedRepeat = 0x10;
// 0xf0..0xff
static const int kFixedRepeat = 0xf0;
static const int kFixedRepeatStart = kFixedRepeat - 1;
// ---------- special values ----------
static const int kAnyOldSpace = -1; static const int kAnyOldSpace = -1;
// A bitmask for getting the space out of an instruction.
static const int kSpaceMask = 7;
STATIC_ASSERT(kNumberOfSpaces <= kSpaceMask + 1);
// Sentinel after a new object to indicate that double alignment is needed. // Sentinel after a new object to indicate that double alignment is needed.
static const int kDoubleAlignmentSentinel = 0; static const int kDoubleAlignmentSentinel = 0;
...@@ -427,6 +422,7 @@ class SerializerDeserializer: public ObjectVisitor { ...@@ -427,6 +422,7 @@ class SerializerDeserializer: public ObjectVisitor {
// Used as index for the attached reference representing the global proxy. // Used as index for the attached reference representing the global proxy.
static const int kGlobalProxyReference = 0; static const int kGlobalProxyReference = 0;
// ---------- member variable ----------
HotObjectsList hot_objects_; HotObjectsList hot_objects_;
}; };
......
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