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/default-serializer-allocator.h"
6 :
7 : #include "src/heap/heap-inl.h"
8 : #include "src/snapshot/serializer.h"
9 : #include "src/snapshot/snapshot-source-sink.h"
10 :
11 : namespace v8 {
12 : namespace internal {
13 :
14 730 : DefaultSerializerAllocator::DefaultSerializerAllocator(
15 : Serializer<DefaultSerializerAllocator>* serializer)
16 2920 : : serializer_(serializer) {
17 2920 : for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) {
18 2190 : pending_chunk_[i] = 0;
19 : }
20 730 : }
21 :
22 1338799 : SerializerReference DefaultSerializerAllocator::Allocate(AllocationSpace space,
23 : uint32_t size) {
24 : DCHECK(space >= 0 && space < kNumberOfPreallocatedSpaces);
25 : DCHECK(size > 0 && size <= MaxChunkSizeInSpace(space));
26 :
27 : // Maps are allocated through AllocateMap.
28 : DCHECK_NE(MAP_SPACE, space);
29 :
30 1338799 : uint32_t new_chunk_size = pending_chunk_[space] + size;
31 1338799 : if (new_chunk_size > MaxChunkSizeInSpace(space)) {
32 : // The new chunk size would not fit onto a single page. Complete the
33 : // current chunk and start a new one.
34 55 : serializer_->PutNextChunk(space);
35 1338854 : completed_chunks_[space].push_back(pending_chunk_[space]);
36 55 : pending_chunk_[space] = 0;
37 : new_chunk_size = size;
38 : }
39 1338799 : uint32_t offset = pending_chunk_[space];
40 1338799 : pending_chunk_[space] = new_chunk_size;
41 : return SerializerReference::BackReference(
42 4016397 : space, static_cast<uint32_t>(completed_chunks_[space].size()), offset);
43 : }
44 :
45 59747 : SerializerReference DefaultSerializerAllocator::AllocateMap() {
46 : // Maps are allocated one-by-one when deserializing.
47 119494 : return SerializerReference::MapReference(num_maps_++);
48 : }
49 :
50 40 : SerializerReference DefaultSerializerAllocator::AllocateLargeObject(
51 : uint32_t size) {
52 : // Large objects are allocated one-by-one when deserializing. We do not
53 : // have to keep track of multiple chunks.
54 40 : large_objects_total_size_ += size;
55 80 : return SerializerReference::LargeObjectReference(seen_large_objects_index_++);
56 : }
57 :
58 30 : SerializerReference DefaultSerializerAllocator::AllocateOffHeapBackingStore() {
59 : DCHECK_NE(0, seen_backing_stores_index_);
60 : return SerializerReference::OffHeapBackingStoreReference(
61 60 : seen_backing_stores_index_++);
62 : }
63 :
64 : #ifdef DEBUG
65 : bool DefaultSerializerAllocator::BackReferenceIsAlreadyAllocated(
66 : SerializerReference reference) const {
67 : DCHECK(reference.is_back_reference());
68 : AllocationSpace space = reference.space();
69 : if (space == LO_SPACE) {
70 : return reference.large_object_index() < seen_large_objects_index_;
71 : } else if (space == MAP_SPACE) {
72 : return reference.map_index() < num_maps_;
73 : } else {
74 : size_t chunk_index = reference.chunk_index();
75 : if (chunk_index == completed_chunks_[space].size()) {
76 : return reference.chunk_offset() < pending_chunk_[space];
77 : } else {
78 : return chunk_index < completed_chunks_[space].size() &&
79 : reference.chunk_offset() < completed_chunks_[space][chunk_index];
80 : }
81 : }
82 : }
83 :
84 : bool DefaultSerializerAllocator::HasNotExceededFirstPageOfEachSpace() const {
85 : for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) {
86 : if (!completed_chunks_[i].empty()) return false;
87 : }
88 : return true;
89 : }
90 : #endif
91 :
92 : std::vector<SerializedData::Reservation>
93 730 : DefaultSerializerAllocator::EncodeReservations() const {
94 : std::vector<SerializedData::Reservation> out;
95 :
96 : STATIC_ASSERT(NEW_SPACE == 0);
97 2920 : for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) {
98 2300 : for (size_t j = 0; j < completed_chunks_[i].size(); j++) {
99 2300 : out.emplace_back(completed_chunks_[i][j]);
100 : }
101 :
102 2190 : if (pending_chunk_[i] > 0 || completed_chunks_[i].size() == 0) {
103 2190 : out.emplace_back(pending_chunk_[i]);
104 : }
105 : out.back().mark_as_last();
106 : }
107 :
108 : STATIC_ASSERT(MAP_SPACE == kNumberOfPreallocatedSpaces);
109 730 : out.emplace_back(num_maps_ * Map::kSize);
110 : out.back().mark_as_last();
111 :
112 : STATIC_ASSERT(LO_SPACE == MAP_SPACE + 1);
113 730 : out.emplace_back(large_objects_total_size_);
114 : out.back().mark_as_last();
115 :
116 730 : return out;
117 : }
118 :
119 0 : void DefaultSerializerAllocator::OutputStatistics() {
120 : DCHECK(FLAG_serialization_statistics);
121 :
122 0 : PrintF(" Spaces (bytes):\n");
123 :
124 : STATIC_ASSERT(NEW_SPACE == 0);
125 0 : for (int space = 0; space < kNumberOfSpaces; space++) {
126 0 : PrintF("%16s", AllocationSpaceName(static_cast<AllocationSpace>(space)));
127 : }
128 0 : PrintF("\n");
129 :
130 : STATIC_ASSERT(NEW_SPACE == 0);
131 0 : for (int space = 0; space < kNumberOfPreallocatedSpaces; space++) {
132 0 : size_t s = pending_chunk_[space];
133 0 : for (uint32_t chunk_size : completed_chunks_[space]) s += chunk_size;
134 0 : PrintF("%16" PRIuS, s);
135 : }
136 :
137 : STATIC_ASSERT(MAP_SPACE == kNumberOfPreallocatedSpaces);
138 0 : PrintF("%16d", num_maps_ * Map::kSize);
139 :
140 : STATIC_ASSERT(LO_SPACE == MAP_SPACE + 1);
141 0 : PrintF("%16d\n", large_objects_total_size_);
142 0 : }
143 :
144 : // static
145 0 : uint32_t DefaultSerializerAllocator::MaxChunkSizeInSpace(int space) {
146 : DCHECK(0 <= space && space < kNumberOfPreallocatedSpaces);
147 :
148 : return static_cast<uint32_t>(
149 1338799 : MemoryAllocator::PageAreaSize(static_cast<AllocationSpace>(space)));
150 : }
151 :
152 : } // namespace internal
153 : } // namespace v8
|