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 { |
11 namespace internal { | 11 namespace internal { |
12 | 12 |
13 Serializer::Serializer(Isolate* isolate) | 13 Serializer::Serializer(Isolate* isolate) |
14 : isolate_(isolate), | 14 : isolate_(isolate), |
15 external_reference_encoder_(isolate), | 15 external_reference_encoder_(isolate), |
16 root_index_map_(isolate), | 16 root_index_map_(isolate), |
17 recursion_depth_(0), | 17 recursion_depth_(0), |
18 code_address_map_(NULL), | 18 code_address_map_(NULL), |
| 19 num_maps_(0), |
19 large_objects_total_size_(0), | 20 large_objects_total_size_(0), |
20 seen_large_objects_index_(0) { | 21 seen_large_objects_index_(0) { |
21 // The serializer is meant to be used only to generate initial heap images | 22 // The serializer is meant to be used only to generate initial heap images |
22 // from a context in which there is only one isolate. | 23 // from a context in which there is only one isolate. |
23 for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) { | 24 for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) { |
24 pending_chunk_[i] = 0; | 25 pending_chunk_[i] = 0; |
25 max_chunk_size_[i] = static_cast<uint32_t>( | 26 max_chunk_size_[i] = static_cast<uint32_t>( |
26 MemoryAllocator::PageAreaSize(static_cast<AllocationSpace>(i))); | 27 MemoryAllocator::PageAreaSize(static_cast<AllocationSpace>(i))); |
27 } | 28 } |
28 | 29 |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) { | 111 for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) { |
111 for (int j = 0; j < completed_chunks_[i].length(); j++) { | 112 for (int j = 0; j < completed_chunks_[i].length(); j++) { |
112 out->Add(SerializedData::Reservation(completed_chunks_[i][j])); | 113 out->Add(SerializedData::Reservation(completed_chunks_[i][j])); |
113 } | 114 } |
114 | 115 |
115 if (pending_chunk_[i] > 0 || completed_chunks_[i].length() == 0) { | 116 if (pending_chunk_[i] > 0 || completed_chunks_[i].length() == 0) { |
116 out->Add(SerializedData::Reservation(pending_chunk_[i])); | 117 out->Add(SerializedData::Reservation(pending_chunk_[i])); |
117 } | 118 } |
118 out->last().mark_as_last(); | 119 out->last().mark_as_last(); |
119 } | 120 } |
120 | 121 out->Add(SerializedData::Reservation(num_maps_ * Map::kSize)); |
| 122 out->last().mark_as_last(); |
121 out->Add(SerializedData::Reservation(large_objects_total_size_)); | 123 out->Add(SerializedData::Reservation(large_objects_total_size_)); |
122 out->last().mark_as_last(); | 124 out->last().mark_as_last(); |
123 } | 125 } |
124 | 126 |
125 #ifdef DEBUG | 127 #ifdef DEBUG |
126 bool Serializer::BackReferenceIsAlreadyAllocated( | 128 bool Serializer::BackReferenceIsAlreadyAllocated( |
127 SerializerReference reference) { | 129 SerializerReference reference) { |
128 DCHECK(reference.is_back_reference()); | 130 DCHECK(reference.is_back_reference()); |
129 AllocationSpace space = reference.space(); | 131 AllocationSpace space = reference.space(); |
130 int chunk_index = reference.chunk_index(); | |
131 if (space == LO_SPACE) { | 132 if (space == LO_SPACE) { |
132 return chunk_index == 0 && | 133 return reference.large_object_index() < seen_large_objects_index_; |
133 reference.large_object_index() < seen_large_objects_index_; | 134 } else if (space == MAP_SPACE) { |
134 } else if (chunk_index == completed_chunks_[space].length()) { | 135 return reference.map_index() < num_maps_; |
135 return reference.chunk_offset() < pending_chunk_[space]; | |
136 } else { | 136 } else { |
137 return chunk_index < completed_chunks_[space].length() && | 137 int chunk_index = reference.chunk_index(); |
138 reference.chunk_offset() < completed_chunks_[space][chunk_index]; | 138 if (chunk_index == completed_chunks_[space].length()) { |
| 139 return reference.chunk_offset() < pending_chunk_[space]; |
| 140 } else { |
| 141 return chunk_index < completed_chunks_[space].length() && |
| 142 reference.chunk_offset() < completed_chunks_[space][chunk_index]; |
| 143 } |
139 } | 144 } |
140 } | 145 } |
141 #endif // DEBUG | 146 #endif // DEBUG |
142 | 147 |
143 bool Serializer::SerializeHotObject(HeapObject* obj, HowToCode how_to_code, | 148 bool Serializer::SerializeHotObject(HeapObject* obj, HowToCode how_to_code, |
144 WhereToPoint where_to_point, int skip) { | 149 WhereToPoint where_to_point, int skip) { |
145 if (how_to_code != kPlain || where_to_point != kStartOfObject) return false; | 150 if (how_to_code != kPlain || where_to_point != kStartOfObject) return false; |
146 // Encode a reference to a hot object by its index in the working set. | 151 // Encode a reference to a hot object by its index in the working set. |
147 int index = hot_objects_.Find(obj); | 152 int index = hot_objects_.Find(obj); |
148 if (index == HotObjectsList::kNotFound) return false; | 153 if (index == HotObjectsList::kNotFound) return false; |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 return 0; | 264 return 0; |
260 } | 265 } |
261 | 266 |
262 SerializerReference Serializer::AllocateLargeObject(int size) { | 267 SerializerReference Serializer::AllocateLargeObject(int size) { |
263 // Large objects are allocated one-by-one when deserializing. We do not | 268 // Large objects are allocated one-by-one when deserializing. We do not |
264 // have to keep track of multiple chunks. | 269 // have to keep track of multiple chunks. |
265 large_objects_total_size_ += size; | 270 large_objects_total_size_ += size; |
266 return SerializerReference::LargeObjectReference(seen_large_objects_index_++); | 271 return SerializerReference::LargeObjectReference(seen_large_objects_index_++); |
267 } | 272 } |
268 | 273 |
| 274 SerializerReference Serializer::AllocateMap() { |
| 275 // Maps are allocated one-by-one when deserializing. |
| 276 return SerializerReference::MapReference(num_maps_++); |
| 277 } |
| 278 |
269 SerializerReference Serializer::Allocate(AllocationSpace space, int size) { | 279 SerializerReference Serializer::Allocate(AllocationSpace space, int size) { |
270 DCHECK(space >= 0 && space < kNumberOfPreallocatedSpaces); | 280 DCHECK(space >= 0 && space < kNumberOfPreallocatedSpaces); |
271 DCHECK(size > 0 && size <= static_cast<int>(max_chunk_size(space))); | 281 DCHECK(size > 0 && size <= static_cast<int>(max_chunk_size(space))); |
272 uint32_t new_chunk_size = pending_chunk_[space] + size; | 282 uint32_t new_chunk_size = pending_chunk_[space] + size; |
273 if (new_chunk_size > max_chunk_size(space)) { | 283 if (new_chunk_size > max_chunk_size(space)) { |
274 // The new chunk size would not fit onto a single page. Complete the | 284 // The new chunk size would not fit onto a single page. Complete the |
275 // current chunk and start a new one. | 285 // current chunk and start a new one. |
276 sink_.Put(kNextChunk, "NextChunk"); | 286 sink_.Put(kNextChunk, "NextChunk"); |
277 sink_.Put(space, "NextChunkSpace"); | 287 sink_.Put(space, "NextChunkSpace"); |
278 completed_chunks_[space].Add(pending_chunk_[space]); | 288 completed_chunks_[space].Add(pending_chunk_[space]); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
329 if (space == LO_SPACE) { | 339 if (space == LO_SPACE) { |
330 sink_->Put(kNewObject + reference_representation_ + space, | 340 sink_->Put(kNewObject + reference_representation_ + space, |
331 "NewLargeObject"); | 341 "NewLargeObject"); |
332 sink_->PutInt(size >> kObjectAlignmentBits, "ObjectSizeInWords"); | 342 sink_->PutInt(size >> kObjectAlignmentBits, "ObjectSizeInWords"); |
333 if (object_->IsCode()) { | 343 if (object_->IsCode()) { |
334 sink_->Put(EXECUTABLE, "executable large object"); | 344 sink_->Put(EXECUTABLE, "executable large object"); |
335 } else { | 345 } else { |
336 sink_->Put(NOT_EXECUTABLE, "not executable large object"); | 346 sink_->Put(NOT_EXECUTABLE, "not executable large object"); |
337 } | 347 } |
338 back_reference = serializer_->AllocateLargeObject(size); | 348 back_reference = serializer_->AllocateLargeObject(size); |
| 349 } else if (space == MAP_SPACE) { |
| 350 DCHECK_EQ(Map::kSize, size); |
| 351 back_reference = serializer_->AllocateMap(); |
| 352 sink_->Put(kNewObject + reference_representation_ + space, "NewMap"); |
| 353 // This is redundant, but we include it anyways. |
| 354 sink_->PutInt(size >> kObjectAlignmentBits, "ObjectSizeInWords"); |
339 } else { | 355 } else { |
340 int fill = serializer_->PutAlignmentPrefix(object_); | 356 int fill = serializer_->PutAlignmentPrefix(object_); |
341 back_reference = serializer_->Allocate(space, size + fill); | 357 back_reference = serializer_->Allocate(space, size + fill); |
342 sink_->Put(kNewObject + reference_representation_ + space, "NewObject"); | 358 sink_->Put(kNewObject + reference_representation_ + space, "NewObject"); |
343 sink_->PutInt(size >> kObjectAlignmentBits, "ObjectSizeInWords"); | 359 sink_->PutInt(size >> kObjectAlignmentBits, "ObjectSizeInWords"); |
344 } | 360 } |
345 | 361 |
346 #ifdef OBJECT_PRINT | 362 #ifdef OBJECT_PRINT |
347 if (FLAG_serialization_statistics) { | 363 if (FLAG_serialization_statistics) { |
348 serializer_->CountInstanceType(map, size); | 364 serializer_->CountInstanceType(map, size); |
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
774 if (to_skip != 0 && return_skip == kIgnoringReturn) { | 790 if (to_skip != 0 && return_skip == kIgnoringReturn) { |
775 sink_->Put(kSkip, "Skip"); | 791 sink_->Put(kSkip, "Skip"); |
776 sink_->PutInt(to_skip, "SkipDistance"); | 792 sink_->PutInt(to_skip, "SkipDistance"); |
777 to_skip = 0; | 793 to_skip = 0; |
778 } | 794 } |
779 return to_skip; | 795 return to_skip; |
780 } | 796 } |
781 | 797 |
782 } // namespace internal | 798 } // namespace internal |
783 } // namespace v8 | 799 } // namespace v8 |
OLD | NEW |