• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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