// Copyright 2016 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_SOURCE_POSITION_TABLE_H_
#define V8_SOURCE_POSITION_TABLE_H_

#include "src/assert-scope.h"
#include "src/checks.h"
#include "src/globals.h"
#include "src/source-position.h"
#include "src/zone/zone-containers.h"

namespace v8 {
namespace internal {

class AbstractCode;
class BytecodeArray;
class ByteArray;
template <typename T>
class Handle;
class Isolate;
class Zone;

struct PositionTableEntry {
  PositionTableEntry()
      : code_offset(0), source_position(0), is_statement(false) {}
  PositionTableEntry(int offset, int64_t source, bool statement)
      : code_offset(offset), source_position(source), is_statement(statement) {}

  int code_offset;
  int64_t source_position;
  bool is_statement;
};

class V8_EXPORT_PRIVATE SourcePositionTableBuilder {
 public:
  enum RecordingMode { OMIT_SOURCE_POSITIONS, RECORD_SOURCE_POSITIONS };

  SourcePositionTableBuilder(Zone* zone,
                             RecordingMode mode = RECORD_SOURCE_POSITIONS);

  void AddPosition(size_t code_offset, SourcePosition source_position,
                   bool is_statement);

  Handle<ByteArray> ToSourcePositionTable(Isolate* isolate,
                                          Handle<AbstractCode> code);

 private:
  void AddEntry(const PositionTableEntry& entry);

  inline bool Omit() const { return mode_ == OMIT_SOURCE_POSITIONS; }

  RecordingMode mode_;
  ZoneVector<byte> bytes_;
#ifdef ENABLE_SLOW_DCHECKS
  ZoneVector<PositionTableEntry> raw_entries_;
#endif
  PositionTableEntry previous_;  // Previously written entry, to compute delta.
};

class V8_EXPORT_PRIVATE SourcePositionTableIterator {
 public:
  // Used for saving/restoring the iterator.
  struct IndexAndPosition {
    int index_;
    PositionTableEntry position_;
  };

  // We expose two flavours of the iterator, depending on the argument passed
  // to the constructor:

  // Handlified iterator allows allocation, but it needs a handle (and thus
  // a handle scope). This is the preferred version.
  explicit SourcePositionTableIterator(Handle<ByteArray> byte_array);

  // Non-handlified iterator does not need a handle scope, but it disallows
  // allocation during its lifetime. This is useful if there is no handle
  // scope around.
  explicit SourcePositionTableIterator(ByteArray* byte_array);

  void Advance();

  int code_offset() const {
    DCHECK(!done());
    return current_.code_offset;
  }
  SourcePosition source_position() const {
    DCHECK(!done());
    return SourcePosition::FromRaw(current_.source_position);
  }
  bool is_statement() const {
    DCHECK(!done());
    return current_.is_statement;
  }
  bool done() const { return index_ == kDone; }

  IndexAndPosition GetState() const { return {index_, current_}; }

  void RestoreState(const IndexAndPosition& saved_state) {
    index_ = saved_state.index_;
    current_ = saved_state.position_;
  }

 private:
  static const int kDone = -1;

  ByteArray* raw_table_ = nullptr;
  Handle<ByteArray> table_;
  int index_ = 0;
  PositionTableEntry current_;
  DisallowHeapAllocation no_gc;
};

}  // namespace internal
}  // namespace v8

#endif  // V8_SOURCE_POSITION_TABLE_H_
