Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(544)

Side by Side Diff: src/d8.cc

Issue 2695823003: [debugger] add lcov support to d8. (Closed)
Patch Set: actual fix Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/d8.h ('k') | src/debug/debug-coverage.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <errno.h> 5 #include <errno.h>
6 #include <stdlib.h> 6 #include <stdlib.h>
7 #include <string.h> 7 #include <string.h>
8 #include <sys/stat.h> 8 #include <sys/stat.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
(...skipping 12 matching lines...) Expand all
23 #include "include/libplatform/libplatform.h" 23 #include "include/libplatform/libplatform.h"
24 #include "include/libplatform/v8-tracing.h" 24 #include "include/libplatform/v8-tracing.h"
25 #include "src/api.h" 25 #include "src/api.h"
26 #include "src/base/cpu.h" 26 #include "src/base/cpu.h"
27 #include "src/base/debug/stack_trace.h" 27 #include "src/base/debug/stack_trace.h"
28 #include "src/base/logging.h" 28 #include "src/base/logging.h"
29 #include "src/base/platform/platform.h" 29 #include "src/base/platform/platform.h"
30 #include "src/base/platform/time.h" 30 #include "src/base/platform/time.h"
31 #include "src/base/sys-info.h" 31 #include "src/base/sys-info.h"
32 #include "src/basic-block-profiler.h" 32 #include "src/basic-block-profiler.h"
33 #include "src/debug/debug-coverage.h"
33 #include "src/interpreter/interpreter.h" 34 #include "src/interpreter/interpreter.h"
34 #include "src/list-inl.h" 35 #include "src/list-inl.h"
35 #include "src/msan.h" 36 #include "src/msan.h"
36 #include "src/objects-inl.h" 37 #include "src/objects-inl.h"
37 #include "src/snapshot/natives.h" 38 #include "src/snapshot/natives.h"
38 #include "src/utils.h" 39 #include "src/utils.h"
39 #include "src/v8.h" 40 #include "src/v8.h"
40 41
41 #ifdef V8_INSPECTOR_ENABLED 42 #ifdef V8_INSPECTOR_ENABLED
42 #include "include/v8-inspector.h" 43 #include "include/v8-inspector.h"
(...skipping 1604 matching lines...) Expand 10 before | Expand all | Expand 10 after
1647 1648
1648 Local<Object> dispatch_counters = reinterpret_cast<i::Isolate*>(isolate) 1649 Local<Object> dispatch_counters = reinterpret_cast<i::Isolate*>(isolate)
1649 ->interpreter() 1650 ->interpreter()
1650 ->GetDispatchCountersObject(); 1651 ->GetDispatchCountersObject();
1651 std::ofstream dispatch_counters_stream( 1652 std::ofstream dispatch_counters_stream(
1652 i::FLAG_trace_ignition_dispatches_output_file); 1653 i::FLAG_trace_ignition_dispatches_output_file);
1653 dispatch_counters_stream << *String::Utf8Value( 1654 dispatch_counters_stream << *String::Utf8Value(
1654 JSON::Stringify(context, dispatch_counters).ToLocalChecked()); 1655 JSON::Stringify(context, dispatch_counters).ToLocalChecked());
1655 } 1656 }
1656 1657
1658 namespace {
1659 void ReadRange(std::ofstream* s, std::vector<uint32_t>* lines,
1660 i::Handle<i::Script> script, const i::Coverage::Range* range) {
1661 // Compute line and column numbers from source position.
1662 i::Script::PositionInfo start;
1663 i::Script::PositionInfo end;
1664 i::Script::GetPositionInfo(script, range->start, &start,
1665 i::Script::NO_OFFSET);
1666 i::Script::GetPositionInfo(script, range->end, &end, i::Script::NO_OFFSET);
1667 // Boundary lines could be shared between two functions with different
1668 // invocation counts. Take the maximum.
1669 lines->at(start.line) = std::max(lines->at(start.line), range->count);
1670 lines->at(end.line) = std::max(lines->at(end.line), range->count);
1671 // Invocation counts for non-boundary lines are overwritten.
1672 for (int i = start.line + 1; i < end.line; i++) lines->at(i) = range->count;
1673 // Note that we use 0-based line numbers. But LCOV uses 1-based line numbers.
1674 if (!range->name.empty()) {
1675 // Truncate UC16 characters down to Latin1.
1676 std::unique_ptr<char[]> name(new char[range->name.size() + 1]);
1677 for (size_t i = 0; i < range->name.size(); i++) {
1678 name[i] = static_cast<char>(range->name.data()[i]);
1679 }
1680 name[range->name.size()] = 0;
1681 *s << "FN:" << (start.line + 1) << "," << name.get() << std::endl;
1682 *s << "FNDA:" << range->count << "," << name.get() << std::endl;
1683 } else {
1684 // Anonymous function. Use line and column as name.
1685 *s << "FN:" << (start.line + 1) << ",";
1686 *s << "<" << (start.line + 1) << "-" << start.column << ">" << std::endl;
1687 *s << "FNDA:" << range->count << ",";
1688 *s << "<" << (start.line + 1) << "-" << start.column << ">" << std::endl;
1689 }
1690 // Recurse over inner ranges.
1691 for (const auto& inner : range->inner) ReadRange(s, lines, script, &inner);
1692 }
1693 } // anonymous namespace
1694
1695 // Write coverage data in LCOV format. See man page for geninfo(1).
1696 void Shell::WriteLcovData(v8::Isolate* isolate, const char* file) {
1697 if (!file) return;
1698 HandleScope handle_scope(isolate);
1699 std::vector<i::Coverage::ScriptData> data =
1700 i::Coverage::Collect(reinterpret_cast<i::Isolate*>(isolate));
1701 std::ofstream sink(file, std::ofstream::app);
1702 for (const auto& script_data : data) {
1703 i::Handle<i::Script> script = script_data.script;
1704 // Skip unnamed scripts.
1705 if (!script->name()->IsString()) continue;
1706 std::string file_name = ToSTLString(v8::Utils::ToLocal(
1707 i::Handle<i::String>(i::String::cast(script->name()))));
1708 // Skip scripts not backed by a file.
1709 if (!std::ifstream(file_name).good()) continue;
1710 sink << "SF:";
1711 sink << NormalizePath(file_name, GetWorkingDirectory()) << std::endl;
1712 std::vector<uint32_t> lines;
1713 lines.resize(i::FixedArray::cast(script->line_ends())->length(), 0);
1714 ReadRange(&sink, &lines, script, &script_data.toplevel);
1715 // Write per-line coverage. LCOV uses 1-based line numbers.
1716 for (size_t i = 0; i < lines.size(); i++) {
1717 sink << "DA:" << (i + 1) << "," << lines[i] << std::endl;
1718 }
1719 sink << "end_of_record" << std::endl;
1720 }
1721 }
1657 1722
1658 void Shell::OnExit(v8::Isolate* isolate) { 1723 void Shell::OnExit(v8::Isolate* isolate) {
1659 if (i::FLAG_dump_counters || i::FLAG_dump_counters_nvp) { 1724 if (i::FLAG_dump_counters || i::FLAG_dump_counters_nvp) {
1660 int number_of_counters = 0; 1725 int number_of_counters = 0;
1661 for (CounterMap::Iterator i(counter_map_); i.More(); i.Next()) { 1726 for (CounterMap::Iterator i(counter_map_); i.More(); i.Next()) {
1662 number_of_counters++; 1727 number_of_counters++;
1663 } 1728 }
1664 CounterAndKey* counters = new CounterAndKey[number_of_counters]; 1729 CounterAndKey* counters = new CounterAndKey[number_of_counters];
1665 int j = 0; 1730 int j = 0;
1666 for (CounterMap::Iterator i(counter_map_); i.More(); i.Next(), j++) { 1731 for (CounterMap::Iterator i(counter_map_); i.More(); i.Next(), j++) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1707 "-------------+\n"); 1772 "-------------+\n");
1708 } 1773 }
1709 delete [] counters; 1774 delete [] counters;
1710 } 1775 }
1711 1776
1712 delete counters_file_; 1777 delete counters_file_;
1713 delete counter_map_; 1778 delete counter_map_;
1714 } 1779 }
1715 1780
1716 1781
1717
1718 static FILE* FOpen(const char* path, const char* mode) { 1782 static FILE* FOpen(const char* path, const char* mode) {
1719 #if defined(_MSC_VER) && (defined(_WIN32) || defined(_WIN64)) 1783 #if defined(_MSC_VER) && (defined(_WIN32) || defined(_WIN64))
1720 FILE* result; 1784 FILE* result;
1721 if (fopen_s(&result, path, mode) == 0) { 1785 if (fopen_s(&result, path, mode) == 0) {
1722 return result; 1786 return result;
1723 } else { 1787 } else {
1724 return NULL; 1788 return NULL;
1725 } 1789 }
1726 #else 1790 #else
1727 FILE* file = fopen(path, mode); 1791 FILE* file = fopen(path, mode);
(...skipping 661 matching lines...) Expand 10 before | Expand all | Expand 10 after
2389 argv[i] = NULL; 2453 argv[i] = NULL;
2390 } else if (strcmp(argv[i], "--enable-tracing") == 0) { 2454 } else if (strcmp(argv[i], "--enable-tracing") == 0) {
2391 options.trace_enabled = true; 2455 options.trace_enabled = true;
2392 argv[i] = NULL; 2456 argv[i] = NULL;
2393 } else if (strncmp(argv[i], "--trace-config=", 15) == 0) { 2457 } else if (strncmp(argv[i], "--trace-config=", 15) == 0) {
2394 options.trace_config = argv[i] + 15; 2458 options.trace_config = argv[i] + 15;
2395 argv[i] = NULL; 2459 argv[i] = NULL;
2396 } else if (strcmp(argv[i], "--enable-inspector") == 0) { 2460 } else if (strcmp(argv[i], "--enable-inspector") == 0) {
2397 options.enable_inspector = true; 2461 options.enable_inspector = true;
2398 argv[i] = NULL; 2462 argv[i] = NULL;
2463 } else if (strncmp(argv[i], "--lcov=", 7) == 0) {
2464 options.lcov_file = argv[i] + 7;
2465 argv[i] = NULL;
2399 } 2466 }
2400 } 2467 }
2401 2468
2402 v8::V8::SetFlagsFromCommandLine(&argc, argv, true); 2469 v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
2403 2470
2404 // Set up isolated source groups. 2471 // Set up isolated source groups.
2405 options.isolate_sources = new SourceGroup[options.num_isolates]; 2472 options.isolate_sources = new SourceGroup[options.num_isolates];
2406 SourceGroup* current = options.isolate_sources; 2473 SourceGroup* current = options.isolate_sources;
2407 current->Begin(argv, 1); 2474 current->Begin(argv, 1);
2408 for (int i = 1; i < argc; i++) { 2475 for (int i = 1; i < argc; i++) {
(...skipping 21 matching lines...) Expand all
2430 2497
2431 return true; 2498 return true;
2432 } 2499 }
2433 2500
2434 2501
2435 int Shell::RunMain(Isolate* isolate, int argc, char* argv[], bool last_run) { 2502 int Shell::RunMain(Isolate* isolate, int argc, char* argv[], bool last_run) {
2436 for (int i = 1; i < options.num_isolates; ++i) { 2503 for (int i = 1; i < options.num_isolates; ++i) {
2437 options.isolate_sources[i].StartExecuteInThread(); 2504 options.isolate_sources[i].StartExecuteInThread();
2438 } 2505 }
2439 { 2506 {
2507 if (options.lcov_file) {
2508 i::Coverage::EnablePrecise(reinterpret_cast<i::Isolate*>(isolate));
2509 }
2440 HandleScope scope(isolate); 2510 HandleScope scope(isolate);
2441 Local<Context> context = CreateEvaluationContext(isolate); 2511 Local<Context> context = CreateEvaluationContext(isolate);
2442 if (last_run && options.use_interactive_shell()) { 2512 if (last_run && options.use_interactive_shell()) {
2443 // Keep using the same context in the interactive shell. 2513 // Keep using the same context in the interactive shell.
2444 evaluation_context_.Reset(isolate, context); 2514 evaluation_context_.Reset(isolate, context);
2445 } 2515 }
2446 { 2516 {
2447 Context::Scope cscope(context); 2517 Context::Scope cscope(context);
2448 InspectorClient inspector_client(context, options.enable_inspector); 2518 InspectorClient inspector_client(context, options.enable_inspector);
2449 PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate)); 2519 PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate));
2450 options.isolate_sources[0].Execute(isolate); 2520 options.isolate_sources[0].Execute(isolate);
2451 } 2521 }
2452 DisposeModuleEmbedderData(context); 2522 DisposeModuleEmbedderData(context);
2523 WriteLcovData(isolate, options.lcov_file);
2453 } 2524 }
2454 CollectGarbage(isolate); 2525 CollectGarbage(isolate);
2455 for (int i = 1; i < options.num_isolates; ++i) { 2526 for (int i = 1; i < options.num_isolates; ++i) {
2456 if (last_run) { 2527 if (last_run) {
2457 options.isolate_sources[i].JoinThread(); 2528 options.isolate_sources[i].JoinThread();
2458 } else { 2529 } else {
2459 options.isolate_sources[i].WaitForThread(); 2530 options.isolate_sources[i].WaitForThread();
2460 } 2531 }
2461 } 2532 }
2462 CleanupWorkers(); 2533 CleanupWorkers();
(...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after
2928 } 2999 }
2929 3000
2930 } // namespace v8 3001 } // namespace v8
2931 3002
2932 3003
2933 #ifndef GOOGLE3 3004 #ifndef GOOGLE3
2934 int main(int argc, char* argv[]) { 3005 int main(int argc, char* argv[]) {
2935 return v8::Shell::Main(argc, argv); 3006 return v8::Shell::Main(argc, argv);
2936 } 3007 }
2937 #endif 3008 #endif
OLDNEW
« no previous file with comments | « src/d8.h ('k') | src/debug/debug-coverage.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698