Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/snapshot/snapshot-common.cc

Issue 2055203002: [snapshot] support multiple contexts in the same snapshot. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@sinkmember
Patch Set: fix test. again. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/snapshot/snapshot.h ('k') | src/snapshot/startup-serializer.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // The common functionality when building with or without snapshots. 5 // The common functionality when building with or without snapshots.
6 6
7 #include "src/snapshot/snapshot.h" 7 #include "src/snapshot/snapshot.h"
8 8
9 #include "src/api.h" 9 #include "src/api.h"
10 #include "src/base/platform/platform.h" 10 #include "src/base/platform/platform.h"
11 #include "src/full-codegen/full-codegen.h" 11 #include "src/full-codegen/full-codegen.h"
12 #include "src/snapshot/deserializer.h" 12 #include "src/snapshot/deserializer.h"
13 #include "src/snapshot/snapshot-source-sink.h" 13 #include "src/snapshot/snapshot-source-sink.h"
14 #include "src/version.h" 14 #include "src/version.h"
15 15
16 namespace v8 { 16 namespace v8 {
17 namespace internal { 17 namespace internal {
18 18
19 #ifdef DEBUG 19 #ifdef DEBUG
20 bool Snapshot::SnapshotIsValid(v8::StartupData* snapshot_blob) { 20 bool Snapshot::SnapshotIsValid(v8::StartupData* snapshot_blob) {
21 return !Snapshot::ExtractStartupData(snapshot_blob).is_empty() && 21 return Snapshot::ExtractNumContexts(snapshot_blob) > 0;
22 !Snapshot::ExtractContextData(snapshot_blob).is_empty();
23 } 22 }
24 #endif // DEBUG 23 #endif // DEBUG
25 24
26 25
27 bool Snapshot::HaveASnapshotToStartFrom(Isolate* isolate) { 26 bool Snapshot::HaveASnapshotToStartFrom(Isolate* isolate) {
28 // Do not use snapshots if the isolate is used to create snapshots. 27 // Do not use snapshots if the isolate is used to create snapshots.
29 return isolate->snapshot_blob() != NULL && 28 return isolate->snapshot_blob() != NULL &&
30 isolate->snapshot_blob()->data != NULL; 29 isolate->snapshot_blob()->data != NULL;
31 } 30 }
32 31
(...skipping 21 matching lines...) Expand all
54 Deserializer deserializer(&snapshot_data); 53 Deserializer deserializer(&snapshot_data);
55 bool success = isolate->Init(&deserializer); 54 bool success = isolate->Init(&deserializer);
56 if (FLAG_profile_deserialization) { 55 if (FLAG_profile_deserialization) {
57 double ms = timer.Elapsed().InMillisecondsF(); 56 double ms = timer.Elapsed().InMillisecondsF();
58 int bytes = startup_data.length(); 57 int bytes = startup_data.length();
59 PrintF("[Deserializing isolate (%d bytes) took %0.3f ms]\n", bytes, ms); 58 PrintF("[Deserializing isolate (%d bytes) took %0.3f ms]\n", bytes, ms);
60 } 59 }
61 return success; 60 return success;
62 } 61 }
63 62
64
65 MaybeHandle<Context> Snapshot::NewContextFromSnapshot( 63 MaybeHandle<Context> Snapshot::NewContextFromSnapshot(
66 Isolate* isolate, Handle<JSGlobalProxy> global_proxy) { 64 Isolate* isolate, Handle<JSGlobalProxy> global_proxy,
65 size_t context_index) {
67 if (!isolate->snapshot_available()) return Handle<Context>(); 66 if (!isolate->snapshot_available()) return Handle<Context>();
68 base::ElapsedTimer timer; 67 base::ElapsedTimer timer;
69 if (FLAG_profile_deserialization) timer.Start(); 68 if (FLAG_profile_deserialization) timer.Start();
70 69
71 const v8::StartupData* blob = isolate->snapshot_blob(); 70 const v8::StartupData* blob = isolate->snapshot_blob();
72 Vector<const byte> context_data = ExtractContextData(blob); 71 Vector<const byte> context_data =
72 ExtractContextData(blob, static_cast<int>(context_index));
73 SnapshotData snapshot_data(context_data); 73 SnapshotData snapshot_data(context_data);
74 Deserializer deserializer(&snapshot_data); 74 Deserializer deserializer(&snapshot_data);
75 75
76 MaybeHandle<Object> maybe_context = 76 MaybeHandle<Object> maybe_context =
77 deserializer.DeserializePartial(isolate, global_proxy); 77 deserializer.DeserializePartial(isolate, global_proxy);
78 Handle<Object> result; 78 Handle<Object> result;
79 if (!maybe_context.ToHandle(&result)) return MaybeHandle<Context>(); 79 if (!maybe_context.ToHandle(&result)) return MaybeHandle<Context>();
80 CHECK(result->IsContext()); 80 CHECK(result->IsContext());
81 if (FLAG_profile_deserialization) { 81 if (FLAG_profile_deserialization) {
82 double ms = timer.Elapsed().InMillisecondsF(); 82 double ms = timer.Elapsed().InMillisecondsF();
83 int bytes = context_data.length(); 83 int bytes = context_data.length();
84 PrintF("[Deserializing context (%d bytes) took %0.3f ms]\n", bytes, ms); 84 PrintF("[Deserializing context #%zu (%d bytes) took %0.3f ms]\n",
85 context_index, bytes, ms);
85 } 86 }
86 return Handle<Context>::cast(result); 87 return Handle<Context>::cast(result);
87 } 88 }
88 89
90 void UpdateMaxRequirementPerPage(
91 uint32_t* requirements,
92 Vector<const SerializedData::Reservation> reservations) {
93 int space = 0;
94 uint32_t current_requirement = 0;
95 for (const auto& reservation : reservations) {
96 current_requirement += reservation.chunk_size();
97 if (reservation.is_last()) {
98 requirements[space] = std::max(requirements[space], current_requirement);
99 current_requirement = 0;
100 space++;
101 }
102 }
103 DCHECK_EQ(i::Serializer::kNumberOfSpaces, space);
104 }
105
89 void CalculateFirstPageSizes(const SnapshotData* startup_snapshot, 106 void CalculateFirstPageSizes(const SnapshotData* startup_snapshot,
90 const SnapshotData* context_snapshot, 107 const List<SnapshotData*>* context_snapshots,
91 uint32_t* sizes_out) { 108 uint32_t* sizes_out) {
92 Vector<const SerializedData::Reservation> startup_reservations =
93 startup_snapshot->Reservations();
94 Vector<const SerializedData::Reservation> context_reservations =
95 context_snapshot->Reservations();
96 int startup_index = 0;
97 int context_index = 0;
98
99 if (FLAG_profile_deserialization) { 109 if (FLAG_profile_deserialization) {
100 int startup_total = 0; 110 int startup_total = 0;
101 int context_total = 0; 111 PrintF("Deserialization will reserve:\n");
102 for (const auto& reservation : startup_reservations) { 112 for (const auto& reservation : startup_snapshot->Reservations()) {
103 startup_total += reservation.chunk_size(); 113 startup_total += reservation.chunk_size();
104 } 114 }
105 for (const auto& reservation : context_reservations) { 115 PrintF("%10d bytes per isolate\n", startup_total);
106 context_total += reservation.chunk_size(); 116 for (int i = 0; i < context_snapshots->length(); i++) {
117 int context_total = 0;
118 for (const auto& reservation : context_snapshots->at(i)->Reservations()) {
119 context_total += reservation.chunk_size();
120 }
121 PrintF("%10d bytes per context #%d\n", context_total, i);
107 } 122 }
108 PrintF( 123 }
109 "Deserialization will reserve:\n" 124
110 "%10d bytes per isolate\n" 125 uint32_t startup_requirements[i::Serializer::kNumberOfSpaces];
111 "%10d bytes per context\n", 126 uint32_t context_requirements[i::Serializer::kNumberOfSpaces];
112 startup_total, context_total); 127 for (int space = 0; space < i::Serializer::kNumberOfSpaces; space++) {
128 startup_requirements[space] = 0;
129 context_requirements[space] = 0;
130 }
131
132 UpdateMaxRequirementPerPage(startup_requirements,
133 startup_snapshot->Reservations());
134 for (const auto& context_snapshot : *context_snapshots) {
135 UpdateMaxRequirementPerPage(context_requirements,
136 context_snapshot->Reservations());
113 } 137 }
114 138
115 for (int space = 0; space < i::Serializer::kNumberOfSpaces; space++) { 139 for (int space = 0; space < i::Serializer::kNumberOfSpaces; space++) {
116 bool single_chunk = true; 140 // If the space requirement for a page is less than a page size, we consider
117 while (!startup_reservations[startup_index].is_last()) { 141 // limiting the size of the first page in order to save memory on startup.
118 single_chunk = false; 142 uint32_t required = startup_requirements[space] +
119 startup_index++; 143 2 * context_requirements[space] +
120 } 144 Page::kObjectStartOffset;
121 while (!context_reservations[context_index].is_last()) { 145 // Add a small allowance to the code space for small scripts.
122 single_chunk = false; 146 if (space == CODE_SPACE) required += 32 * KB;
123 context_index++;
124 }
125
126 uint32_t required = kMaxUInt32;
127 if (single_chunk) {
128 // If both the startup snapshot data and the context snapshot data on
129 // this space fit in a single page, then we consider limiting the size
130 // of the first page. For this, we add the chunk sizes and some extra
131 // allowance. This way we achieve a smaller startup memory footprint.
132 required = (startup_reservations[startup_index].chunk_size() +
133 2 * context_reservations[context_index].chunk_size()) +
134 Page::kObjectStartOffset;
135 // Add a small allowance to the code space for small scripts.
136 if (space == CODE_SPACE) required += 32 * KB;
137 }
138 147
139 if (space >= FIRST_PAGED_SPACE && space <= LAST_PAGED_SPACE) { 148 if (space >= FIRST_PAGED_SPACE && space <= LAST_PAGED_SPACE) {
140 uint32_t max_size = 149 uint32_t max_size =
141 MemoryAllocator::PageAreaSize(static_cast<AllocationSpace>(space)); 150 MemoryAllocator::PageAreaSize(static_cast<AllocationSpace>(space));
142 sizes_out[space - FIRST_PAGED_SPACE] = Min(required, max_size); 151 sizes_out[space - FIRST_PAGED_SPACE] = std::min(required, max_size);
143 } else {
144 DCHECK(single_chunk);
145 } 152 }
146 startup_index++;
147 context_index++;
148 } 153 }
149
150 DCHECK_EQ(startup_reservations.length(), startup_index);
151 DCHECK_EQ(context_reservations.length(), context_index);
152 } 154 }
153 155
154 v8::StartupData Snapshot::CreateSnapshotBlob( 156 v8::StartupData Snapshot::CreateSnapshotBlob(
155 const StartupSerializer* startup_serializer, 157 const SnapshotData* startup_snapshot,
156 const PartialSerializer* context_serializer) { 158 const List<SnapshotData*>* context_snapshots) {
157 SnapshotData startup_snapshot(startup_serializer); 159 int num_contexts = context_snapshots->length();
158 SnapshotData context_snapshot(context_serializer); 160 int startup_snapshot_offset = StartupSnapshotOffset(num_contexts);
159 Vector<const byte> startup_data = startup_snapshot.RawData(); 161 int total_length = startup_snapshot_offset;
160 Vector<const byte> context_data = context_snapshot.RawData(); 162 total_length += startup_snapshot->RawData().length();
163 for (const auto& context_snapshot : *context_snapshots) {
164 total_length += context_snapshot->RawData().length();
165 }
161 166
162 uint32_t first_page_sizes[kNumPagedSpaces]; 167 uint32_t first_page_sizes[kNumPagedSpaces];
163 168 CalculateFirstPageSizes(startup_snapshot, context_snapshots,
164 CalculateFirstPageSizes(&startup_snapshot, &context_snapshot,
165 first_page_sizes); 169 first_page_sizes);
166 170
167 int startup_length = startup_data.length(); 171 char* data = new char[total_length];
168 int context_length = context_data.length();
169 int context_offset = ContextOffset(startup_length);
170
171 int length = context_offset + context_length;
172 char* data = new char[length];
173
174 memcpy(data + kFirstPageSizesOffset, first_page_sizes, 172 memcpy(data + kFirstPageSizesOffset, first_page_sizes,
175 kNumPagedSpaces * kInt32Size); 173 kNumPagedSpaces * kInt32Size);
176 memcpy(data + kStartupLengthOffset, &startup_length, kInt32Size); 174 memcpy(data + kNumberOfContextsOffset, &num_contexts, kInt32Size);
177 memcpy(data + kStartupDataOffset, startup_data.begin(), startup_length); 175 int payload_offset = StartupSnapshotOffset(num_contexts);
178 memcpy(data + context_offset, context_data.begin(), context_length); 176 int payload_length = startup_snapshot->RawData().length();
179 v8::StartupData result = {data, length}; 177 memcpy(data + payload_offset, startup_snapshot->RawData().start(),
178 payload_length);
179 if (FLAG_profile_deserialization) {
180 PrintF("Snapshot blob consists of:\n%10d bytes for startup\n",
181 payload_length);
182 }
183 payload_offset += payload_length;
184 for (int i = 0; i < num_contexts; i++) {
185 memcpy(data + ContextSnapshotOffsetOffset(i), &payload_offset, kInt32Size);
186 SnapshotData* context_snapshot = context_snapshots->at(i);
187 payload_length = context_snapshot->RawData().length();
188 memcpy(data + payload_offset, context_snapshot->RawData().start(),
189 payload_length);
190 if (FLAG_profile_deserialization) {
191 PrintF("%10d bytes for context #%d\n", payload_length, i);
192 }
193 payload_offset += payload_length;
194 }
180 195
181 if (FLAG_profile_deserialization) { 196 v8::StartupData result = {data, total_length};
182 PrintF(
183 "Snapshot blob consists of:\n"
184 "%10d bytes for startup\n"
185 "%10d bytes for context\n",
186 startup_length, context_length);
187 }
188 return result; 197 return result;
189 } 198 }
190 199
200 int Snapshot::ExtractNumContexts(const v8::StartupData* data) {
201 CHECK_LT(kNumberOfContextsOffset, data->raw_size);
202 int num_contexts;
203 memcpy(&num_contexts, data->data + kNumberOfContextsOffset, kInt32Size);
204 return num_contexts;
205 }
206
191 Vector<const byte> Snapshot::ExtractStartupData(const v8::StartupData* data) { 207 Vector<const byte> Snapshot::ExtractStartupData(const v8::StartupData* data) {
192 DCHECK_LT(kIntSize, data->raw_size); 208 int num_contexts = ExtractNumContexts(data);
193 int startup_length; 209 int startup_offset = StartupSnapshotOffset(num_contexts);
194 memcpy(&startup_length, data->data + kStartupLengthOffset, kInt32Size); 210 CHECK_LT(startup_offset, data->raw_size);
195 DCHECK_LT(startup_length, data->raw_size); 211 int first_context_offset;
212 memcpy(&first_context_offset, data->data + ContextSnapshotOffsetOffset(0),
213 kInt32Size);
214 CHECK_LT(first_context_offset, data->raw_size);
215 int startup_length = first_context_offset - startup_offset;
196 const byte* startup_data = 216 const byte* startup_data =
197 reinterpret_cast<const byte*>(data->data + kStartupDataOffset); 217 reinterpret_cast<const byte*>(data->data + startup_offset);
198 return Vector<const byte>(startup_data, startup_length); 218 return Vector<const byte>(startup_data, startup_length);
199 } 219 }
200 220
221 Vector<const byte> Snapshot::ExtractContextData(const v8::StartupData* data,
222 int index) {
223 int num_contexts = ExtractNumContexts(data);
224 CHECK_LT(index, num_contexts);
201 225
202 Vector<const byte> Snapshot::ExtractContextData(const v8::StartupData* data) { 226 int context_offset;
203 DCHECK_LT(kIntSize, data->raw_size); 227 memcpy(&context_offset, data->data + ContextSnapshotOffsetOffset(index),
204 int startup_length; 228 kInt32Size);
205 memcpy(&startup_length, data->data + kStartupLengthOffset, kIntSize); 229 int next_context_offset;
206 int context_offset = ContextOffset(startup_length); 230 if (index == num_contexts - 1) {
231 next_context_offset = data->raw_size;
232 } else {
233 memcpy(&next_context_offset,
234 data->data + ContextSnapshotOffsetOffset(index + 1), kInt32Size);
235 CHECK_LT(next_context_offset, data->raw_size);
236 }
237
207 const byte* context_data = 238 const byte* context_data =
208 reinterpret_cast<const byte*>(data->data + context_offset); 239 reinterpret_cast<const byte*>(data->data + context_offset);
209 DCHECK_LT(context_offset, data->raw_size); 240 int context_length = next_context_offset - context_offset;
210 int context_length = data->raw_size - context_offset;
211 return Vector<const byte>(context_data, context_length); 241 return Vector<const byte>(context_data, context_length);
212 } 242 }
213 243
214 SnapshotData::SnapshotData(const Serializer* serializer) { 244 SnapshotData::SnapshotData(const Serializer* serializer) {
215 DisallowHeapAllocation no_gc; 245 DisallowHeapAllocation no_gc;
216 List<Reservation> reservations; 246 List<Reservation> reservations;
217 serializer->EncodeReservations(&reservations); 247 serializer->EncodeReservations(&reservations);
218 const List<byte>* payload = serializer->sink()->data(); 248 const List<byte>* payload = serializer->sink()->data();
219 249
220 // Calculate sizes. 250 // Calculate sizes.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
252 Vector<const byte> SnapshotData::Payload() const { 282 Vector<const byte> SnapshotData::Payload() const {
253 int reservations_size = GetHeaderValue(kNumReservationsOffset) * kInt32Size; 283 int reservations_size = GetHeaderValue(kNumReservationsOffset) * kInt32Size;
254 const byte* payload = data_ + kHeaderSize + reservations_size; 284 const byte* payload = data_ + kHeaderSize + reservations_size;
255 int length = GetHeaderValue(kPayloadLengthOffset); 285 int length = GetHeaderValue(kPayloadLengthOffset);
256 DCHECK_EQ(data_ + size_, payload + length); 286 DCHECK_EQ(data_ + size_, payload + length);
257 return Vector<const byte>(payload, length); 287 return Vector<const byte>(payload, length);
258 } 288 }
259 289
260 } // namespace internal 290 } // namespace internal
261 } // namespace v8 291 } // namespace v8
OLDNEW
« no previous file with comments | « src/snapshot/snapshot.h ('k') | src/snapshot/startup-serializer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698