Merge V8 5.3.332.45. DO NOT MERGE
Test: Manual
FPIIM-449
Change-Id: Id3254828b068abdea3cb10442e0172a8c9a98e03
(cherry picked from commit 13e2dadd00298019ed862f2b2fc5068bba730bcf)
diff --git a/src/snapshot/snapshot-common.cc b/src/snapshot/snapshot-common.cc
index a951b0d..5eac4af 100644
--- a/src/snapshot/snapshot-common.cc
+++ b/src/snapshot/snapshot-common.cc
@@ -18,8 +18,7 @@
#ifdef DEBUG
bool Snapshot::SnapshotIsValid(v8::StartupData* snapshot_blob) {
- return !Snapshot::ExtractStartupData(snapshot_blob).is_empty() &&
- !Snapshot::ExtractContextData(snapshot_blob).is_empty();
+ return Snapshot::ExtractNumContexts(snapshot_blob) > 0;
}
#endif // DEBUG
@@ -31,12 +30,6 @@
}
-bool Snapshot::EmbedsScript(Isolate* isolate) {
- if (!isolate->snapshot_available()) return false;
- return ExtractMetadata(isolate->snapshot_blob()).embeds_script();
-}
-
-
uint32_t Snapshot::SizeOfFirstPage(Isolate* isolate, AllocationSpace space) {
DCHECK(space >= FIRST_PAGED_SPACE && space <= LAST_PAGED_SPACE);
if (!isolate->snapshot_available()) {
@@ -67,15 +60,16 @@
return success;
}
-
MaybeHandle<Context> Snapshot::NewContextFromSnapshot(
- Isolate* isolate, Handle<JSGlobalProxy> global_proxy) {
+ Isolate* isolate, Handle<JSGlobalProxy> global_proxy,
+ size_t context_index) {
if (!isolate->snapshot_available()) return Handle<Context>();
base::ElapsedTimer timer;
if (FLAG_profile_deserialization) timer.Start();
const v8::StartupData* blob = isolate->snapshot_blob();
- Vector<const byte> context_data = ExtractContextData(blob);
+ Vector<const byte> context_data =
+ ExtractContextData(blob, static_cast<int>(context_index));
SnapshotData snapshot_data(context_data);
Deserializer deserializer(&snapshot_data);
@@ -87,178 +81,192 @@
if (FLAG_profile_deserialization) {
double ms = timer.Elapsed().InMillisecondsF();
int bytes = context_data.length();
- PrintF("[Deserializing context (%d bytes) took %0.3f ms]\n", bytes, ms);
+ PrintF("[Deserializing context #%zu (%d bytes) took %0.3f ms]\n",
+ context_index, bytes, ms);
}
return Handle<Context>::cast(result);
}
+void UpdateMaxRequirementPerPage(
+ uint32_t* requirements,
+ Vector<const SerializedData::Reservation> reservations) {
+ int space = 0;
+ uint32_t current_requirement = 0;
+ for (const auto& reservation : reservations) {
+ current_requirement += reservation.chunk_size();
+ if (reservation.is_last()) {
+ requirements[space] = std::max(requirements[space], current_requirement);
+ current_requirement = 0;
+ space++;
+ }
+ }
+ DCHECK_EQ(i::Serializer::kNumberOfSpaces, space);
+}
-void CalculateFirstPageSizes(bool is_default_snapshot,
- const SnapshotData& startup_snapshot,
- const SnapshotData& context_snapshot,
+void CalculateFirstPageSizes(const SnapshotData* startup_snapshot,
+ const List<SnapshotData*>* context_snapshots,
uint32_t* sizes_out) {
- Vector<const SerializedData::Reservation> startup_reservations =
- startup_snapshot.Reservations();
- Vector<const SerializedData::Reservation> context_reservations =
- context_snapshot.Reservations();
- int startup_index = 0;
- int context_index = 0;
-
if (FLAG_profile_deserialization) {
int startup_total = 0;
- int context_total = 0;
- for (auto& reservation : startup_reservations) {
+ PrintF("Deserialization will reserve:\n");
+ for (const auto& reservation : startup_snapshot->Reservations()) {
startup_total += reservation.chunk_size();
}
- for (auto& reservation : context_reservations) {
- context_total += reservation.chunk_size();
+ PrintF("%10d bytes per isolate\n", startup_total);
+ for (int i = 0; i < context_snapshots->length(); i++) {
+ int context_total = 0;
+ for (const auto& reservation : context_snapshots->at(i)->Reservations()) {
+ context_total += reservation.chunk_size();
+ }
+ PrintF("%10d bytes per context #%d\n", context_total, i);
}
- PrintF(
- "Deserialization will reserve:\n"
- "%10d bytes per isolate\n"
- "%10d bytes per context\n",
- startup_total, context_total);
+ }
+
+ uint32_t startup_requirements[i::Serializer::kNumberOfSpaces];
+ uint32_t context_requirements[i::Serializer::kNumberOfSpaces];
+ for (int space = 0; space < i::Serializer::kNumberOfSpaces; space++) {
+ startup_requirements[space] = 0;
+ context_requirements[space] = 0;
+ }
+
+ UpdateMaxRequirementPerPage(startup_requirements,
+ startup_snapshot->Reservations());
+ for (const auto& context_snapshot : *context_snapshots) {
+ UpdateMaxRequirementPerPage(context_requirements,
+ context_snapshot->Reservations());
}
for (int space = 0; space < i::Serializer::kNumberOfSpaces; space++) {
- bool single_chunk = true;
- while (!startup_reservations[startup_index].is_last()) {
- single_chunk = false;
- startup_index++;
- }
- while (!context_reservations[context_index].is_last()) {
- single_chunk = false;
- context_index++;
- }
-
- uint32_t required = kMaxUInt32;
- if (single_chunk) {
- // If both the startup snapshot data and the context snapshot data on
- // this space fit in a single page, then we consider limiting the size
- // of the first page. For this, we add the chunk sizes and some extra
- // allowance. This way we achieve a smaller startup memory footprint.
- required = (startup_reservations[startup_index].chunk_size() +
- 2 * context_reservations[context_index].chunk_size()) +
- Page::kObjectStartOffset;
- // Add a small allowance to the code space for small scripts.
- if (space == CODE_SPACE) required += 32 * KB;
- } else if (!FLAG_debug_code) {
- // We expect the vanilla snapshot to only require one page per space,
- // unless we are emitting debug code.
- DCHECK(!is_default_snapshot);
- }
+ // If the space requirement for a page is less than a page size, we consider
+ // limiting the size of the first page in order to save memory on startup.
+ uint32_t required = startup_requirements[space] +
+ 2 * context_requirements[space] +
+ Page::kObjectStartOffset;
+ // Add a small allowance to the code space for small scripts.
+ if (space == CODE_SPACE) required += 32 * KB;
if (space >= FIRST_PAGED_SPACE && space <= LAST_PAGED_SPACE) {
uint32_t max_size =
MemoryAllocator::PageAreaSize(static_cast<AllocationSpace>(space));
- sizes_out[space - FIRST_PAGED_SPACE] = Min(required, max_size);
- } else {
- DCHECK(single_chunk);
+ sizes_out[space - FIRST_PAGED_SPACE] = std::min(required, max_size);
}
- startup_index++;
- context_index++;
}
-
- DCHECK_EQ(startup_reservations.length(), startup_index);
- DCHECK_EQ(context_reservations.length(), context_index);
}
-
v8::StartupData Snapshot::CreateSnapshotBlob(
- const i::StartupSerializer& startup_ser,
- const i::PartialSerializer& context_ser, Snapshot::Metadata metadata) {
- SnapshotData startup_snapshot(startup_ser);
- SnapshotData context_snapshot(context_ser);
- Vector<const byte> startup_data = startup_snapshot.RawData();
- Vector<const byte> context_data = context_snapshot.RawData();
+ const SnapshotData* startup_snapshot,
+ const List<SnapshotData*>* context_snapshots) {
+ int num_contexts = context_snapshots->length();
+ int startup_snapshot_offset = StartupSnapshotOffset(num_contexts);
+ int total_length = startup_snapshot_offset;
+ total_length += startup_snapshot->RawData().length();
+ for (const auto& context_snapshot : *context_snapshots) {
+ total_length += context_snapshot->RawData().length();
+ }
uint32_t first_page_sizes[kNumPagedSpaces];
+ CalculateFirstPageSizes(startup_snapshot, context_snapshots,
+ first_page_sizes);
- CalculateFirstPageSizes(!metadata.embeds_script(), startup_snapshot,
- context_snapshot, first_page_sizes);
-
- int startup_length = startup_data.length();
- int context_length = context_data.length();
- int context_offset = ContextOffset(startup_length);
-
- int length = context_offset + context_length;
- char* data = new char[length];
-
- memcpy(data + kMetadataOffset, &metadata.RawValue(), kInt32Size);
+ char* data = new char[total_length];
memcpy(data + kFirstPageSizesOffset, first_page_sizes,
kNumPagedSpaces * kInt32Size);
- memcpy(data + kStartupLengthOffset, &startup_length, kInt32Size);
- memcpy(data + kStartupDataOffset, startup_data.begin(), startup_length);
- memcpy(data + context_offset, context_data.begin(), context_length);
- v8::StartupData result = {data, length};
-
+ memcpy(data + kNumberOfContextsOffset, &num_contexts, kInt32Size);
+ int payload_offset = StartupSnapshotOffset(num_contexts);
+ int payload_length = startup_snapshot->RawData().length();
+ memcpy(data + payload_offset, startup_snapshot->RawData().start(),
+ payload_length);
if (FLAG_profile_deserialization) {
- PrintF(
- "Snapshot blob consists of:\n"
- "%10d bytes for startup\n"
- "%10d bytes for context\n",
- startup_length, context_length);
+ PrintF("Snapshot blob consists of:\n%10d bytes for startup\n",
+ payload_length);
}
+ payload_offset += payload_length;
+ for (int i = 0; i < num_contexts; i++) {
+ memcpy(data + ContextSnapshotOffsetOffset(i), &payload_offset, kInt32Size);
+ SnapshotData* context_snapshot = context_snapshots->at(i);
+ payload_length = context_snapshot->RawData().length();
+ memcpy(data + payload_offset, context_snapshot->RawData().start(),
+ payload_length);
+ if (FLAG_profile_deserialization) {
+ PrintF("%10d bytes for context #%d\n", payload_length, i);
+ }
+ payload_offset += payload_length;
+ }
+
+ v8::StartupData result = {data, total_length};
return result;
}
-
-Snapshot::Metadata Snapshot::ExtractMetadata(const v8::StartupData* data) {
- uint32_t raw;
- memcpy(&raw, data->data + kMetadataOffset, kInt32Size);
- return Metadata(raw);
+int Snapshot::ExtractNumContexts(const v8::StartupData* data) {
+ CHECK_LT(kNumberOfContextsOffset, data->raw_size);
+ int num_contexts;
+ memcpy(&num_contexts, data->data + kNumberOfContextsOffset, kInt32Size);
+ return num_contexts;
}
-
Vector<const byte> Snapshot::ExtractStartupData(const v8::StartupData* data) {
- DCHECK_LT(kIntSize, data->raw_size);
- int startup_length;
- memcpy(&startup_length, data->data + kStartupLengthOffset, kInt32Size);
- DCHECK_LT(startup_length, data->raw_size);
+ int num_contexts = ExtractNumContexts(data);
+ int startup_offset = StartupSnapshotOffset(num_contexts);
+ CHECK_LT(startup_offset, data->raw_size);
+ int first_context_offset;
+ memcpy(&first_context_offset, data->data + ContextSnapshotOffsetOffset(0),
+ kInt32Size);
+ CHECK_LT(first_context_offset, data->raw_size);
+ int startup_length = first_context_offset - startup_offset;
const byte* startup_data =
- reinterpret_cast<const byte*>(data->data + kStartupDataOffset);
+ reinterpret_cast<const byte*>(data->data + startup_offset);
return Vector<const byte>(startup_data, startup_length);
}
+Vector<const byte> Snapshot::ExtractContextData(const v8::StartupData* data,
+ int index) {
+ int num_contexts = ExtractNumContexts(data);
+ CHECK_LT(index, num_contexts);
-Vector<const byte> Snapshot::ExtractContextData(const v8::StartupData* data) {
- DCHECK_LT(kIntSize, data->raw_size);
- int startup_length;
- memcpy(&startup_length, data->data + kStartupLengthOffset, kIntSize);
- int context_offset = ContextOffset(startup_length);
+ int context_offset;
+ memcpy(&context_offset, data->data + ContextSnapshotOffsetOffset(index),
+ kInt32Size);
+ int next_context_offset;
+ if (index == num_contexts - 1) {
+ next_context_offset = data->raw_size;
+ } else {
+ memcpy(&next_context_offset,
+ data->data + ContextSnapshotOffsetOffset(index + 1), kInt32Size);
+ CHECK_LT(next_context_offset, data->raw_size);
+ }
+
const byte* context_data =
reinterpret_cast<const byte*>(data->data + context_offset);
- DCHECK_LT(context_offset, data->raw_size);
- int context_length = data->raw_size - context_offset;
+ int context_length = next_context_offset - context_offset;
return Vector<const byte>(context_data, context_length);
}
-SnapshotData::SnapshotData(const Serializer& ser) {
+SnapshotData::SnapshotData(const Serializer* serializer) {
DisallowHeapAllocation no_gc;
List<Reservation> reservations;
- ser.EncodeReservations(&reservations);
- const List<byte>& payload = ser.sink()->data();
+ serializer->EncodeReservations(&reservations);
+ const List<byte>* payload = serializer->sink()->data();
// Calculate sizes.
int reservation_size = reservations.length() * kInt32Size;
- int size = kHeaderSize + reservation_size + payload.length();
+ int size = kHeaderSize + reservation_size + payload->length();
// Allocate backing store and create result data.
AllocateData(size);
// Set header values.
- SetMagicNumber(ser.isolate());
+ SetMagicNumber(serializer->isolate());
SetHeaderValue(kCheckSumOffset, Version::Hash());
SetHeaderValue(kNumReservationsOffset, reservations.length());
- SetHeaderValue(kPayloadLengthOffset, payload.length());
+ SetHeaderValue(kPayloadLengthOffset, payload->length());
// Copy reservation chunk sizes.
CopyBytes(data_ + kHeaderSize, reinterpret_cast<byte*>(reservations.begin()),
reservation_size);
// Copy serialized data.
- CopyBytes(data_ + kHeaderSize + reservation_size, payload.begin(),
- static_cast<size_t>(payload.length()));
+ CopyBytes(data_ + kHeaderSize + reservation_size, payload->begin(),
+ static_cast<size_t>(payload->length()));
}
bool SnapshotData::IsSane() {