summaryrefslogtreecommitdiff
path: root/deps/v8/src/serialize.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/serialize.cc')
-rw-r--r--deps/v8/src/serialize.cc411
1 files changed, 279 insertions, 132 deletions
diff --git a/deps/v8/src/serialize.cc b/deps/v8/src/serialize.cc
index c5f8b6344e..28480e649c 100644
--- a/deps/v8/src/serialize.cc
+++ b/deps/v8/src/serialize.cc
@@ -9,6 +9,7 @@
#include "src/base/platform/platform.h"
#include "src/bootstrapper.h"
#include "src/code-stubs.h"
+#include "src/compiler.h"
#include "src/deoptimizer.h"
#include "src/execution.h"
#include "src/global-handles.h"
@@ -95,12 +96,12 @@ void ExternalReferenceTable::Add(Address address,
TypeCode type,
uint16_t id,
const char* name) {
- DCHECK_NE(NULL, address);
+ DCHECK_NOT_NULL(address);
ExternalReferenceEntry entry;
entry.address = address;
entry.code = EncodeExternal(type, id);
entry.name = name;
- DCHECK_NE(0, entry.code);
+ 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);
@@ -163,8 +164,6 @@ void ExternalReferenceTable::PopulateTable(Isolate* isolate) {
"std::log");
Add(ExternalReference::store_buffer_top(isolate).address(),
"store_buffer_top");
- Add(ExternalReference::address_of_canonical_non_hole_nan().address(),
- "canonical_nan");
Add(ExternalReference::address_of_the_hole_nan().address(), "the_hole_nan");
Add(ExternalReference::get_date_field_function(isolate).address(),
"JSDate::GetField");
@@ -614,7 +613,9 @@ void Deserializer::DecodeReservation(
DCHECK_EQ(0, reservations_[NEW_SPACE].length());
STATIC_ASSERT(NEW_SPACE == 0);
int current_space = NEW_SPACE;
- for (const auto& r : res) {
+ for (int i = 0; i < res.length(); i++) {
+ SerializedData::Reservation r(0);
+ memcpy(&r, res.start() + i, sizeof(r));
reservations_[current_space].Add({r.chunk_size(), NULL, NULL});
if (r.is_last()) current_space++;
}
@@ -633,6 +634,11 @@ void Deserializer::FlushICacheForNewCodeObjects() {
bool Deserializer::ReserveSpace() {
+#ifdef DEBUG
+ for (int i = NEW_SPACE; i < kNumberOfSpaces; ++i) {
+ CHECK(reservations_[i].length() > 0);
+ }
+#endif // DEBUG
if (!isolate_->heap()->ReserveSpace(reservations_)) return false;
for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) {
high_water_[i] = reservations_[i][0].start;
@@ -641,19 +647,25 @@ bool Deserializer::ReserveSpace() {
}
-void Deserializer::Deserialize(Isolate* isolate) {
+void Deserializer::Initialize(Isolate* isolate) {
+ DCHECK_NULL(isolate_);
+ DCHECK_NOT_NULL(isolate);
isolate_ = isolate;
- DCHECK(isolate_ != NULL);
- if (!ReserveSpace()) FatalProcessOutOfMemory("deserializing context");
+ DCHECK_NULL(external_reference_decoder_);
+ external_reference_decoder_ = new ExternalReferenceDecoder(isolate);
+}
+
+
+void Deserializer::Deserialize(Isolate* isolate) {
+ Initialize(isolate);
+ if (!ReserveSpace()) V8::FatalProcessOutOfMemory("deserializing context");
// No active threads.
- DCHECK_EQ(NULL, isolate_->thread_manager()->FirstThreadStateInUse());
+ DCHECK_NULL(isolate_->thread_manager()->FirstThreadStateInUse());
// No active handles.
DCHECK(isolate_->handle_scope_implementer()->blocks()->is_empty());
- DCHECK_EQ(NULL, external_reference_decoder_);
- external_reference_decoder_ = new ExternalReferenceDecoder(isolate);
isolate_->heap()->IterateSmiRoots(this);
isolate_->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG);
- isolate_->heap()->RepairFreeListsAfterBoot();
+ isolate_->heap()->RepairFreeListsAfterDeserialization();
isolate_->heap()->IterateWeakRoots(this, VISIT_ALL);
isolate_->heap()->set_native_contexts_list(
@@ -668,8 +680,6 @@ void Deserializer::Deserialize(Isolate* isolate) {
isolate_->heap()->undefined_value());
}
- isolate_->heap()->InitializeWeakObjectToCodeTable();
-
// Update data pointers to the external strings containing natives sources.
for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
Object* source = isolate_->heap()->natives_source_cache()->get(i);
@@ -686,33 +696,52 @@ void Deserializer::Deserialize(Isolate* isolate) {
}
-void Deserializer::DeserializePartial(Isolate* isolate, Object** root,
- OnOOM on_oom) {
- isolate_ = isolate;
- for (int i = NEW_SPACE; i < kNumberOfSpaces; i++) {
- DCHECK(reservations_[i].length() > 0);
- }
+MaybeHandle<Object> Deserializer::DeserializePartial(
+ Isolate* isolate, Handle<JSGlobalProxy> global_proxy,
+ Handle<FixedArray>* outdated_contexts_out) {
+ Initialize(isolate);
if (!ReserveSpace()) {
- if (on_oom == FATAL_ON_OOM) FatalProcessOutOfMemory("deserialize context");
- *root = NULL;
- return;
- }
- if (external_reference_decoder_ == NULL) {
- external_reference_decoder_ = new ExternalReferenceDecoder(isolate);
+ V8::FatalProcessOutOfMemory("deserialize context");
+ return MaybeHandle<Object>();
}
- DisallowHeapAllocation no_gc;
+ Vector<Handle<Object> > attached_objects = Vector<Handle<Object> >::New(1);
+ attached_objects[kGlobalProxyReference] = global_proxy;
+ SetAttachedObjects(attached_objects);
+ DisallowHeapAllocation no_gc;
// Keep track of the code space start and end pointers in case new
// code objects were unserialized
OldSpace* code_space = isolate_->heap()->code_space();
Address start_address = code_space->top();
- VisitPointer(root);
+ Object* root;
+ Object* outdated_contexts;
+ VisitPointer(&root);
+ VisitPointer(&outdated_contexts);
// There's no code deserialized here. If this assert fires
// then that's changed and logging should be added to notify
// the profiler et al of the new code.
CHECK_EQ(start_address, code_space->top());
+ CHECK(outdated_contexts->IsFixedArray());
+ *outdated_contexts_out =
+ Handle<FixedArray>(FixedArray::cast(outdated_contexts), isolate);
+ return Handle<Object>(root, isolate);
+}
+
+
+MaybeHandle<SharedFunctionInfo> Deserializer::DeserializeCode(
+ Isolate* isolate) {
+ Initialize(isolate);
+ if (!ReserveSpace()) {
+ return Handle<SharedFunctionInfo>();
+ } else {
+ deserializing_user_code_ = true;
+ DisallowHeapAllocation no_gc;
+ Object* root;
+ VisitPointer(&root);
+ return Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(root));
+ }
}
@@ -723,7 +752,7 @@ Deserializer::~Deserializer() {
delete external_reference_decoder_;
external_reference_decoder_ = NULL;
}
- if (attached_objects_) attached_objects_->Dispose();
+ attached_objects_.Dispose();
}
@@ -798,11 +827,12 @@ HeapObject* Deserializer::ProcessNewObjectFromSerializedCode(HeapObject* obj) {
HeapObject* Deserializer::GetBackReferencedObject(int space) {
HeapObject* obj;
+ BackReference back_reference(source_.GetInt());
if (space == LO_SPACE) {
- uint32_t index = source_.GetInt();
+ CHECK(back_reference.chunk_index() == 0);
+ uint32_t index = back_reference.large_object_index();
obj = deserialized_large_objects_[index];
} else {
- BackReference back_reference(source_.GetInt());
DCHECK(space < kNumberOfPreallocatedSpaces);
uint32_t chunk_index = back_reference.chunk_index();
DCHECK_LE(chunk_index, current_chunk_[space]);
@@ -860,7 +890,8 @@ void Deserializer::ReadObject(int space_number, Object** write_back) {
// Fix up strings from serialized user code.
if (deserializing_user_code()) obj = ProcessNewObjectFromSerializedCode(obj);
- *write_back = obj;
+ Object* write_back_obj = obj;
+ UnalignedCopy(write_back, &write_back_obj);
#ifdef DEBUG
if (obj->IsCode()) {
DCHECK(space_number == CODE_SPACE || space_number == LO_SPACE);
@@ -868,6 +899,23 @@ void Deserializer::ReadObject(int space_number, Object** write_back) {
DCHECK(space_number != CODE_SPACE);
}
#endif
+#if V8_TARGET_ARCH_PPC && \
+ (ABI_USES_FUNCTION_DESCRIPTORS || V8_OOL_CONSTANT_POOL)
+ // If we're on a platform that uses function descriptors
+ // these jump tables make use of RelocInfo::INTERNAL_REFERENCE.
+ // As the V8 serialization code doesn't handle that relocation type
+ // we use this to fix up code that has function descriptors.
+ if (space_number == CODE_SPACE) {
+ Code* code = reinterpret_cast<Code*>(HeapObject::FromAddress(address));
+ for (RelocIterator it(code); !it.done(); it.next()) {
+ RelocInfo::Mode rmode = it.rinfo()->rmode();
+ if (rmode == RelocInfo::INTERNAL_REFERENCE) {
+ Assembler::RelocateInternalReference(it.rinfo()->pc(), 0,
+ code->instruction_start());
+ }
+ }
+ }
+#endif
}
@@ -894,7 +942,7 @@ Address Deserializer::Allocate(int space_index, int size) {
} else {
DCHECK(space_index < kNumberOfPreallocatedSpaces);
Address address = high_water_[space_index];
- DCHECK_NE(NULL, address);
+ DCHECK_NOT_NULL(address);
high_water_[space_index] += size;
#ifdef DEBUG
// Assert that the current reserved chunk is still big enough.
@@ -970,9 +1018,9 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
new_object = isolate->builtins()->builtin(name); \
emit_write_barrier = false; \
} else if (where == kAttachedReference) { \
- DCHECK(deserializing_user_code()); \
int index = source_.GetInt(); \
- new_object = *attached_objects_->at(index); \
+ DCHECK(deserializing_user_code() || index == kGlobalProxyReference); \
+ new_object = *attached_objects_[index]; \
emit_write_barrier = isolate->heap()->InNewSpace(new_object); \
} else { \
DCHECK(where == kBackrefWithSkip); \
@@ -1003,7 +1051,7 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
current = reinterpret_cast<Object**>(location_of_branch_data); \
current_was_incremented = true; \
} else { \
- *current = new_object; \
+ UnalignedCopy(current, &new_object); \
} \
} \
if (emit_write_barrier && write_barrier_needed) { \
@@ -1104,7 +1152,7 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
int root_id = RootArrayConstantFromByteCode(data);
Object* object = isolate->heap()->roots_array_start()[root_id];
DCHECK(!isolate->heap()->InNewSpace(object));
- *current++ = object;
+ UnalignedCopy(current++, &object);
break;
}
@@ -1116,7 +1164,7 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
reinterpret_cast<intptr_t>(current) + skip);
Object* object = isolate->heap()->roots_array_start()[root_id];
DCHECK(!isolate->heap()->InNewSpace(object));
- *current++ = object;
+ UnalignedCopy(current++, &object);
break;
}
@@ -1124,8 +1172,7 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
int repeats = source_.GetInt();
Object* object = current[-1];
DCHECK(!isolate->heap()->InNewSpace(object));
- for (int i = 0; i < repeats; i++) current[i] = object;
- current += repeats;
+ for (int i = 0; i < repeats; i++) UnalignedCopy(current++, &object);
break;
}
@@ -1139,10 +1186,10 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
case kFixedRepeat + 13:
case kFixedRepeat + 14: {
int repeats = RepeatsForCode(data);
- Object* object = current[-1];
+ Object* object;
+ UnalignedCopy(&object, current - 1);
DCHECK(!isolate->heap()->InNewSpace(object));
- for (int i = 0; i < repeats; i++) current[i] = object;
- current += repeats;
+ for (int i = 0; i < repeats; i++) UnalignedCopy(current++, &object);
break;
}
@@ -1161,16 +1208,16 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
// allocation point and write a pointer to it to the current object.
ALL_SPACES(kBackref, kPlain, kStartOfObject)
ALL_SPACES(kBackrefWithSkip, kPlain, kStartOfObject)
-#if defined(V8_TARGET_ARCH_MIPS) || V8_OOL_CONSTANT_POOL || \
- defined(V8_TARGET_ARCH_MIPS64)
+#if defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64) || \
+ defined(V8_TARGET_ARCH_PPC) || V8_OOL_CONSTANT_POOL
// Deserialize a new object from pointer found in code and write
- // a pointer to it to the current object. Required only for MIPS or ARM
- // with ool constant pool, and omitted on the other architectures because
- // it is fully unrolled and would cause bloat.
+ // a pointer to it to the current object. Required only for MIPS, PPC or
+ // ARM with ool constant pool, and omitted on the other architectures
+ // because it is fully unrolled and would cause bloat.
ALL_SPACES(kNewObject, kFromCode, kStartOfObject)
// Find a recently deserialized code object using its offset from the
// current allocation point and write a pointer to it to the current
- // object. Required only for MIPS or ARM with ool constant pool.
+ // object. Required only for MIPS, PPC or ARM with ool constant pool.
ALL_SPACES(kBackref, kFromCode, kStartOfObject)
ALL_SPACES(kBackrefWithSkip, kFromCode, kStartOfObject)
#endif
@@ -1187,7 +1234,7 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
CASE_STATEMENT(kRootArray, kPlain, kStartOfObject, 0)
CASE_BODY(kRootArray, kPlain, kStartOfObject, 0)
#if defined(V8_TARGET_ARCH_MIPS) || V8_OOL_CONSTANT_POOL || \
- defined(V8_TARGET_ARCH_MIPS64)
+ defined(V8_TARGET_ARCH_MIPS64) || defined(V8_TARGET_ARCH_PPC)
// Find an object in the roots array and write a pointer to it to in code.
CASE_STATEMENT(kRootArray, kFromCode, kStartOfObject, 0)
CASE_BODY(kRootArray, kFromCode, kStartOfObject, 0)
@@ -1248,13 +1295,14 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
}
case kNativesStringResource: {
+ DCHECK(!isolate_->heap()->deserialization_complete());
int index = source_.Get();
Vector<const char> source_vector = Natives::GetScriptSource(index);
NativesExternalStringResource* resource =
- new NativesExternalStringResource(isolate->bootstrapper(),
- source_vector.start(),
+ new NativesExternalStringResource(source_vector.start(),
source_vector.length());
- *current++ = reinterpret_cast<Object*>(resource);
+ Object* resource_obj = reinterpret_cast<Object*>(resource);
+ UnalignedCopy(current++, &resource_obj);
break;
}
@@ -1267,7 +1315,7 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
CHECK_EQ(reservation[chunk_index].end, high_water_[space]);
// Move to next reserved chunk.
chunk_index = ++current_chunk_[space];
- DCHECK_LT(chunk_index, reservation.length());
+ CHECK_LT(chunk_index, reservation.length());
high_water_[space] = reservation[chunk_index].start;
break;
}
@@ -1282,8 +1330,9 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
FOUR_CASES(kHotObject)
FOUR_CASES(kHotObject + 4) {
int index = data & kHotObjectIndexMask;
- *current = hot_objects_.Get(index);
- if (write_barrier_needed && isolate->heap()->InNewSpace(*current)) {
+ Object* hot_object = hot_objects_.Get(index);
+ UnalignedCopy(current, &hot_object);
+ if (write_barrier_needed && isolate->heap()->InNewSpace(hot_object)) {
Address current_address = reinterpret_cast<Address>(current);
isolate->heap()->RecordWrite(
current_object_address,
@@ -1296,14 +1345,14 @@ void Deserializer::ReadData(Object** current, Object** limit, int source_space,
case kSynchronize: {
// If we get here then that indicates that you have a mismatch between
// the number of GC roots when serializing and deserializing.
- UNREACHABLE();
+ CHECK(false);
}
default:
- UNREACHABLE();
+ CHECK(false);
}
}
- DCHECK_EQ(limit, current);
+ CHECK_EQ(limit, current);
}
@@ -1334,7 +1383,7 @@ Serializer::~Serializer() {
void StartupSerializer::SerializeStrongReferences() {
Isolate* isolate = this->isolate();
// No active threads.
- CHECK_EQ(NULL, isolate->thread_manager()->FirstThreadStateInUse());
+ CHECK_NULL(isolate->thread_manager()->FirstThreadStateInUse());
// No active or weak handles.
CHECK(isolate->handle_scope_implementer()->blocks()->is_empty());
CHECK_EQ(0, isolate->global_handles()->NumberOfWeakHandles());
@@ -1367,12 +1416,46 @@ void StartupSerializer::VisitPointers(Object** start, Object** end) {
}
-void PartialSerializer::Serialize(Object** object) {
- this->VisitPointer(object);
+void PartialSerializer::Serialize(Object** o) {
+ if ((*o)->IsContext()) {
+ Context* context = Context::cast(*o);
+ global_object_ = context->global_object();
+ back_reference_map()->AddGlobalProxy(context->global_proxy());
+ }
+ VisitPointer(o);
+ SerializeOutdatedContextsAsFixedArray();
Pad();
}
+void PartialSerializer::SerializeOutdatedContextsAsFixedArray() {
+ int length = outdated_contexts_.length();
+ if (length == 0) {
+ FixedArray* empty = isolate_->heap()->empty_fixed_array();
+ SerializeObject(empty, kPlain, kStartOfObject, 0);
+ } else {
+ // Serialize an imaginary fixed array containing outdated contexts.
+ int size = FixedArray::SizeFor(length);
+ Allocate(NEW_SPACE, size);
+ sink_->Put(kNewObject + NEW_SPACE, "emulated FixedArray");
+ sink_->PutInt(size >> kObjectAlignmentBits, "FixedArray size in words");
+ Map* map = isolate_->heap()->fixed_array_map();
+ SerializeObject(map, kPlain, kStartOfObject, 0);
+ Smi* length_smi = Smi::FromInt(length);
+ sink_->Put(kOnePointerRawData, "Smi");
+ for (int i = 0; i < kPointerSize; i++) {
+ sink_->Put(reinterpret_cast<byte*>(&length_smi)[i], "Byte");
+ }
+ for (int i = 0; i < length; i++) {
+ BackReference back_ref = outdated_contexts_[i];
+ DCHECK(BackReferenceIsAlreadyAllocated(back_ref));
+ sink_->Put(kBackref + back_ref.space(), "BackRef");
+ sink_->PutInt(back_ref.reference(), "BackRefValue");
+ }
+ }
+}
+
+
bool Serializer::ShouldBeSkipped(Object** current) {
Object** roots = isolate()->heap()->roots_array_start();
return current == &roots[Heap::kStoreBufferTopRootIndex]
@@ -1464,6 +1547,26 @@ int PartialSerializer::PartialSnapshotCacheIndex(HeapObject* heap_object) {
}
+#ifdef DEBUG
+bool Serializer::BackReferenceIsAlreadyAllocated(BackReference reference) {
+ DCHECK(reference.is_valid());
+ DCHECK(!reference.is_source());
+ DCHECK(!reference.is_global_proxy());
+ AllocationSpace space = reference.space();
+ int chunk_index = reference.chunk_index();
+ if (space == LO_SPACE) {
+ return chunk_index == 0 &&
+ reference.large_object_index() < seen_large_objects_index_;
+ } else if (chunk_index == completed_chunks_[space].length()) {
+ return reference.chunk_offset() < pending_chunk_[space];
+ } else {
+ return chunk_index < completed_chunks_[space].length() &&
+ reference.chunk_offset() < completed_chunks_[space][chunk_index];
+ }
+}
+#endif // DEBUG
+
+
bool Serializer::SerializeKnownObject(HeapObject* obj, HowToCode how_to_code,
WhereToPoint where_to_point, int skip) {
if (how_to_code == kPlain && where_to_point == kStartOfObject) {
@@ -1495,8 +1598,14 @@ bool Serializer::SerializeKnownObject(HeapObject* obj, HowToCode how_to_code,
FlushSkip(skip);
if (FLAG_trace_serializer) PrintF(" Encoding source object\n");
DCHECK(how_to_code == kPlain && where_to_point == kStartOfObject);
- sink_->Put(kAttachedReference + how_to_code + where_to_point, "Source");
- sink_->PutInt(kSourceObjectReference, "kSourceObjectIndex");
+ sink_->Put(kAttachedReference + kPlain + kStartOfObject, "Source");
+ sink_->PutInt(kSourceObjectReference, "kSourceObjectReference");
+ } else if (back_reference.is_global_proxy()) {
+ FlushSkip(skip);
+ if (FLAG_trace_serializer) PrintF(" Encoding global proxy\n");
+ DCHECK(how_to_code == kPlain && where_to_point == kStartOfObject);
+ sink_->Put(kAttachedReference + kPlain + kStartOfObject, "Global Proxy");
+ sink_->PutInt(kGlobalProxyReference, "kGlobalProxyReference");
} else {
if (FLAG_trace_serializer) {
PrintF(" Encoding back reference to: ");
@@ -1512,6 +1621,7 @@ bool Serializer::SerializeKnownObject(HeapObject* obj, HowToCode how_to_code,
"BackRefWithSkip");
sink_->PutInt(skip, "BackRefSkipDistance");
}
+ DCHECK(BackReferenceIsAlreadyAllocated(back_reference));
sink_->PutInt(back_reference.reference(), "BackRefValue");
hot_objects_.Add(obj);
@@ -1598,6 +1708,9 @@ void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
DCHECK(Map::cast(obj)->code_cache() == obj->GetHeap()->empty_fixed_array());
}
+ // Replace typed arrays by undefined.
+ if (obj->IsJSTypedArray()) obj = isolate_->heap()->undefined_value();
+
int root_index = root_index_map_.Lookup(obj);
if (root_index != RootIndexMap::kInvalidRootIndex) {
PutRoot(root_index, obj, how_to_code, where_to_point, skip);
@@ -1629,6 +1742,15 @@ void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
// Object has not yet been serialized. Serialize it here.
ObjectSerializer serializer(this, obj, sink_, how_to_code, where_to_point);
serializer.Serialize();
+
+ if (obj->IsContext() &&
+ Context::cast(obj)->global_object() == global_object_) {
+ // Context refers to the current global object. This reference will
+ // become outdated after deserialization.
+ BackReference back_reference = back_reference_map_.Lookup(obj);
+ DCHECK(back_reference.is_valid());
+ outdated_contexts_.Add(back_reference);
+ }
}
@@ -1748,6 +1870,9 @@ void Serializer::ObjectSerializer::Serialize() {
PrintF("\n");
}
+ // We cannot serialize typed array objects correctly.
+ DCHECK(!object_->IsJSTypedArray());
+
if (object_->IsScript()) {
// Clear cached line ends.
Object* undefined = serializer_->isolate()->heap()->undefined_value();
@@ -1994,6 +2119,10 @@ int Serializer::ObjectSerializer::OutputRawData(
}
const char* description = code_object_ ? "Code" : "Byte";
+#ifdef MEMORY_SANITIZER
+ // Object sizes are usually rounded up with uninitialized padding space.
+ MSAN_MEMORY_IS_INITIALIZED(object_start + base, bytes_to_output);
+#endif // MEMORY_SANITIZER
sink_->PutRaw(object_start + base, bytes_to_output, description);
if (code_object_) delete[] object_start;
}
@@ -2261,67 +2390,52 @@ int CodeSerializer::AddCodeStubKey(uint32_t stub_key) {
}
-void CodeSerializer::SerializeSourceObject(HowToCode how_to_code,
- WhereToPoint where_to_point) {
- if (FLAG_trace_serializer) PrintF(" Encoding source object\n");
-
- DCHECK(how_to_code == kPlain && where_to_point == kStartOfObject);
- sink_->Put(kAttachedReference + how_to_code + where_to_point, "Source");
- sink_->PutInt(kSourceObjectIndex, "kSourceObjectIndex");
-}
-
-
MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
Isolate* isolate, ScriptData* cached_data, Handle<String> source) {
base::ElapsedTimer timer;
if (FLAG_profile_deserialization) timer.Start();
- Object* root;
+ HandleScope scope(isolate);
- {
- HandleScope scope(isolate);
+ SmartPointer<SerializedCodeData> scd(
+ SerializedCodeData::FromCachedData(cached_data, *source));
+ if (scd.is_empty()) {
+ if (FLAG_profile_deserialization) PrintF("[Cached code failed check]\n");
+ DCHECK(cached_data->rejected());
+ return MaybeHandle<SharedFunctionInfo>();
+ }
- SmartPointer<SerializedCodeData> scd(
- SerializedCodeData::FromCachedData(cached_data, *source));
- if (scd.is_empty()) {
- if (FLAG_profile_deserialization) PrintF("[Cached code failed check]\n");
- DCHECK(cached_data->rejected());
- return MaybeHandle<SharedFunctionInfo>();
- }
+ // Eagerly expand string table to avoid allocations during deserialization.
+ StringTable::EnsureCapacityForDeserialization(isolate,
+ scd->NumInternalizedStrings());
- // Eagerly expand string table to avoid allocations during deserialization.
- StringTable::EnsureCapacityForDeserialization(
- isolate, scd->NumInternalizedStrings());
-
- // Prepare and register list of attached objects.
- Vector<const uint32_t> code_stub_keys = scd->CodeStubKeys();
- Vector<Handle<Object> > attached_objects = Vector<Handle<Object> >::New(
- code_stub_keys.length() + kCodeStubsBaseIndex);
- attached_objects[kSourceObjectIndex] = source;
- for (int i = 0; i < code_stub_keys.length(); i++) {
- attached_objects[i + kCodeStubsBaseIndex] =
- CodeStub::GetCode(isolate, code_stub_keys[i]).ToHandleChecked();
- }
+ // Prepare and register list of attached objects.
+ Vector<const uint32_t> code_stub_keys = scd->CodeStubKeys();
+ Vector<Handle<Object> > attached_objects = Vector<Handle<Object> >::New(
+ code_stub_keys.length() + kCodeStubsBaseIndex);
+ attached_objects[kSourceObjectIndex] = source;
+ for (int i = 0; i < code_stub_keys.length(); i++) {
+ attached_objects[i + kCodeStubsBaseIndex] =
+ CodeStub::GetCode(isolate, code_stub_keys[i]).ToHandleChecked();
+ }
- Deserializer deserializer(scd.get());
- deserializer.SetAttachedObjects(&attached_objects);
+ Deserializer deserializer(scd.get());
+ deserializer.SetAttachedObjects(attached_objects);
- // Deserialize.
- deserializer.DeserializePartial(isolate, &root, Deserializer::NULL_ON_OOM);
- if (root == NULL) {
- // Deserializing may fail if the reservations cannot be fulfilled.
- if (FLAG_profile_deserialization) PrintF("[Deserializing failed]\n");
- return MaybeHandle<SharedFunctionInfo>();
- }
- deserializer.FlushICacheForNewCodeObjects();
+ // Deserialize.
+ Handle<SharedFunctionInfo> result;
+ if (!deserializer.DeserializeCode(isolate).ToHandle(&result)) {
+ // Deserializing may fail if the reservations cannot be fulfilled.
+ if (FLAG_profile_deserialization) PrintF("[Deserializing failed]\n");
+ return MaybeHandle<SharedFunctionInfo>();
}
+ deserializer.FlushICacheForNewCodeObjects();
if (FLAG_profile_deserialization) {
double ms = timer.Elapsed().InMillisecondsF();
int length = cached_data->length();
PrintF("[Deserializing from %d bytes took %0.3f ms]\n", length, ms);
}
- Handle<SharedFunctionInfo> result(SharedFunctionInfo::cast(root), isolate);
result->set_deserialized(true);
if (isolate->logger()->is_logging_code_events() ||
@@ -2335,7 +2449,7 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
*result, NULL, name);
}
- return result;
+ return scope.CloseAndEscape(result);
}
@@ -2348,12 +2462,11 @@ void SerializedData::AllocateData(int size) {
}
-SnapshotData::SnapshotData(const SnapshotByteSink& sink,
- const Serializer& ser) {
+SnapshotData::SnapshotData(const Serializer& ser) {
DisallowHeapAllocation no_gc;
List<Reservation> reservations;
ser.EncodeReservations(&reservations);
- const List<byte>& payload = sink.data();
+ const List<byte>& payload = ser.sink()->data();
// Calculate sizes.
int reservation_size = reservations.length() * kInt32Size;
@@ -2364,7 +2477,7 @@ SnapshotData::SnapshotData(const SnapshotByteSink& sink,
// Set header values.
SetHeaderValue(kCheckSumOffset, Version::Hash());
- SetHeaderValue(kReservationsOffset, reservations.length());
+ SetHeaderValue(kNumReservationsOffset, reservations.length());
SetHeaderValue(kPayloadLengthOffset, payload.length());
// Copy reservation chunk sizes.
@@ -2385,12 +2498,12 @@ bool SnapshotData::IsSane() {
Vector<const SerializedData::Reservation> SnapshotData::Reservations() const {
return Vector<const Reservation>(
reinterpret_cast<const Reservation*>(data_ + kHeaderSize),
- GetHeaderValue(kReservationsOffset));
+ GetHeaderValue(kNumReservationsOffset));
}
Vector<const byte> SnapshotData::Payload() const {
- int reservations_size = GetHeaderValue(kReservationsOffset) * kInt32Size;
+ int reservations_size = GetHeaderValue(kNumReservationsOffset) * kInt32Size;
const byte* payload = data_ + kHeaderSize + reservations_size;
int length = GetHeaderValue(kPayloadLengthOffset);
DCHECK_EQ(data_ + size_, payload + length);
@@ -2445,19 +2558,22 @@ SerializedCodeData::SerializedCodeData(const List<byte>& payload,
int reservation_size = reservations.length() * kInt32Size;
int num_stub_keys = stub_keys->length();
int stub_keys_size = stub_keys->length() * kInt32Size;
- int size = kHeaderSize + reservation_size + stub_keys_size + payload.length();
+ int payload_offset = kHeaderSize + reservation_size + stub_keys_size;
+ int padded_payload_offset = POINTER_SIZE_ALIGN(payload_offset);
+ int size = padded_payload_offset + payload.length();
// Allocate backing store and create result data.
AllocateData(size);
// Set header values.
+ SetHeaderValue(kMagicNumberOffset, kMagicNumber);
SetHeaderValue(kVersionHashOffset, Version::Hash());
SetHeaderValue(kSourceHashOffset, SourceHash(cs.source()));
SetHeaderValue(kCpuFeaturesOffset,
static_cast<uint32_t>(CpuFeatures::SupportedFeatures()));
SetHeaderValue(kFlagHashOffset, FlagList::Hash());
SetHeaderValue(kNumInternalizedStringsOffset, cs.num_internalized_strings());
- SetHeaderValue(kReservationsOffset, reservations.length());
+ SetHeaderValue(kNumReservationsOffset, reservations.length());
SetHeaderValue(kNumCodeStubKeysOffset, num_stub_keys);
SetHeaderValue(kPayloadLengthOffset, payload.length());
@@ -2473,20 +2589,32 @@ SerializedCodeData::SerializedCodeData(const List<byte>& payload,
CopyBytes(data_ + kHeaderSize + reservation_size,
reinterpret_cast<byte*>(stub_keys->begin()), stub_keys_size);
+ memset(data_ + payload_offset, 0, padded_payload_offset - payload_offset);
+
// Copy serialized data.
- CopyBytes(data_ + kHeaderSize + reservation_size + stub_keys_size,
- payload.begin(), static_cast<size_t>(payload.length()));
+ CopyBytes(data_ + padded_payload_offset, payload.begin(),
+ static_cast<size_t>(payload.length()));
}
-bool SerializedCodeData::IsSane(String* source) const {
- return GetHeaderValue(kVersionHashOffset) == Version::Hash() &&
- GetHeaderValue(kSourceHashOffset) == SourceHash(source) &&
- GetHeaderValue(kCpuFeaturesOffset) ==
- static_cast<uint32_t>(CpuFeatures::SupportedFeatures()) &&
- GetHeaderValue(kFlagHashOffset) == FlagList::Hash() &&
- Checksum(Payload()).Check(GetHeaderValue(kChecksum1Offset),
- GetHeaderValue(kChecksum2Offset));
+SerializedCodeData::SanityCheckResult SerializedCodeData::SanityCheck(
+ String* source) const {
+ uint32_t magic_number = GetHeaderValue(kMagicNumberOffset);
+ uint32_t version_hash = GetHeaderValue(kVersionHashOffset);
+ uint32_t source_hash = GetHeaderValue(kSourceHashOffset);
+ uint32_t cpu_features = GetHeaderValue(kCpuFeaturesOffset);
+ uint32_t flags_hash = GetHeaderValue(kFlagHashOffset);
+ uint32_t c1 = GetHeaderValue(kChecksum1Offset);
+ uint32_t c2 = GetHeaderValue(kChecksum2Offset);
+ if (magic_number != kMagicNumber) return MAGIC_NUMBER_MISMATCH;
+ if (version_hash != Version::Hash()) return VERSION_MISMATCH;
+ if (source_hash != SourceHash(source)) return SOURCE_MISMATCH;
+ if (cpu_features != static_cast<uint32_t>(CpuFeatures::SupportedFeatures())) {
+ return CPU_FEATURES_MISMATCH;
+ }
+ if (flags_hash != FlagList::Hash()) return FLAGS_MISMATCH;
+ if (!Checksum(Payload()).Check(c1, c2)) return CHECKSUM_MISMATCH;
+ return CHECK_SUCCESS;
}
@@ -2505,15 +2633,17 @@ Vector<const SerializedData::Reservation> SerializedCodeData::Reservations()
const {
return Vector<const Reservation>(
reinterpret_cast<const Reservation*>(data_ + kHeaderSize),
- GetHeaderValue(kReservationsOffset));
+ GetHeaderValue(kNumReservationsOffset));
}
Vector<const byte> SerializedCodeData::Payload() const {
- int reservations_size = GetHeaderValue(kReservationsOffset) * kInt32Size;
+ int reservations_size = GetHeaderValue(kNumReservationsOffset) * kInt32Size;
int code_stubs_size = GetHeaderValue(kNumCodeStubKeysOffset) * kInt32Size;
- const byte* payload =
- data_ + kHeaderSize + reservations_size + code_stubs_size;
+ int payload_offset = kHeaderSize + reservations_size + code_stubs_size;
+ int padded_payload_offset = POINTER_SIZE_ALIGN(payload_offset);
+ const byte* payload = data_ + padded_payload_offset;
+ DCHECK(IsAligned(reinterpret_cast<intptr_t>(payload), kPointerAlignment));
int length = GetHeaderValue(kPayloadLengthOffset);
DCHECK_EQ(data_ + size_, payload + length);
return Vector<const byte>(payload, length);
@@ -2525,9 +2655,26 @@ int SerializedCodeData::NumInternalizedStrings() const {
}
Vector<const uint32_t> SerializedCodeData::CodeStubKeys() const {
- int reservations_size = GetHeaderValue(kReservationsOffset) * kInt32Size;
+ int reservations_size = GetHeaderValue(kNumReservationsOffset) * kInt32Size;
const byte* start = data_ + kHeaderSize + reservations_size;
return Vector<const uint32_t>(reinterpret_cast<const uint32_t*>(start),
GetHeaderValue(kNumCodeStubKeysOffset));
}
+
+
+SerializedCodeData::SerializedCodeData(ScriptData* data)
+ : SerializedData(const_cast<byte*>(data->data()), data->length()) {}
+
+
+SerializedCodeData* SerializedCodeData::FromCachedData(ScriptData* cached_data,
+ String* source) {
+ DisallowHeapAllocation no_gc;
+ SerializedCodeData* scd = new SerializedCodeData(cached_data);
+ SanityCheckResult r = scd->SanityCheck(source);
+ if (r == CHECK_SUCCESS) return scd;
+ cached_data->Reject();
+ source->GetIsolate()->counters()->code_cache_reject_reason()->AddSample(r);
+ delete scd;
+ return NULL;
+}
} } // namespace v8::internal