GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/stream_base-inl.h Lines: 205 212 96.7 %
Date: 2019-02-26 22:23:30 Branches: 83 134 61.9 %

Line Branch Exec Source
1
#ifndef SRC_STREAM_BASE_INL_H_
2
#define SRC_STREAM_BASE_INL_H_
3
4
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
5
6
#include "stream_base.h"
7
8
#include "node.h"
9
#include "env-inl.h"
10
#include "v8.h"
11
12
namespace node {
13
14
using v8::Signature;
15
using v8::External;
16
using v8::FunctionCallbackInfo;
17
using v8::FunctionTemplate;
18
using v8::HandleScope;
19
using v8::Local;
20
using v8::Object;
21
using v8::PropertyAttribute;
22
using v8::PropertyCallbackInfo;
23
using v8::String;
24
using v8::Value;
25
26
using AsyncHooks = Environment::AsyncHooks;
27
28
48024
inline void StreamReq::AttachToObject(v8::Local<v8::Object> req_wrap_obj) {
29
96048
  CHECK_EQ(req_wrap_obj->GetAlignedPointerFromInternalField(kStreamReqField),
30
           nullptr);
31
48024
  req_wrap_obj->SetAlignedPointerInInternalField(kStreamReqField, this);
32
48024
}
33
34
592
inline StreamReq* StreamReq::FromObject(v8::Local<v8::Object> req_wrap_obj) {
35
  return static_cast<StreamReq*>(
36
1184
      req_wrap_obj->GetAlignedPointerFromInternalField(kStreamReqField));
37
}
38
39
48001
inline void StreamReq::Dispose() {
40
96002
  object()->SetAlignedPointerInInternalField(kStreamReqField, nullptr);
41
48001
  delete this;
42
48001
}
43
44
48599
inline v8::Local<v8::Object> StreamReq::object() {
45
48599
  return GetAsyncWrap()->object();
46
}
47
48
112925
inline StreamListener::~StreamListener() {
49
112925
  if (stream_ != nullptr)
50
98007
    stream_->RemoveStreamListener(this);
51
112925
}
52
53
10718
inline void StreamListener::PassReadErrorToPreviousListener(ssize_t nread) {
54
10718
  CHECK_NOT_NULL(previous_listener_);
55
10718
  previous_listener_->OnStreamRead(nread, uv_buf_init(nullptr, 0));
56
10718
}
57
58
18884
inline void StreamListener::OnStreamAfterShutdown(ShutdownWrap* w, int status) {
59
18884
  CHECK_NOT_NULL(previous_listener_);
60
18884
  previous_listener_->OnStreamAfterShutdown(w, status);
61
18884
}
62
63
2596
inline void StreamListener::OnStreamAfterWrite(WriteWrap* w, int status) {
64
2596
  CHECK_NOT_NULL(previous_listener_);
65
2596
  previous_listener_->OnStreamAfterWrite(w, status);
66
2596
}
67
68
76715
inline StreamResource::~StreamResource() {
69
153950
  while (listener_ != nullptr) {
70
520
    StreamListener* listener = listener_;
71
520
    listener->OnStreamDestroy();
72
    // Remove the listener if it didn’t remove itself. This makes the logic
73
    // in `OnStreamDestroy()` implementations easier, because they
74
    // may call generic cleanup functions which can just remove the
75
    // listener unconditionally.
76
520
    if (listener == listener_)
77
520
      RemoveStreamListener(listener_);
78
  }
79
76715
}
80
81
130746
inline void StreamResource::PushStreamListener(StreamListener* listener) {
82
130746
  CHECK_NOT_NULL(listener);
83
130746
  CHECK_NULL(listener->stream_);
84
85
130746
  listener->previous_listener_ = listener_;
86
130746
  listener->stream_ = this;
87
88
130746
  listener_ = listener;
89
130746
}
90
91
130240
inline void StreamResource::RemoveStreamListener(StreamListener* listener) {
92
130240
  CHECK_NOT_NULL(listener);
93
94
  StreamListener* previous;
95
  StreamListener* current;
96
97
  // Remove from the linked list.
98
130760
  for (current = listener_, previous = nullptr;
99
       /* No loop condition because we want a crash if listener is not found */
100
       ; previous = current, current = current->previous_listener_) {
101
130760
    CHECK_NOT_NULL(current);
102
130760
    if (current == listener) {
103
130240
      if (previous != nullptr)
104
520
        previous->previous_listener_ = current->previous_listener_;
105
      else
106
129720
        listener_ = listener->previous_listener_;
107
130240
      break;
108
    }
109
520
  }
110
111
130240
  listener->stream_ = nullptr;
112
130240
  listener->previous_listener_ = nullptr;
113
130240
}
114
115
477656
inline uv_buf_t StreamResource::EmitAlloc(size_t suggested_size) {
116
#ifdef DEBUG
117
  v8::SealHandleScope handle_scope(v8::Isolate::GetCurrent());
118
#endif
119
477656
  return listener_->OnStreamAlloc(suggested_size);
120
}
121
122
489258
inline void StreamResource::EmitRead(ssize_t nread, const uv_buf_t& buf) {
123
#ifdef DEBUG
124
  v8::SealHandleScope handle_scope(v8::Isolate::GetCurrent());
125
#endif
126
489258
  if (nread > 0)
127
471477
    bytes_read_ += static_cast<uint64_t>(nread);
128
489258
  listener_->OnStreamRead(nread, buf);
129
489185
}
130
131
4937
inline void StreamResource::EmitAfterWrite(WriteWrap* w, int status) {
132
#ifdef DEBUG
133
  v8::SealHandleScope handle_scope(v8::Isolate::GetCurrent());
134
#endif
135
4937
  listener_->OnStreamAfterWrite(w, status);
136
4934
}
137
138
21484
inline void StreamResource::EmitAfterShutdown(ShutdownWrap* w, int status) {
139
#ifdef DEBUG
140
  v8::SealHandleScope handle_scope(v8::Isolate::GetCurrent());
141
#endif
142
21484
  listener_->OnStreamAfterShutdown(w, status);
143
21484
}
144
145
2599
inline void StreamResource::EmitWantsWrite(size_t suggested_size) {
146
#ifdef DEBUG
147
  v8::SealHandleScope handle_scope(v8::Isolate::GetCurrent());
148
#endif
149
2599
  listener_->OnStreamWantsWrite(suggested_size);
150
2599
}
151
152
77191
inline StreamBase::StreamBase(Environment* env) : env_(env) {
153
77191
  PushStreamListener(&default_listener_);
154
77191
}
155
156
989533
inline Environment* StreamBase::stream_env() const {
157
989533
  return env_;
158
}
159
160
43067
inline int StreamBase::Shutdown(v8::Local<v8::Object> req_wrap_obj) {
161
43067
  Environment* env = stream_env();
162
163
43067
  HandleScope handle_scope(env->isolate());
164
165
43067
  if (req_wrap_obj.IsEmpty()) {
166
904
    if (!env->shutdown_wrap_template()
167
1356
             ->NewInstance(env->context())
168
1356
             .ToLocal(&req_wrap_obj)) {
169
      return UV_EBUSY;
170
    }
171
452
    StreamReq::ResetObject(req_wrap_obj);
172
  }
173
174
86134
  AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(GetAsyncWrap());
175
43067
  ShutdownWrap* req_wrap = CreateShutdownWrap(req_wrap_obj);
176
43067
  int err = DoShutdown(req_wrap);
177
178
43067
  if (err != 0) {
179
21580
    req_wrap->Dispose();
180
  }
181
182
43067
  const char* msg = Error();
183
43067
  if (msg != nullptr) {
184
    req_wrap_obj->Set(
185
        env->context(),
186
        env->error_string(), OneByteString(env->isolate(), msg)).FromJust();
187
    ClearError();
188
  }
189
190
86134
  return err;
191
}
192
193
125600
inline StreamWriteResult StreamBase::Write(
194
    uv_buf_t* bufs,
195
    size_t count,
196
    uv_stream_t* send_handle,
197
    v8::Local<v8::Object> req_wrap_obj) {
198
125600
  Environment* env = stream_env();
199
  int err;
200
201
125600
  size_t total_bytes = 0;
202
610395
  for (size_t i = 0; i < count; ++i)
203
484795
    total_bytes += bufs[i].len;
204
125600
  bytes_written_ += total_bytes;
205
206
125600
  if (send_handle == nullptr) {
207
125498
    err = DoTryWrite(&bufs, &count);
208

125498
    if (err != 0 || count == 0) {
209
120643
      return StreamWriteResult { false, err, nullptr, total_bytes };
210
    }
211
  }
212
213
4957
  HandleScope handle_scope(env->isolate());
214
215
4957
  if (req_wrap_obj.IsEmpty()) {
216
2870
    if (!env->write_wrap_template()
217
4305
             ->NewInstance(env->context())
218
4305
             .ToLocal(&req_wrap_obj)) {
219
      return StreamWriteResult { false, UV_EBUSY, nullptr, 0 };
220
    }
221
1435
    StreamReq::ResetObject(req_wrap_obj);
222
  }
223
224
9913
  AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(GetAsyncWrap());
225
4957
  WriteWrap* req_wrap = CreateWriteWrap(req_wrap_obj);
226
227
4957
  err = DoWrite(req_wrap, bufs, count, send_handle);
228
4956
  bool async = err == 0;
229
230
4956
  if (!async) {
231
3
    req_wrap->Dispose();
232
3
    req_wrap = nullptr;
233
  }
234
235
4956
  const char* msg = Error();
236
4956
  if (msg != nullptr) {
237
    req_wrap_obj->Set(env->context(),
238
                      env->error_string(),
239
                      OneByteString(env->isolate(), msg)).FromJust();
240
    ClearError();
241
  }
242
243
9912
  return StreamWriteResult { async, err, req_wrap, total_bytes };
244
}
245
246
template <typename OtherBase>
247
43067
SimpleShutdownWrap<OtherBase>::SimpleShutdownWrap(
248
    StreamBase* stream,
249
    v8::Local<v8::Object> req_wrap_obj)
250
  : ShutdownWrap(stream, req_wrap_obj),
251
    OtherBase(stream->stream_env(),
252
              req_wrap_obj,
253
43067
              AsyncWrap::PROVIDER_SHUTDOWNWRAP) {
254
43067
}
255
256
21586
inline ShutdownWrap* StreamBase::CreateShutdownWrap(
257
    v8::Local<v8::Object> object) {
258
21586
  return new SimpleShutdownWrap<AsyncWrap>(this, object);
259
}
260
261
template <typename OtherBase>
262
4957
SimpleWriteWrap<OtherBase>::SimpleWriteWrap(
263
    StreamBase* stream,
264
    v8::Local<v8::Object> req_wrap_obj)
265
  : WriteWrap(stream, req_wrap_obj),
266
    OtherBase(stream->stream_env(),
267
              req_wrap_obj,
268
4957
              AsyncWrap::PROVIDER_WRITEWRAP) {
269
4957
}
270
271
4519
inline WriteWrap* StreamBase::CreateWriteWrap(
272
    v8::Local<v8::Object> object) {
273
4519
  return new SimpleWriteWrap<AsyncWrap>(this, object);
274
}
275
276
template <class Base>
277
9627
void StreamBase::AddMethods(Environment* env, Local<FunctionTemplate> t) {
278
9627
  HandleScope scope(env->isolate());
279
280
  enum PropertyAttribute attributes =
281
      static_cast<PropertyAttribute>(
282
9627
          v8::ReadOnly | v8::DontDelete | v8::DontEnum);
283
284
9627
  Local<Signature> signature = Signature::New(env->isolate(), t);
285
286
  Local<FunctionTemplate> get_fd_templ =
287
      env->NewFunctionTemplate(GetFD<Base>,
288
                               signature,
289
                               v8::ConstructorBehavior::kThrow,
290
9627
                               v8::SideEffectType::kHasNoSideEffect);
291
292
  Local<FunctionTemplate> get_external_templ =
293
      env->NewFunctionTemplate(GetExternal<Base>,
294
                               signature,
295
                               v8::ConstructorBehavior::kThrow,
296
9627
                               v8::SideEffectType::kHasNoSideEffect);
297
298
  Local<FunctionTemplate> get_bytes_read_templ =
299
      env->NewFunctionTemplate(GetBytesRead<Base>,
300
                               signature,
301
                               v8::ConstructorBehavior::kThrow,
302
9627
                               v8::SideEffectType::kHasNoSideEffect);
303
304
  Local<FunctionTemplate> get_bytes_written_templ =
305
      env->NewFunctionTemplate(GetBytesWritten<Base>,
306
                               signature,
307
                               v8::ConstructorBehavior::kThrow,
308
9627
                               v8::SideEffectType::kHasNoSideEffect);
309
310
19254
  t->PrototypeTemplate()->SetAccessorProperty(env->fd_string(),
311
                                              get_fd_templ,
312
                                              Local<FunctionTemplate>(),
313
38508
                                              attributes);
314
315
19254
  t->PrototypeTemplate()->SetAccessorProperty(env->external_stream_string(),
316
                                              get_external_templ,
317
                                              Local<FunctionTemplate>(),
318
38508
                                              attributes);
319
320
19254
  t->PrototypeTemplate()->SetAccessorProperty(env->bytes_read_string(),
321
                                              get_bytes_read_templ,
322
                                              Local<FunctionTemplate>(),
323
38508
                                              attributes);
324
325
19254
  t->PrototypeTemplate()->SetAccessorProperty(env->bytes_written_string(),
326
                                              get_bytes_written_templ,
327
                                              Local<FunctionTemplate>(),
328
38508
                                              attributes);
329
330
9627
  env->SetProtoMethod(t, "readStart", JSMethod<Base, &StreamBase::ReadStartJS>);
331
9627
  env->SetProtoMethod(t, "readStop", JSMethod<Base, &StreamBase::ReadStopJS>);
332
9627
  env->SetProtoMethod(t, "shutdown", JSMethod<Base, &StreamBase::Shutdown>);
333
9627
  env->SetProtoMethod(t, "writev", JSMethod<Base, &StreamBase::Writev>);
334
9627
  env->SetProtoMethod(t,
335
                      "writeBuffer",
336
                      JSMethod<Base, &StreamBase::WriteBuffer>);
337
9627
  env->SetProtoMethod(t,
338
                      "writeAsciiString",
339
                      JSMethod<Base, &StreamBase::WriteString<ASCII> >);
340
9627
  env->SetProtoMethod(t,
341
                      "writeUtf8String",
342
                      JSMethod<Base, &StreamBase::WriteString<UTF8> >);
343
9627
  env->SetProtoMethod(t,
344
                      "writeUcs2String",
345
                      JSMethod<Base, &StreamBase::WriteString<UCS2> >);
346
9627
  env->SetProtoMethod(t,
347
                      "writeLatin1String",
348
9627
                      JSMethod<Base, &StreamBase::WriteString<LATIN1> >);
349
9627
}
350
351
352
template <class Base>
353
189
void StreamBase::GetFD(const FunctionCallbackInfo<Value>& args) {
354
  // Mimic implementation of StreamBase::GetFD() and UDPWrap::GetFD().
355
  Base* handle;
356
189
  ASSIGN_OR_RETURN_UNWRAP(&handle,
357
                          args.This(),
358
                          args.GetReturnValue().Set(UV_EINVAL));
359
360
189
  StreamBase* wrap = static_cast<StreamBase*>(handle);
361
189
  if (!wrap->IsAlive())
362
    return args.GetReturnValue().Set(UV_EINVAL);
363
364
567
  args.GetReturnValue().Set(wrap->GetFD());
365
}
366
367
template <class Base>
368
50995
void StreamBase::GetBytesRead(const FunctionCallbackInfo<Value>& args) {
369
  Base* handle;
370
101992
  ASSIGN_OR_RETURN_UNWRAP(&handle,
371
                          args.This(),
372
                          args.GetReturnValue().Set(0));
373
374
50994
  StreamBase* wrap = static_cast<StreamBase*>(handle);
375
  // uint64_t -> double. 53bits is enough for all real cases.
376
152982
  args.GetReturnValue().Set(static_cast<double>(wrap->bytes_read_));
377
}
378
379
template <class Base>
380
50995
void StreamBase::GetBytesWritten(const FunctionCallbackInfo<Value>& args) {
381
  Base* handle;
382
101990
  ASSIGN_OR_RETURN_UNWRAP(&handle,
383
                          args.This(),
384
                          args.GetReturnValue().Set(0));
385
386
50995
  StreamBase* wrap = static_cast<StreamBase*>(handle);
387
  // uint64_t -> double. 53bits is enough for all real cases.
388
152985
  args.GetReturnValue().Set(static_cast<double>(wrap->bytes_written_));
389
}
390
391
template <class Base>
392
33878
void StreamBase::GetExternal(const FunctionCallbackInfo<Value>& args) {
393
  Base* handle;
394
67756
  ASSIGN_OR_RETURN_UNWRAP(&handle, args.This());
395
396
33878
  StreamBase* wrap = static_cast<StreamBase*>(handle);
397
33878
  Local<External> ext = External::New(args.GetIsolate(), wrap);
398
67756
  args.GetReturnValue().Set(ext);
399
}
400
401
402
template <class Base,
403
          int (StreamBase::*Method)(const FunctionCallbackInfo<Value>& args)>
404
859111
void StreamBase::JSMethod(const FunctionCallbackInfo<Value>& args) {
405
  Base* handle;
406




859112
  ASSIGN_OR_RETURN_UNWRAP(&handle, args.Holder());
407
408




859111
  StreamBase* wrap = static_cast<StreamBase*>(handle);
409




859111
  if (!wrap->IsAlive())
410
2
    return args.GetReturnValue().Set(UV_EINVAL);
411
412
859110
  AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(handle);
413
2577330
  args.GetReturnValue().Set((wrap->*Method)(args));
414
}
415
416
417
21484
inline void ShutdownWrap::OnDone(int status) {
418
21484
  stream()->EmitAfterShutdown(this, status);
419
21484
  Dispose();
420
21484
}
421
422
2253
inline void WriteWrap::SetAllocatedStorage(AllocatedBuffer&& storage) {
423
2253
  CHECK_NULL(storage_.data());
424
2253
  storage_ = std::move(storage);
425
2253
}
426
427
4937
inline void WriteWrap::OnDone(int status) {
428
4937
  stream()->EmitAfterWrite(this, status);
429
4934
  Dispose();
430
4934
}
431
432
26421
inline void StreamReq::Done(int status, const char* error_str) {
433
26421
  AsyncWrap* async_wrap = GetAsyncWrap();
434
26421
  Environment* env = async_wrap->env();
435
26421
  if (error_str != nullptr) {
436
6
    async_wrap->object()->Set(env->context(),
437
                              env->error_string(),
438
36
                              OneByteString(env->isolate(), error_str))
439
12
                              .FromJust();
440
  }
441
442
26421
  OnDone(status);
443
26418
}
444
445
798969
inline void StreamReq::ResetObject(v8::Local<v8::Object> obj) {
446
  DCHECK_GT(obj->InternalFieldCount(), StreamReq::kStreamReqField);
447
448
798969
  obj->SetAlignedPointerInInternalField(0, nullptr);  // BaseObject field.
449
798969
  obj->SetAlignedPointerInInternalField(StreamReq::kStreamReqField, nullptr);
450
798969
}
451
452
453
}  // namespace node
454
455
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
456
457
#endif  // SRC_STREAM_BASE_INL_H_