| OLD | NEW |
| 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 Loading... |
| 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/debug/debug-interface.h" |
| 34 #include "src/interpreter/interpreter.h" | 34 #include "src/interpreter/interpreter.h" |
| 35 #include "src/list-inl.h" | 35 #include "src/list-inl.h" |
| 36 #include "src/msan.h" | 36 #include "src/msan.h" |
| 37 #include "src/objects-inl.h" | 37 #include "src/objects-inl.h" |
| 38 #include "src/snapshot/natives.h" | 38 #include "src/snapshot/natives.h" |
| 39 #include "src/utils.h" | 39 #include "src/utils.h" |
| 40 #include "src/v8.h" | 40 #include "src/v8.h" |
| 41 | 41 |
| 42 #ifdef V8_INSPECTOR_ENABLED | 42 #ifdef V8_INSPECTOR_ENABLED |
| 43 #include "include/v8-inspector.h" | 43 #include "include/v8-inspector.h" |
| (...skipping 1607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1651 ->interpreter() | 1651 ->interpreter() |
| 1652 ->GetDispatchCountersObject(); | 1652 ->GetDispatchCountersObject(); |
| 1653 std::ofstream dispatch_counters_stream( | 1653 std::ofstream dispatch_counters_stream( |
| 1654 i::FLAG_trace_ignition_dispatches_output_file); | 1654 i::FLAG_trace_ignition_dispatches_output_file); |
| 1655 dispatch_counters_stream << *String::Utf8Value( | 1655 dispatch_counters_stream << *String::Utf8Value( |
| 1656 JSON::Stringify(context, dispatch_counters).ToLocalChecked()); | 1656 JSON::Stringify(context, dispatch_counters).ToLocalChecked()); |
| 1657 } | 1657 } |
| 1658 | 1658 |
| 1659 namespace { | 1659 namespace { |
| 1660 void ReadRange(std::ofstream* s, std::vector<uint32_t>* lines, | 1660 void ReadRange(std::ofstream* s, std::vector<uint32_t>* lines, |
| 1661 i::Handle<i::Script> script, const i::Coverage::Range* range) { | 1661 debug::Coverage::Range range) { |
| 1662 // Compute line and column numbers from source position. | 1662 // Ensure space in the array. |
| 1663 i::Script::PositionInfo start; | 1663 lines->resize(std::max(static_cast<size_t>(range.End().GetLineNumber() + 1), |
| 1664 i::Script::PositionInfo end; | 1664 lines->size()), |
| 1665 i::Script::GetPositionInfo(script, range->start, &start, | 1665 0); |
| 1666 i::Script::NO_OFFSET); | |
| 1667 i::Script::GetPositionInfo(script, range->end, &end, i::Script::NO_OFFSET); | |
| 1668 // Boundary lines could be shared between two functions with different | 1666 // Boundary lines could be shared between two functions with different |
| 1669 // invocation counts. Take the maximum. | 1667 // invocation counts. Take the maximum. |
| 1670 lines->at(start.line) = std::max(lines->at(start.line), range->count); | 1668 lines->at(range.Start().GetLineNumber()) = |
| 1671 lines->at(end.line) = std::max(lines->at(end.line), range->count); | 1669 std::max(lines->at(range.Start().GetLineNumber()), range.Count()); |
| 1670 lines->at(range.End().GetLineNumber()) = |
| 1671 std::max(lines->at(range.End().GetLineNumber()), range.Count()); |
| 1672 // Invocation counts for non-boundary lines are overwritten. | 1672 // Invocation counts for non-boundary lines are overwritten. |
| 1673 for (int i = start.line + 1; i < end.line; i++) lines->at(i) = range->count; | 1673 int line_plus_one = range.Start().GetLineNumber() + 1; |
| 1674 for (int i = line_plus_one; i < range.End().GetLineNumber(); i++) { |
| 1675 lines->at(i) = range.Count(); |
| 1676 } |
| 1674 // Note that we use 0-based line numbers. But LCOV uses 1-based line numbers. | 1677 // Note that we use 0-based line numbers. But LCOV uses 1-based line numbers. |
| 1675 if (!range->name.empty()) { | 1678 // Recurse over inner ranges. |
| 1676 // Truncate UC16 characters down to Latin1. | 1679 for (size_t i = 0; i < range.NestedCount(); i++) { |
| 1677 std::unique_ptr<char[]> name(new char[range->name.size() + 1]); | 1680 ReadRange(s, lines, range.GetNested(i)); |
| 1678 for (size_t i = 0; i < range->name.size(); i++) { | 1681 } |
| 1679 name[i] = static_cast<char>(range->name.data()[i]); | 1682 // Write function stats. |
| 1680 } | 1683 Local<String> name; |
| 1681 name[range->name.size()] = 0; | 1684 std::stringstream name_stream; |
| 1682 *s << "FN:" << (start.line + 1) << "," << name.get() << std::endl; | 1685 if (range.Name().ToLocal(&name)) { |
| 1683 *s << "FNDA:" << range->count << "," << name.get() << std::endl; | 1686 name_stream << ToSTLString(name); |
| 1684 } else { | 1687 } else { |
| 1685 // Anonymous function. Use line and column as name. | 1688 name_stream << "<" << line_plus_one << "-"; |
| 1686 *s << "FN:" << (start.line + 1) << ","; | 1689 name_stream << range.Start().GetColumnNumber() << ">"; |
| 1687 *s << "<" << (start.line + 1) << "-" << start.column << ">" << std::endl; | |
| 1688 *s << "FNDA:" << range->count << ","; | |
| 1689 *s << "<" << (start.line + 1) << "-" << start.column << ">" << std::endl; | |
| 1690 } | 1690 } |
| 1691 // Recurse over inner ranges. | 1691 *s << "FN:" << line_plus_one << "," << name_stream.str() << std::endl; |
| 1692 for (const auto& inner : range->inner) ReadRange(s, lines, script, &inner); | 1692 *s << "FNDA:" << range.Count() << "," << name_stream.str() << std::endl; |
| 1693 } | 1693 } |
| 1694 } // anonymous namespace | 1694 } // anonymous namespace |
| 1695 | 1695 |
| 1696 // Write coverage data in LCOV format. See man page for geninfo(1). | 1696 // Write coverage data in LCOV format. See man page for geninfo(1). |
| 1697 void Shell::WriteLcovData(v8::Isolate* isolate, const char* file) { | 1697 void Shell::WriteLcovData(v8::Isolate* isolate, const char* file) { |
| 1698 if (!file) return; | 1698 if (!file) return; |
| 1699 HandleScope handle_scope(isolate); | 1699 HandleScope handle_scope(isolate); |
| 1700 std::vector<i::Coverage::ScriptData> data = | 1700 debug::Coverage coverage = debug::Coverage::Collect(isolate); |
| 1701 i::Coverage::Collect(reinterpret_cast<i::Isolate*>(isolate)); | |
| 1702 std::ofstream sink(file, std::ofstream::app); | 1701 std::ofstream sink(file, std::ofstream::app); |
| 1703 for (const auto& script_data : data) { | 1702 for (size_t i = 0; i < coverage.ScriptCount(); i++) { |
| 1704 i::Handle<i::Script> script = script_data.script; | 1703 Local<debug::Script> script = coverage.GetScript(i); |
| 1705 // Skip unnamed scripts. | 1704 // Skip unnamed scripts. |
| 1706 if (!script->name()->IsString()) continue; | 1705 Local<String> name; |
| 1707 std::string file_name = ToSTLString(v8::Utils::ToLocal( | 1706 if (!script->Name().ToLocal(&name)) continue; |
| 1708 i::Handle<i::String>(i::String::cast(script->name())))); | 1707 std::string file_name = ToSTLString(name); |
| 1709 // Skip scripts not backed by a file. | 1708 // Skip scripts not backed by a file. |
| 1710 if (!std::ifstream(file_name).good()) continue; | 1709 if (!std::ifstream(file_name).good()) continue; |
| 1711 sink << "SF:"; | 1710 sink << "SF:"; |
| 1712 sink << NormalizePath(file_name, GetWorkingDirectory()) << std::endl; | 1711 sink << NormalizePath(file_name, GetWorkingDirectory()) << std::endl; |
| 1713 std::vector<uint32_t> lines; | 1712 std::vector<uint32_t> lines; |
| 1714 lines.resize(i::FixedArray::cast(script->line_ends())->length(), 0); | 1713 ReadRange(&sink, &lines, coverage.GetRange(i)); |
| 1715 ReadRange(&sink, &lines, script, &script_data.toplevel); | |
| 1716 // Write per-line coverage. LCOV uses 1-based line numbers. | 1714 // Write per-line coverage. LCOV uses 1-based line numbers. |
| 1717 for (size_t i = 0; i < lines.size(); i++) { | 1715 for (size_t i = 0; i < lines.size(); i++) { |
| 1718 sink << "DA:" << (i + 1) << "," << lines[i] << std::endl; | 1716 sink << "DA:" << (i + 1) << "," << lines[i] << std::endl; |
| 1719 } | 1717 } |
| 1720 sink << "end_of_record" << std::endl; | 1718 sink << "end_of_record" << std::endl; |
| 1721 } | 1719 } |
| 1722 } | 1720 } |
| 1723 | 1721 |
| 1724 void Shell::OnExit(v8::Isolate* isolate) { | 1722 void Shell::OnExit(v8::Isolate* isolate) { |
| 1725 // Dump basic block profiling data. | 1723 // Dump basic block profiling data. |
| (...skipping 780 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2506 | 2504 |
| 2507 return true; | 2505 return true; |
| 2508 } | 2506 } |
| 2509 | 2507 |
| 2510 | 2508 |
| 2511 int Shell::RunMain(Isolate* isolate, int argc, char* argv[], bool last_run) { | 2509 int Shell::RunMain(Isolate* isolate, int argc, char* argv[], bool last_run) { |
| 2512 for (int i = 1; i < options.num_isolates; ++i) { | 2510 for (int i = 1; i < options.num_isolates; ++i) { |
| 2513 options.isolate_sources[i].StartExecuteInThread(); | 2511 options.isolate_sources[i].StartExecuteInThread(); |
| 2514 } | 2512 } |
| 2515 { | 2513 { |
| 2516 if (options.lcov_file) { | 2514 if (options.lcov_file) debug::Coverage::TogglePrecise(isolate, true); |
| 2517 i::Coverage::EnablePrecise(reinterpret_cast<i::Isolate*>(isolate)); | |
| 2518 } | |
| 2519 HandleScope scope(isolate); | 2515 HandleScope scope(isolate); |
| 2520 Local<Context> context = CreateEvaluationContext(isolate); | 2516 Local<Context> context = CreateEvaluationContext(isolate); |
| 2521 if (last_run && options.use_interactive_shell()) { | 2517 if (last_run && options.use_interactive_shell()) { |
| 2522 // Keep using the same context in the interactive shell. | 2518 // Keep using the same context in the interactive shell. |
| 2523 evaluation_context_.Reset(isolate, context); | 2519 evaluation_context_.Reset(isolate, context); |
| 2524 } | 2520 } |
| 2525 { | 2521 { |
| 2526 Context::Scope cscope(context); | 2522 Context::Scope cscope(context); |
| 2527 InspectorClient inspector_client(context, options.enable_inspector); | 2523 InspectorClient inspector_client(context, options.enable_inspector); |
| 2528 PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate)); | 2524 PerIsolateData::RealmScope realm_scope(PerIsolateData::Get(isolate)); |
| (...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3001 } | 2997 } |
| 3002 | 2998 |
| 3003 } // namespace v8 | 2999 } // namespace v8 |
| 3004 | 3000 |
| 3005 | 3001 |
| 3006 #ifndef GOOGLE3 | 3002 #ifndef GOOGLE3 |
| 3007 int main(int argc, char* argv[]) { | 3003 int main(int argc, char* argv[]) { |
| 3008 return v8::Shell::Main(argc, argv); | 3004 return v8::Shell::Main(argc, argv); |
| 3009 } | 3005 } |
| 3010 #endif | 3006 #endif |
| OLD | NEW |