// Copyright (c) 2015, 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/globals.h"
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
#include "vm/source_report.h"

#include "vm/bit_vector.h"
#include "vm/closure_functions_cache.h"
#include "vm/compiler/jit/compiler.h"
#include "vm/isolate.h"
#include "vm/kernel_loader.h"
#include "vm/object.h"
#include "vm/object_store.h"
#include "vm/profiler.h"
#include "vm/profiler_service.h"

namespace dart {

const char* SourceReport::kCallSitesStr = "_CallSites";
const char* SourceReport::kCoverageStr = "Coverage";
const char* SourceReport::kPossibleBreakpointsStr = "PossibleBreakpoints";
const char* SourceReport::kProfileStr = "_Profile";
const char* SourceReport::kBranchCoverageStr = "BranchCoverage";

SourceReport::SourceReport(intptr_t report_set,
                           CompileMode compile_mode,
                           bool report_lines)
    : report_set_(report_set),
      compile_mode_(compile_mode),
      report_lines_(report_lines),
      thread_(NULL),
      script_(NULL),
      start_pos_(TokenPosition::kMinSource),
      end_pos_(TokenPosition::kMaxSource),
      next_script_index_(0) {}

SourceReport::~SourceReport() {
  ClearScriptTable();
}

void SourceReport::ClearScriptTable() {
  for (intptr_t i = 0; i < script_table_entries_.length(); i++) {
    delete script_table_entries_[i];
    script_table_entries_[i] = NULL;
  }
  script_table_entries_.Clear();
  script_table_.Clear();
  next_script_index_ = 0;
}

void SourceReport::Init(Thread* thread,
                        const Script* script,
                        TokenPosition start_pos,
                        TokenPosition end_pos) {
  thread_ = thread;
  script_ = script;
  start_pos_ = TokenPosition::Max(start_pos, TokenPosition::kMinSource);
  end_pos_ = TokenPosition::Min(end_pos, TokenPosition::kMaxSource);
  ClearScriptTable();
  if (IsReportRequested(kProfile)) {
    // Build the profile.
    SampleFilter samplesForIsolate(thread_->isolate()->main_port(),
                                   Thread::kMutatorTask, -1, -1);
    profile_.Build(thread, &samplesForIsolate, Profiler::sample_block_buffer());
  }
}

bool SourceReport::IsReportRequested(ReportKind report_kind) {
  return (report_set_ & report_kind) != 0;
}

bool SourceReport::ShouldSkipFunction(const Function& func) {
  // TODO(32315): Verify that the check is still needed after the issue is
  // resolved.
  if (!func.token_pos().IsReal() || !func.end_token_pos().IsReal()) {
    // At least one of the token positions is not known.
    return true;
  }

  if (script_ != NULL && !script_->IsNull()) {
    if (func.script() != script_->ptr()) {
      // The function is from the wrong script.
      return true;
    }
    if ((func.end_token_pos() < start_pos_) || (func.token_pos() > end_pos_)) {
      // The function does not intersect with the requested token range.
      return true;
    }
  }

  // These don't have unoptimized code and are only used for synthetic stubs.
  if (func.ForceOptimize()) return true;

  switch (func.kind()) {
    case UntaggedFunction::kRegularFunction:
    case UntaggedFunction::kClosureFunction:
    case UntaggedFunction::kImplicitClosureFunction:
    case UntaggedFunction::kImplicitStaticGetter:
    case UntaggedFunction::kFieldInitializer:
    case UntaggedFunction::kGetterFunction:
    case UntaggedFunction::kSetterFunction:
    case UntaggedFunction::kConstructor:
      break;
    default:
      return true;
  }
  if (func.is_abstract() || func.IsImplicitConstructor() ||
      func.is_synthetic() || func.is_redirecting_factory()) {
    return true;
  }
  if (func.IsNonImplicitClosureFunction() &&
      (func.context_scope() == ContextScope::null())) {
    // TODO(iposva): This can arise if we attempt to compile an inner function
    // before we have compiled its enclosing function or if the enclosing
    // function failed to compile.
    return true;
  }

  // There is an idiom where static utility classes are given a private
  // constructor to prevent the class from being instantiated. Ignore these
  // constructors so that they don't lower the coverage rate. See #47021.
  SafepointReadRwLocker ml(thread_, thread_->isolate_group()->program_lock());
  if (func.kind() == UntaggedFunction::kConstructor &&
      func.NumParameters() == func.NumImplicitParameters() &&
      func.IsPrivate()) {
    // Check that the class has no non-static members and no subclasses.
    Class& cls = Class::Handle(func.Owner());
    GrowableObjectArray& subclasses =
        GrowableObjectArray::Handle(cls.direct_subclasses());
    if (cls.is_abstract() && !cls.HasInstanceFields() &&
        (subclasses.IsNull() || subclasses.Length() == 0)) {
      // Check that the constructor is the only non-static function.
      Array& clsFuncs = Array::Handle(cls.functions());
      Function& otherFunc = Function::Handle();
      intptr_t numNonStaticFunctions = 0;
      for (intptr_t i = 0; i < clsFuncs.Length(); ++i) {
        otherFunc ^= clsFuncs.At(i);
        if (!otherFunc.IsStaticFunction()) {
          ++numNonStaticFunctions;
        }
      }
      if (numNonStaticFunctions == 1) {
        return true;
      }
    }
  }

  return false;
}

bool SourceReport::ShouldSkipField(const Field& field) {
  if (!field.token_pos().IsReal() || !field.end_token_pos().IsReal()) {
    // At least one of the token positions is not known.
    return true;
  }

  if (script_ != NULL && !script_->IsNull()) {
    if (field.Script() != script_->ptr()) {
      // The field is from the wrong script.
      return true;
    }
    if ((field.end_token_pos() < start_pos_) ||
        (field.token_pos() > end_pos_)) {
      // The field does not intersect with the requested token range.
      return true;
    }
  }
  return false;
}

intptr_t SourceReport::GetScriptIndex(const Script& script) {
  ScriptTableEntry wrapper;
  const String& url = String::Handle(zone(), script.url());
  wrapper.key = &url;
  wrapper.script = &Script::Handle(zone(), script.ptr());
  ScriptTableEntry* pair = script_table_.LookupValue(&wrapper);
  if (pair != NULL) {
    return pair->index;
  }
  ScriptTableEntry* tmp = new ScriptTableEntry();
  tmp->key = &url;
  tmp->index = next_script_index_++;
  tmp->script = wrapper.script;
  script_table_entries_.Add(tmp);
  script_table_.Insert(tmp);
  ASSERT(script_table_entries_.length() == next_script_index_);
#if defined(DEBUG)
  VerifyScriptTable();
#endif
  return tmp->index;
}

#if defined(DEBUG)
void SourceReport::VerifyScriptTable() {
  for (intptr_t i = 0; i < script_table_entries_.length(); i++) {
    const String* url = script_table_entries_[i]->key;
    const Script* script = script_table_entries_[i]->script;
    intptr_t index = script_table_entries_[i]->index;
    ASSERT(i == index);
    const String& url2 = String::Handle(zone(), script->url());
    ASSERT(url2.Equals(*url));
    ScriptTableEntry wrapper;
    wrapper.key = &url2;
    wrapper.script = &Script::Handle(zone(), script->ptr());
    ScriptTableEntry* pair = script_table_.LookupValue(&wrapper);
    ASSERT(i == pair->index);
  }
}
#endif

bool SourceReport::ScriptIsLoadedByLibrary(const Script& script,
                                           const Library& lib) {
  const Array& scripts = Array::Handle(zone(), lib.LoadedScripts());
  for (intptr_t j = 0; j < scripts.Length(); j++) {
    if (scripts.At(j) == script.ptr()) {
      return true;
    }
  }
  return false;
}

void SourceReport::PrintCallSitesData(JSONObject* jsobj,
                                      const Function& function,
                                      const Code& code) {
  ASSERT(!code.IsNull());
  const TokenPosition& begin_pos = function.token_pos();
  const TokenPosition& end_pos = function.end_token_pos();
  ZoneGrowableArray<const ICData*>* ic_data_array =
      new (zone()) ZoneGrowableArray<const ICData*>();
  function.RestoreICDataMap(ic_data_array, false /* clone ic-data */);
  const PcDescriptors& descriptors =
      PcDescriptors::Handle(zone(), code.pc_descriptors());

  JSONArray sites(jsobj, "callSites");

  PcDescriptors::Iterator iter(
      descriptors,
      UntaggedPcDescriptors::kIcCall | UntaggedPcDescriptors::kUnoptStaticCall);
  while (iter.MoveNext()) {
    HANDLESCOPE(thread());
    ASSERT(iter.DeoptId() < ic_data_array->length());
    const ICData* ic_data = (*ic_data_array)[iter.DeoptId()];
    if (ic_data != NULL) {
      const TokenPosition& token_pos = iter.TokenPos();
      if (!token_pos.IsWithin(begin_pos, end_pos)) {
        // Does not correspond to a valid source position.
        continue;
      }
      ic_data->PrintToJSONArray(sites, token_pos);
    }
  }
}

intptr_t SourceReport::GetTokenPosOrLine(const Script& script,
                                         const TokenPosition& token_pos) {
  if (!report_lines_) {
    return token_pos.Pos();
  }
  intptr_t line = -1;
  const bool found = script.GetTokenLocation(token_pos, &line);
  ASSERT(found);
  return line;
}

bool SourceReport::ShouldCoverageSkipCallSite(const ICData* ic_data) {
  if (ic_data == NULL) return true;
  if (!ic_data->is_static_call()) return false;
  Function& func = Function::Handle(ic_data->GetTargetAt(0));

  // Ignore calls to the LateError functions. These are used to throw errors to
  // do with late variables. These errors shouldn't be hit in working code, so
  // shouldn't count against the coverage total.
  // See https://github.com/dart-lang/coverage/issues/341
  if (late_error_class_id_ == ClassId::kIllegalCid) {
    const Class& lateErrorClass =
        Class::Handle(Library::LookupCoreClass(Symbols::LateError()));
    late_error_class_id_ = lateErrorClass.id();
  }
  Class& cls = Class::Handle(func.Owner());
  if (late_error_class_id_ == cls.id()) {
    return true;
  }
  return false;
}

void SourceReport::PrintCoverageData(JSONObject* jsobj,
                                     const Function& function,
                                     const Code& code,
                                     bool report_branch_coverage) {
  ASSERT(!code.IsNull());
  const TokenPosition& begin_pos = function.token_pos();
  const TokenPosition& end_pos = function.end_token_pos();

  ZoneGrowableArray<const ICData*>* ic_data_array =
      new (zone()) ZoneGrowableArray<const ICData*>();
  function.RestoreICDataMap(ic_data_array, false /* clone ic-data */);
  const PcDescriptors& descriptors =
      PcDescriptors::Handle(zone(), code.pc_descriptors());
  const Script& script = Script::Handle(zone(), function.script());

  const int kCoverageNone = 0;
  const int kCoverageMiss = 1;
  const int kCoverageHit = 2;

  intptr_t func_length = function.SourceSize() + 1;
  GrowableArray<char> coverage(func_length);
  coverage.SetLength(func_length);
  for (int i = 0; i < func_length; i++) {
    coverage[i] = kCoverageNone;
  }

  if (function.WasExecuted()) {
    coverage[0] = kCoverageHit;
  } else {
    coverage[0] = kCoverageMiss;
  }

  auto update_coverage = [&](TokenPosition token_pos, bool was_executed) {
    if (!token_pos.IsWithin(begin_pos, end_pos)) {
      return;
    }

    const intptr_t token_offset = token_pos.Pos() - begin_pos.Pos();
    if (was_executed) {
      coverage[token_offset] = kCoverageHit;
    } else {
      if (coverage[token_offset] == kCoverageNone) {
        coverage[token_offset] = kCoverageMiss;
      }
    }
  };

  if (!report_branch_coverage) {
    PcDescriptors::Iterator iter(descriptors,
                                 UntaggedPcDescriptors::kIcCall |
                                     UntaggedPcDescriptors::kUnoptStaticCall);
    while (iter.MoveNext()) {
      HANDLESCOPE(thread());
      ASSERT(iter.DeoptId() < ic_data_array->length());
      const ICData* ic_data = (*ic_data_array)[iter.DeoptId()];
      if (!ShouldCoverageSkipCallSite(ic_data)) {
        const TokenPosition& token_pos = iter.TokenPos();
        update_coverage(token_pos, ic_data->AggregateCount() > 0);
      }
    }
  }

  // Merge the coverage from coverage_array attached to the function.
  const Array& coverage_array = Array::Handle(function.GetCoverageArray());
  if (!coverage_array.IsNull()) {
    for (intptr_t i = 0; i < coverage_array.Length(); i += 2) {
      bool is_branch_coverage;
      const TokenPosition token_pos = TokenPosition::DecodeCoveragePosition(
          Smi::Value(Smi::RawCast(coverage_array.At(i))), &is_branch_coverage);
      if (is_branch_coverage == report_branch_coverage) {
        const bool was_executed =
            Smi::Value(Smi::RawCast(coverage_array.At(i + 1))) != 0;
        update_coverage(token_pos, was_executed);
      }
    }
  }

  JSONObject cov(jsobj, report_branch_coverage ? "branchCoverage" : "coverage");
  {
    JSONArray hits(&cov, "hits");
    TokenPosition pos = begin_pos;
    for (int i = 0; i < func_length; i++) {
      if (coverage[i] == kCoverageHit) {
        // Add the token position or line number of the hit.
        hits.AddValue(GetTokenPosOrLine(script, pos));
      }
      pos = pos.Next();
    }
  }
  {
    JSONArray misses(&cov, "misses");
    TokenPosition pos = begin_pos;
    for (int i = 0; i < func_length; i++) {
      if (coverage[i] == kCoverageMiss) {
        // Add the token position or line number of the miss.
        misses.AddValue(GetTokenPosOrLine(script, pos));
      }
      pos = pos.Next();
    }
  }
}

void SourceReport::PrintPossibleBreakpointsData(JSONObject* jsobj,
                                                const Function& func,
                                                const Code& code) {
  const TokenPosition& begin_pos = func.token_pos();
  const TokenPosition& end_pos = func.end_token_pos();
  intptr_t func_length = func.SourceSize() + 1;

  BitVector possible(zone(), func_length);

  ASSERT(!code.IsNull());

  const uint8_t kSafepointKind = (UntaggedPcDescriptors::kIcCall |
                                  UntaggedPcDescriptors::kUnoptStaticCall |
                                  UntaggedPcDescriptors::kRuntimeCall);

  const PcDescriptors& descriptors =
      PcDescriptors::Handle(zone(), code.pc_descriptors());
  const Script& script = Script::Handle(zone(), func.script());

  PcDescriptors::Iterator iter(descriptors, kSafepointKind);
  while (iter.MoveNext()) {
    const TokenPosition& token_pos = iter.TokenPos();
    if (!token_pos.IsWithin(begin_pos, end_pos)) {
      // Does not correspond to a valid source position.
      continue;
    }
    intptr_t token_offset = token_pos.Pos() - begin_pos.Pos();
    possible.Add(token_offset);
  }

  JSONArray bpts(jsobj, "possibleBreakpoints");
  TokenPosition pos = begin_pos;
  for (int i = 0; i < func_length; i++) {
    if (possible.Contains(i)) {
      // Add the token position or line number.
      bpts.AddValue(GetTokenPosOrLine(script, pos));
    }
    pos = pos.Next();
  }
}

void SourceReport::PrintProfileData(JSONObject* jsobj,
                                    ProfileFunction* profile_function) {
  ASSERT(profile_function != NULL);
  ASSERT(profile_function->NumSourcePositions() > 0);

  {
    JSONObject profile(jsobj, "profile");

    {
      JSONObject profileData(&profile, "metadata");
      profileData.AddProperty("sampleCount", profile_.sample_count());
    }

    // Positions.
    {
      JSONArray positions(&profile, "positions");
      for (intptr_t i = 0; i < profile_function->NumSourcePositions(); i++) {
        const ProfileFunctionSourcePosition& position =
            profile_function->GetSourcePosition(i);
        if (position.token_pos().IsReal()) {
          // Add as an integer.
          positions.AddValue(position.token_pos().Pos());
        } else {
          // Add as a string.
          positions.AddValue(position.token_pos().ToCString());
        }
      }
    }

    // Exclusive ticks.
    {
      JSONArray exclusiveTicks(&profile, "exclusiveTicks");
      for (intptr_t i = 0; i < profile_function->NumSourcePositions(); i++) {
        const ProfileFunctionSourcePosition& position =
            profile_function->GetSourcePosition(i);
        exclusiveTicks.AddValue(position.exclusive_ticks());
      }
    }
    // Inclusive ticks.
    {
      JSONArray inclusiveTicks(&profile, "inclusiveTicks");
      for (intptr_t i = 0; i < profile_function->NumSourcePositions(); i++) {
        const ProfileFunctionSourcePosition& position =
            profile_function->GetSourcePosition(i);
        inclusiveTicks.AddValue(position.inclusive_ticks());
      }
    }
  }
}

void SourceReport::PrintScriptTable(JSONArray* scripts) {
  for (intptr_t i = 0; i < script_table_entries_.length(); i++) {
    const Script* script = script_table_entries_[i]->script;
    scripts->AddValue(*script);
  }
}

void SourceReport::VisitFunction(JSONArray* jsarr, const Function& func) {
  if (ShouldSkipFunction(func)) {
    return;
  }

  const Script& script = Script::Handle(zone(), func.script());
  const TokenPosition begin_pos = func.token_pos();
  const TokenPosition end_pos = func.end_token_pos();

  Code& code = Code::Handle(zone(), func.unoptimized_code());
  if (code.IsNull()) {
    if (func.HasCode() || (compile_mode_ == kForceCompile)) {
      const Error& err =
          Error::Handle(Compiler::EnsureUnoptimizedCode(thread(), func));
      if (!err.IsNull()) {
        // Emit an uncompiled range for this function with error information.
        JSONObject range(jsarr);
        range.AddProperty("scriptIndex", GetScriptIndex(script));
        range.AddProperty("startPos", begin_pos);
        range.AddProperty("endPos", end_pos);
        range.AddProperty("compiled", false);
        range.AddProperty("error", err);
        return;
      }
      code = func.unoptimized_code();
    } else {
      // This function has not been compiled yet.
      JSONObject range(jsarr);
      range.AddProperty("scriptIndex", GetScriptIndex(script));
      range.AddProperty("startPos", begin_pos);
      range.AddProperty("endPos", end_pos);
      range.AddProperty("compiled", false);
      return;
    }
  }
  ASSERT(!code.IsNull());

  // We skip compiled async functions.  Once an async function has
  // been compiled, there is another function with the same range which
  // actually contains the user code.
  if (!func.IsAsyncFunction() && !func.IsAsyncGenerator() &&
      !func.IsSyncGenerator()) {
    JSONObject range(jsarr);
    range.AddProperty("scriptIndex", GetScriptIndex(script));
    range.AddProperty("startPos", begin_pos);
    range.AddProperty("endPos", end_pos);
    range.AddProperty("compiled", true);

    if (IsReportRequested(kCallSites)) {
      PrintCallSitesData(&range, func, code);
    }
    if (IsReportRequested(kCoverage)) {
      PrintCoverageData(&range, func, code, /* report_branch_coverage */ false);
    }
    if (IsReportRequested(kBranchCoverage)) {
      PrintCoverageData(&range, func, code, /* report_branch_coverage */ true);
    }
    if (IsReportRequested(kPossibleBreakpoints)) {
      PrintPossibleBreakpointsData(&range, func, code);
    }
    if (IsReportRequested(kProfile)) {
      ProfileFunction* profile_function = profile_.FindFunction(func);
      if ((profile_function != NULL) &&
          (profile_function->NumSourcePositions() > 0)) {
        PrintProfileData(&range, profile_function);
      }
    }
  }
}

void SourceReport::VisitField(JSONArray* jsarr, const Field& field) {
  if (ShouldSkipField(field) || !field.HasInitializerFunction()) return;
  const Function& func = Function::Handle(field.InitializerFunction());
  VisitFunction(jsarr, func);
}

void SourceReport::VisitLibrary(JSONArray* jsarr, const Library& lib) {
  Class& cls = Class::Handle(zone());
  Array& functions = Array::Handle(zone());
  Array& fields = Array::Handle(zone());
  Function& func = Function::Handle(zone());
  Field& field = Field::Handle(zone());
  Script& script = Script::Handle(zone());
  ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
  while (it.HasNext()) {
    cls = it.GetNextClass();
    if (!cls.is_finalized()) {
      if (compile_mode_ == kForceCompile) {
        Error& err = Error::Handle(cls.EnsureIsFinalized(thread()));
        if (!err.IsNull()) {
          // Emit an uncompiled range for this class with error information.
          JSONObject range(jsarr);
          script = cls.script();
          range.AddProperty("scriptIndex", GetScriptIndex(script));
          range.AddProperty("startPos", cls.token_pos());
          range.AddProperty("endPos", cls.end_token_pos());
          range.AddProperty("compiled", false);
          range.AddProperty("error", err);
          continue;
        }
        ASSERT(cls.is_finalized());
      } else {
        cls.EnsureDeclarationLoaded();
        // Emit one range for the whole uncompiled class.
        JSONObject range(jsarr);
        script = cls.script();
        range.AddProperty("scriptIndex", GetScriptIndex(script));
        range.AddProperty("startPos", cls.token_pos());
        range.AddProperty("endPos", cls.end_token_pos());
        range.AddProperty("compiled", false);
        continue;
      }
    }

    functions = cls.current_functions();
    for (int i = 0; i < functions.Length(); i++) {
      func ^= functions.At(i);
      // Skip getter functions of static const field.
      if (func.kind() == UntaggedFunction::kImplicitStaticGetter) {
        field ^= func.accessor_field();
        if (field.is_const() && field.is_static()) {
          continue;
        }
      }
      VisitFunction(jsarr, func);
    }

    fields = cls.fields();
    for (intptr_t i = 0; i < fields.Length(); i++) {
      field ^= fields.At(i);
      VisitField(jsarr, field);
    }
  }
}

void SourceReport::VisitClosures(JSONArray* jsarr) {
  ClosureFunctionsCache::ForAllClosureFunctions([&](const Function& func) {
    VisitFunction(jsarr, func);
    return true;  // Continue iteration.
  });
}

void SourceReport::PrintJSON(JSONStream* js,
                             const Script& script,
                             TokenPosition start_pos,
                             TokenPosition end_pos) {
  Init(Thread::Current(), &script, start_pos, end_pos);

  JSONObject report(js);
  report.AddProperty("type", "SourceReport");
  {
    JSONArray ranges(&report, "ranges");

    const GrowableObjectArray& libs = GrowableObjectArray::Handle(
        zone(), thread()->isolate_group()->object_store()->libraries());

    // We only visit the libraries which actually load the specified script.
    Library& lib = Library::Handle(zone());
    for (int i = 0; i < libs.Length(); i++) {
      lib ^= libs.At(i);
      if (script.IsNull() || ScriptIsLoadedByLibrary(script, lib)) {
        VisitLibrary(&ranges, lib);
      }
    }

    // Visit all closures for this isolate.
    VisitClosures(&ranges);

    // Output constant coverage if coverage is requested.
    if (IsReportRequested(kCoverage)) {
      // Find all scripts. We need to go though all scripts because a script
      // (even one we don't want) can add coverage to another library (i.e.
      // potentially one we want).
      DirectChainedHashMap<ScriptTableTrait> local_script_table;
      GrowableArray<ScriptTableEntry*> local_script_table_entries;
      CollectAllScripts(&local_script_table, &local_script_table_entries);
      CollectConstConstructorCoverageFromScripts(&local_script_table_entries,
                                                 &ranges);
      CleanupCollectedScripts(&local_script_table, &local_script_table_entries);
    }
  }

  // Print the script table.
  JSONArray scripts(&report, "scripts");
  PrintScriptTable(&scripts);
}

void SourceReport::CollectAllScripts(
    DirectChainedHashMap<ScriptTableTrait>* local_script_table,
    GrowableArray<ScriptTableEntry*>* local_script_table_entries) {
  ScriptTableEntry wrapper;
  const GrowableObjectArray& libs = GrowableObjectArray::Handle(
      zone(), thread()->isolate_group()->object_store()->libraries());
  Library& lib = Library::Handle(zone());
  Script& scriptRef = Script::Handle(zone());
  for (int i = 0; i < libs.Length(); i++) {
    lib ^= libs.At(i);
    const Array& scripts = Array::Handle(zone(), lib.LoadedScripts());
    for (intptr_t j = 0; j < scripts.Length(); j++) {
      scriptRef ^= scripts.At(j);
      const String& url = String::Handle(zone(), scriptRef.url());
      wrapper.key = &url;
      wrapper.script = &Script::Handle(zone(), scriptRef.ptr());
      ScriptTableEntry* pair = local_script_table->LookupValue(&wrapper);
      if (pair != NULL) {
        // Existing one.
        continue;
      }
      // New one. Insert.
      ScriptTableEntry* tmp = new ScriptTableEntry();
      tmp->key = &url;
      tmp->index = next_script_index_++;
      tmp->script = wrapper.script;
      local_script_table_entries->Add(tmp);
      local_script_table->Insert(tmp);
    }
  }
}

void SourceReport::CleanupCollectedScripts(
    DirectChainedHashMap<ScriptTableTrait>* local_script_table,
    GrowableArray<ScriptTableEntry*>* local_script_table_entries) {
  for (intptr_t i = 0; i < local_script_table_entries->length(); i++) {
    delete local_script_table_entries->operator[](i);
    local_script_table_entries->operator[](i) = NULL;
  }
  local_script_table_entries->Clear();
  local_script_table->Clear();
}

void SourceReport::CollectConstConstructorCoverageFromScripts(
    GrowableArray<ScriptTableEntry*>* local_script_table_entries,
    JSONArray* ranges) {
  // Now output the wanted constant coverage.
  for (intptr_t i = 0; i < local_script_table_entries->length(); i++) {
    const Script* script = local_script_table_entries->At(i)->script;

    // Whether we want *this* script or not we need to look at the constant
    // constructor coverage. Any of those could be in a script we *do* want.
    {
      Script& scriptRef = Script::Handle(zone());
      const Array& constructors =
          Array::Handle(kernel::CollectConstConstructorCoverageFrom(*script));
      intptr_t constructors_count = constructors.Length();
      Function& constructor = Function::Handle(zone());
      Code& code = Code::Handle(zone());
      for (intptr_t i = 0; i < constructors_count; i++) {
        constructor ^= constructors.At(i);
        // Check if we want coverage for this constructor.
        if (ShouldSkipFunction(constructor)) {
          continue;
        }
        scriptRef ^= constructor.script();
        code ^= constructor.unoptimized_code();
        const TokenPosition begin_pos = constructor.token_pos();
        const TokenPosition end_pos = constructor.end_token_pos();
        JSONObject range(ranges);
        range.AddProperty("scriptIndex", GetScriptIndex(scriptRef));
        range.AddProperty("compiled",
                          !code.IsNull());  // Does this make a difference?
        range.AddProperty("startPos", begin_pos);
        range.AddProperty("endPos", end_pos);

        JSONObject cov(&range, "coverage");
        {
          JSONArray hits(&cov, "hits");
          hits.AddValue(GetTokenPosOrLine(scriptRef, begin_pos));
        }
        {
          JSONArray misses(&cov, "misses");
          // No misses
        }
      }
    }
  }
}

}  // namespace dart
#endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
