11cb0ef41Sopenharmony_ci// Copyright 2018 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#ifndef V8_PARSING_PREPARSE_DATA_IMPL_H_
61cb0ef41Sopenharmony_ci#define V8_PARSING_PREPARSE_DATA_IMPL_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include <memory>
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#include "src/common/assert-scope.h"
111cb0ef41Sopenharmony_ci#include "src/parsing/preparse-data.h"
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_cinamespace v8 {
141cb0ef41Sopenharmony_cinamespace internal {
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ci// Classes which are internal to prepared-scope-data.cc, but are exposed in
171cb0ef41Sopenharmony_ci// a header for tests.
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ci// Wraps a ZoneVector<uint8_t> to have with functions named the same as
201cb0ef41Sopenharmony_ci// PodArray<uint8_t>.
211cb0ef41Sopenharmony_ciclass ZoneVectorWrapper {
221cb0ef41Sopenharmony_ci public:
231cb0ef41Sopenharmony_ci  ZoneVectorWrapper() = default;
241cb0ef41Sopenharmony_ci  explicit ZoneVectorWrapper(ZoneVector<uint8_t>* data) : data_(data) {}
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ci  int data_length() const { return static_cast<int>(data_->size()); }
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci  uint8_t get(int index) const { return data_->at(index); }
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci private:
311cb0ef41Sopenharmony_ci  ZoneVector<uint8_t>* data_ = nullptr;
321cb0ef41Sopenharmony_ci};
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_citemplate <class Data>
351cb0ef41Sopenharmony_ciclass BaseConsumedPreparseData : public ConsumedPreparseData {
361cb0ef41Sopenharmony_ci public:
371cb0ef41Sopenharmony_ci  class ByteData : public PreparseByteDataConstants {
381cb0ef41Sopenharmony_ci   public:
391cb0ef41Sopenharmony_ci    // Reading from the ByteData is only allowed when a ReadingScope is on the
401cb0ef41Sopenharmony_ci    // stack. This ensures that we have a DisallowGarbageCollection in place
411cb0ef41Sopenharmony_ci    // whenever ByteData holds a raw pointer into the heap.
421cb0ef41Sopenharmony_ci    class V8_NODISCARD ReadingScope {
431cb0ef41Sopenharmony_ci     public:
441cb0ef41Sopenharmony_ci      ReadingScope(ByteData* consumed_data, Data data)
451cb0ef41Sopenharmony_ci          : consumed_data_(consumed_data) {
461cb0ef41Sopenharmony_ci        consumed_data->data_ = data;
471cb0ef41Sopenharmony_ci#ifdef DEBUG
481cb0ef41Sopenharmony_ci        consumed_data->has_data_ = true;
491cb0ef41Sopenharmony_ci#endif
501cb0ef41Sopenharmony_ci      }
511cb0ef41Sopenharmony_ci      explicit ReadingScope(BaseConsumedPreparseData<Data>* parent)
521cb0ef41Sopenharmony_ci          : ReadingScope(parent->scope_data_.get(), parent->GetScopeData()) {}
531cb0ef41Sopenharmony_ci      ~ReadingScope() {
541cb0ef41Sopenharmony_ci#ifdef DEBUG
551cb0ef41Sopenharmony_ci        consumed_data_->has_data_ = false;
561cb0ef41Sopenharmony_ci#endif
571cb0ef41Sopenharmony_ci      }
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci     private:
601cb0ef41Sopenharmony_ci      ByteData* consumed_data_;
611cb0ef41Sopenharmony_ci      DISALLOW_GARBAGE_COLLECTION(no_gc)
621cb0ef41Sopenharmony_ci    };
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci    void SetPosition(int position) {
651cb0ef41Sopenharmony_ci      DCHECK_LE(position, data_.data_length());
661cb0ef41Sopenharmony_ci      index_ = position;
671cb0ef41Sopenharmony_ci    }
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ci    size_t RemainingBytes() const {
701cb0ef41Sopenharmony_ci      DCHECK(has_data_);
711cb0ef41Sopenharmony_ci      DCHECK_LE(index_, data_.data_length());
721cb0ef41Sopenharmony_ci      return data_.data_length() - index_;
731cb0ef41Sopenharmony_ci    }
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci    bool HasRemainingBytes(size_t bytes) const {
761cb0ef41Sopenharmony_ci      DCHECK(has_data_);
771cb0ef41Sopenharmony_ci      return index_ <= data_.data_length() && bytes <= RemainingBytes();
781cb0ef41Sopenharmony_ci    }
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci    int32_t ReadUint32() {
811cb0ef41Sopenharmony_ci      DCHECK(has_data_);
821cb0ef41Sopenharmony_ci      DCHECK(HasRemainingBytes(kUint32Size));
831cb0ef41Sopenharmony_ci      // Check that there indeed is an integer following.
841cb0ef41Sopenharmony_ci      DCHECK_EQ(data_.get(index_++), kUint32Size);
851cb0ef41Sopenharmony_ci      int32_t result = data_.get(index_) + (data_.get(index_ + 1) << 8) +
861cb0ef41Sopenharmony_ci                       (data_.get(index_ + 2) << 16) +
871cb0ef41Sopenharmony_ci                       (data_.get(index_ + 3) << 24);
881cb0ef41Sopenharmony_ci      index_ += 4;
891cb0ef41Sopenharmony_ci      stored_quarters_ = 0;
901cb0ef41Sopenharmony_ci      return result;
911cb0ef41Sopenharmony_ci    }
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci    int32_t ReadVarint32() {
941cb0ef41Sopenharmony_ci      DCHECK(HasRemainingBytes(kVarint32MinSize));
951cb0ef41Sopenharmony_ci      DCHECK_EQ(data_.get(index_++), kVarint32MinSize);
961cb0ef41Sopenharmony_ci      int32_t value = 0;
971cb0ef41Sopenharmony_ci      bool has_another_byte;
981cb0ef41Sopenharmony_ci      unsigned shift = 0;
991cb0ef41Sopenharmony_ci      do {
1001cb0ef41Sopenharmony_ci        uint8_t byte = data_.get(index_++);
1011cb0ef41Sopenharmony_ci        value |= static_cast<int32_t>(byte & 0x7F) << shift;
1021cb0ef41Sopenharmony_ci        shift += 7;
1031cb0ef41Sopenharmony_ci        has_another_byte = byte & 0x80;
1041cb0ef41Sopenharmony_ci      } while (has_another_byte);
1051cb0ef41Sopenharmony_ci      DCHECK_EQ(data_.get(index_++), kVarint32EndMarker);
1061cb0ef41Sopenharmony_ci      stored_quarters_ = 0;
1071cb0ef41Sopenharmony_ci      return value;
1081cb0ef41Sopenharmony_ci    }
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ci    uint8_t ReadUint8() {
1111cb0ef41Sopenharmony_ci      DCHECK(has_data_);
1121cb0ef41Sopenharmony_ci      DCHECK(HasRemainingBytes(kUint8Size));
1131cb0ef41Sopenharmony_ci      // Check that there indeed is a byte following.
1141cb0ef41Sopenharmony_ci      DCHECK_EQ(data_.get(index_++), kUint8Size);
1151cb0ef41Sopenharmony_ci      stored_quarters_ = 0;
1161cb0ef41Sopenharmony_ci      return data_.get(index_++);
1171cb0ef41Sopenharmony_ci    }
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ci    uint8_t ReadQuarter() {
1201cb0ef41Sopenharmony_ci      DCHECK(has_data_);
1211cb0ef41Sopenharmony_ci      if (stored_quarters_ == 0) {
1221cb0ef41Sopenharmony_ci        DCHECK(HasRemainingBytes(kUint8Size));
1231cb0ef41Sopenharmony_ci        // Check that there indeed are quarters following.
1241cb0ef41Sopenharmony_ci        DCHECK_EQ(data_.get(index_++), kQuarterMarker);
1251cb0ef41Sopenharmony_ci        stored_byte_ = data_.get(index_++);
1261cb0ef41Sopenharmony_ci        stored_quarters_ = 4;
1271cb0ef41Sopenharmony_ci      }
1281cb0ef41Sopenharmony_ci      // Read the first 2 bits from stored_byte_.
1291cb0ef41Sopenharmony_ci      uint8_t result = (stored_byte_ >> 6) & 3;
1301cb0ef41Sopenharmony_ci      DCHECK_LE(result, 3);
1311cb0ef41Sopenharmony_ci      --stored_quarters_;
1321cb0ef41Sopenharmony_ci      stored_byte_ <<= 2;
1331cb0ef41Sopenharmony_ci      return result;
1341cb0ef41Sopenharmony_ci    }
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_ci   private:
1371cb0ef41Sopenharmony_ci    Data data_ = {};
1381cb0ef41Sopenharmony_ci    int index_ = 0;
1391cb0ef41Sopenharmony_ci    uint8_t stored_quarters_ = 0;
1401cb0ef41Sopenharmony_ci    uint8_t stored_byte_ = 0;
1411cb0ef41Sopenharmony_ci#ifdef DEBUG
1421cb0ef41Sopenharmony_ci    bool has_data_ = false;
1431cb0ef41Sopenharmony_ci#endif
1441cb0ef41Sopenharmony_ci  };
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci  BaseConsumedPreparseData() : scope_data_(new ByteData()), child_index_(0) {}
1471cb0ef41Sopenharmony_ci  BaseConsumedPreparseData(const BaseConsumedPreparseData&) = delete;
1481cb0ef41Sopenharmony_ci  BaseConsumedPreparseData& operator=(const BaseConsumedPreparseData&) = delete;
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci  virtual Data GetScopeData() = 0;
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_ci  virtual ProducedPreparseData* GetChildData(Zone* zone, int child_index) = 0;
1531cb0ef41Sopenharmony_ci
1541cb0ef41Sopenharmony_ci  ProducedPreparseData* GetDataForSkippableFunction(
1551cb0ef41Sopenharmony_ci      Zone* zone, int start_position, int* end_position, int* num_parameters,
1561cb0ef41Sopenharmony_ci      int* function_length, int* num_inner_functions, bool* uses_super_property,
1571cb0ef41Sopenharmony_ci      LanguageMode* language_mode) final;
1581cb0ef41Sopenharmony_ci
1591cb0ef41Sopenharmony_ci  void RestoreScopeAllocationData(DeclarationScope* scope,
1601cb0ef41Sopenharmony_ci                                  AstValueFactory* ast_value_factory,
1611cb0ef41Sopenharmony_ci                                  Zone* zone) final;
1621cb0ef41Sopenharmony_ci
1631cb0ef41Sopenharmony_ci#ifdef DEBUG
1641cb0ef41Sopenharmony_ci  bool VerifyDataStart();
1651cb0ef41Sopenharmony_ci#endif
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_ci private:
1681cb0ef41Sopenharmony_ci  void RestoreDataForScope(Scope* scope, AstValueFactory* ast_value_factory,
1691cb0ef41Sopenharmony_ci                           Zone* zone);
1701cb0ef41Sopenharmony_ci  void RestoreDataForVariable(Variable* var);
1711cb0ef41Sopenharmony_ci  void RestoreDataForInnerScopes(Scope* scope,
1721cb0ef41Sopenharmony_ci                                 AstValueFactory* ast_value_factory,
1731cb0ef41Sopenharmony_ci                                 Zone* zone);
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_ci  std::unique_ptr<ByteData> scope_data_;
1761cb0ef41Sopenharmony_ci  // When consuming the data, these indexes point to the data we're going to
1771cb0ef41Sopenharmony_ci  // consume next.
1781cb0ef41Sopenharmony_ci  int child_index_;
1791cb0ef41Sopenharmony_ci};
1801cb0ef41Sopenharmony_ci
1811cb0ef41Sopenharmony_ci// Implementation of ConsumedPreparseData for on-heap data.
1821cb0ef41Sopenharmony_ciclass OnHeapConsumedPreparseData final
1831cb0ef41Sopenharmony_ci    : public BaseConsumedPreparseData<PreparseData> {
1841cb0ef41Sopenharmony_ci public:
1851cb0ef41Sopenharmony_ci  OnHeapConsumedPreparseData(LocalIsolate* isolate, Handle<PreparseData> data);
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci  PreparseData GetScopeData() final;
1881cb0ef41Sopenharmony_ci  ProducedPreparseData* GetChildData(Zone* zone, int child_index) final;
1891cb0ef41Sopenharmony_ci
1901cb0ef41Sopenharmony_ci private:
1911cb0ef41Sopenharmony_ci  LocalIsolate* isolate_;
1921cb0ef41Sopenharmony_ci  Handle<PreparseData> data_;
1931cb0ef41Sopenharmony_ci};
1941cb0ef41Sopenharmony_ci
1951cb0ef41Sopenharmony_ci// A serialized PreparseData in zone memory (as apposed to being on-heap).
1961cb0ef41Sopenharmony_ciclass ZonePreparseData : public ZoneObject {
1971cb0ef41Sopenharmony_ci public:
1981cb0ef41Sopenharmony_ci  V8_EXPORT_PRIVATE ZonePreparseData(Zone* zone,
1991cb0ef41Sopenharmony_ci                                     base::Vector<uint8_t>* byte_data,
2001cb0ef41Sopenharmony_ci                                     int child_length);
2011cb0ef41Sopenharmony_ci
2021cb0ef41Sopenharmony_ci  ZonePreparseData(const ZonePreparseData&) = delete;
2031cb0ef41Sopenharmony_ci  ZonePreparseData& operator=(const ZonePreparseData&) = delete;
2041cb0ef41Sopenharmony_ci
2051cb0ef41Sopenharmony_ci  Handle<PreparseData> Serialize(Isolate* isolate);
2061cb0ef41Sopenharmony_ci  Handle<PreparseData> Serialize(LocalIsolate* isolate);
2071cb0ef41Sopenharmony_ci
2081cb0ef41Sopenharmony_ci  int children_length() const { return static_cast<int>(children_.size()); }
2091cb0ef41Sopenharmony_ci
2101cb0ef41Sopenharmony_ci  ZonePreparseData* get_child(int index) { return children_[index]; }
2111cb0ef41Sopenharmony_ci
2121cb0ef41Sopenharmony_ci  void set_child(int index, ZonePreparseData* child) {
2131cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(child);
2141cb0ef41Sopenharmony_ci    children_[index] = child;
2151cb0ef41Sopenharmony_ci  }
2161cb0ef41Sopenharmony_ci
2171cb0ef41Sopenharmony_ci  ZoneVector<uint8_t>* byte_data() { return &byte_data_; }
2181cb0ef41Sopenharmony_ci
2191cb0ef41Sopenharmony_ci private:
2201cb0ef41Sopenharmony_ci  ZoneVector<uint8_t> byte_data_;
2211cb0ef41Sopenharmony_ci  ZoneVector<ZonePreparseData*> children_;
2221cb0ef41Sopenharmony_ci};
2231cb0ef41Sopenharmony_ci
2241cb0ef41Sopenharmony_ciZonePreparseData* PreparseDataBuilder::ByteData::CopyToZone(
2251cb0ef41Sopenharmony_ci    Zone* zone, int children_length) {
2261cb0ef41Sopenharmony_ci  DCHECK(is_finalized_);
2271cb0ef41Sopenharmony_ci  return zone->New<ZonePreparseData>(zone, &zone_byte_data_, children_length);
2281cb0ef41Sopenharmony_ci}
2291cb0ef41Sopenharmony_ci
2301cb0ef41Sopenharmony_ci// Implementation of ConsumedPreparseData for PreparseData
2311cb0ef41Sopenharmony_ci// serialized into zone memory.
2321cb0ef41Sopenharmony_ciclass ZoneConsumedPreparseData final
2331cb0ef41Sopenharmony_ci    : public BaseConsumedPreparseData<ZoneVectorWrapper> {
2341cb0ef41Sopenharmony_ci public:
2351cb0ef41Sopenharmony_ci  ZoneConsumedPreparseData(Zone* zone, ZonePreparseData* data);
2361cb0ef41Sopenharmony_ci
2371cb0ef41Sopenharmony_ci  ZoneVectorWrapper GetScopeData() final;
2381cb0ef41Sopenharmony_ci  ProducedPreparseData* GetChildData(Zone* zone, int child_index) final;
2391cb0ef41Sopenharmony_ci
2401cb0ef41Sopenharmony_ci private:
2411cb0ef41Sopenharmony_ci  ZonePreparseData* data_;
2421cb0ef41Sopenharmony_ci  ZoneVectorWrapper scope_data_wrapper_;
2431cb0ef41Sopenharmony_ci};
2441cb0ef41Sopenharmony_ci
2451cb0ef41Sopenharmony_ci}  // namespace internal
2461cb0ef41Sopenharmony_ci}  // namespace v8
2471cb0ef41Sopenharmony_ci
2481cb0ef41Sopenharmony_ci#endif  // V8_PARSING_PREPARSE_DATA_IMPL_H_
249