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
13namespace v8 {
14namespace 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>.
21class ZoneVectorWrapper {
22 public:
23  ZoneVectorWrapper() = default;
24  explicit ZoneVectorWrapper(ZoneVector<uint8_t>* data) : data_(data) {}
25
26  int data_length() const { return static_cast<int>(data_->size()); }
27
28  uint8_t get(int index) const { return data_->at(index); }
29
30 private:
31  ZoneVector<uint8_t>* data_ = nullptr;
32};
33
34template <class Data>
35class 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:
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      }
51      explicit ReadingScope(BaseConsumedPreparseData<Data>* parent)
52          : ReadingScope(parent->scope_data_.get(), parent->GetScopeData()) {}
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
64    void SetPosition(int position) {
65      DCHECK_LE(position, data_.data_length());
66      index_ = position;
67    }
68
69    size_t RemainingBytes() const {
70      DCHECK(has_data_);
71      DCHECK_LE(index_, data_.data_length());
72      return data_.data_length() - index_;
73    }
74
75    bool HasRemainingBytes(size_t bytes) const {
76      DCHECK(has_data_);
77      return index_ <= data_.data_length() && bytes <= RemainingBytes();
78    }
79
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
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
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
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
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.
182class 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).
196class 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
208  int children_length() const { return static_cast<int>(children_.size()); }
209
210  ZonePreparseData* get_child(int index) { return children_[index]; }
211
212  void set_child(int index, ZonePreparseData* child) {
213    DCHECK_NOT_NULL(child);
214    children_[index] = child;
215  }
216
217  ZoneVector<uint8_t>* byte_data() { return &byte_data_; }
218
219 private:
220  ZoneVector<uint8_t> byte_data_;
221  ZoneVector<ZonePreparseData*> children_;
222};
223
224ZonePreparseData* 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.
232class 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