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: 206 213 96.7 %
Date: 2019-02-13 22:28:58 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
48659
inline void StreamReq::AttachToObject(v8::Local<v8::Object> req_wrap_obj) {
29
97318
  CHECK_EQ(req_wrap_obj->GetAlignedPointerFromInternalField(kStreamReqField),
30
           nullptr);
31
48659
  req_wrap_obj->SetAlignedPointerInInternalField(kStreamReqField, this);
32
48659
}
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
48638
inline void StreamReq::Dispose() {
40
97276
  object()->SetAlignedPointerInInternalField(kStreamReqField, nullptr);
41
48638
  delete this;
42
48638
}
43
44
49234
inline v8::Local<v8::Object> StreamReq::object() {
45
49234
  return GetAsyncWrap()->object();
46
}
47
48
113618
inline StreamListener::~StreamListener() {
49
113618
  if (stream_ != nullptr)
50
98707
    stream_->RemoveStreamListener(this);
51
113618
}
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
19540
inline void StreamListener::OnStreamAfterShutdown(ShutdownWrap* w, int status) {
59
19540
  CHECK_NOT_NULL(previous_listener_);
60
19540
  previous_listener_->OnStreamAfterShutdown(w, status);
61
19540
}
62
63
2605
inline void StreamListener::OnStreamAfterWrite(WriteWrap* w, int status) {
64
2605
  CHECK_NOT_NULL(previous_listener_);
65
2605
  previous_listener_->OnStreamAfterWrite(w, status);
66
2605
}
67
68
77427
inline StreamResource::~StreamResource() {
69
155375
  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
77427
}
80
81
132103
inline void StreamResource::PushStreamListener(StreamListener* listener) {
82
132103
  CHECK_NOT_NULL(listener);
83
132103
  CHECK_NULL(listener->stream_);
84
85
132103
  listener->previous_listener_ = listener_;
86
132103
  listener->stream_ = this;
87
88
132103
  listener_ = listener;
89
132103
}
90
91
131599
inline void StreamResource::RemoveStreamListener(StreamListener* listener) {
92
131599
  CHECK_NOT_NULL(listener);
93
94
  StreamListener* previous;
95
  StreamListener* current;
96
97
  // Remove from the linked list.
98
132120
  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
132120
    CHECK_NOT_NULL(current);
102
132120
    if (current == listener) {
103
131599
      if (previous != nullptr)
104
521
        previous->previous_listener_ = current->previous_listener_;
105
      else
106
131078
        listener_ = listener->previous_listener_;
107
131599
      break;
108
    }
109
521
  }
110
111
131599
  listener->stream_ = nullptr;
112
131599
  listener->previous_listener_ = nullptr;
113
131599
}
114
115
462145
inline uv_buf_t StreamResource::EmitAlloc(size_t suggested_size) {
116
#ifdef DEBUG
117
  v8::SealHandleScope handle_scope(v8::Isolate::GetCurrent());
118
#endif
119
462145
  return listener_->OnStreamAlloc(suggested_size);
120
}
121
122
473773
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
473773
  if (nread > 0)
127
455991
    bytes_read_ += static_cast<uint64_t>(nread);
128
473773
  listener_->OnStreamRead(nread, buf);
129
473701
}
130
131
4931
inline void StreamResource::EmitAfterWrite(WriteWrap* w, int status) {
132
#ifdef DEBUG
133
  v8::SealHandleScope handle_scope(v8::Isolate::GetCurrent());
134
#endif
135
4931
  listener_->OnStreamAfterWrite(w, status);
136
4928
}
137
138
22143
inline void StreamResource::EmitAfterShutdown(ShutdownWrap* w, int status) {
139
#ifdef DEBUG
140
  v8::SealHandleScope handle_scope(v8::Isolate::GetCurrent());
141
#endif
142
22143
  listener_->OnStreamAfterShutdown(w, status);
143
22143
}
144
145
2608
inline void StreamResource::EmitWantsWrite(size_t suggested_size) {
146
#ifdef DEBUG
147
  v8::SealHandleScope handle_scope(v8::Isolate::GetCurrent());
148
#endif
149
2608
  listener_->OnStreamWantsWrite(suggested_size);
150
2608
}
151
152
77902
inline StreamBase::StreamBase(Environment* env) : env_(env) {
153
77902
  PushStreamListener(&default_listener_);
154
77902
}
155
156
607042
inline Environment* StreamBase::stream_env() const {
157
607042
  return env_;
158
}
159
160
43710
inline int StreamBase::Shutdown(v8::Local<v8::Object> req_wrap_obj) {
161
43710
  Environment* env = stream_env();
162
163
43710
  HandleScope handle_scope(env->isolate());
164
165
43710
  if (req_wrap_obj.IsEmpty()) {
166
894
    if (!env->shutdown_wrap_template()
167
1341
             ->NewInstance(env->context())
168
1341
             .ToLocal(&req_wrap_obj)) {
169
      return UV_EBUSY;
170
    }
171
447
    StreamReq::ResetObject(req_wrap_obj);
172
  }
173
174
87420
  AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(GetAsyncWrap());
175
43710
  ShutdownWrap* req_wrap = CreateShutdownWrap(req_wrap_obj);
176
43710
  int err = DoShutdown(req_wrap);
177
178
43710
  if (err != 0) {
179
21565
    req_wrap->Dispose();
180
  }
181
182
43710
  const char* msg = Error();
183
43710
  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
87420
  return err;
191
}
192
193
125575
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
125575
  Environment* env = stream_env();
199
  int err;
200
201
125575
  size_t total_bytes = 0;
202
609354
  for (size_t i = 0; i < count; ++i)
203
483779
    total_bytes += bufs[i].len;
204
125575
  bytes_written_ += total_bytes;
205
206
125575
  if (send_handle == nullptr) {
207
125471
    err = DoTryWrite(&bufs, &count);
208

125471
    if (err != 0 || count == 0) {
209
120626
      return StreamWriteResult { false, err, nullptr, total_bytes };
210
    }
211
  }
212
213
4949
  HandleScope handle_scope(env->isolate());
214
215
4949
  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
9897
  AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(GetAsyncWrap());
225
4949
  WriteWrap* req_wrap = CreateWriteWrap(req_wrap_obj);
226
227
4949
  err = DoWrite(req_wrap, bufs, count, send_handle);
228
4948
  bool async = err == 0;
229
230
4948
  if (!async) {
231
2
    req_wrap->Dispose();
232
2
    req_wrap = nullptr;
233
  }
234
235
4948
  const char* msg = Error();
236
4948
  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
9896
  return StreamWriteResult { async, err, req_wrap, total_bytes };
244
}
245
246
template <typename OtherBase>
247
43710
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
43710
              AsyncWrap::PROVIDER_SHUTDOWNWRAP) {
254
43710
}
255
256
21571
inline ShutdownWrap* StreamBase::CreateShutdownWrap(
257
    v8::Local<v8::Object> object) {
258
21571
  return new SimpleShutdownWrap<AsyncWrap>(this, object);
259
}
260
261
template <typename OtherBase>
262
4949
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
4949
              AsyncWrap::PROVIDER_WRITEWRAP) {
269
4949
}
270
271
4506
inline WriteWrap* StreamBase::CreateWriteWrap(
272
    v8::Local<v8::Object> object) {
273
4506
  return new SimpleWriteWrap<AsyncWrap>(this, object);
274
}
275
276
template <class Base>
277
9667
void StreamBase::AddMethods(Environment* env, Local<FunctionTemplate> t) {
278
9667
  HandleScope scope(env->isolate());
279
280
  enum PropertyAttribute attributes =
281
      static_cast<PropertyAttribute>(
282
9667
          v8::ReadOnly | v8::DontDelete | v8::DontEnum);
283
284
9667
  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
9667
                               v8::SideEffectType::kHasNoSideEffect);
291
292
  Local<FunctionTemplate> get_external_templ =
293
      env->NewFunctionTemplate(GetExternal<Base>,
294
                               signature,
295
                               v8::ConstructorBehavior::kThrow,
296
9667
                               v8::SideEffectType::kHasNoSideEffect);
297
298
  Local<FunctionTemplate> get_bytes_read_templ =
299
      env->NewFunctionTemplate(GetBytesRead<Base>,
300
                               signature,
301
                               v8::ConstructorBehavior::kThrow,
302
9667
                               v8::SideEffectType::kHasNoSideEffect);
303
304
  Local<FunctionTemplate> get_bytes_written_templ =
305
      env->NewFunctionTemplate(GetBytesWritten<Base>,
306
                               signature,
307
                               v8::ConstructorBehavior::kThrow,
308
9667
                               v8::SideEffectType::kHasNoSideEffect);
309
310
19334
  t->PrototypeTemplate()->SetAccessorProperty(env->fd_string(),
311
                                              get_fd_templ,
312
                                              Local<FunctionTemplate>(),
313
38668
                                              attributes);
314
315
19334
  t->PrototypeTemplate()->SetAccessorProperty(env->external_stream_string(),
316
                                              get_external_templ,
317
                                              Local<FunctionTemplate>(),
318
38668
                                              attributes);
319
320
19334
  t->PrototypeTemplate()->SetAccessorProperty(env->bytes_read_string(),
321
                                              get_bytes_read_templ,
322
                                              Local<FunctionTemplate>(),
323
38668
                                              attributes);
324
325
19334
  t->PrototypeTemplate()->SetAccessorProperty(env->bytes_written_string(),
326
                                              get_bytes_written_templ,
327
                                              Local<FunctionTemplate>(),
328
38668
                                              attributes);
329
330
9667
  env->SetProtoMethod(t, "readStart", JSMethod<Base, &StreamBase::ReadStartJS>);
331
9667
  env->SetProtoMethod(t, "readStop", JSMethod<Base, &StreamBase::ReadStopJS>);
332
9667
  env->SetProtoMethod(t, "shutdown", JSMethod<Base, &StreamBase::Shutdown>);
333
9667
  env->SetProtoMethod(t, "writev", JSMethod<Base, &StreamBase::Writev>);
334
9667
  env->SetProtoMethod(t,
335
                      "writeBuffer",
336
                      JSMethod<Base, &StreamBase::WriteBuffer>);
337
9667
  env->SetProtoMethod(t,
338
                      "writeAsciiString",
339
                      JSMethod<Base, &StreamBase::WriteString<ASCII> >);
340
9667
  env->SetProtoMethod(t,
341
                      "writeUtf8String",
342
                      JSMethod<Base, &StreamBase::WriteString<UTF8> >);
343
9667
  env->SetProtoMethod(t,
344
                      "writeUcs2String",
345
                      JSMethod<Base, &StreamBase::WriteString<UCS2> >);
346
9667
  env->SetProtoMethod(t,
347
                      "writeLatin1String",
348
9667
                      JSMethod<Base, &StreamBase::WriteString<LATIN1> >);
349
9667
}
350
351
352
template <class Base>
353
195
void StreamBase::GetFD(const FunctionCallbackInfo<Value>& args) {
354
  // Mimic implementation of StreamBase::GetFD() and UDPWrap::GetFD().
355
  Base* handle;
356
195
  ASSIGN_OR_RETURN_UNWRAP(&handle,
357
                          args.This(),
358
                          args.GetReturnValue().Set(UV_EINVAL));
359
360
195
  StreamBase* wrap = static_cast<StreamBase*>(handle);
361
195
  if (!wrap->IsAlive())
362
    return args.GetReturnValue().Set(UV_EINVAL);
363
364
585
  args.GetReturnValue().Set(wrap->GetFD());
365
}
366
367
template <class Base>
368
51659
void StreamBase::GetBytesRead(const FunctionCallbackInfo<Value>& args) {
369
  Base* handle;
370
103320
  ASSIGN_OR_RETURN_UNWRAP(&handle,
371
                          args.This(),
372
                          args.GetReturnValue().Set(0));
373
374
51658
  StreamBase* wrap = static_cast<StreamBase*>(handle);
375
  // uint64_t -> double. 53bits is enough for all real cases.
376
154974
  args.GetReturnValue().Set(static_cast<double>(wrap->bytes_read_));
377
}
378
379
template <class Base>
380
51659
void StreamBase::GetBytesWritten(const FunctionCallbackInfo<Value>& args) {
381
  Base* handle;
382
103318
  ASSIGN_OR_RETURN_UNWRAP(&handle,
383
                          args.This(),
384
                          args.GetReturnValue().Set(0));
385
386
51659
  StreamBase* wrap = static_cast<StreamBase*>(handle);
387
  // uint64_t -> double. 53bits is enough for all real cases.
388
154977
  args.GetReturnValue().Set(static_cast<double>(wrap->bytes_written_));
389
}
390
391
template <class Base>
392
34534
void StreamBase::GetExternal(const FunctionCallbackInfo<Value>& args) {
393
  Base* handle;
394
69068
  ASSIGN_OR_RETURN_UNWRAP(&handle, args.This());
395
396
34534
  StreamBase* wrap = static_cast<StreamBase*>(handle);
397
34534
  Local<External> ext = External::New(args.GetIsolate(), wrap);
398
69068
  args.GetReturnValue().Set(ext);
399
}
400
401
402
template <class Base,
403
          int (StreamBase::*Method)(const FunctionCallbackInfo<Value>& args)>
404
872520
void StreamBase::JSMethod(const FunctionCallbackInfo<Value>& args) {
405
  Base* handle;
406




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




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




872520
  if (!wrap->IsAlive())
410
2
    return args.GetReturnValue().Set(UV_EINVAL);
411
412
872519
  AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(handle);
413
2617557
  args.GetReturnValue().Set((wrap->*Method)(args));
414
}
415
416
417
22143
inline void ShutdownWrap::OnDone(int status) {
418
22143
  stream()->EmitAfterShutdown(this, status);
419
22143
  Dispose();
420
22143
}
421
422
2239
inline void WriteWrap::SetAllocatedStorage(char* data, size_t size) {
423
2239
  CHECK_NULL(storage_);
424
2239
  storage_ = data;
425
2239
  storage_size_ = size;
426
2239
}
427
428
inline char* WriteWrap::Storage() {
429
  return storage_;
430
}
431
432
inline size_t WriteWrap::StorageSize() const {
433
  return storage_size_;
434
}
435
436
4931
inline void WriteWrap::OnDone(int status) {
437
4931
  stream()->EmitAfterWrite(this, status);
438
4928
  Dispose();
439
4928
}
440
441
27074
inline void StreamReq::Done(int status, const char* error_str) {
442
27074
  AsyncWrap* async_wrap = GetAsyncWrap();
443
27074
  Environment* env = async_wrap->env();
444
27074
  if (error_str != nullptr) {
445
6
    async_wrap->object()->Set(env->context(),
446
                              env->error_string(),
447
36
                              OneByteString(env->isolate(), error_str))
448
12
                              .FromJust();
449
  }
450
451
27074
  OnDone(status);
452
27071
}
453
454
811674
inline void StreamReq::ResetObject(v8::Local<v8::Object> obj) {
455
  DCHECK_GT(obj->InternalFieldCount(), StreamReq::kStreamReqField);
456
457
811674
  obj->SetAlignedPointerInInternalField(0, nullptr);  // BaseObject field.
458
811674
  obj->SetAlignedPointerInInternalField(StreamReq::kStreamReqField, nullptr);
459
811674
}
460
461
462
}  // namespace node
463
464
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
465
466
#endif  // SRC_STREAM_BASE_INL_H_