// 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.

#include "vm/code_descriptors.h"

#include "platform/utils.h"
#include "vm/compiler/api/deopt_id.h"
#include "vm/flags.h"
#include "vm/log.h"
#include "vm/object.h"
#include "vm/object_store.h"
#include "vm/zone_text_buffer.h"

namespace dart {

DescriptorList::DescriptorList(
    Zone* zone,
    const GrowableArray<const Function*>* inline_id_to_function)
    : function_(Function::Handle(
          zone,
          FLAG_check_token_positions && (inline_id_to_function != nullptr)
              ? inline_id_to_function->At(0)->ptr()
              : Function::null())),
      script_(Script::Handle(
          zone,
          function_.IsNull() ? Script::null() : function_.script())),
      encoded_data_(zone, kInitialStreamSize),
      prev_pc_offset(0),
      prev_deopt_id(0),
      prev_token_pos(0) {}

void DescriptorList::AddDescriptor(UntaggedPcDescriptors::Kind kind,
                                   intptr_t pc_offset,
                                   intptr_t deopt_id,
                                   const TokenPosition token_pos,
                                   intptr_t try_index,
                                   intptr_t yield_index) {
  // yield index 0 is reserved for normal entry.
  RELEASE_ASSERT(yield_index != 0);

  ASSERT((kind == UntaggedPcDescriptors::kRuntimeCall) ||
         (kind == UntaggedPcDescriptors::kBSSRelocation) ||
         (kind == UntaggedPcDescriptors::kOther) ||
         (yield_index != UntaggedPcDescriptors::kInvalidYieldIndex) ||
         (deopt_id != DeoptId::kNone));

  // When precompiling, we only use pc descriptors for exceptions,
  // relocations and yield indices.
  if (!FLAG_precompiled_mode || try_index != -1 ||
      yield_index != UntaggedPcDescriptors::kInvalidYieldIndex ||
      kind == UntaggedPcDescriptors::kBSSRelocation) {
    const int32_t kind_and_metadata =
        UntaggedPcDescriptors::KindAndMetadata::Encode(kind, try_index,
                                                       yield_index);

    encoded_data_.WriteSLEB128(kind_and_metadata);
    encoded_data_.WriteSLEB128(pc_offset - prev_pc_offset);
    prev_pc_offset = pc_offset;

    if (!FLAG_precompiled_mode) {
      if (FLAG_check_token_positions && token_pos.IsReal()) {
        if (!function_.IsNull() &&
            !token_pos.IsWithin(function_.token_pos(),
                                function_.end_token_pos())) {
          FATAL("Token position %s for PC descriptor %s at offset 0x%" Px
                " invalid for function %s (%s, %s)",
                token_pos.ToCString(),
                UntaggedPcDescriptors::KindToCString(kind), pc_offset,
                function_.ToFullyQualifiedCString(),
                function_.token_pos().ToCString(),
                function_.end_token_pos().ToCString());
        }
        if (!script_.IsNull() && !script_.IsValidTokenPosition(token_pos)) {
          FATAL("Token position %s for PC descriptor %s at offset 0x%" Px
                " invalid for script %s of function %s",
                token_pos.ToCString(),
                UntaggedPcDescriptors::KindToCString(kind), pc_offset,
                script_.ToCString(), function_.ToFullyQualifiedCString());
        }
      }
      const int32_t encoded_pos = token_pos.Serialize();
      encoded_data_.WriteSLEB128(deopt_id - prev_deopt_id);
      encoded_data_.WriteSLEB128(
          Utils::SubWithWrapAround(encoded_pos, prev_token_pos));
      prev_deopt_id = deopt_id;
      prev_token_pos = encoded_pos;
    }
  }
}

PcDescriptorsPtr DescriptorList::FinalizePcDescriptors(uword entry_point) {
  if (encoded_data_.bytes_written() == 0) {
    return Object::empty_descriptors().ptr();
  }
  return PcDescriptors::New(encoded_data_.buffer(),
                            encoded_data_.bytes_written());
}

void CompressedStackMapsBuilder::AddEntry(intptr_t pc_offset,
                                          BitmapBuilder* bitmap,
                                          intptr_t spill_slot_bit_count) {
  ASSERT(bitmap != nullptr);
  ASSERT(pc_offset > last_pc_offset_);
  ASSERT(spill_slot_bit_count >= 0 && spill_slot_bit_count <= bitmap->Length());
  const uword pc_delta = pc_offset - last_pc_offset_;
  const uword non_spill_slot_bit_count =
      bitmap->Length() - spill_slot_bit_count;
  encoded_bytes_.WriteLEB128(pc_delta);
  encoded_bytes_.WriteLEB128(spill_slot_bit_count);
  encoded_bytes_.WriteLEB128(non_spill_slot_bit_count);
  bitmap->AppendAsBytesTo(&encoded_bytes_);
  last_pc_offset_ = pc_offset;
}

CompressedStackMapsPtr CompressedStackMapsBuilder::Finalize() const {
  if (encoded_bytes_.bytes_written() == 0) {
    return Object::empty_compressed_stackmaps().ptr();
  }
  return CompressedStackMaps::NewInlined(encoded_bytes_.buffer(),
                                         encoded_bytes_.bytes_written());
}

ExceptionHandlersPtr ExceptionHandlerList::FinalizeExceptionHandlers(
    uword entry_point) const {
  intptr_t num_handlers = Length();
  if (num_handlers == 0) {
    return has_async_handler_ ? Object::empty_async_exception_handlers().ptr()
                              : Object::empty_exception_handlers().ptr();
  }
  const ExceptionHandlers& handlers =
      ExceptionHandlers::Handle(ExceptionHandlers::New(num_handlers));
  handlers.set_has_async_handler(has_async_handler_);
  for (intptr_t i = 0; i < num_handlers; i++) {
    // Assert that every element in the array has been initialized.
    if (list_[i].handler_types == nullptr) {
      // Unreachable handler, entry not computed.
      // Initialize it to some meaningful value.
      const bool has_catch_all = false;
      // Check it is uninitialized.
      ASSERT((list_[i].outer_try_index == -1) &&
             (list_[i].pc_offset == ExceptionHandlers::kInvalidPcOffset));
      handlers.SetHandlerInfo(i, list_[i].outer_try_index, list_[i].pc_offset,
                              list_[i].needs_stacktrace, has_catch_all,
                              list_[i].is_generated);
      handlers.SetHandledTypes(i, Array::empty_array());
    } else {
      const bool has_catch_all = ContainsCatchAllType(*list_[i].handler_types);
      handlers.SetHandlerInfo(i, list_[i].outer_try_index, list_[i].pc_offset,
                              list_[i].needs_stacktrace, has_catch_all,
                              list_[i].is_generated);
      handlers.SetHandledTypes(i, *list_[i].handler_types);
    }
  }
  return handlers.ptr();
}

#if !defined(DART_PRECOMPILED_RUNTIME)
class CatchEntryMovesMapBuilder::TrieNode : public ZoneAllocated {
 public:
  TrieNode() : move_(), entry_state_offset_(-1) {}
  TrieNode(CatchEntryMove move, intptr_t index)
      : move_(move), entry_state_offset_(index) {}

  intptr_t Offset() { return entry_state_offset_; }

  TrieNode* Insert(TrieNode* node) {
    children_.Add(node);
    return node;
  }

  TrieNode* Follow(CatchEntryMove next) {
    for (intptr_t i = 0; i < children_.length(); i++) {
      if (children_[i]->move_ == next) return children_[i];
    }
    return nullptr;
  }

 private:
  CatchEntryMove move_;
  const intptr_t entry_state_offset_;
  GrowableArray<TrieNode*> children_;
};

CatchEntryMovesMapBuilder::CatchEntryMovesMapBuilder()
    : zone_(Thread::Current()->zone()),
      root_(new TrieNode()),
      current_pc_offset_(0),
      stream_(zone_, 64) {}

void CatchEntryMovesMapBuilder::Append(const CatchEntryMove& move) {
  moves_.Add(move);
}

void CatchEntryMovesMapBuilder::NewMapping(intptr_t pc_offset) {
  moves_.Clear();
  current_pc_offset_ = pc_offset;
}

void CatchEntryMovesMapBuilder::EndMapping() {
  intptr_t suffix_length = 0;
  TrieNode* suffix = root_;
  // Find the largest common suffix, get the last node of the path.
  for (intptr_t i = moves_.length() - 1; i >= 0; i--) {
    TrieNode* n = suffix->Follow(moves_[i]);
    if (n == nullptr) break;
    suffix_length++;
    suffix = n;
  }
  intptr_t length = moves_.length() - suffix_length;
  intptr_t current_offset = stream_.bytes_written();

  typedef ZoneWriteStream::Raw<sizeof(intptr_t), intptr_t> Writer;
  Writer::Write(&stream_, current_pc_offset_);
  Writer::Write(&stream_, length);
  Writer::Write(&stream_, suffix_length);
  Writer::Write(&stream_, suffix->Offset());

  // Write the unshared part, adding it to the trie.
  TrieNode* node = suffix;
  for (intptr_t i = length - 1; i >= 0; i--) {
    moves_[i].WriteTo(&stream_);

    TrieNode* child = new (zone_) TrieNode(moves_[i], current_offset);
    node->Insert(child);
    node = child;
  }
}

TypedDataPtr CatchEntryMovesMapBuilder::FinalizeCatchEntryMovesMap() {
  TypedData& td = TypedData::Handle(TypedData::New(
      kTypedDataInt8ArrayCid, stream_.bytes_written(), Heap::kOld));
  NoSafepointScope no_safepoint;
  uint8_t* dest = reinterpret_cast<uint8_t*>(td.DataAddr(0));
  uint8_t* src = stream_.buffer();
  for (intptr_t i = 0; i < stream_.bytes_written(); i++) {
    dest[i] = src[i];
  }
  return td.ptr();
}
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

uint8_t CodeSourceMapOps::Read(ReadStream* stream,
                               int32_t* arg1,
                               int32_t* arg2) {
  ASSERT(stream != nullptr && arg1 != nullptr);
  const int32_t n = stream->Read<int32_t>();
  const uint8_t op = OpField::decode(n);
  *arg1 = ArgField::decode(n);
  if (*arg1 > kMaxArgValue) {
    *arg1 |= kSignBits;
  }
#if defined(DART_PRECOMPILER)
  // The special handling for non-symbolic stack trace mode only needs to
  // happen in the precompiler, because those CSMs are not serialized in
  // precompiled snapshots.
  if (op == kChangePosition && FLAG_dwarf_stack_traces_mode) {
    const int32_t m = stream->Read<int32_t>();
    if (arg2 != nullptr) {
      *arg2 = m;
    }
  }
#endif
  return op;
}

void CodeSourceMapOps::Write(BaseWriteStream* stream,
                             uint8_t op,
                             int32_t arg1,
                             int32_t arg2) {
  ASSERT(stream != nullptr);
  ASSERT(arg1 >= kMinArgValue && arg1 <= kMaxArgValue);
  if (arg1 < 0) {
    arg1 &= ~kSignBits;
  }
  const int32_t n = OpField::encode(op) | ArgField::encode(arg1);
  stream->Write(n);
#if defined(DART_PRECOMPILER)
  if (op == kChangePosition && FLAG_dwarf_stack_traces_mode) {
    // For non-symbolic stack traces, the CodeSourceMaps are not serialized,
    // so we need not worry about increasing snapshot size by including more
    // information here.
    stream->Write(arg2);
  }
#endif
}

const TokenPosition& CodeSourceMapBuilder::kInitialPosition =
    TokenPosition::kDartCodePrologue;

CodeSourceMapBuilder::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)
    : zone_(zone),
      buffered_pc_offset_(0),
      buffered_inline_id_stack_(),
      buffered_token_pos_stack_(),
      written_pc_offset_(0),
      written_inline_id_stack_(),
      written_token_pos_stack_(),
      caller_inline_id_(caller_inline_id),
      inline_id_to_token_pos_(inline_id_to_token_pos),
      inline_id_to_function_(inline_id_to_function),
      inlined_functions_(
          GrowableObjectArray::Handle(GrowableObjectArray::New(Heap::kOld))),
      script_(Script::Handle(zone, Script::null())),
      stream_(zone, 64),
      stack_traces_only_(stack_traces_only) {
  buffered_inline_id_stack_.Add(0);
  buffered_token_pos_stack_.Add(kInitialPosition);
  written_inline_id_stack_.Add(0);
  written_token_pos_stack_.Add(kInitialPosition);
}

void CodeSourceMapBuilder::FlushBuffer() {
  // 1. Flush the inlining stack.
  //
  // The top-most position where the buffered and written stack match.
  intptr_t common_index;
  for (common_index = buffered_inline_id_stack_.length() - 1; common_index >= 0;
       common_index--) {
    intptr_t buffered_id = buffered_inline_id_stack_[common_index];
    if (common_index < written_inline_id_stack_.length()) {
      intptr_t written_id = written_inline_id_stack_[common_index];
      if (buffered_id == written_id) {
        break;
      }
    }
  }
  if (common_index < 0) {
    // The base, which is the root function, should _always_ match.
    UNREACHABLE();
  }
  while (written_inline_id_stack_.length() > common_index + 1) {
    WritePop();
  }
  for (intptr_t j = common_index + 1; j < buffered_inline_id_stack_.length();
       j++) {
    const auto& buffered_pos = buffered_token_pos_stack_[j - 1];
    const auto& written_pos = written_token_pos_stack_[j - 1];
    if (buffered_pos != written_pos) {
      WriteChangePosition(buffered_pos);
    }
    WritePush(buffered_inline_id_stack_[j]);
  }

  ASSERT_EQUAL(buffered_token_pos_stack_.length(),
               written_token_pos_stack_.length());

  // 2. Flush the current token position.
  intptr_t top = buffered_token_pos_stack_.length() - 1;
  const auto& buffered_pos = buffered_token_pos_stack_[top];
  const auto& written_pos = written_token_pos_stack_[top];
  if (buffered_pos != written_pos) {
    WriteChangePosition(buffered_pos);
  }

  // 3. Flush the current PC offset.
  if (buffered_pc_offset_ != written_pc_offset_) {
    WriteAdvancePC(buffered_pc_offset_ - written_pc_offset_);
  }
}

void CodeSourceMapBuilder::StartInliningInterval(
    int32_t pc_offset,
    const InstructionSource& source) {
  if (!source.token_pos.IsReal() && !source.token_pos.IsSynthetic()) {
    // Only record inlining intervals for token positions that might need
    // to be checked against the appropriate function and/or script.
    return;
  }

  if (buffered_inline_id_stack_.Last() == source.inlining_id) {
    // No change in function stack.
    return;
  }

  if (source.inlining_id < 0) {
    // Inlining ID is unset for this source, so assume the current inlining ID.
    return;
  }

  if (!stack_traces_only_) {
    FlushBuffer();
  }

  // Find a minimal set of pops and pushes to bring us to the new function
  // stack.

  // Pop to a common ancestor.
  intptr_t common_parent = source.inlining_id;
  while (!IsOnBufferedStack(common_parent)) {
    common_parent = caller_inline_id_[common_parent];
  }
  while (buffered_inline_id_stack_.Last() != common_parent) {
    BufferPop();
  }

  // Push to the new top-of-stack function.
  GrowableArray<intptr_t> to_push;
  for (intptr_t id = source.inlining_id; id != common_parent;
       id = caller_inline_id_[id]) {
    to_push.Add(id);
  }
  for (intptr_t i = to_push.length() - 1; i >= 0; i--) {
    intptr_t callee_id = to_push[i];
    // We should never push the root function or its "caller".
    ASSERT(callee_id > 0);
    BufferChangePosition(inline_id_to_token_pos_[callee_id - 1]);
    BufferPush(callee_id);
  }
  if (FLAG_check_token_positions) {
    // Only update the cached script_ on inlining interval changes, since it's
    // a non-trivial computation.
    script_ = inline_id_to_function_[source.inlining_id]->script();
  }
}

void CodeSourceMapBuilder::WriteFunctionEntrySourcePosition(
    const InstructionSource& source) {
  ASSERT(written_pc_offset_ == 0 && buffered_pc_offset_ == 0);
  ASSERT(stream_.bytes_written() == 0);
  WriteChangePosition(source.token_pos);
  WriteAdvancePC(0);
}

void CodeSourceMapBuilder::BeginCodeSourceRange(
    int32_t pc_offset,
    const InstructionSource& source) {
  StartInliningInterval(pc_offset, source);
}

void CodeSourceMapBuilder::EndCodeSourceRange(int32_t pc_offset,
                                              const InstructionSource& source) {
  if (pc_offset == buffered_pc_offset_) {
    return;  // Empty intermediate instruction.
  }
  StartInliningInterval(pc_offset, source);
  if (source.token_pos != buffered_token_pos_stack_.Last()) {
    if (!stack_traces_only_) {
      FlushBuffer();
    }
    BufferChangePosition(source.token_pos);
  }
  BufferAdvancePC(pc_offset - buffered_pc_offset_);
}

void CodeSourceMapBuilder::NoteDescriptor(UntaggedPcDescriptors::Kind kind,
                                          int32_t pc_offset,
                                          const InstructionSource& source) {
  const uint8_t kCanThrow =
      UntaggedPcDescriptors::kIcCall | UntaggedPcDescriptors::kUnoptStaticCall |
      UntaggedPcDescriptors::kRuntimeCall | UntaggedPcDescriptors::kOther;
  if ((kind & kCanThrow) != 0) {
    StartInliningInterval(pc_offset, source);
    BufferChangePosition(source.token_pos);
    BufferAdvancePC(pc_offset - buffered_pc_offset_);
    FlushBuffer();
  }
}

void CodeSourceMapBuilder::NoteNullCheck(int32_t pc_offset,
                                         const InstructionSource& source,
                                         intptr_t name_index) {
  StartInliningInterval(pc_offset, source);
  BufferChangePosition(source.token_pos);
  BufferAdvancePC(pc_offset - buffered_pc_offset_);
  FlushBuffer();
  WriteNullCheck(name_index);
}

intptr_t CodeSourceMapBuilder::GetFunctionId(intptr_t inline_id) {
  const Function& function = *inline_id_to_function_[inline_id];
  for (intptr_t i = 0; i < inlined_functions_.Length(); i++) {
    if (inlined_functions_.At(i) == function.ptr()) {
      return i;
    }
  }
  RELEASE_ASSERT(!function.IsNull());
  inlined_functions_.Add(function, Heap::kOld);
  return inlined_functions_.Length() - 1;
}

TokenPosition CodeSourceMapBuilder::RootPosition(
    const InstructionSource& source) {
  if (source.inlining_id <= 0) return source.token_pos;

  intptr_t id = source.inlining_id;
  while (caller_inline_id_[id] != 0) {
    id = caller_inline_id_[id];
  }
  return inline_id_to_token_pos_[id - 1];
}

ArrayPtr CodeSourceMapBuilder::InliningIdToFunction() {
  if (inlined_functions_.Length() == 0) {
    return Object::empty_array().ptr();
  }
  return Array::MakeFixedLength(inlined_functions_);
}

CodeSourceMapPtr CodeSourceMapBuilder::Finalize() {
  if (!stack_traces_only_) {
    FlushBuffer();
  }
  intptr_t length = stream_.bytes_written();
  const auto& map = CodeSourceMap::Handle(zone_, CodeSourceMap::New(length));
  NoSafepointScope no_safepoint;
  if (length > 0) {
    ASSERT(stream_.buffer() != nullptr);
    memmove(map.Data(), stream_.buffer(), length);
  }
  return map.ptr();
}

void CodeSourceMapBuilder::BufferChangePosition(TokenPosition pos) {
  if (FLAG_check_token_positions && pos.IsReal()) {
    const intptr_t inline_id = buffered_inline_id_stack_.Last();
    const auto& function = *inline_id_to_function_[inline_id];
    if (function.end_token_pos().IsReal() &&
        !pos.IsWithin(function.token_pos(), function.end_token_pos())) {
      TextBuffer buffer(256);
      buffer.Printf("Token position %s is invalid for function %s (%s, %s)",
                    pos.ToCString(), function.ToFullyQualifiedCString(),
                    function.token_pos().ToCString(),
                    function.end_token_pos().ToCString());
      if (inline_id > 0) {
        buffer.Printf(" while compiling function %s",
                      inline_id_to_function_[0]->ToFullyQualifiedCString());
      }
      FATAL("%s", buffer.buffer());
    }
    script_ = function.script();
    if (!script_.IsNull() && !script_.IsValidTokenPosition(pos)) {
      TextBuffer buffer(256);
      buffer.Printf("Token position %s is invalid for script %s of function %s",
                    pos.ToCString(), script_.ToCString(),
                    function.ToFullyQualifiedCString());
      if (inline_id != 0) {
        buffer.Printf(" inlined into function %s",
                      inline_id_to_function_[0]->ToFullyQualifiedCString());
      }
      FATAL("%s", buffer.buffer());
    }
  }
  buffered_token_pos_stack_.Last() = pos;
}

void CodeSourceMapBuilder::WriteChangePosition(const TokenPosition pos) {
  const TokenPosition& last_written = written_token_pos_stack_.Last();
  intptr_t position_or_line =
      Utils::SubWithWrapAround(pos.Serialize(), last_written.Serialize());
  intptr_t column = TokenPosition::kNoSource.Serialize();
#if defined(DART_PRECOMPILER)
  if (FLAG_precompiled_mode) {
    // Don't use the raw position value directly in precompiled mode. Instead,
    // use the value of kNoSource as a fallback when no line or column
    // information is found.
    position_or_line = TokenPosition::kNoSource.Serialize();
    const intptr_t inline_id = written_inline_id_stack_.Last();
    ASSERT(inline_id < inline_id_to_function_.length());
    script_ = inline_id_to_function_[inline_id]->script();
    script_.GetTokenLocation(pos, &position_or_line, &column);
    intptr_t old_line = TokenPosition::kNoSource.Serialize();
    script_.GetTokenLocation(last_written, &old_line);
    position_or_line =
        Utils::SubWithWrapAround<int32_t>(position_or_line, old_line);
  }
#endif
  CodeSourceMapOps::Write(&stream_, CodeSourceMapOps::kChangePosition,
                          position_or_line, column);
  written_token_pos_stack_.Last() = pos;
}

void CodeSourceMapReader::GetInlinedFunctionsAt(
    int32_t pc_offset,
    GrowableArray<const Function*>* function_stack,
    GrowableArray<TokenPosition>* token_positions) {
  function_stack->Clear();
  token_positions->Clear();

  NoSafepointScope no_safepoint;
  ReadStream stream(map_.Data(), map_.Length());

  int32_t current_pc_offset = 0;
  function_stack->Add(&root_);
  token_positions->Add(InitialPosition());

  while (stream.PendingBytes() > 0) {
    int32_t arg;
    const uint8_t opcode = CodeSourceMapOps::Read(&stream, &arg);
    switch (opcode) {
      case CodeSourceMapOps::kChangePosition: {
        const TokenPosition& old_token = token_positions->Last();
        token_positions->Last() = TokenPosition::Deserialize(
            Utils::AddWithWrapAround(arg, old_token.Serialize()));
        break;
      }
      case CodeSourceMapOps::kAdvancePC: {
        current_pc_offset += arg;
        if (current_pc_offset > pc_offset) {
          return;
        }
        break;
      }
      case CodeSourceMapOps::kPushFunction: {
        function_stack->Add(
            &Function::Handle(Function::RawCast(functions_.At(arg))));
        token_positions->Add(InitialPosition());
        break;
      }
      case CodeSourceMapOps::kPopFunction: {
        // We never pop the root function.
        ASSERT(function_stack->length() > 1);
        ASSERT(token_positions->length() > 1);
        function_stack->RemoveLast();
        token_positions->RemoveLast();
        break;
      }
      case CodeSourceMapOps::kNullCheck: {
        break;
      }
      default:
        UNREACHABLE();
    }
  }
}

#ifndef PRODUCT
void CodeSourceMapReader::PrintJSONInlineIntervals(JSONObject* jsobj) {
  {
    JSONArray inlined_functions(jsobj, "_inlinedFunctions");
    Function& function = Function::Handle();
    for (intptr_t i = 0; i < functions_.Length(); i++) {
      function ^= functions_.At(i);
      ASSERT(!function.IsNull());
      inlined_functions.AddValue(function);
    }
  }

  GrowableArray<intptr_t> function_stack;
  JSONArray inline_intervals(jsobj, "_inlinedIntervals");
  NoSafepointScope no_safepoint;
  ReadStream stream(map_.Data(), map_.Length());

  int32_t current_pc_offset = 0;
  function_stack.Add(0);

  while (stream.PendingBytes() > 0) {
    int32_t arg;
    const uint8_t opcode = CodeSourceMapOps::Read(&stream, &arg);
    switch (opcode) {
      case CodeSourceMapOps::kChangePosition: {
        break;
      }
      case CodeSourceMapOps::kAdvancePC: {
        // Format: [start, end, inline functions...]
        JSONArray inline_interval(&inline_intervals);
        inline_interval.AddValue(static_cast<intptr_t>(current_pc_offset));
        inline_interval.AddValue(
            static_cast<intptr_t>(current_pc_offset + arg - 1));
        for (intptr_t i = 0; i < function_stack.length(); i++) {
          inline_interval.AddValue(function_stack[i]);
        }
        current_pc_offset += arg;
        break;
      }
      case CodeSourceMapOps::kPushFunction: {
        function_stack.Add(arg);
        break;
      }
      case CodeSourceMapOps::kPopFunction: {
        // We never pop the root function.
        ASSERT(function_stack.length() > 1);
        function_stack.RemoveLast();
        break;
      }
      case CodeSourceMapOps::kNullCheck: {
        break;
      }
      default:
        UNREACHABLE();
    }
  }
}
#endif  // !PRODUCT

void CodeSourceMapReader::DumpInlineIntervals(uword start) {
  GrowableArray<const Function*> function_stack;
  GrowableArray<TokenPosition> token_positions;
  LogBlock lb;
  NoSafepointScope no_safepoint;
  ReadStream stream(map_.Data(), map_.Length());

  int32_t current_pc_offset = 0;
  function_stack.Add(&root_);
  token_positions.Add(InitialPosition());

  THR_Print("Inline intervals for function '%s' {\n",
            root_.ToFullyQualifiedCString());
  while (stream.PendingBytes() > 0) {
    int32_t arg;
    const uint8_t opcode = CodeSourceMapOps::Read(&stream, &arg);
    switch (opcode) {
      case CodeSourceMapOps::kChangePosition: {
        const TokenPosition& old_token = token_positions.Last();
        token_positions.Last() = TokenPosition::Deserialize(
            Utils::AddWithWrapAround(arg, old_token.Serialize()));
        break;
      }
      case CodeSourceMapOps::kAdvancePC: {
        THR_Print("%" Px "-%" Px ": ", start + current_pc_offset,
                  start + current_pc_offset + arg - 1);
        for (intptr_t i = 0; i < function_stack.length(); i++) {
          THR_Print("%s", function_stack[i]->ToCString());
          if (token_positions[i].IsReal()) {
            THR_Print(" @%" Pd, token_positions[i].Pos());
          }
        }
        THR_Print("\n");
        current_pc_offset += arg;
        break;
      }
      case CodeSourceMapOps::kPushFunction: {
        function_stack.Add(
            &Function::Handle(Function::RawCast(functions_.At(arg))));
        token_positions.Add(InitialPosition());
        break;
      }
      case CodeSourceMapOps::kPopFunction: {
        // We never pop the root function.
        ASSERT(function_stack.length() > 1);
        ASSERT(token_positions.length() > 1);
        function_stack.RemoveLast();
        token_positions.RemoveLast();
        break;
      }
      case CodeSourceMapOps::kNullCheck: {
        break;
      }
      default:
        UNREACHABLE();
    }
  }
  THR_Print("}\n");
}

void CodeSourceMapReader::DumpSourcePositions(uword start) {
  GrowableArray<const Function*> function_stack;
  GrowableArray<TokenPosition> token_positions;
  LogBlock lb;
  NoSafepointScope no_safepoint;
  ReadStream stream(map_.Data(), map_.Length());

  int32_t current_pc_offset = 0;
  function_stack.Add(&root_);
  token_positions.Add(InitialPosition());

  THR_Print("Source positions for function '%s' {\n",
            root_.ToFullyQualifiedCString());
  while (stream.PendingBytes() > 0) {
    int32_t arg;
    const uint8_t opcode = CodeSourceMapOps::Read(&stream, &arg);
    switch (opcode) {
      case CodeSourceMapOps::kChangePosition: {
        const TokenPosition& old_token =
            token_positions[token_positions.length() - 1];
        token_positions[token_positions.length() - 1] =
            TokenPosition::Deserialize(
                Utils::AddWithWrapAround(arg, old_token.Serialize()));
        break;
      }
      case CodeSourceMapOps::kAdvancePC: {
        THR_Print("%" Px "-%" Px ": ", start + current_pc_offset,
                  start + current_pc_offset + arg - 1);
        for (intptr_t i = 0; i < function_stack.length(); i++) {
          THR_Print("%s@%s", function_stack[i]->ToCString(),
                    token_positions[i].ToCString());
        }
        THR_Print("\n");
        current_pc_offset += arg;
        break;
      }
      case CodeSourceMapOps::kPushFunction: {
        function_stack.Add(
            &Function::Handle(Function::RawCast(functions_.At(arg))));
        token_positions.Add(InitialPosition());
        break;
      }
      case CodeSourceMapOps::kPopFunction: {
        // We never pop the root function.
        ASSERT(function_stack.length() > 1);
        ASSERT(token_positions.length() > 1);
        function_stack.RemoveLast();
        token_positions.RemoveLast();
        break;
      }
      case CodeSourceMapOps::kNullCheck: {
        THR_Print("%" Px "-%" Px ": null check PP#%" Pd32 "\n",
                  start + current_pc_offset, start + current_pc_offset, arg);
        break;
      }
      default:
        UNREACHABLE();
    }
  }
  THR_Print("}\n");
}

intptr_t CodeSourceMapReader::GetNullCheckNameIndexAt(int32_t pc_offset) {
  NoSafepointScope no_safepoint;
  ReadStream stream(map_.Data(), map_.Length());

  int32_t current_pc_offset = 0;

  while (stream.PendingBytes() > 0) {
    int32_t arg;
    const uint8_t opcode = CodeSourceMapOps::Read(&stream, &arg);
    switch (opcode) {
      case CodeSourceMapOps::kChangePosition: {
        break;
      }
      case CodeSourceMapOps::kAdvancePC: {
        current_pc_offset += arg;
        RELEASE_ASSERT(current_pc_offset <= pc_offset);
        break;
      }
      case CodeSourceMapOps::kPushFunction: {
        break;
      }
      case CodeSourceMapOps::kPopFunction: {
        break;
      }
      case CodeSourceMapOps::kNullCheck: {
        if (current_pc_offset == pc_offset) {
          return arg;
        }
        break;
      }
      default:
        UNREACHABLE();
    }
  }

  UNREACHABLE();
  return -1;
}

}  // namespace dart
