// Copyright (c) 2013, 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/coverage.h"

#include "include/dart_api.h"

#include "vm/compiler.h"
#include "vm/isolate.h"
#include "vm/json_stream.h"
#include "vm/object.h"
#include "vm/object_store.h"

namespace dart {

DEFINE_FLAG(charp, coverage_dir, NULL,
            "Enable writing coverage data into specified directory.");


void CodeCoverage::CompileAndAdd(const Function& function,
                                 const JSONArray& hits_arr) {
  if (!function.HasCode()) {
    if (Compiler::CompileFunction(function) != Error::null()) {
      return;
    }
  }
  ASSERT(function.HasCode());

  Isolate* isolate = Isolate::Current();
  // Print the hit counts for all IC datas.
  const Script& script = Script::Handle(function.script());
  const Code& code = Code::Handle(function.unoptimized_code());
  const Array& ic_array = Array::Handle(code.ExtractTypeFeedbackArray());
  const PcDescriptors& descriptors = PcDescriptors::Handle(
      code.pc_descriptors());
  ICData& ic_data = ICData::Handle();

  for (int j = 0; j < descriptors.Length(); j++) {
    HANDLESCOPE(isolate);
    PcDescriptors::Kind kind = descriptors.DescriptorKind(j);
    // Only IC based calls have counting.
    if ((kind == PcDescriptors::kIcCall) ||
        (kind == PcDescriptors::kUnoptStaticCall)) {
      intptr_t deopt_id = descriptors.DeoptId(j);
      ic_data ^= ic_array.At(deopt_id);
      if (!ic_data.IsNull()) {
        intptr_t token_pos = descriptors.TokenPos(j);
        intptr_t line = -1;
        script.GetTokenLocation(token_pos, &line, NULL);
        hits_arr.AddValue(line);
        hits_arr.AddValue(ic_data.AggregateCount());
      }
    }
  }
}


void CodeCoverage::PrintClass(const Class& cls, const JSONArray& jsarr) {
  Isolate* isolate = Isolate::Current();
  Array& functions = Array::Handle(cls.functions());
  ASSERT(!functions.IsNull());
  Function& function = Function::Handle();
  Script& script = Script::Handle();
  String& saved_url = String::Handle();
  String& url = String::Handle();

  int i = 0;
  while (i < functions.Length()) {
    HANDLESCOPE(isolate);
    function ^= functions.At(i);
    JSONObject jsobj(&jsarr);
    script = function.script();
    saved_url = script.url();
    jsobj.AddProperty("source", saved_url.ToCString());
    JSONArray hits_arr(&jsobj, "hits");

    // We stay within this loop while we are seeing functions from the same
    // source URI.
    while (i < functions.Length()) {
      function ^= functions.At(i);
      script = function.script();
      url = script.url();
      if (!url.Equals(saved_url)) {
        break;
      }
      CompileAndAdd(function, hits_arr);
      i++;
    }
  }

  GrowableObjectArray& closures =
      GrowableObjectArray::Handle(cls.closures());
  if (!closures.IsNull()) {
    i = 0;
    // We need to keep rechecking the length of the closures array, as handling
    // a closure potentially adds new entries to the end.
    while (i < closures.Length()) {
      HANDLESCOPE(isolate);
      function ^= closures.At(i);
      JSONObject jsobj(&jsarr);
      script = function.script();
      saved_url = script.url();
      jsobj.AddProperty("source", saved_url.ToCString());
      JSONArray hits_arr(&jsobj, "hits");

      // We stay within this loop while we are seeing functions from the same
      // source URI.
      while (i < closures.Length()) {
        function ^= closures.At(i);
        script = function.script();
        url = script.url();
        if (!url.Equals(saved_url)) {
          break;
        }
        CompileAndAdd(function, hits_arr);
        i++;
      }
    }
  }
}


void CodeCoverage::Write(Isolate* isolate) {
  if (FLAG_coverage_dir == NULL) {
    return;
  }

  Dart_FileOpenCallback file_open = Isolate::file_open_callback();
  Dart_FileWriteCallback file_write = Isolate::file_write_callback();
  Dart_FileCloseCallback file_close = Isolate::file_close_callback();
  if ((file_open == NULL) || (file_write == NULL) || (file_close == NULL)) {
    return;
  }

  JSONStream stream;
  {
    const GrowableObjectArray& libs = GrowableObjectArray::Handle(
        isolate, isolate->object_store()->libraries());
    Library& lib = Library::Handle();
    Class& cls = Class::Handle();
    JSONArray jsarr(&stream);
    for (int i = 0; i < libs.Length(); i++) {
      lib ^= libs.At(i);
      ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
      while (it.HasNext()) {
        cls = it.GetNextClass();
        if (cls.EnsureIsFinalized(isolate) == Error::null()) {
          // Only classes that have been finalized do have a meaningful list of
          // functions.
          PrintClass(cls, jsarr);
        }
      }
    }
  }

  const char* format = "%s/dart-cov-%" Pd "-%" Pd ".json";
  intptr_t pid = OS::ProcessId();
  intptr_t len = OS::SNPrint(NULL, 0, format,
                             FLAG_coverage_dir, pid, isolate->main_port());
  char* filename = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
  OS::SNPrint(filename, len + 1, format,
              FLAG_coverage_dir, pid, isolate->main_port());
  void* file = (*file_open)(filename, true);
  if (file == NULL) {
    OS::Print("Failed to write coverage file: %s\n", filename);
    return;
  }
  (*file_write)(stream.buffer()->buf(), stream.buffer()->length(), file);
  (*file_close)(file);
}

}  // namespace dart
