GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage/nodes/benchmark/out/../src/env.cc Lines: 95 112 84.8 %
Date: 2017-10-21 Branches: 30 44 68.2 %

Line Branch Exec Source
1
#include "node_internals.h"
2
#include "async-wrap.h"
3
#include "v8-profiler.h"
4
5
#if defined(_MSC_VER)
6
#define getpid GetCurrentProcessId
7
#else
8
#include <unistd.h>
9
#endif
10
11
#include <stdio.h>
12
#include <algorithm>
13
14
namespace node {
15
16
using v8::Context;
17
using v8::FunctionTemplate;
18
using v8::HandleScope;
19
using v8::Local;
20
using v8::Message;
21
using v8::StackFrame;
22
using v8::StackTrace;
23
24
3206
void Environment::Start(int argc,
25
                        const char* const* argv,
26
                        int exec_argc,
27
                        const char* const* exec_argv,
28
                        bool start_profiler_idle_notifier) {
29
3206
  HandleScope handle_scope(isolate());
30
3206
  Context::Scope context_scope(context());
31
32
3206
  uv_check_init(event_loop(), immediate_check_handle());
33
3206
  uv_unref(reinterpret_cast<uv_handle_t*>(immediate_check_handle()));
34
35
3206
  uv_idle_init(event_loop(), immediate_idle_handle());
36
37
  // Inform V8's CPU profiler when we're idle.  The profiler is sampling-based
38
  // but not all samples are created equal; mark the wall clock time spent in
39
  // epoll_wait() and friends so profiling tools can filter it out.  The samples
40
  // still end up in v8.log but with state=IDLE rather than state=EXTERNAL.
41
  // TODO(bnoordhuis) Depends on a libuv implementation detail that we should
42
  // probably fortify in the API contract, namely that the last started prepare
43
  // or check watcher runs first.  It's not 100% foolproof; if an add-on starts
44
  // a prepare or check watcher after us, any samples attributed to its callback
45
  // will be recorded with state=IDLE.
46
3206
  uv_prepare_init(event_loop(), &idle_prepare_handle_);
47
3206
  uv_check_init(event_loop(), &idle_check_handle_);
48
3206
  uv_unref(reinterpret_cast<uv_handle_t*>(&idle_prepare_handle_));
49
3206
  uv_unref(reinterpret_cast<uv_handle_t*>(&idle_check_handle_));
50
51
3206
  uv_timer_init(event_loop(), destroy_async_ids_timer_handle());
52
53
16070
  auto close_and_finish = [](Environment* env, uv_handle_t* handle, void* arg) {
54
20
    handle->data = env;
55
56
60
    uv_close(handle, [](uv_handle_t* handle) {
57
20
      static_cast<Environment*>(handle->data)->FinishHandleCleanup(handle);
58
80
    });
59
16070
  };
60
61
  RegisterHandleCleanup(
62
3206
      reinterpret_cast<uv_handle_t*>(immediate_check_handle()),
63
      close_and_finish,
64
6412
      nullptr);
65
  RegisterHandleCleanup(
66
3206
      reinterpret_cast<uv_handle_t*>(immediate_idle_handle()),
67
      close_and_finish,
68
6412
      nullptr);
69
  RegisterHandleCleanup(
70
      reinterpret_cast<uv_handle_t*>(&idle_prepare_handle_),
71
      close_and_finish,
72
3206
      nullptr);
73
  RegisterHandleCleanup(
74
      reinterpret_cast<uv_handle_t*>(&idle_check_handle_),
75
      close_and_finish,
76
3206
      nullptr);
77
  RegisterHandleCleanup(
78
      reinterpret_cast<uv_handle_t*>(&destroy_async_ids_timer_handle_),
79
      close_and_finish,
80
3206
      nullptr);
81
82
3206
  if (start_profiler_idle_notifier) {
83
    StartProfilerIdleNotifier();
84
  }
85
86
3206
  auto process_template = FunctionTemplate::New(isolate());
87
6412
  process_template->SetClassName(FIXED_ONE_BYTE_STRING(isolate(), "process"));
88
89
  auto process_object =
90
12824
      process_template->GetFunction()->NewInstance(context()).ToLocalChecked();
91
3206
  set_process_object(process_object);
92
93
3206
  SetupProcessObject(this, argc, argv, exec_argc, exec_argv);
94
6412
  LoadAsyncWrapperInfo(this);
95
3206
}
96
97
24
void Environment::CleanupHandles() {
98
24
  while (HandleCleanup* hc = handle_cleanup_queue_.PopFront()) {
99
20
    handle_cleanup_waiting_++;
100
20
    hc->cb_(this, hc->handle_, hc->arg_);
101
20
    delete hc;
102
  }
103
104
12
  while (handle_cleanup_waiting_ != 0)
105
24
    uv_run(event_loop(), UV_RUN_ONCE);
106
4
}
107
108
void Environment::StartProfilerIdleNotifier() {
109
  uv_prepare_start(&idle_prepare_handle_, [](uv_prepare_t* handle) {
110
    Environment* env = ContainerOf(&Environment::idle_prepare_handle_, handle);
111
    env->isolate()->GetCpuProfiler()->SetIdle(true);
112
  });
113
114
  uv_check_start(&idle_check_handle_, [](uv_check_t* handle) {
115
    Environment* env = ContainerOf(&Environment::idle_check_handle_, handle);
116
    env->isolate()->GetCpuProfiler()->SetIdle(false);
117
  });
118
}
119
120
void Environment::StopProfilerIdleNotifier() {
121
  uv_prepare_stop(&idle_prepare_handle_);
122
  uv_check_stop(&idle_check_handle_);
123
}
124
125
246552
void Environment::PrintSyncTrace() const {
126
246552
  if (!trace_sync_io_)
127
493092
    return;
128
129
12
  HandleScope handle_scope(isolate());
130
  Local<v8::StackTrace> stack =
131
12
      StackTrace::CurrentStackTrace(isolate(), 10, StackTrace::kDetailed);
132
133
12
  fprintf(stderr, "(node:%d) WARNING: Detected use of sync API\n", getpid());
134
135
198
  for (int i = 0; i < stack->GetFrameCount() - 1; i++) {
136
174
    Local<StackFrame> stack_frame = stack->GetFrame(i);
137
174
    node::Utf8Value fn_name_s(isolate(), stack_frame->GetFunctionName());
138
261
    node::Utf8Value script_name(isolate(), stack_frame->GetScriptName());
139
87
    const int line_number = stack_frame->GetLineNumber();
140
87
    const int column = stack_frame->GetColumn();
141
142
87
    if (stack_frame->IsEval()) {
143
      if (stack_frame->GetScriptId() == Message::kNoScriptIdInfo) {
144
        fprintf(stderr, "    at [eval]:%i:%i\n", line_number, column);
145
      } else {
146
        fprintf(stderr,
147
                "    at [eval] (%s:%i:%i)\n",
148
                *script_name,
149
                line_number,
150
                column);
151
      }
152
      break;
153
    }
154
155
87
    if (fn_name_s.length() == 0) {
156
12
      fprintf(stderr, "    at %s:%i:%i\n", *script_name, line_number, column);
157
    } else {
158
      fprintf(stderr,
159
              "    at %s (%s:%i:%i)\n",
160
              *fn_name_s,
161
              *script_name,
162
              line_number,
163
75
              column);
164
    }
165
87
  }
166
12
  fflush(stderr);
167
}
168
169
2844
void Environment::RunAtExitCallbacks() {
170
2855
  for (AtExitCallback at_exit : at_exit_functions_) {
171
11
    at_exit.cb_(at_exit.arg_);
172
  }
173
2844
  at_exit_functions_.clear();
174
2844
}
175
176
11
void Environment::AtExit(void (*cb)(void* arg), void* arg) {
177
11
  at_exit_functions_.push_back(AtExitCallback{cb, arg});
178
11
}
179
180
346
void Environment::AddPromiseHook(promise_hook_func fn, void* arg) {
181
  auto it = std::find_if(
182
      promise_hooks_.begin(), promise_hooks_.end(),
183
3
      [&](const PromiseHookCallback& hook) {
184

3
        return hook.cb_ == fn && hook.arg_ == arg;
185
349
      });
186
346
  if (it != promise_hooks_.end()) {
187
3
    it->enable_count_++;
188
349
    return;
189
  }
190
343
  promise_hooks_.push_back(PromiseHookCallback{fn, arg, 1});
191
192
343
  if (promise_hooks_.size() == 1) {
193
343
    isolate_->SetPromiseHook(EnvPromiseHook);
194
  }
195
}
196
197
98
bool Environment::RemovePromiseHook(promise_hook_func fn, void* arg) {
198
  auto it = std::find_if(
199
      promise_hooks_.begin(), promise_hooks_.end(),
200
98
      [&](const PromiseHookCallback& hook) {
201

98
        return hook.cb_ == fn && hook.arg_ == arg;
202
196
      });
203
204
98
  if (it == promise_hooks_.end()) return false;
205
206
98
  if (--it->enable_count_ > 0) return true;
207
208
95
  promise_hooks_.erase(it);
209
95
  if (promise_hooks_.empty()) {
210
95
    isolate_->SetPromiseHook(nullptr);
211
  }
212
213
95
  return true;
214
}
215
216
44
bool Environment::EmitNapiWarning() {
217
44
  bool current_value = emit_napi_warning_;
218
44
  emit_napi_warning_ = false;
219
44
  return current_value;
220
}
221
222
1181
void Environment::EnvPromiseHook(v8::PromiseHookType type,
223
                                 v8::Local<v8::Promise> promise,
224
                                 v8::Local<v8::Value> parent) {
225
1181
  Environment* env = Environment::GetCurrent(promise->CreationContext());
226
2362
  for (const PromiseHookCallback& hook : env->promise_hooks_) {
227
1181
    hook.cb_(type, promise, parent, hook.arg_);
228
  }
229
1181
}
230
231
}  // namespace node