OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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 #include "src/snapshot/serializer.h" | 5 #include "src/snapshot/serializer.h" |
6 | 6 |
7 #include "src/macro-assembler.h" | 7 #include "src/macro-assembler.h" |
8 #include "src/snapshot/natives.h" | 8 #include "src/snapshot/natives.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 out->Add(SerializedData::Reservation(pending_chunk_[i])); | 117 out->Add(SerializedData::Reservation(pending_chunk_[i])); |
118 } | 118 } |
119 out->last().mark_as_last(); | 119 out->last().mark_as_last(); |
120 } | 120 } |
121 | 121 |
122 out->Add(SerializedData::Reservation(large_objects_total_size_)); | 122 out->Add(SerializedData::Reservation(large_objects_total_size_)); |
123 out->last().mark_as_last(); | 123 out->last().mark_as_last(); |
124 } | 124 } |
125 | 125 |
126 #ifdef DEBUG | 126 #ifdef DEBUG |
127 bool Serializer::BackReferenceIsAlreadyAllocated(BackReference reference) { | 127 bool Serializer::BackReferenceIsAlreadyAllocated( |
128 DCHECK(reference.is_valid()); | 128 SerializerReference reference) { |
129 DCHECK(!reference.is_source()); | 129 DCHECK(reference.is_back_reference()); |
130 DCHECK(!reference.is_global_proxy()); | |
131 AllocationSpace space = reference.space(); | 130 AllocationSpace space = reference.space(); |
132 int chunk_index = reference.chunk_index(); | 131 int chunk_index = reference.chunk_index(); |
133 if (space == LO_SPACE) { | 132 if (space == LO_SPACE) { |
134 return chunk_index == 0 && | 133 return chunk_index == 0 && |
135 reference.large_object_index() < seen_large_objects_index_; | 134 reference.large_object_index() < seen_large_objects_index_; |
136 } else if (chunk_index == completed_chunks_[space].length()) { | 135 } else if (chunk_index == completed_chunks_[space].length()) { |
137 return reference.chunk_offset() < pending_chunk_[space]; | 136 return reference.chunk_offset() < pending_chunk_[space]; |
138 } else { | 137 } else { |
139 return chunk_index < completed_chunks_[space].length() && | 138 return chunk_index < completed_chunks_[space].length() && |
140 reference.chunk_offset() < completed_chunks_[space][chunk_index]; | 139 reference.chunk_offset() < completed_chunks_[space][chunk_index]; |
(...skipping 15 matching lines...) Expand all Loading... |
156 } | 155 } |
157 if (skip != 0) { | 156 if (skip != 0) { |
158 sink_->Put(kHotObjectWithSkip + index, "HotObjectWithSkip"); | 157 sink_->Put(kHotObjectWithSkip + index, "HotObjectWithSkip"); |
159 sink_->PutInt(skip, "HotObjectSkipDistance"); | 158 sink_->PutInt(skip, "HotObjectSkipDistance"); |
160 } else { | 159 } else { |
161 sink_->Put(kHotObject + index, "HotObject"); | 160 sink_->Put(kHotObject + index, "HotObject"); |
162 } | 161 } |
163 return true; | 162 return true; |
164 } | 163 } |
165 } | 164 } |
166 BackReference back_reference = back_reference_map_.Lookup(obj); | 165 SerializerReference reference = reference_map_.Lookup(obj); |
167 if (back_reference.is_valid()) { | 166 if (reference.is_valid()) { |
168 // Encode the location of an already deserialized object in order to write | 167 // Encode the location of an already deserialized object in order to write |
169 // its location into a later object. We can encode the location as an | 168 // its location into a later object. We can encode the location as an |
170 // offset fromthe start of the deserialized objects or as an offset | 169 // offset fromthe start of the deserialized objects or as an offset |
171 // backwards from thecurrent allocation pointer. | 170 // backwards from thecurrent allocation pointer. |
172 if (back_reference.is_source()) { | 171 if (reference.is_attached_reference()) { |
173 FlushSkip(skip); | 172 FlushSkip(skip); |
174 if (FLAG_trace_serializer) PrintF(" Encoding source object\n"); | 173 if (FLAG_trace_serializer) { |
175 DCHECK(how_to_code == kPlain && where_to_point == kStartOfObject); | 174 PrintF(" Encoding attached reference %d\n", |
176 sink_->Put(kAttachedReference + kPlain + kStartOfObject, "Source"); | 175 reference.attached_reference_index()); |
177 sink_->PutInt(kSourceObjectReference, "kSourceObjectReference"); | 176 } |
178 } else if (back_reference.is_global_proxy()) { | 177 PutAttachedReference(reference, how_to_code, where_to_point); |
179 FlushSkip(skip); | |
180 if (FLAG_trace_serializer) PrintF(" Encoding global proxy\n"); | |
181 DCHECK(how_to_code == kPlain && where_to_point == kStartOfObject); | |
182 sink_->Put(kAttachedReference + kPlain + kStartOfObject, "Global Proxy"); | |
183 sink_->PutInt(kGlobalProxyReference, "kGlobalProxyReference"); | |
184 } else { | 178 } else { |
| 179 DCHECK(reference.is_back_reference()); |
185 if (FLAG_trace_serializer) { | 180 if (FLAG_trace_serializer) { |
186 PrintF(" Encoding back reference to: "); | 181 PrintF(" Encoding back reference to: "); |
187 obj->ShortPrint(); | 182 obj->ShortPrint(); |
188 PrintF("\n"); | 183 PrintF("\n"); |
189 } | 184 } |
190 | 185 |
191 PutAlignmentPrefix(obj); | 186 PutAlignmentPrefix(obj); |
192 AllocationSpace space = back_reference.space(); | 187 AllocationSpace space = reference.space(); |
193 if (skip == 0) { | 188 if (skip == 0) { |
194 sink_->Put(kBackref + how_to_code + where_to_point + space, "BackRef"); | 189 sink_->Put(kBackref + how_to_code + where_to_point + space, "BackRef"); |
195 } else { | 190 } else { |
196 sink_->Put(kBackrefWithSkip + how_to_code + where_to_point + space, | 191 sink_->Put(kBackrefWithSkip + how_to_code + where_to_point + space, |
197 "BackRefWithSkip"); | 192 "BackRefWithSkip"); |
198 sink_->PutInt(skip, "BackRefSkipDistance"); | 193 sink_->PutInt(skip, "BackRefSkipDistance"); |
199 } | 194 } |
200 PutBackReference(obj, back_reference); | 195 PutBackReference(obj, reference); |
201 } | 196 } |
202 return true; | 197 return true; |
203 } | 198 } |
204 return false; | 199 return false; |
205 } | 200 } |
206 | 201 |
207 void Serializer::PutRoot(int root_index, HeapObject* object, | 202 void Serializer::PutRoot(int root_index, HeapObject* object, |
208 SerializerDeserializer::HowToCode how_to_code, | 203 SerializerDeserializer::HowToCode how_to_code, |
209 SerializerDeserializer::WhereToPoint where_to_point, | 204 SerializerDeserializer::WhereToPoint where_to_point, |
210 int skip) { | 205 int skip) { |
(...skipping 18 matching lines...) Expand all Loading... |
229 sink_->PutInt(root_index, "root_index"); | 224 sink_->PutInt(root_index, "root_index"); |
230 } | 225 } |
231 } | 226 } |
232 | 227 |
233 void Serializer::PutSmi(Smi* smi) { | 228 void Serializer::PutSmi(Smi* smi) { |
234 sink_->Put(kOnePointerRawData, "Smi"); | 229 sink_->Put(kOnePointerRawData, "Smi"); |
235 byte* bytes = reinterpret_cast<byte*>(&smi); | 230 byte* bytes = reinterpret_cast<byte*>(&smi); |
236 for (int i = 0; i < kPointerSize; i++) sink_->Put(bytes[i], "Byte"); | 231 for (int i = 0; i < kPointerSize; i++) sink_->Put(bytes[i], "Byte"); |
237 } | 232 } |
238 | 233 |
239 void Serializer::PutBackReference(HeapObject* object, BackReference reference) { | 234 void Serializer::PutBackReference(HeapObject* object, |
| 235 SerializerReference reference) { |
240 DCHECK(BackReferenceIsAlreadyAllocated(reference)); | 236 DCHECK(BackReferenceIsAlreadyAllocated(reference)); |
241 sink_->PutInt(reference.reference(), "BackRefValue"); | 237 sink_->PutInt(reference.back_reference(), "BackRefValue"); |
242 hot_objects_.Add(object); | 238 hot_objects_.Add(object); |
243 } | 239 } |
244 | 240 |
| 241 void Serializer::PutAttachedReference(SerializerReference reference, |
| 242 HowToCode how_to_code, |
| 243 WhereToPoint where_to_point) { |
| 244 DCHECK(reference.is_attached_reference()); |
| 245 DCHECK((how_to_code == kPlain && where_to_point == kStartOfObject) || |
| 246 (how_to_code == kPlain && where_to_point == kInnerPointer) || |
| 247 (how_to_code == kFromCode && where_to_point == kInnerPointer)); |
| 248 sink_->Put(kAttachedReference + how_to_code + where_to_point, "AttachedRef"); |
| 249 sink_->PutInt(reference.attached_reference_index(), "AttachedRefIndex"); |
| 250 } |
| 251 |
245 int Serializer::PutAlignmentPrefix(HeapObject* object) { | 252 int Serializer::PutAlignmentPrefix(HeapObject* object) { |
246 AllocationAlignment alignment = object->RequiredAlignment(); | 253 AllocationAlignment alignment = object->RequiredAlignment(); |
247 if (alignment != kWordAligned) { | 254 if (alignment != kWordAligned) { |
248 DCHECK(1 <= alignment && alignment <= 3); | 255 DCHECK(1 <= alignment && alignment <= 3); |
249 byte prefix = (kAlignmentPrefix - 1) + alignment; | 256 byte prefix = (kAlignmentPrefix - 1) + alignment; |
250 sink_->Put(prefix, "Alignment"); | 257 sink_->Put(prefix, "Alignment"); |
251 return Heap::GetMaximumFillToAlign(alignment); | 258 return Heap::GetMaximumFillToAlign(alignment); |
252 } | 259 } |
253 return 0; | 260 return 0; |
254 } | 261 } |
255 | 262 |
256 BackReference Serializer::AllocateLargeObject(int size) { | 263 SerializerReference Serializer::AllocateLargeObject(int size) { |
257 // Large objects are allocated one-by-one when deserializing. We do not | 264 // Large objects are allocated one-by-one when deserializing. We do not |
258 // have to keep track of multiple chunks. | 265 // have to keep track of multiple chunks. |
259 large_objects_total_size_ += size; | 266 large_objects_total_size_ += size; |
260 return BackReference::LargeObjectReference(seen_large_objects_index_++); | 267 return SerializerReference::LargeObjectReference(seen_large_objects_index_++); |
261 } | 268 } |
262 | 269 |
263 BackReference Serializer::Allocate(AllocationSpace space, int size) { | 270 SerializerReference Serializer::Allocate(AllocationSpace space, int size) { |
264 DCHECK(space >= 0 && space < kNumberOfPreallocatedSpaces); | 271 DCHECK(space >= 0 && space < kNumberOfPreallocatedSpaces); |
265 DCHECK(size > 0 && size <= static_cast<int>(max_chunk_size(space))); | 272 DCHECK(size > 0 && size <= static_cast<int>(max_chunk_size(space))); |
266 uint32_t new_chunk_size = pending_chunk_[space] + size; | 273 uint32_t new_chunk_size = pending_chunk_[space] + size; |
267 if (new_chunk_size > max_chunk_size(space)) { | 274 if (new_chunk_size > max_chunk_size(space)) { |
268 // The new chunk size would not fit onto a single page. Complete the | 275 // The new chunk size would not fit onto a single page. Complete the |
269 // current chunk and start a new one. | 276 // current chunk and start a new one. |
270 sink_->Put(kNextChunk, "NextChunk"); | 277 sink_->Put(kNextChunk, "NextChunk"); |
271 sink_->Put(space, "NextChunkSpace"); | 278 sink_->Put(space, "NextChunkSpace"); |
272 completed_chunks_[space].Add(pending_chunk_[space]); | 279 completed_chunks_[space].Add(pending_chunk_[space]); |
273 DCHECK_LE(completed_chunks_[space].length(), BackReference::kMaxChunkIndex); | |
274 pending_chunk_[space] = 0; | 280 pending_chunk_[space] = 0; |
275 new_chunk_size = size; | 281 new_chunk_size = size; |
276 } | 282 } |
277 uint32_t offset = pending_chunk_[space]; | 283 uint32_t offset = pending_chunk_[space]; |
278 pending_chunk_[space] = new_chunk_size; | 284 pending_chunk_[space] = new_chunk_size; |
279 return BackReference::Reference(space, completed_chunks_[space].length(), | 285 return SerializerReference::BackReference( |
280 offset); | 286 space, completed_chunks_[space].length(), offset); |
281 } | 287 } |
282 | 288 |
283 void Serializer::Pad() { | 289 void Serializer::Pad() { |
284 // The non-branching GetInt will read up to 3 bytes too far, so we need | 290 // The non-branching GetInt will read up to 3 bytes too far, so we need |
285 // to pad the snapshot to make sure we don't read over the end. | 291 // to pad the snapshot to make sure we don't read over the end. |
286 for (unsigned i = 0; i < sizeof(int32_t) - 1; i++) { | 292 for (unsigned i = 0; i < sizeof(int32_t) - 1; i++) { |
287 sink_->Put(kNop, "Padding"); | 293 sink_->Put(kNop, "Padding"); |
288 } | 294 } |
289 // Pad up to pointer size for checksum. | 295 // Pad up to pointer size for checksum. |
290 while (!IsAligned(sink_->Position(), kPointerAlignment)) { | 296 while (!IsAligned(sink_->Position(), kPointerAlignment)) { |
(...skipping 22 matching lines...) Expand all Loading... |
313 | 319 |
314 void Serializer::ObjectSerializer::SerializePrologue(AllocationSpace space, | 320 void Serializer::ObjectSerializer::SerializePrologue(AllocationSpace space, |
315 int size, Map* map) { | 321 int size, Map* map) { |
316 if (serializer_->code_address_map_) { | 322 if (serializer_->code_address_map_) { |
317 const char* code_name = | 323 const char* code_name = |
318 serializer_->code_address_map_->Lookup(object_->address()); | 324 serializer_->code_address_map_->Lookup(object_->address()); |
319 LOG(serializer_->isolate_, | 325 LOG(serializer_->isolate_, |
320 CodeNameEvent(object_->address(), sink_->Position(), code_name)); | 326 CodeNameEvent(object_->address(), sink_->Position(), code_name)); |
321 } | 327 } |
322 | 328 |
323 BackReference back_reference; | 329 SerializerReference back_reference; |
324 if (space == LO_SPACE) { | 330 if (space == LO_SPACE) { |
325 sink_->Put(kNewObject + reference_representation_ + space, | 331 sink_->Put(kNewObject + reference_representation_ + space, |
326 "NewLargeObject"); | 332 "NewLargeObject"); |
327 sink_->PutInt(size >> kObjectAlignmentBits, "ObjectSizeInWords"); | 333 sink_->PutInt(size >> kObjectAlignmentBits, "ObjectSizeInWords"); |
328 if (object_->IsCode()) { | 334 if (object_->IsCode()) { |
329 sink_->Put(EXECUTABLE, "executable large object"); | 335 sink_->Put(EXECUTABLE, "executable large object"); |
330 } else { | 336 } else { |
331 sink_->Put(NOT_EXECUTABLE, "not executable large object"); | 337 sink_->Put(NOT_EXECUTABLE, "not executable large object"); |
332 } | 338 } |
333 back_reference = serializer_->AllocateLargeObject(size); | 339 back_reference = serializer_->AllocateLargeObject(size); |
334 } else { | 340 } else { |
335 int fill = serializer_->PutAlignmentPrefix(object_); | 341 int fill = serializer_->PutAlignmentPrefix(object_); |
336 back_reference = serializer_->Allocate(space, size + fill); | 342 back_reference = serializer_->Allocate(space, size + fill); |
337 sink_->Put(kNewObject + reference_representation_ + space, "NewObject"); | 343 sink_->Put(kNewObject + reference_representation_ + space, "NewObject"); |
338 sink_->PutInt(size >> kObjectAlignmentBits, "ObjectSizeInWords"); | 344 sink_->PutInt(size >> kObjectAlignmentBits, "ObjectSizeInWords"); |
339 } | 345 } |
340 | 346 |
341 #ifdef OBJECT_PRINT | 347 #ifdef OBJECT_PRINT |
342 if (FLAG_serialization_statistics) { | 348 if (FLAG_serialization_statistics) { |
343 serializer_->CountInstanceType(map, size); | 349 serializer_->CountInstanceType(map, size); |
344 } | 350 } |
345 #endif // OBJECT_PRINT | 351 #endif // OBJECT_PRINT |
346 | 352 |
347 // Mark this object as already serialized. | 353 // Mark this object as already serialized. |
348 serializer_->back_reference_map()->Add(object_, back_reference); | 354 serializer_->reference_map()->Add(object_, back_reference); |
349 | 355 |
350 // Serialize the map (first word of the object). | 356 // Serialize the map (first word of the object). |
351 serializer_->SerializeObject(map, kPlain, kStartOfObject, 0); | 357 serializer_->SerializeObject(map, kPlain, kStartOfObject, 0); |
352 } | 358 } |
353 | 359 |
354 void Serializer::ObjectSerializer::SerializeExternalString() { | 360 void Serializer::ObjectSerializer::SerializeExternalString() { |
355 // Instead of serializing this as an external string, we serialize | 361 // Instead of serializing this as an external string, we serialize |
356 // an imaginary sequential string with the same content. | 362 // an imaginary sequential string with the same content. |
357 Isolate* isolate = serializer_->isolate(); | 363 Isolate* isolate = serializer_->isolate(); |
358 DCHECK(object_->IsExternalString()); | 364 DCHECK(object_->IsExternalString()); |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
506 | 512 |
507 void Serializer::ObjectSerializer::SerializeDeferred() { | 513 void Serializer::ObjectSerializer::SerializeDeferred() { |
508 if (FLAG_trace_serializer) { | 514 if (FLAG_trace_serializer) { |
509 PrintF(" Encoding deferred heap object: "); | 515 PrintF(" Encoding deferred heap object: "); |
510 object_->ShortPrint(); | 516 object_->ShortPrint(); |
511 PrintF("\n"); | 517 PrintF("\n"); |
512 } | 518 } |
513 | 519 |
514 int size = object_->Size(); | 520 int size = object_->Size(); |
515 Map* map = object_->map(); | 521 Map* map = object_->map(); |
516 BackReference reference = serializer_->back_reference_map()->Lookup(object_); | 522 SerializerReference back_reference = |
| 523 serializer_->reference_map()->Lookup(object_); |
| 524 DCHECK(back_reference.is_back_reference()); |
517 | 525 |
518 // Serialize the rest of the object. | 526 // Serialize the rest of the object. |
519 CHECK_EQ(0, bytes_processed_so_far_); | 527 CHECK_EQ(0, bytes_processed_so_far_); |
520 bytes_processed_so_far_ = kPointerSize; | 528 bytes_processed_so_far_ = kPointerSize; |
521 | 529 |
522 serializer_->PutAlignmentPrefix(object_); | 530 serializer_->PutAlignmentPrefix(object_); |
523 sink_->Put(kNewObject + reference.space(), "deferred object"); | 531 sink_->Put(kNewObject + back_reference.space(), "deferred object"); |
524 serializer_->PutBackReference(object_, reference); | 532 serializer_->PutBackReference(object_, back_reference); |
525 sink_->PutInt(size >> kPointerSizeLog2, "deferred object size"); | 533 sink_->PutInt(size >> kPointerSizeLog2, "deferred object size"); |
526 | 534 |
527 UnlinkWeakNextScope unlink_weak_next(object_); | 535 UnlinkWeakNextScope unlink_weak_next(object_); |
528 | 536 |
529 object_->IterateBody(map->instance_type(), size, this); | 537 object_->IterateBody(map->instance_type(), size, this); |
530 OutputRawData(object_->address() + size); | 538 OutputRawData(object_->address() + size); |
531 } | 539 } |
532 | 540 |
533 void Serializer::ObjectSerializer::VisitPointers(Object** start, Object** end) { | 541 void Serializer::ObjectSerializer::VisitPointers(Object** start, Object** end) { |
534 Object** current = start; | 542 Object** current = start; |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
761 if (to_skip != 0 && return_skip == kIgnoringReturn) { | 769 if (to_skip != 0 && return_skip == kIgnoringReturn) { |
762 sink_->Put(kSkip, "Skip"); | 770 sink_->Put(kSkip, "Skip"); |
763 sink_->PutInt(to_skip, "SkipDistance"); | 771 sink_->PutInt(to_skip, "SkipDistance"); |
764 to_skip = 0; | 772 to_skip = 0; |
765 } | 773 } |
766 return to_skip; | 774 return to_skip; |
767 } | 775 } |
768 | 776 |
769 } // namespace internal | 777 } // namespace internal |
770 } // namespace v8 | 778 } // namespace v8 |
OLD | NEW |