// 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_CODEGEN_SOURCE_POSITION_TABLE_H_
#define V8_CODEGEN_SOURCE_POSITION_TABLE_H_

#include "src/base/export-template.h"
#include "src/codegen/source-position.h"
#include "src/common/assert-scope.h"
#include "src/common/checks.h"
#include "src/common/globals.h"
#include "src/utils/vector.h"
#include "src/zone/zone-containers.h"

namespace v8 {
namespace internal {

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

struct PositionTableEntry {
  PositionTableEntry()
      : code_offset(kFunctionEntryBytecodeOffset),
        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 {
    // Indicates that source positions are never to be generated. (Resulting in
    // an empty table).
    OMIT_SOURCE_POSITIONS,
    // Indicates that source positions are not currently required, but may be
    // generated later.
    LAZY_SOURCE_POSITIONS,
    // Indicates that source positions should be immediately generated.
    RECORD_SOURCE_POSITIONS
  };

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

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

  template <typename LocalIsolate>
  EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
  Handle<ByteArray> ToSourcePositionTable(LocalIsolate* isolate);
  OwnedVector<byte> ToSourcePositionTableVector();

  inline bool Omit() const { return mode_ != RECORD_SOURCE_POSITIONS; }
  inline bool Lazy() const { return mode_ == LAZY_SOURCE_POSITIONS; }

 private:
  void AddEntry(const PositionTableEntry& entry);

  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:
  // Filter that applies when advancing the iterator. If the filter isn't
  // satisfied, we advance the iterator again.
  enum IterationFilter { kJavaScriptOnly = 0, kExternalOnly = 1, kAll = 2 };
  // Filter that applies only to the first entry of the source position table.
  // If it is kSkipFunctionEntry, it will skip the FunctionEntry entry if it
  // exists.
  enum FunctionEntryFilter {
    kSkipFunctionEntry = 0,
    kDontSkipFunctionEntry = 1
  };

  // Used for saving/restoring the iterator.
  struct IndexAndPositionState {
    int index_;
    PositionTableEntry position_;
    IterationFilter iteration_filter_;
    FunctionEntryFilter function_entry_filter_;
  };

  // We expose three 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,
      IterationFilter iteration_filter = kJavaScriptOnly,
      FunctionEntryFilter function_entry_filter = kSkipFunctionEntry);

  // 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, IterationFilter iteration_filter = kJavaScriptOnly,
      FunctionEntryFilter function_entry_filter = kSkipFunctionEntry);

  // Handle-safe iterator based on an a vector located outside the garbage
  // collected heap, allows allocation during its lifetime.
  explicit SourcePositionTableIterator(
      Vector<const byte> bytes,
      IterationFilter iteration_filter = kJavaScriptOnly,
      FunctionEntryFilter function_entry_filter = kSkipFunctionEntry);

  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; }

  IndexAndPositionState GetState() const {
    return {index_, current_, iteration_filter_, function_entry_filter_};
  }

  void RestoreState(const IndexAndPositionState& saved_state) {
    index_ = saved_state.index_;
    current_ = saved_state.position_;
    iteration_filter_ = saved_state.iteration_filter_;
    function_entry_filter_ = saved_state.function_entry_filter_;
  }

 private:
  // Initializes the source position interator with the first valid bytecode.
  // Also sets the FunctionEntry SourcePosition if it exists.
  void Initialize();

  static const int kDone = -1;

  Vector<const byte> raw_table_;
  Handle<ByteArray> table_;
  int index_ = 0;
  PositionTableEntry current_;
  IterationFilter iteration_filter_;
  FunctionEntryFilter function_entry_filter_;
  DISALLOW_HEAP_ALLOCATION(no_gc)
};

}  // namespace internal
}  // namespace v8

#endif  // V8_CODEGEN_SOURCE_POSITION_TABLE_H_
