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-23 22:23:05 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
48093
inline void StreamReq::AttachToObject(v8::Local<v8::Object> req_wrap_obj) {
29
96186
  CHECK_EQ(req_wrap_obj->GetAlignedPointerFromInternalField(kStreamReqField),
30
           nullptr);
31
48093
  req_wrap_obj->SetAlignedPointerInInternalField(kStreamReqField, this);
32
48093
}
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
48071
inline void StreamReq::Dispose() {
40
96142
  object()->SetAlignedPointerInInternalField(kStreamReqField, nullptr);
41
48071
  delete this;
42
48071
}
43
44
48669
inline v8::Local<v8::Object> StreamReq::object() {
45
48669
  return GetAsyncWrap()->object();
46
}
47
48
113030
inline StreamListener::~StreamListener() {
49
113030
  if (stream_ != nullptr)
50
98122
    stream_->RemoveStreamListener(this);
51
113030
}
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
18953
inline void StreamListener::OnStreamAfterShutdown(ShutdownWrap* w, int status) {
59
18953
  CHECK_NOT_NULL(previous_listener_);
60
18953
  previous_listener_->OnStreamAfterShutdown(w, status);
61
18953
}
62
63
2635
inline void StreamListener::OnStreamAfterWrite(WriteWrap* w, int status) {
64
2635
  CHECK_NOT_NULL(previous_listener_);
65
2635
  previous_listener_->OnStreamAfterWrite(w, status);
66
2635
}
67
68
76812
inline StreamResource::~StreamResource() {
69
154145
  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
76812
}
80
81
130929
inline void StreamResource::PushStreamListener(StreamListener* listener) {
82
130929
  CHECK_NOT_NULL(listener);
83
130929
  CHECK_NULL(listener->stream_);
84
85
130929
  listener->previous_listener_ = listener_;
86
130929
  listener->stream_ = this;
87
88
130929
  listener_ = listener;
89
130929
}
90
91
130424
inline void StreamResource::RemoveStreamListener(StreamListener* listener) {
92
130424
  CHECK_NOT_NULL(listener);
93
94
  StreamListener* previous;
95
  StreamListener* current;
96
97
  // Remove from the linked list.
98
130945
  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
130945
    CHECK_NOT_NULL(current);
102
130945
    if (current == listener) {
103
130424
      if (previous != nullptr)
104
521
        previous->previous_listener_ = current->previous_listener_;
105
      else
106
129903
        listener_ = listener->previous_listener_;
107
130424
      break;
108
    }
109
521
  }
110
111
130424
  listener->stream_ = nullptr;
112
130424
  listener->previous_listener_ = nullptr;
113
130424
}
114
115
477214
inline uv_buf_t StreamResource::EmitAlloc(size_t suggested_size) {
116
#ifdef DEBUG
117
  v8::SealHandleScope handle_scope(v8::Isolate::GetCurrent());
118
#endif
119
477214
  return listener_->OnStreamAlloc(suggested_size);
120
}
121
122
488824
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
488824
  if (nread > 0)
127
471084
    bytes_read_ += static_cast<uint64_t>(nread);
128
488824
  listener_->OnStreamRead(nread, buf);
129
488751
}
130
131
4910
inline void StreamResource::EmitAfterWrite(WriteWrap* w, int status) {
132
#ifdef DEBUG
133
  v8::SealHandleScope handle_scope(v8::Isolate::GetCurrent());
134
#endif
135
4910
  listener_->OnStreamAfterWrite(w, status);
136
4907
}
137
138
21554
inline void StreamResource::EmitAfterShutdown(ShutdownWrap* w, int status) {
139
#ifdef DEBUG
140
  v8::SealHandleScope handle_scope(v8::Isolate::GetCurrent());
141
#endif
142
21554
  listener_->OnStreamAfterShutdown(w, status);
143
21554
}
144
145
2638
inline void StreamResource::EmitWantsWrite(size_t suggested_size) {
146
#ifdef DEBUG
147
  v8::SealHandleScope handle_scope(v8::Isolate::GetCurrent());
148
#endif
149
2638
  listener_->OnStreamWantsWrite(suggested_size);
150
2638
}
151
152
77288
inline StreamBase::StreamBase(Environment* env) : env_(env) {
153
77288
  PushStreamListener(&default_listener_);
154
77288
}
155
156
621388
inline Environment* StreamBase::stream_env() const {
157
621388
  return env_;
158
}
159
160
43163
inline int StreamBase::Shutdown(v8::Local<v8::Object> req_wrap_obj) {
161
43163
  Environment* env = stream_env();
162
163
43163
  HandleScope handle_scope(env->isolate());
164
165
43163
  if (req_wrap_obj.IsEmpty()) {
166
922
    if (!env->shutdown_wrap_template()
167
1383
             ->NewInstance(env->context())
168
1383
             .ToLocal(&req_wrap_obj)) {
169
      return UV_EBUSY;
170
    }
171
461
    StreamReq::ResetObject(req_wrap_obj);
172
  }
173
174
86326
  AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(GetAsyncWrap());
175
43163
  ShutdownWrap* req_wrap = CreateShutdownWrap(req_wrap_obj);
176
43163
  int err = DoShutdown(req_wrap);
177
178
43163
  if (err != 0) {
179
21607
    req_wrap->Dispose();
180
  }
181
182
43163
  const char* msg = Error();
183
43163
  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
86326
  return err;
191
}
192
193
125733
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
125733
  Environment* env = stream_env();
199
  int err;
200
201
125733
  size_t total_bytes = 0;
202
609324
  for (size_t i = 0; i < count; ++i)
203
483591
    total_bytes += bufs[i].len;
204
125733
  bytes_written_ += total_bytes;
205
206
125733
  if (send_handle == nullptr) {
207
125634
    err = DoTryWrite(&bufs, &count);
208

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




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




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




861112
  if (!wrap->IsAlive())
410
2
    return args.GetReturnValue().Set(UV_EINVAL);
411
412
861111
  AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(handle);
413
2583333
  args.GetReturnValue().Set((wrap->*Method)(args));
414
}
415
416
417
21554
inline void ShutdownWrap::OnDone(int status) {
418
21554
  stream()->EmitAfterShutdown(this, status);
419
21554
  Dispose();
420
21554
}
421
422
2300
inline void WriteWrap::SetAllocatedStorage(char* data, size_t size) {
423
2300
  CHECK_NULL(storage_);
424
2300
  storage_ = data;
425
2300
  storage_size_ = size;
426
2300
}
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
4910
inline void WriteWrap::OnDone(int status) {
437
4910
  stream()->EmitAfterWrite(this, status);
438
4907
  Dispose();
439
4907
}
440
441
26464
inline void StreamReq::Done(int status, const char* error_str) {
442
26464
  AsyncWrap* async_wrap = GetAsyncWrap();
443
26464
  Environment* env = async_wrap->env();
444
26464
  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
26464
  OnDone(status);
452
26461
}
453
454
801068
inline void StreamReq::ResetObject(v8::Local<v8::Object> obj) {
455
  DCHECK_GT(obj->InternalFieldCount(), StreamReq::kStreamReqField);
456
457
801068
  obj->SetAlignedPointerInInternalField(0, nullptr);  // BaseObject field.
458
801068
  obj->SetAlignedPointerInInternalField(StreamReq::kStreamReqField, nullptr);
459
801068
}
460
461
462
}  // namespace node
463
464
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
465
466
#endif  // SRC_STREAM_BASE_INL_H_