Skip to content
Permalink
Browse files

src: port coverage serialization to C++

This patch moves the serialization of coverage profiles into
C++. With this we no longer need to patch `process.reallyExit`
and hook into the exit events, but instead hook into relevant
places in C++ which are safe from user manipulation. This also
makes the code easier to reuse for other types of profiles.

PR-URL: #26874
Reviewed-By: Ben Coe <bencoe@gmail.com>
  • Loading branch information...
joyeecheung committed Mar 22, 2019
1 parent baa54a5 commit 864860e9f3d4eed0b0b81af55197d7e525ea6306
@@ -110,20 +110,10 @@ function setupWarningHandler() {
// Setup User-facing NODE_V8_COVERAGE environment variable that writes
// ScriptCoverage to a specified file.
function setupCoverageHooks(dir) {
const originalReallyExit = process.reallyExit;
const cwd = require('internal/process/execution').tryGetCwd();
const { resolve } = require('path');
const coverageDirectory = resolve(cwd, dir);
const {
writeCoverage,
setCoverageDirectory
} = require('internal/profiler');
setCoverageDirectory(coverageDirectory);
process.on('exit', writeCoverage);
process.reallyExit = (code) => {
writeCoverage();
originalReallyExit(code);
};
internalBinding('profiler').setCoverageDirectory(coverageDirectory);
return coverageDirectory;
}

@@ -157,10 +157,6 @@ function wrapProcessMethods(binding) {

function kill(pid, sig) {
var err;
if (process.env.NODE_V8_COVERAGE) {
const { writeCoverage } = require('internal/profiler');
writeCoverage();
}

// eslint-disable-next-line eqeqeq
if (pid != (pid | 0)) {

This file was deleted.

@@ -169,7 +169,6 @@
'lib/internal/process/worker_thread_only.js',
'lib/internal/process/report.js',
'lib/internal/process/task_queues.js',
'lib/internal/profiler.js',
'lib/internal/querystring.js',
'lib/internal/readline.js',
'lib/internal/repl.js',
@@ -638,6 +638,26 @@ inline const std::vector<std::string>& Environment::exec_argv() {
return exec_argv_;
}

#if HAVE_INSPECTOR
inline void Environment::set_coverage_directory(const char* dir) {
coverage_directory_ = std::string(dir);
}

inline void Environment::set_coverage_connection(
std::unique_ptr<profiler::V8CoverageConnection> connection) {
CHECK_NULL(coverage_connection_);
std::swap(coverage_connection_, connection);
}

inline profiler::V8CoverageConnection* Environment::coverage_connection() {
return coverage_connection_.get();
}

inline const std::string& Environment::coverage_directory() const {
return coverage_directory_;
}
#endif // HAVE_INSPECTOR

inline std::shared_ptr<HostPort> Environment::inspector_host_port() {
return inspector_host_port_;
}
@@ -715,7 +715,6 @@ Local<Value> Environment::GetNow() {
return Number::New(isolate(), static_cast<double>(now));
}


void Environment::set_debug_categories(const std::string& cats, bool enabled) {
std::string debug_categories = cats;
while (!debug_categories.empty()) {
@@ -27,6 +27,7 @@
#include "aliased_buffer.h"
#if HAVE_INSPECTOR
#include "inspector_agent.h"
#include "inspector_profiler.h"
#endif
#include "handle_wrap.h"
#include "node.h"
@@ -67,6 +68,12 @@ namespace tracing {
class AgentWriterHandle;
}

#if HAVE_INSPECTOR
namespace profiler {
class V8CoverageConnection;
} // namespace profiler
#endif // HAVE_INSPECTOR

namespace worker {
class Worker;
}
@@ -366,7 +373,6 @@ constexpr size_t kFsStatsBufferLength = kFsStatsFieldsNumber * 2;
V(async_hooks_init_function, v8::Function) \
V(async_hooks_promise_resolve_function, v8::Function) \
V(buffer_prototype_object, v8::Object) \
V(coverage_connection, v8::Object) \
V(crypto_key_object_constructor, v8::Function) \
V(domain_callback, v8::Function) \
V(domexception_function, v8::Function) \
@@ -390,7 +396,6 @@ constexpr size_t kFsStatsBufferLength = kFsStatsFieldsNumber * 2;
V(inspector_console_extension_installer, v8::Function) \
V(message_port, v8::Object) \
V(native_module_require, v8::Function) \
V(on_coverage_message_function, v8::Function) \
V(performance_entry_callback, v8::Function) \
V(performance_entry_template, v8::Function) \
V(process_object, v8::Object) \
@@ -1116,6 +1121,15 @@ class Environment : public MemoryRetainer {

inline AsyncRequest* thread_stopper() { return &thread_stopper_; }

#if HAVE_INSPECTOR
void set_coverage_connection(
std::unique_ptr<profiler::V8CoverageConnection> connection);
profiler::V8CoverageConnection* coverage_connection();

inline void set_coverage_directory(const char* directory);
inline const std::string& coverage_directory() const;
#endif // HAVE_INSPECTOR

private:
inline void CreateImmediate(native_immediate_callback cb,
void* data,
@@ -1146,6 +1160,11 @@ class Environment : public MemoryRetainer {
size_t async_callback_scope_depth_ = 0;
std::vector<double> destroy_async_id_list_;

#if HAVE_INSPECTOR
std::unique_ptr<profiler::V8CoverageConnection> coverage_connection_;
std::string coverage_directory_;
#endif // HAVE_INSPECTOR

std::shared_ptr<EnvironmentOptions> options_;
// options_ contains debug options parsed from CLI arguments,
// while inspector_host_port_ stores the actual inspector host
@@ -44,6 +44,7 @@
'../../src/inspector_io.cc',
'../../src/inspector_agent.h',
'../../src/inspector_io.h',
'../../src/inspector_profiler.h',
'../../src/inspector_profiler.cc',
'../../src/inspector_js_api.cc',
'../../src/inspector_socket.cc',

0 comments on commit 864860e

Please sign in to comment.
You can’t perform that action at this time.