// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#ifndef RUNTIME_VM_CODE_DESCRIPTORS_H_
#define RUNTIME_VM_CODE_DESCRIPTORS_H_

#include "vm/datastream.h"
#include "vm/globals.h"
#include "vm/growable_array.h"
#include "vm/log.h"
#include "vm/runtime_entry.h"
#include "vm/token_position.h"

namespace dart {

static constexpr intptr_t kInvalidTryIndex = -1;

class DescriptorList : public ZoneAllocated {
 public:
  explicit DescriptorList(
      Zone* zone,
      const GrowableArray<const Function*>* inline_id_to_function = nullptr);

  ~DescriptorList() {}

  void AddDescriptor(UntaggedPcDescriptors::Kind kind,
                     intptr_t pc_offset,
                     intptr_t deopt_id,
                     TokenPosition token_pos,
                     intptr_t try_index,
                     intptr_t yield_index);

  PcDescriptorsPtr FinalizePcDescriptors(uword entry_point);

 private:
  static constexpr intptr_t kInitialStreamSize = 64;

  const Function& function_;
  const Script& script_;
  ZoneWriteStream encoded_data_;

  intptr_t prev_pc_offset;
  intptr_t prev_deopt_id;
  int32_t prev_token_pos;

  DISALLOW_COPY_AND_ASSIGN(DescriptorList);
};

class CompressedStackMapsBuilder : public ZoneAllocated {
 public:
  explicit CompressedStackMapsBuilder(Zone* zone)
      : encoded_bytes_(zone, kInitialStreamSize) {}

  void AddEntry(intptr_t pc_offset,
                BitmapBuilder* bitmap,
                intptr_t spill_slot_bit_count);

  CompressedStackMapsPtr Finalize() const;

 private:
  static constexpr intptr_t kInitialStreamSize = 16;

  ZoneWriteStream encoded_bytes_;
  intptr_t last_pc_offset_ = 0;
  DISALLOW_COPY_AND_ASSIGN(CompressedStackMapsBuilder);
};

class ExceptionHandlerList : public ZoneAllocated {
 public:
  struct HandlerDesc {
    intptr_t outer_try_index;    // Try block in which this try block is nested.
    intptr_t pc_offset;          // Handler PC offset value.
    bool is_generated;           // False if this is directly from Dart code.
    const Array* handler_types;  // Catch clause guards.
    bool needs_stacktrace;
  };

  explicit ExceptionHandlerList(const Function& function)
      : list_(),
        has_async_handler_(
            (function.IsAsyncFunction() || function.IsAsyncGenerator()) &&
            !function.is_declared_in_bytecode()) {}

  intptr_t Length() const { return list_.length(); }

  void AddPlaceHolder() {
    struct HandlerDesc data;
    data.outer_try_index = -1;
    data.pc_offset = ExceptionHandlers::kInvalidPcOffset;
    data.is_generated = true;
    data.handler_types = nullptr;
    data.needs_stacktrace = false;
    list_.Add(data);
  }

  void AddHandler(intptr_t try_index,
                  intptr_t outer_try_index,
                  intptr_t pc_offset,
                  bool is_generated,
                  const Array& handler_types,
                  bool needs_stacktrace) {
    ASSERT(try_index >= 0);
    while (Length() <= try_index) {
      AddPlaceHolder();
    }
    list_[try_index].outer_try_index = outer_try_index;
    ASSERT(list_[try_index].pc_offset == ExceptionHandlers::kInvalidPcOffset);
    list_[try_index].pc_offset = pc_offset;
    list_[try_index].is_generated = is_generated;
    DEBUG_ASSERT(handler_types.IsNotTemporaryScopedHandle());
    list_[try_index].handler_types = &handler_types;
    list_[try_index].needs_stacktrace |= needs_stacktrace;
  }

  // Called by rethrows, to mark their enclosing handlers.
  void SetNeedsStackTrace(intptr_t try_index) {
    // Rethrows can be generated outside a try by the compiler.
    if (try_index == kInvalidTryIndex) {
      return;
    }
    ASSERT(try_index >= 0);
    while (Length() <= try_index) {
      AddPlaceHolder();
    }
    list_[try_index].needs_stacktrace = true;
  }

  static bool ContainsCatchAllType(const Array& array) {
    auto& type = AbstractType::Handle();
    for (intptr_t i = 0; i < array.Length(); i++) {
      type ^= array.At(i);
      if (type.IsCatchAllType()) {
        return true;
      }
    }
    return false;
  }

  ExceptionHandlersPtr FinalizeExceptionHandlers(uword entry_point) const;

 private:
  GrowableArray<struct HandlerDesc> list_;
  const bool has_async_handler_;
  DISALLOW_COPY_AND_ASSIGN(ExceptionHandlerList);
};

#if !defined(DART_PRECOMPILED_RUNTIME)
// Used to construct CatchEntryMoves for the AOT mode of compilation.
class CatchEntryMovesMapBuilder : public ZoneAllocated {
 public:
  CatchEntryMovesMapBuilder();

  void NewMapping(intptr_t pc_offset);
  void Append(const CatchEntryMove& move);
  void EndMapping();
  TypedDataPtr FinalizeCatchEntryMovesMap();

 private:
  class TrieNode;

  Zone* zone_;
  TrieNode* root_;
  intptr_t current_pc_offset_;
  GrowableArray<CatchEntryMove> moves_;
  ZoneWriteStream stream_;

  DISALLOW_COPY_AND_ASSIGN(CatchEntryMovesMapBuilder);
};
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

// Instructions have two pieces of information needed to get accurate source
// locations: the token position and the inlining id. The inlining id tells us
// which function, and thus which script, to use for this instruction and the
// token position, when real, tells us the position in the source for the
// script for the instruction.
//
// Thus, we bundle the two pieces of information in InstructionSource structs
// when copying or retrieving to lower the likelihood that the token position
// is used without the appropriate inlining id.
struct InstructionSource {
  // Treat an instruction source without inlining id information as unset.
  InstructionSource() : InstructionSource(TokenPosition::kNoSource) {}
  explicit InstructionSource(TokenPosition pos) : InstructionSource(pos, -1) {}
  InstructionSource(TokenPosition pos, intptr_t inlining_id)
      : token_pos(pos), inlining_id(inlining_id) {}

  const TokenPosition token_pos;
  const intptr_t inlining_id;

  DISALLOW_ALLOCATION();
};

struct CodeSourceMapOps : AllStatic {
  static constexpr uint8_t kChangePosition = 0;
  static constexpr uint8_t kAdvancePC = 1;
  static constexpr uint8_t kPushFunction = 2;
  static constexpr uint8_t kPopFunction = 3;
  static constexpr uint8_t kNullCheck = 4;

  static uint8_t Read(ReadStream* stream,
                      int32_t* arg1,
                      int32_t* arg2 = nullptr);

  static void Write(BaseWriteStream* stream,
                    uint8_t op,
                    int32_t arg1 = 0,
                    int32_t arg2 = 0);

 private:
  static constexpr intptr_t kOpBits = 3;

  using OpField = BitField<int32_t, uint8_t, 0, kOpBits>;
  using ArgField = BitField<int32_t, int32_t, OpField::kNextBit>;

  static constexpr int32_t kMaxArgValue =
      Utils::NBitMask<int32_t>(ArgField::bitsize() - 1);
  static constexpr int32_t kMinArgValue = ~kMaxArgValue;
  static constexpr int32_t kSignBits = static_cast<uint32_t>(kMinArgValue) << 1;
};

// A CodeSourceMap maps from pc offsets to a stack of inlined functions and
// their positions. This is encoded as a little bytecode that pushes and pops
// functions and changes the top function's position as the PC advances.
// Decoding happens by running this bytecode until we reach the desired PC.
//
// The implementation keeps track of two sets of state: one written to the byte
// stream and one that is buffered. On the JIT, this buffering effectively gives
// us a peephole optimization that merges adjacent advance PC bytecodes. On AOT,
// this allows to skip encoding our position until we reach a PC where we might
// throw.
class CodeSourceMapBuilder : public ZoneAllocated {
 public:
  CodeSourceMapBuilder(
      Zone* zone,
      bool stack_traces_only,
      const GrowableArray<intptr_t>& caller_inline_id,
      const GrowableArray<TokenPosition>& inline_id_to_token_pos,
      const GrowableArray<const Function*>& inline_id_to_function);

  // The position at which a function implicitly starts, for both the root and
  // after a push bytecode. We use the classifying position kDartCodePrologue
  // since it is the most common.
  static const TokenPosition& kInitialPosition;

  void BeginCodeSourceRange(int32_t pc_offset, const InstructionSource& source);
  void EndCodeSourceRange(int32_t pc_offset, const InstructionSource& source);
  void NoteDescriptor(UntaggedPcDescriptors::Kind kind,
                      int32_t pc_offset,
                      const InstructionSource& source);
  void NoteNullCheck(int32_t pc_offset,
                     const InstructionSource& source,
                     intptr_t name_index);
  void WriteFunctionEntrySourcePosition(const InstructionSource& source);

  // If source is from an inlined call, returns the token position of the
  // original call in the root function, otherwise the source's token position.
  TokenPosition RootPosition(const InstructionSource& source);
  ArrayPtr InliningIdToFunction();
  CodeSourceMapPtr Finalize();

  const GrowableArray<const Function*>& inline_id_to_function() const {
    return inline_id_to_function_;
  }

 private:
  intptr_t GetFunctionId(intptr_t inline_id);
  void StartInliningInterval(int32_t pc_offset,
                             const InstructionSource& source);

  void BufferChangePosition(TokenPosition pos);
  void WriteChangePosition(TokenPosition pos);
  void BufferAdvancePC(int32_t distance) { buffered_pc_offset_ += distance; }
  void WriteAdvancePC(int32_t distance) {
    CodeSourceMapOps::Write(&stream_, CodeSourceMapOps::kAdvancePC, distance);
    written_pc_offset_ += distance;
  }
  void BufferPush(intptr_t inline_id) {
    buffered_inline_id_stack_.Add(inline_id);
    buffered_token_pos_stack_.Add(kInitialPosition);
  }
  void WritePush(intptr_t inline_id) {
    CodeSourceMapOps::Write(&stream_, CodeSourceMapOps::kPushFunction,
                            GetFunctionId(inline_id));
    written_inline_id_stack_.Add(inline_id);
    written_token_pos_stack_.Add(kInitialPosition);
  }
  void BufferPop() {
    buffered_inline_id_stack_.RemoveLast();
    buffered_token_pos_stack_.RemoveLast();
  }
  void WritePop() {
    CodeSourceMapOps::Write(&stream_, CodeSourceMapOps::kPopFunction);
    written_inline_id_stack_.RemoveLast();
    written_token_pos_stack_.RemoveLast();
  }
  void WriteNullCheck(int32_t name_index) {
    CodeSourceMapOps::Write(&stream_, CodeSourceMapOps::kNullCheck, name_index);
  }

  void FlushBuffer();

  bool IsOnBufferedStack(intptr_t inline_id) {
    for (intptr_t i = 0; i < buffered_inline_id_stack_.length(); i++) {
      if (buffered_inline_id_stack_[i] == inline_id) return true;
    }
    return false;
  }

  Zone* const zone_;
  intptr_t buffered_pc_offset_;
  GrowableArray<intptr_t> buffered_inline_id_stack_;
  GrowableArray<TokenPosition> buffered_token_pos_stack_;

  intptr_t written_pc_offset_;
  GrowableArray<intptr_t> written_inline_id_stack_;
  GrowableArray<TokenPosition> written_token_pos_stack_;

  const GrowableArray<intptr_t>& caller_inline_id_;
  const GrowableArray<TokenPosition>& inline_id_to_token_pos_;
  const GrowableArray<const Function*>& inline_id_to_function_;

  const GrowableObjectArray& inlined_functions_;

  Script& script_;
  ZoneWriteStream stream_;

  const bool stack_traces_only_;

  DISALLOW_COPY_AND_ASSIGN(CodeSourceMapBuilder);
};

class CodeSourceMapReader : public ValueObject {
 public:
  CodeSourceMapReader(const CodeSourceMap& map,
                      const Array& functions,
                      const Function& root)
      : map_(map), functions_(functions), root_(root) {}

  void GetInlinedFunctionsAt(int32_t pc_offset,
                             GrowableArray<const Function*>* function_stack,
                             GrowableArray<TokenPosition>* token_positions);
  NOT_IN_PRODUCT(void PrintJSONInlineIntervals(JSONObject* jsobj));
  void DumpInlineIntervals(uword start);
  void DumpSourcePositions(uword start);

  intptr_t GetNullCheckNameIndexAt(int32_t pc_offset);

 private:
  static const TokenPosition& InitialPosition() {
    if (FLAG_precompiled_mode) {
      // In precompiled mode, the CodeSourceMap stores lines instead of
      // real token positions and uses kNoSourcePos for no line information.
      return TokenPosition::kNoSource;
    } else {
      return CodeSourceMapBuilder::kInitialPosition;
    }
  }

  // Reads a TokenPosition value from a CSM, handling the different encoding for
  // when non-symbolic stack traces are enabled.
  static TokenPosition ReadPosition(ReadStream* stream);

  const CodeSourceMap& map_;
  const Array& functions_;
  const Function& root_;

  DISALLOW_COPY_AND_ASSIGN(CodeSourceMapReader);
};

}  // namespace dart

#endif  // RUNTIME_VM_CODE_DESCRIPTORS_H_
