// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_PARSING_PREPARSE_DATA_IMPL_H_
#define V8_PARSING_PREPARSE_DATA_IMPL_H_

#include "src/parsing/preparse-data.h"

#include "src/common/assert-scope.h"

namespace v8 {
namespace internal {

// Classes which are internal to prepared-scope-data.cc, but are exposed in
// a header for tests.

// Wraps a ZoneVector<uint8_t> to have with functions named the same as
// PodArray<uint8_t>.
class ZoneVectorWrapper {
 public:
  ZoneVectorWrapper() = default;
  explicit ZoneVectorWrapper(ZoneVector<uint8_t>* data) : data_(data) {}

  int data_length() const { return static_cast<int>(data_->size()); }

  uint8_t get(int index) const { return data_->at(index); }

 private:
  ZoneVector<uint8_t>* data_ = nullptr;
};

template <class Data>
class BaseConsumedPreparseData : public ConsumedPreparseData {
 public:
  class ByteData : public PreparseByteDataConstants {
   public:
    ByteData() {}

    // Reading from the ByteData is only allowed when a ReadingScope is on the
    // stack. This ensures that we have a DisallowHeapAllocation in place
    // whenever ByteData holds a raw pointer into the heap.
    class ReadingScope {
     public:
      ReadingScope(ByteData* consumed_data, Data data)
          : consumed_data_(consumed_data) {
        consumed_data->data_ = data;
#ifdef DEBUG
        consumed_data->has_data_ = true;
#endif
      }
      explicit ReadingScope(BaseConsumedPreparseData<Data>* parent)
          : ReadingScope(parent->scope_data_.get(), parent->GetScopeData()) {}
      ~ReadingScope() {
#ifdef DEBUG
        consumed_data_->has_data_ = false;
#endif
      }

     private:
      ByteData* consumed_data_;
      DISALLOW_HEAP_ALLOCATION(no_gc)
    };

    void SetPosition(int position) {
      DCHECK_LE(position, data_.data_length());
      index_ = position;
    }

    size_t RemainingBytes() const {
      DCHECK(has_data_);
      DCHECK_LE(index_, data_.data_length());
      return data_.data_length() - index_;
    }

    bool HasRemainingBytes(size_t bytes) const {
      DCHECK(has_data_);
      return index_ <= data_.data_length() && bytes <= RemainingBytes();
    }

    int32_t ReadUint32() {
      DCHECK(has_data_);
      DCHECK(HasRemainingBytes(kUint32Size));
      // Check that there indeed is an integer following.
      DCHECK_EQ(data_.get(index_++), kUint32Size);
      int32_t result = data_.get(index_) + (data_.get(index_ + 1) << 8) +
                       (data_.get(index_ + 2) << 16) +
                       (data_.get(index_ + 3) << 24);
      index_ += 4;
      stored_quarters_ = 0;
      return result;
    }

    int32_t ReadVarint32() {
      DCHECK(HasRemainingBytes(kVarint32MinSize));
      DCHECK_EQ(data_.get(index_++), kVarint32MinSize);
      int32_t value = 0;
      bool has_another_byte;
      unsigned shift = 0;
      do {
        uint8_t byte = data_.get(index_++);
        value |= static_cast<int32_t>(byte & 0x7F) << shift;
        shift += 7;
        has_another_byte = byte & 0x80;
      } while (has_another_byte);
      DCHECK_EQ(data_.get(index_++), kVarint32EndMarker);
      stored_quarters_ = 0;
      return value;
    }

    uint8_t ReadUint8() {
      DCHECK(has_data_);
      DCHECK(HasRemainingBytes(kUint8Size));
      // Check that there indeed is a byte following.
      DCHECK_EQ(data_.get(index_++), kUint8Size);
      stored_quarters_ = 0;
      return data_.get(index_++);
    }

    uint8_t ReadQuarter() {
      DCHECK(has_data_);
      if (stored_quarters_ == 0) {
        DCHECK(HasRemainingBytes(kUint8Size));
        // Check that there indeed are quarters following.
        DCHECK_EQ(data_.get(index_++), kQuarterMarker);
        stored_byte_ = data_.get(index_++);
        stored_quarters_ = 4;
      }
      // Read the first 2 bits from stored_byte_.
      uint8_t result = (stored_byte_ >> 6) & 3;
      DCHECK_LE(result, 3);
      --stored_quarters_;
      stored_byte_ <<= 2;
      return result;
    }

   private:
    Data data_ = {};
    int index_ = 0;
    uint8_t stored_quarters_ = 0;
    uint8_t stored_byte_ = 0;
#ifdef DEBUG
    bool has_data_ = false;
#endif
  };

  BaseConsumedPreparseData() : scope_data_(new ByteData()), child_index_(0) {}

  virtual Data GetScopeData() = 0;

  virtual ProducedPreparseData* GetChildData(Zone* zone, int child_index) = 0;

  ProducedPreparseData* GetDataForSkippableFunction(
      Zone* zone, int start_position, int* end_position, int* num_parameters,
      int* function_length, int* num_inner_functions, bool* uses_super_property,
      LanguageMode* language_mode) final;

  void RestoreScopeAllocationData(DeclarationScope* scope) final;

#ifdef DEBUG
  bool VerifyDataStart();
#endif

 private:
  void RestoreDataForScope(Scope* scope);
  void RestoreDataForVariable(Variable* var);
  void RestoreDataForInnerScopes(Scope* scope);

  std::unique_ptr<ByteData> scope_data_;
  // When consuming the data, these indexes point to the data we're going to
  // consume next.
  int child_index_;

  DISALLOW_COPY_AND_ASSIGN(BaseConsumedPreparseData);
};

// Implementation of ConsumedPreparseData for on-heap data.
class OnHeapConsumedPreparseData final
    : public BaseConsumedPreparseData<PreparseData> {
 public:
  OnHeapConsumedPreparseData(Isolate* isolate, Handle<PreparseData> data);

  PreparseData GetScopeData() final;
  ProducedPreparseData* GetChildData(Zone* zone, int child_index) final;

 private:
  Isolate* isolate_;
  Handle<PreparseData> data_;
};

// A serialized PreparseData in zone memory (as apposed to being on-heap).
class ZonePreparseData : public ZoneObject {
 public:
  V8_EXPORT_PRIVATE ZonePreparseData(Zone* zone, Vector<uint8_t>* byte_data,
                                     int child_length);

  Handle<PreparseData> Serialize(Isolate* isolate);

  int children_length() const { return static_cast<int>(children_.size()); }

  ZonePreparseData* get_child(int index) { return children_[index]; }

  void set_child(int index, ZonePreparseData* child) {
    DCHECK_NOT_NULL(child);
    children_[index] = child;
  }

  ZoneVector<uint8_t>* byte_data() { return &byte_data_; }

 private:
  ZoneVector<uint8_t> byte_data_;
  ZoneVector<ZonePreparseData*> children_;

  DISALLOW_COPY_AND_ASSIGN(ZonePreparseData);
};

ZonePreparseData* PreparseDataBuilder::ByteData::CopyToZone(
    Zone* zone, int children_length) {
  DCHECK(is_finalized_);
  return new (zone) ZonePreparseData(zone, &zone_byte_data_, children_length);
}

// Implementation of ConsumedPreparseData for PreparseData
// serialized into zone memory.
class ZoneConsumedPreparseData final
    : public BaseConsumedPreparseData<ZoneVectorWrapper> {
 public:
  ZoneConsumedPreparseData(Zone* zone, ZonePreparseData* data);

  ZoneVectorWrapper GetScopeData() final;
  ProducedPreparseData* GetChildData(Zone* zone, int child_index) final;

 private:
  ZonePreparseData* data_;
  ZoneVectorWrapper scope_data_wrapper_;
};

}  // namespace internal
}  // namespace v8

#endif  // V8_PARSING_PREPARSE_DATA_IMPL_H_
