Line data Source code
1 : // Copyright 2017 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/snapshot/serializer-allocator.h"
6 :
7 : #include "src/heap/heap-inl.h" // crbug.com/v8/8499
8 : #include "src/snapshot/references.h"
9 : #include "src/snapshot/serializer.h"
10 : #include "src/snapshot/snapshot-source-sink.h"
11 :
12 : namespace v8 {
13 : namespace internal {
14 :
15 1137 : SerializerAllocator::SerializerAllocator(Serializer* serializer)
16 5685 : : serializer_(serializer) {
17 10233 : for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) {
18 4548 : pending_chunk_[i] = 0;
19 : }
20 1137 : }
21 :
22 615 : void SerializerAllocator::UseCustomChunkSize(uint32_t chunk_size) {
23 615 : custom_chunk_size_ = chunk_size;
24 615 : }
25 :
26 : static uint32_t PageSizeOfSpace(int space) {
27 : return static_cast<uint32_t>(
28 1346820 : MemoryChunkLayout::AllocatableMemoryInMemoryChunk(
29 1346820 : static_cast<AllocationSpace>(space)));
30 : }
31 :
32 0 : uint32_t SerializerAllocator::TargetChunkSize(int space) {
33 1867348 : if (custom_chunk_size_ == 0) return PageSizeOfSpace(space);
34 : DCHECK_LE(custom_chunk_size_, PageSizeOfSpace(space));
35 : return custom_chunk_size_;
36 : }
37 :
38 1867348 : SerializerReference SerializerAllocator::Allocate(AllocationSpace space,
39 : uint32_t size) {
40 : DCHECK(space >= 0 && space < kNumberOfPreallocatedSpaces);
41 : DCHECK(size > 0 && size <= PageSizeOfSpace(space));
42 :
43 : // Maps are allocated through AllocateMap.
44 : DCHECK_NE(MAP_SPACE, space);
45 : // We tenure large object allocations.
46 : DCHECK_NE(NEW_LO_SPACE, space);
47 :
48 1867348 : uint32_t old_chunk_size = pending_chunk_[space];
49 1867348 : uint32_t new_chunk_size = old_chunk_size + size;
50 : // Start a new chunk if the new size exceeds the target chunk size.
51 : // We may exceed the target chunk size if the single object size does.
52 1867348 : if (new_chunk_size > TargetChunkSize(space) && old_chunk_size != 0) {
53 10109 : serializer_->PutNextChunk(space);
54 10109 : completed_chunks_[space].push_back(pending_chunk_[space]);
55 10109 : pending_chunk_[space] = 0;
56 : new_chunk_size = size;
57 : }
58 1867348 : uint32_t offset = pending_chunk_[space];
59 1867348 : pending_chunk_[space] = new_chunk_size;
60 : return SerializerReference::BackReference(
61 5602044 : space, static_cast<uint32_t>(completed_chunks_[space].size()), offset);
62 : }
63 :
64 60811 : SerializerReference SerializerAllocator::AllocateMap() {
65 : // Maps are allocated one-by-one when deserializing.
66 60811 : return SerializerReference::MapReference(num_maps_++);
67 : }
68 :
69 60 : SerializerReference SerializerAllocator::AllocateLargeObject(uint32_t size) {
70 : // Large objects are allocated one-by-one when deserializing. We do not
71 : // have to keep track of multiple chunks.
72 60 : large_objects_total_size_ += size;
73 60 : return SerializerReference::LargeObjectReference(seen_large_objects_index_++);
74 : }
75 :
76 35 : SerializerReference SerializerAllocator::AllocateOffHeapBackingStore() {
77 : DCHECK_NE(0, seen_backing_stores_index_);
78 : return SerializerReference::OffHeapBackingStoreReference(
79 35 : seen_backing_stores_index_++);
80 : }
81 :
82 : #ifdef DEBUG
83 : bool SerializerAllocator::BackReferenceIsAlreadyAllocated(
84 : SerializerReference reference) const {
85 : DCHECK(reference.is_back_reference());
86 : AllocationSpace space = reference.space();
87 : if (space == LO_SPACE) {
88 : return reference.large_object_index() < seen_large_objects_index_;
89 : } else if (space == MAP_SPACE) {
90 : return reference.map_index() < num_maps_;
91 : } else if (space == RO_SPACE &&
92 : serializer_->isolate()->heap()->deserialization_complete()) {
93 : // If not deserializing the isolate itself, then we create BackReferences
94 : // for all RO_SPACE objects without ever allocating.
95 : return true;
96 : } else {
97 : size_t chunk_index = reference.chunk_index();
98 : if (chunk_index == completed_chunks_[space].size()) {
99 : return reference.chunk_offset() < pending_chunk_[space];
100 : } else {
101 : return chunk_index < completed_chunks_[space].size() &&
102 : reference.chunk_offset() < completed_chunks_[space][chunk_index];
103 : }
104 : }
105 : }
106 : #endif
107 :
108 : std::vector<SerializedData::Reservation>
109 1137 : SerializerAllocator::EncodeReservations() const {
110 : std::vector<SerializedData::Reservation> out;
111 :
112 10233 : for (int i = FIRST_SPACE; i < kNumberOfPreallocatedSpaces; i++) {
113 39423 : for (size_t j = 0; j < completed_chunks_[i].size(); j++) {
114 10109 : out.emplace_back(completed_chunks_[i][j]);
115 : }
116 :
117 4548 : if (pending_chunk_[i] > 0 || completed_chunks_[i].size() == 0) {
118 4548 : out.emplace_back(pending_chunk_[i]);
119 : }
120 : out.back().mark_as_last();
121 : }
122 :
123 : STATIC_ASSERT(MAP_SPACE == kNumberOfPreallocatedSpaces);
124 1137 : out.emplace_back(num_maps_ * Map::kSize);
125 : out.back().mark_as_last();
126 :
127 : STATIC_ASSERT(LO_SPACE == MAP_SPACE + 1);
128 1137 : out.emplace_back(large_objects_total_size_);
129 : out.back().mark_as_last();
130 :
131 1137 : return out;
132 : }
133 :
134 0 : void SerializerAllocator::OutputStatistics() {
135 : DCHECK(FLAG_serialization_statistics);
136 :
137 0 : PrintF(" Spaces (bytes):\n");
138 :
139 0 : for (int space = FIRST_SPACE; space < kNumberOfSpaces; space++) {
140 0 : PrintF("%16s", Heap::GetSpaceName(static_cast<AllocationSpace>(space)));
141 : }
142 0 : PrintF("\n");
143 :
144 0 : for (int space = FIRST_SPACE; space < kNumberOfPreallocatedSpaces; space++) {
145 0 : size_t s = pending_chunk_[space];
146 0 : for (uint32_t chunk_size : completed_chunks_[space]) s += chunk_size;
147 0 : PrintF("%16" PRIuS, s);
148 : }
149 :
150 : STATIC_ASSERT(MAP_SPACE == kNumberOfPreallocatedSpaces);
151 0 : PrintF("%16d", num_maps_ * Map::kSize);
152 :
153 : STATIC_ASSERT(LO_SPACE == MAP_SPACE + 1);
154 0 : PrintF("%16d\n", large_objects_total_size_);
155 0 : }
156 :
157 : } // namespace internal
158 122036 : } // namespace v8
|