1 // Copyright 2018 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 #ifndef V8_PARSING_PREPARSE_DATA_IMPL_H_
6 #define V8_PARSING_PREPARSE_DATA_IMPL_H_
7
8 #include <memory>
9
10 #include "src/common/assert-scope.h"
11 #include "src/parsing/preparse-data.h"
12
13 namespace v8 {
14 namespace internal {
15
16 // Classes which are internal to prepared-scope-data.cc, but are exposed in
17 // a header for tests.
18
19 // Wraps a ZoneVector<uint8_t> to have with functions named the same as
20 // PodArray<uint8_t>.
21 class ZoneVectorWrapper {
22 public:
23 ZoneVectorWrapper() = default;
ZoneVectorWrapper(ZoneVector<uint8_t> * data)24 explicit ZoneVectorWrapper(ZoneVector<uint8_t>* data) : data_(data) {}
25
data_length()26 int data_length() const { return static_cast<int>(data_->size()); }
27
get(int index)28 uint8_t get(int index) const { return data_->at(index); }
29
30 private:
31 ZoneVector<uint8_t>* data_ = nullptr;
32 };
33
34 template <class Data>
35 class BaseConsumedPreparseData : public ConsumedPreparseData {
36 public:
37 class ByteData : public PreparseByteDataConstants {
38 public:
39 // Reading from the ByteData is only allowed when a ReadingScope is on the
40 // stack. This ensures that we have a DisallowGarbageCollection in place
41 // whenever ByteData holds a raw pointer into the heap.
42 class V8_NODISCARD ReadingScope {
43 public:
ReadingScope(ByteData * consumed_data,Data data)44 ReadingScope(ByteData* consumed_data, Data data)
45 : consumed_data_(consumed_data) {
46 consumed_data->data_ = data;
47 #ifdef DEBUG
48 consumed_data->has_data_ = true;
49 #endif
50 }
ReadingScope(BaseConsumedPreparseData<Data> * parent)51 explicit ReadingScope(BaseConsumedPreparseData<Data>* parent)
52 : ReadingScope(parent->scope_data_.get(), parent->GetScopeData()) {}
~ReadingScope()53 ~ReadingScope() {
54 #ifdef DEBUG
55 consumed_data_->has_data_ = false;
56 #endif
57 }
58
59 private:
60 ByteData* consumed_data_;
61 DISALLOW_GARBAGE_COLLECTION(no_gc)
62 };
63
SetPosition(int position)64 void SetPosition(int position) {
65 DCHECK_LE(position, data_.data_length());
66 index_ = position;
67 }
68
RemainingBytes()69 size_t RemainingBytes() const {
70 DCHECK(has_data_);
71 DCHECK_LE(index_, data_.data_length());
72 return data_.data_length() - index_;
73 }
74
HasRemainingBytes(size_t bytes)75 bool HasRemainingBytes(size_t bytes) const {
76 DCHECK(has_data_);
77 return index_ <= data_.data_length() && bytes <= RemainingBytes();
78 }
79
ReadUint32()80 int32_t ReadUint32() {
81 DCHECK(has_data_);
82 DCHECK(HasRemainingBytes(kUint32Size));
83 // Check that there indeed is an integer following.
84 DCHECK_EQ(data_.get(index_++), kUint32Size);
85 int32_t result = data_.get(index_) + (data_.get(index_ + 1) << 8) +
86 (data_.get(index_ + 2) << 16) +
87 (data_.get(index_ + 3) << 24);
88 index_ += 4;
89 stored_quarters_ = 0;
90 return result;
91 }
92
ReadVarint32()93 int32_t ReadVarint32() {
94 DCHECK(HasRemainingBytes(kVarint32MinSize));
95 DCHECK_EQ(data_.get(index_++), kVarint32MinSize);
96 int32_t value = 0;
97 bool has_another_byte;
98 unsigned shift = 0;
99 do {
100 uint8_t byte = data_.get(index_++);
101 value |= static_cast<int32_t>(byte & 0x7F) << shift;
102 shift += 7;
103 has_another_byte = byte & 0x80;
104 } while (has_another_byte);
105 DCHECK_EQ(data_.get(index_++), kVarint32EndMarker);
106 stored_quarters_ = 0;
107 return value;
108 }
109
ReadUint8()110 uint8_t ReadUint8() {
111 DCHECK(has_data_);
112 DCHECK(HasRemainingBytes(kUint8Size));
113 // Check that there indeed is a byte following.
114 DCHECK_EQ(data_.get(index_++), kUint8Size);
115 stored_quarters_ = 0;
116 return data_.get(index_++);
117 }
118
ReadQuarter()119 uint8_t ReadQuarter() {
120 DCHECK(has_data_);
121 if (stored_quarters_ == 0) {
122 DCHECK(HasRemainingBytes(kUint8Size));
123 // Check that there indeed are quarters following.
124 DCHECK_EQ(data_.get(index_++), kQuarterMarker);
125 stored_byte_ = data_.get(index_++);
126 stored_quarters_ = 4;
127 }
128 // Read the first 2 bits from stored_byte_.
129 uint8_t result = (stored_byte_ >> 6) & 3;
130 DCHECK_LE(result, 3);
131 --stored_quarters_;
132 stored_byte_ <<= 2;
133 return result;
134 }
135
136 private:
137 Data data_ = {};
138 int index_ = 0;
139 uint8_t stored_quarters_ = 0;
140 uint8_t stored_byte_ = 0;
141 #ifdef DEBUG
142 bool has_data_ = false;
143 #endif
144 };
145
BaseConsumedPreparseData()146 BaseConsumedPreparseData() : scope_data_(new ByteData()), child_index_(0) {}
147 BaseConsumedPreparseData(const BaseConsumedPreparseData&) = delete;
148 BaseConsumedPreparseData& operator=(const BaseConsumedPreparseData&) = delete;
149
150 virtual Data GetScopeData() = 0;
151
152 virtual ProducedPreparseData* GetChildData(Zone* zone, int child_index) = 0;
153
154 ProducedPreparseData* GetDataForSkippableFunction(
155 Zone* zone, int start_position, int* end_position, int* num_parameters,
156 int* function_length, int* num_inner_functions, bool* uses_super_property,
157 LanguageMode* language_mode) final;
158
159 void RestoreScopeAllocationData(DeclarationScope* scope,
160 AstValueFactory* ast_value_factory,
161 Zone* zone) final;
162
163 #ifdef DEBUG
164 bool VerifyDataStart();
165 #endif
166
167 private:
168 void RestoreDataForScope(Scope* scope, AstValueFactory* ast_value_factory,
169 Zone* zone);
170 void RestoreDataForVariable(Variable* var);
171 void RestoreDataForInnerScopes(Scope* scope,
172 AstValueFactory* ast_value_factory,
173 Zone* zone);
174
175 std::unique_ptr<ByteData> scope_data_;
176 // When consuming the data, these indexes point to the data we're going to
177 // consume next.
178 int child_index_;
179 };
180
181 // Implementation of ConsumedPreparseData for on-heap data.
182 class OnHeapConsumedPreparseData final
183 : public BaseConsumedPreparseData<PreparseData> {
184 public:
185 OnHeapConsumedPreparseData(LocalIsolate* isolate, Handle<PreparseData> data);
186
187 PreparseData GetScopeData() final;
188 ProducedPreparseData* GetChildData(Zone* zone, int child_index) final;
189
190 private:
191 LocalIsolate* isolate_;
192 Handle<PreparseData> data_;
193 };
194
195 // A serialized PreparseData in zone memory (as apposed to being on-heap).
196 class ZonePreparseData : public ZoneObject {
197 public:
198 V8_EXPORT_PRIVATE ZonePreparseData(Zone* zone,
199 base::Vector<uint8_t>* byte_data,
200 int child_length);
201
202 ZonePreparseData(const ZonePreparseData&) = delete;
203 ZonePreparseData& operator=(const ZonePreparseData&) = delete;
204
205 Handle<PreparseData> Serialize(Isolate* isolate);
206 Handle<PreparseData> Serialize(LocalIsolate* isolate);
207
children_length()208 int children_length() const { return static_cast<int>(children_.size()); }
209
get_child(int index)210 ZonePreparseData* get_child(int index) { return children_[index]; }
211
set_child(int index,ZonePreparseData * child)212 void set_child(int index, ZonePreparseData* child) {
213 DCHECK_NOT_NULL(child);
214 children_[index] = child;
215 }
216
byte_data()217 ZoneVector<uint8_t>* byte_data() { return &byte_data_; }
218
219 private:
220 ZoneVector<uint8_t> byte_data_;
221 ZoneVector<ZonePreparseData*> children_;
222 };
223
CopyToZone(Zone * zone,int children_length)224 ZonePreparseData* PreparseDataBuilder::ByteData::CopyToZone(
225 Zone* zone, int children_length) {
226 DCHECK(is_finalized_);
227 return zone->New<ZonePreparseData>(zone, &zone_byte_data_, children_length);
228 }
229
230 // Implementation of ConsumedPreparseData for PreparseData
231 // serialized into zone memory.
232 class ZoneConsumedPreparseData final
233 : public BaseConsumedPreparseData<ZoneVectorWrapper> {
234 public:
235 ZoneConsumedPreparseData(Zone* zone, ZonePreparseData* data);
236
237 ZoneVectorWrapper GetScopeData() final;
238 ProducedPreparseData* GetChildData(Zone* zone, int child_index) final;
239
240 private:
241 ZonePreparseData* data_;
242 ZoneVectorWrapper scope_data_wrapper_;
243 };
244
245 } // namespace internal
246 } // namespace v8
247
248 #endif // V8_PARSING_PREPARSE_DATA_IMPL_H_
249