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-03-02 22:23:06 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
47692
inline void StreamReq::AttachToObject(v8::Local<v8::Object> req_wrap_obj) {
29
95384
  CHECK_EQ(req_wrap_obj->GetAlignedPointerFromInternalField(kStreamReqField),
30
           nullptr);
31
47692
  req_wrap_obj->SetAlignedPointerInInternalField(kStreamReqField, this);
32
47692
}
33
34
596
inline StreamReq* StreamReq::FromObject(v8::Local<v8::Object> req_wrap_obj) {
35
  return static_cast<StreamReq*>(
36
1192
      req_wrap_obj->GetAlignedPointerFromInternalField(kStreamReqField));
37
}
38
39
47666
inline void StreamReq::Dispose() {
40
95332
  object()->SetAlignedPointerInInternalField(kStreamReqField, nullptr);
41
47666
  delete this;
42
47666
}
43
44
48269
inline v8::Local<v8::Object> StreamReq::object() {
45
48269
  return GetAsyncWrap()->object();
46
}
47
48
112744
inline StreamListener::~StreamListener() {
49
112744
  if (stream_ != nullptr)
50
97829
    stream_->RemoveStreamListener(this);
51
112744
}
52
53
10720
inline void StreamListener::PassReadErrorToPreviousListener(ssize_t nread) {
54
10720
  CHECK_NOT_NULL(previous_listener_);
55
10720
  previous_listener_->OnStreamRead(nread, uv_buf_init(nullptr, 0));
56
10720
}
57
58
18626
inline void StreamListener::OnStreamAfterShutdown(ShutdownWrap* w, int status) {
59
18626
  CHECK_NOT_NULL(previous_listener_);
60
18626
  previous_listener_->OnStreamAfterShutdown(w, status);
61
18626
}
62
63
2621
inline void StreamListener::OnStreamAfterWrite(WriteWrap* w, int status) {
64
2621
  CHECK_NOT_NULL(previous_listener_);
65
2621
  previous_listener_->OnStreamAfterWrite(w, status);
66
2621
}
67
68
76513
inline StreamResource::~StreamResource() {
69
153547
  while (listener_ != nullptr) {
70
521
    StreamListener* listener = listener_;
71
521
    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
521
    if (listener == listener_)
77
521
      RemoveStreamListener(listener_);
78
  }
79
76513
}
80
81
130339
inline void StreamResource::PushStreamListener(StreamListener* listener) {
82
130339
  CHECK_NOT_NULL(listener);
83
130339
  CHECK_NULL(listener->stream_);
84
85
130339
  listener->previous_listener_ = listener_;
86
130339
  listener->stream_ = this;
87
88
130339
  listener_ = listener;
89
130339
}
90
91
129832
inline void StreamResource::RemoveStreamListener(StreamListener* listener) {
92
129832
  CHECK_NOT_NULL(listener);
93
94
  StreamListener* previous;
95
  StreamListener* current;
96
97
  // Remove from the linked list.
98
130353
  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
130353
    CHECK_NOT_NULL(current);
102
130353
    if (current == listener) {
103
129832
      if (previous != nullptr)
104
521
        previous->previous_listener_ = current->previous_listener_;
105
      else
106
129311
        listener_ = listener->previous_listener_;
107
129832
      break;
108
    }
109
521
  }
110
111
129832
  listener->stream_ = nullptr;
112
129832
  listener->previous_listener_ = nullptr;
113
129832
}
114
115
487829
inline uv_buf_t StreamResource::EmitAlloc(size_t suggested_size) {
116
#ifdef DEBUG
117
  v8::SealHandleScope handle_scope(v8::Isolate::GetCurrent());
118
#endif
119
487829
  return listener_->OnStreamAlloc(suggested_size);
120
}
121
122
499439
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
499439
  if (nread > 0)
127
481667
    bytes_read_ += static_cast<uint64_t>(nread);
128
499439
  listener_->OnStreamRead(nread, buf);
129
499366
}
130
131
4827
inline void StreamResource::EmitAfterWrite(WriteWrap* w, int status) {
132
#ifdef DEBUG
133
  v8::SealHandleScope handle_scope(v8::Isolate::GetCurrent());
134
#endif
135
4827
  listener_->OnStreamAfterWrite(w, status);
136
4824
}
137
138
21227
inline void StreamResource::EmitAfterShutdown(ShutdownWrap* w, int status) {
139
#ifdef DEBUG
140
  v8::SealHandleScope handle_scope(v8::Isolate::GetCurrent());
141
#endif
142
21227
  listener_->OnStreamAfterShutdown(w, status);
143
21227
}
144
145
2625
inline void StreamResource::EmitWantsWrite(size_t suggested_size) {
146
#ifdef DEBUG
147
  v8::SealHandleScope handle_scope(v8::Isolate::GetCurrent());
148
#endif
149
2625
  listener_->OnStreamWantsWrite(suggested_size);
150
2625
}
151
152
76990
inline StreamBase::StreamBase(Environment* env) : env_(env) {
153
76990
  PushStreamListener(&default_listener_);
154
76990
}
155
156
1009457
inline Environment* StreamBase::stream_env() const {
157
1009457
  return env_;
158
}
159
160
42842
inline int StreamBase::Shutdown(v8::Local<v8::Object> req_wrap_obj) {
161
42842
  Environment* env = stream_env();
162
163
42842
  HandleScope handle_scope(env->isolate());
164
165
42842
  if (req_wrap_obj.IsEmpty()) {
166
926
    if (!env->shutdown_wrap_template()
167
1389
             ->NewInstance(env->context())
168
1389
             .ToLocal(&req_wrap_obj)) {
169
      return UV_EBUSY;
170
    }
171
463
    StreamReq::ResetObject(req_wrap_obj);
172
  }
173
174
85684
  AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(GetAsyncWrap());
175
42842
  ShutdownWrap* req_wrap = CreateShutdownWrap(req_wrap_obj);
176
42842
  int err = DoShutdown(req_wrap);
177
178
42842
  if (err != 0) {
179
21612
    req_wrap->Dispose();
180
  }
181
182
42842
  const char* msg = Error();
183
42842
  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
85684
  return err;
191
}
192
193
125648
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
125648
  Environment* env = stream_env();
199
  int err;
200
201
125648
  size_t total_bytes = 0;
202
610217
  for (size_t i = 0; i < count; ++i)
203
484569
    total_bytes += bufs[i].len;
204
125648
  bytes_written_ += total_bytes;
205
206
125648
  if (send_handle == nullptr) {
207
125545
    err = DoTryWrite(&bufs, &count);
208

125545
    if (err != 0 || count == 0) {
209
120798
      return StreamWriteResult { false, err, nullptr, total_bytes };
210
    }
211
  }
212
213
4850
  HandleScope handle_scope(env->isolate());
214
215
4850
  if (req_wrap_obj.IsEmpty()) {
216
2884
    if (!env->write_wrap_template()
217
4326
             ->NewInstance(env->context())
218
4326
             .ToLocal(&req_wrap_obj)) {
219
      return StreamWriteResult { false, UV_EBUSY, nullptr, 0 };
220
    }
221
1442
    StreamReq::ResetObject(req_wrap_obj);
222
  }
223
224
9699
  AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(GetAsyncWrap());
225
4850
  WriteWrap* req_wrap = CreateWriteWrap(req_wrap_obj);
226
227
4850
  err = DoWrite(req_wrap, bufs, count, send_handle);
228
4849
  bool async = err == 0;
229
230
4849
  if (!async) {
231
3
    req_wrap->Dispose();
232
3
    req_wrap = nullptr;
233
  }
234
235
4849
  const char* msg = Error();
236
4849
  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
9698
  return StreamWriteResult { async, err, req_wrap, total_bytes };
244
}
245
246
template <typename OtherBase>
247
42842
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
42842
              AsyncWrap::PROVIDER_SHUTDOWNWRAP) {
254
42842
}
255
256
21618
inline ShutdownWrap* StreamBase::CreateShutdownWrap(
257
    v8::Local<v8::Object> object) {
258
21618
  return new SimpleShutdownWrap<AsyncWrap>(this, object);
259
}
260
261
template <typename OtherBase>
262
4850
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
4850
              AsyncWrap::PROVIDER_WRITEWRAP) {
269
4850
}
270
271
4545
inline WriteWrap* StreamBase::CreateWriteWrap(
272
    v8::Local<v8::Object> object) {
273
4545
  return new SimpleWriteWrap<AsyncWrap>(this, object);
274
}
275
276
template <class Base>
277
9673
void StreamBase::AddMethods(Environment* env, Local<FunctionTemplate> t) {
278
9673
  HandleScope scope(env->isolate());
279
280
  enum PropertyAttribute attributes =
281
      static_cast<PropertyAttribute>(
282
9673
          v8::ReadOnly | v8::DontDelete | v8::DontEnum);
283
284
9673
  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
9673
                               v8::SideEffectType::kHasNoSideEffect);
291
292
  Local<FunctionTemplate> get_external_templ =
293
      env->NewFunctionTemplate(GetExternal<Base>,
294
                               signature,
295
                               v8::ConstructorBehavior::kThrow,
296
9673
                               v8::SideEffectType::kHasNoSideEffect);
297
298
  Local<FunctionTemplate> get_bytes_read_templ =
299
      env->NewFunctionTemplate(GetBytesRead<Base>,
300
                               signature,
301
                               v8::ConstructorBehavior::kThrow,
302
9673
                               v8::SideEffectType::kHasNoSideEffect);
303
304
  Local<FunctionTemplate> get_bytes_written_templ =
305
      env->NewFunctionTemplate(GetBytesWritten<Base>,
306
                               signature,
307
                               v8::ConstructorBehavior::kThrow,
308
9673
                               v8::SideEffectType::kHasNoSideEffect);
309
310
19346
  t->PrototypeTemplate()->SetAccessorProperty(env->fd_string(),
311
                                              get_fd_templ,
312
                                              Local<FunctionTemplate>(),
313
38692
                                              attributes);
314
315
19346
  t->PrototypeTemplate()->SetAccessorProperty(env->external_stream_string(),
316
                                              get_external_templ,
317
                                              Local<FunctionTemplate>(),
318
38692
                                              attributes);
319
320
19346
  t->PrototypeTemplate()->SetAccessorProperty(env->bytes_read_string(),
321
                                              get_bytes_read_templ,
322
                                              Local<FunctionTemplate>(),
323
38692
                                              attributes);
324
325
19346
  t->PrototypeTemplate()->SetAccessorProperty(env->bytes_written_string(),
326
                                              get_bytes_written_templ,
327
                                              Local<FunctionTemplate>(),
328
38692
                                              attributes);
329
330
9673
  env->SetProtoMethod(t, "readStart", JSMethod<Base, &StreamBase::ReadStartJS>);
331
9673
  env->SetProtoMethod(t, "readStop", JSMethod<Base, &StreamBase::ReadStopJS>);
332
9673
  env->SetProtoMethod(t, "shutdown", JSMethod<Base, &StreamBase::Shutdown>);
333
9673
  env->SetProtoMethod(t, "writev", JSMethod<Base, &StreamBase::Writev>);
334
9673
  env->SetProtoMethod(t,
335
                      "writeBuffer",
336
                      JSMethod<Base, &StreamBase::WriteBuffer>);
337
9673
  env->SetProtoMethod(t,
338
                      "writeAsciiString",
339
                      JSMethod<Base, &StreamBase::WriteString<ASCII> >);
340
9673
  env->SetProtoMethod(t,
341
                      "writeUtf8String",
342
                      JSMethod<Base, &StreamBase::WriteString<UTF8> >);
343
9673
  env->SetProtoMethod(t,
344
                      "writeUcs2String",
345
                      JSMethod<Base, &StreamBase::WriteString<UCS2> >);
346
9673
  env->SetProtoMethod(t,
347
                      "writeLatin1String",
348
9673
                      JSMethod<Base, &StreamBase::WriteString<LATIN1> >);
349
9673
}
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
50757
void StreamBase::GetBytesRead(const FunctionCallbackInfo<Value>& args) {
369
  Base* handle;
370
101516
  ASSIGN_OR_RETURN_UNWRAP(&handle,
371
                          args.This(),
372
                          args.GetReturnValue().Set(0));
373
374
50756
  StreamBase* wrap = static_cast<StreamBase*>(handle);
375
  // uint64_t -> double. 53bits is enough for all real cases.
376
152268
  args.GetReturnValue().Set(static_cast<double>(wrap->bytes_read_));
377
}
378
379
template <class Base>
380
50757
void StreamBase::GetBytesWritten(const FunctionCallbackInfo<Value>& args) {
381
  Base* handle;
382
101514
  ASSIGN_OR_RETURN_UNWRAP(&handle,
383
                          args.This(),
384
                          args.GetReturnValue().Set(0));
385
386
50757
  StreamBase* wrap = static_cast<StreamBase*>(handle);
387
  // uint64_t -> double. 53bits is enough for all real cases.
388
152271
  args.GetReturnValue().Set(static_cast<double>(wrap->bytes_written_));
389
}
390
391
template <class Base>
392
33650
void StreamBase::GetExternal(const FunctionCallbackInfo<Value>& args) {
393
  Base* handle;
394
67300
  ASSIGN_OR_RETURN_UNWRAP(&handle, args.This());
395
396
33650
  StreamBase* wrap = static_cast<StreamBase*>(handle);
397
33650
  Local<External> ext = External::New(args.GetIsolate(), wrap);
398
67300
  args.GetReturnValue().Set(ext);
399
}
400
401
402
template <class Base,
403
          int (StreamBase::*Method)(const FunctionCallbackInfo<Value>& args)>
404
859065
void StreamBase::JSMethod(const FunctionCallbackInfo<Value>& args) {
405
  Base* handle;
406




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




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




859065
  if (!wrap->IsAlive())
410
2
    return args.GetReturnValue().Set(UV_EINVAL);
411
412
859064
  AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(handle);
413
2577192
  args.GetReturnValue().Set((wrap->*Method)(args));
414
}
415
416
417
21227
inline void ShutdownWrap::OnDone(int status) {
418
21227
  stream()->EmitAfterShutdown(this, status);
419
21227
  Dispose();
420
21227
}
421
422
2261
inline void WriteWrap::SetAllocatedStorage(AllocatedBuffer&& storage) {
423
2261
  CHECK_NULL(storage_.data());
424
2261
  storage_ = std::move(storage);
425
2261
}
426
427
4827
inline void WriteWrap::OnDone(int status) {
428
4827
  stream()->EmitAfterWrite(this, status);
429
4824
  Dispose();
430
4824
}
431
432
26054
inline void StreamReq::Done(int status, const char* error_str) {
433
26054
  AsyncWrap* async_wrap = GetAsyncWrap();
434
26054
  Environment* env = async_wrap->env();
435
26054
  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
26054
  OnDone(status);
443
26051
}
444
445
799319
inline void StreamReq::ResetObject(v8::Local<v8::Object> obj) {
446
  DCHECK_GT(obj->InternalFieldCount(), StreamReq::kStreamReqField);
447
448
799319
  obj->SetAlignedPointerInInternalField(0, nullptr);  // BaseObject field.
449
799319
  obj->SetAlignedPointerInInternalField(StreamReq::kStreamReqField, nullptr);
450
799319
}
451
452
453
}  // namespace node
454
455
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
456
457
#endif  // SRC_STREAM_BASE_INL_H_