| 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 |