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: 88 107 82.2 %
Date: 2017-06-14 Branches: 26 44 59.1 %

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

51
        return hook.cb_ == fn && hook.arg_ == arg;
200
102
      });
201
202
51
  if (it == promise_hooks_.end()) return false;
203
204
51
  promise_hooks_.erase(it);
205
51
  if (promise_hooks_.empty()) {
206
51
    isolate_->SetPromiseHook(nullptr);
207
  }
208
209
51
  return true;
210
}
211
212
985
void Environment::EnvPromiseHook(v8::PromiseHookType type,
213
                                 v8::Local<v8::Promise> promise,
214
                                 v8::Local<v8::Value> parent) {
215
985
  Environment* env = Environment::GetCurrent(promise->CreationContext());
216
1970
  for (const PromiseHookCallback& hook : env->promise_hooks_) {
217
985
    hook.cb_(type, promise, parent, hook.arg_);
218
  }
219
985
}
220
221
}  // namespace node