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