GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/util-inl.h Lines: 182 196 92.9 %
Date: 2019-07-27 22:37:30 Branches: 106 174 60.9 %

Line Branch Exec Source
1
// Copyright Joyent, Inc. and other Node contributors.
2
//
3
// Permission is hereby granted, free of charge, to any person obtaining a
4
// copy of this software and associated documentation files (the
5
// "Software"), to deal in the Software without restriction, including
6
// without limitation the rights to use, copy, modify, merge, publish,
7
// distribute, sublicense, and/or sell copies of the Software, and to permit
8
// persons to whom the Software is furnished to do so, subject to the
9
// following conditions:
10
//
11
// The above copyright notice and this permission notice shall be included
12
// in all copies or substantial portions of the Software.
13
//
14
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22
#ifndef SRC_UTIL_INL_H_
23
#define SRC_UTIL_INL_H_
24
25
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
26
27
#include <cstring>
28
#include "util.h"
29
30
// These are defined by <sys/byteorder.h> or <netinet/in.h> on some systems.
31
// To avoid warnings, undefine them before redefining them.
32
#ifdef BSWAP_2
33
# undef BSWAP_2
34
#endif
35
#ifdef BSWAP_4
36
# undef BSWAP_4
37
#endif
38
#ifdef BSWAP_8
39
# undef BSWAP_8
40
#endif
41
42
#if defined(_MSC_VER)
43
#include <intrin.h>
44
#define BSWAP_2(x) _byteswap_ushort(x)
45
#define BSWAP_4(x) _byteswap_ulong(x)
46
#define BSWAP_8(x) _byteswap_uint64(x)
47
#else
48
#define BSWAP_2(x) ((x) << 8) | ((x) >> 8)
49
#define BSWAP_4(x)                                                            \
50
  (((x) & 0xFF) << 24) |                                                      \
51
  (((x) & 0xFF00) << 8) |                                                     \
52
  (((x) >> 8) & 0xFF00) |                                                     \
53
  (((x) >> 24) & 0xFF)
54
#define BSWAP_8(x)                                                            \
55
  (((x) & 0xFF00000000000000ull) >> 56) |                                     \
56
  (((x) & 0x00FF000000000000ull) >> 40) |                                     \
57
  (((x) & 0x0000FF0000000000ull) >> 24) |                                     \
58
  (((x) & 0x000000FF00000000ull) >> 8) |                                      \
59
  (((x) & 0x00000000FF000000ull) << 8) |                                      \
60
  (((x) & 0x0000000000FF0000ull) << 24) |                                     \
61
  (((x) & 0x000000000000FF00ull) << 40) |                                     \
62
  (((x) & 0x00000000000000FFull) << 56)
63
#endif
64
65
namespace node {
66
67
template <typename T>
68
171389
ListNode<T>::ListNode() : prev_(this), next_(this) {}
69
70
template <typename T>
71
170057
ListNode<T>::~ListNode() {
72
170057
  Remove();
73
170059
}
74
75
template <typename T>
76
172180
void ListNode<T>::Remove() {
77
172180
  prev_->next_ = next_;
78
172180
  next_->prev_ = prev_;
79
172180
  prev_ = this;
80
172180
  next_ = this;
81
172180
}
82
83
template <typename T>
84
28408
bool ListNode<T>::IsEmpty() const {
85
28408
  return prev_ == this;
86
}
87
88
template <typename T, ListNode<T> (T::*M)>
89
37346
ListHead<T, M>::Iterator::Iterator(ListNode<T>* node) : node_(node) {}
90
91
template <typename T, ListNode<T> (T::*M)>
92
2699
T* ListHead<T, M>::Iterator::operator*() const {
93
2699
  return ContainerOf(M, node_);
94
}
95
96
template <typename T, ListNode<T> (T::*M)>
97
const typename ListHead<T, M>::Iterator&
98
2699
ListHead<T, M>::Iterator::operator++() {
99
2699
  node_ = node_->next_;
100
2699
  return *this;
101
}
102
103
template <typename T, ListNode<T> (T::*M)>
104
21372
bool ListHead<T, M>::Iterator::operator!=(const Iterator& that) const {
105
21372
  return node_ != that.node_;
106
}
107
108
template <typename T, ListNode<T> (T::*M)>
109
9144
ListHead<T, M>::~ListHead() {
110

18288
  while (IsEmpty() == false)
111
    head_.next_->Remove();
112
9144
}
113
114
template <typename T, ListNode<T> (T::*M)>
115
163549
void ListHead<T, M>::PushBack(T* element) {
116
163549
  ListNode<T>* that = &(element->*M);
117
163549
  head_.prev_->next_ = that;
118
163549
  that->prev_ = head_.prev_;
119
163549
  that->next_ = &head_;
120
163549
  head_.prev_ = that;
121
163549
}
122
123
template <typename T, ListNode<T> (T::*M)>
124
void ListHead<T, M>::PushFront(T* element) {
125
  ListNode<T>* that = &(element->*M);
126
  head_.next_->prev_ = that;
127
  that->prev_ = &head_;
128
  that->next_ = head_.next_;
129
  head_.next_ = that;
130
}
131
132
template <typename T, ListNode<T> (T::*M)>
133
28408
bool ListHead<T, M>::IsEmpty() const {
134
28408
  return head_.IsEmpty();
135
}
136
137
template <typename T, ListNode<T> (T::*M)>
138
T* ListHead<T, M>::PopFront() {
139
  if (IsEmpty())
140
    return nullptr;
141
  ListNode<T>* node = head_.next_;
142
  node->Remove();
143
  return ContainerOf(M, node);
144
}
145
146
template <typename T, ListNode<T> (T::*M)>
147
18673
typename ListHead<T, M>::Iterator ListHead<T, M>::begin() const {
148
18673
  return Iterator(head_.next_);
149
}
150
151
template <typename T, ListNode<T> (T::*M)>
152
18673
typename ListHead<T, M>::Iterator ListHead<T, M>::end() const {
153
18673
  return Iterator(const_cast<ListNode<T>*>(&head_));
154
}
155
156
template <typename Inner, typename Outer>
157
2095813
constexpr uintptr_t OffsetOf(Inner Outer::*field) {
158
2095813
  return reinterpret_cast<uintptr_t>(&(static_cast<Outer*>(nullptr)->*field));
159
}
160
161
template <typename Inner, typename Outer>
162
2052344
ContainerOfHelper<Inner, Outer>::ContainerOfHelper(Inner Outer::*field,
163
                                                   Inner* pointer)
164
    : pointer_(
165
        reinterpret_cast<Outer*>(
166
2052344
            reinterpret_cast<uintptr_t>(pointer) - OffsetOf(field))) {}
167
168
template <typename Inner, typename Outer>
169
template <typename TypeName>
170
2052327
ContainerOfHelper<Inner, Outer>::operator TypeName*() const {
171
2052327
  return static_cast<TypeName*>(pointer_);
172
}
173
174
template <typename Inner, typename Outer>
175
2052347
constexpr ContainerOfHelper<Inner, Outer> ContainerOf(Inner Outer::*field,
176
                                                      Inner* pointer) {
177
2052347
  return ContainerOfHelper<Inner, Outer>(field, pointer);
178
}
179
180
4929757
inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
181
                                           const char* data,
182
                                           int length) {
183
  return v8::String::NewFromOneByte(isolate,
184
                                    reinterpret_cast<const uint8_t*>(data),
185
                                    v8::NewStringType::kNormal,
186
9859541
                                    length).ToLocalChecked();
187
}
188
189
inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
190
                                           const signed char* data,
191
                                           int length) {
192
  return v8::String::NewFromOneByte(isolate,
193
                                    reinterpret_cast<const uint8_t*>(data),
194
                                    v8::NewStringType::kNormal,
195
                                    length).ToLocalChecked();
196
}
197
198
76
inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
199
                                           const unsigned char* data,
200
                                           int length) {
201
  return v8::String::NewFromOneByte(
202
             isolate, data, v8::NewStringType::kNormal, length)
203
152
      .ToLocalChecked();
204
}
205
206
6
void SwapBytes16(char* data, size_t nbytes) {
207
6
  CHECK_EQ(nbytes % 2, 0);
208
209
#if defined(_MSC_VER)
210
  int align = reinterpret_cast<uintptr_t>(data) % sizeof(uint16_t);
211
  if (align == 0) {
212
    // MSVC has no strict aliasing, and is able to highly optimize this case.
213
    uint16_t* data16 = reinterpret_cast<uint16_t*>(data);
214
    size_t len16 = nbytes / sizeof(*data16);
215
    for (size_t i = 0; i < len16; i++) {
216
      data16[i] = BSWAP_2(data16[i]);
217
    }
218
    return;
219
  }
220
#endif
221
222
  uint16_t temp;
223
2053
  for (size_t i = 0; i < nbytes; i += sizeof(temp)) {
224
2047
    memcpy(&temp, &data[i], sizeof(temp));
225
2047
    temp = BSWAP_2(temp);
226
2047
    memcpy(&data[i], &temp, sizeof(temp));
227
  }
228
6
}
229
230
2
void SwapBytes32(char* data, size_t nbytes) {
231
2
  CHECK_EQ(nbytes % 4, 0);
232
233
#if defined(_MSC_VER)
234
  int align = reinterpret_cast<uintptr_t>(data) % sizeof(uint32_t);
235
  // MSVC has no strict aliasing, and is able to highly optimize this case.
236
  if (align == 0) {
237
    uint32_t* data32 = reinterpret_cast<uint32_t*>(data);
238
    size_t len32 = nbytes / sizeof(*data32);
239
    for (size_t i = 0; i < len32; i++) {
240
      data32[i] = BSWAP_4(data32[i]);
241
    }
242
    return;
243
  }
244
#endif
245
246
  uint32_t temp;
247
769
  for (size_t i = 0; i < nbytes; i += sizeof(temp)) {
248
767
    memcpy(&temp, &data[i], sizeof(temp));
249
767
    temp = BSWAP_4(temp);
250
767
    memcpy(&data[i], &temp, sizeof(temp));
251
  }
252
2
}
253
254
2
void SwapBytes64(char* data, size_t nbytes) {
255
2
  CHECK_EQ(nbytes % 8, 0);
256
257
#if defined(_MSC_VER)
258
  int align = reinterpret_cast<uintptr_t>(data) % sizeof(uint64_t);
259
  if (align == 0) {
260
    // MSVC has no strict aliasing, and is able to highly optimize this case.
261
    uint64_t* data64 = reinterpret_cast<uint64_t*>(data);
262
    size_t len64 = nbytes / sizeof(*data64);
263
    for (size_t i = 0; i < len64; i++) {
264
      data64[i] = BSWAP_8(data64[i]);
265
    }
266
    return;
267
  }
268
#endif
269
270
  uint64_t temp;
271
513
  for (size_t i = 0; i < nbytes; i += sizeof(temp)) {
272
511
    memcpy(&temp, &data[i], sizeof(temp));
273
511
    temp = BSWAP_8(temp);
274
511
    memcpy(&data[i], &temp, sizeof(temp));
275
  }
276
2
}
277
278
12033883
char ToLower(char c) {
279

12033883
  return c >= 'A' && c <= 'Z' ? c + ('a' - 'A') : c;
280
}
281
282
877
std::string ToLower(const std::string& in) {
283
877
  std::string out(in.size(), 0);
284
11316
  for (size_t i = 0; i < in.size(); ++i)
285
10439
    out[i] = ToLower(in[i]);
286
877
  return out;
287
}
288
289
12239
char ToUpper(char c) {
290

12239
  return c >= 'a' && c <= 'z' ? (c - 'a') + 'A' : c;
291
}
292
293
std::string ToUpper(const std::string& in) {
294
  std::string out(in.size(), 0);
295
  for (size_t i = 0; i < in.size(); ++i)
296
    out[i] = ToUpper(in[i]);
297
  return out;
298
}
299
300
6464771
bool StringEqualNoCase(const char* a, const char* b) {
301
6010585
  do {
302
6464771
    if (*a == '\0')
303
454172
      return *b == '\0';
304
6010599
    if (*b == '\0')
305
14
      return *a == '\0';
306
6010585
  } while (ToLower(*a++) == ToLower(*b++));
307
4547030
  return false;
308
}
309
310
332
bool StringEqualNoCaseN(const char* a, const char* b, size_t length) {
311
1243
  for (size_t i = 0; i < length; i++) {
312
1137
    if (ToLower(a[i]) != ToLower(b[i]))
313
226
      return false;
314
911
    if (a[i] == '\0')
315
      return true;
316
  }
317
106
  return true;
318
}
319
320
template <typename T>
321
3679633
inline T MultiplyWithOverflowCheck(T a, T b) {
322
3679633
  auto ret = a * b;
323
3679633
  if (a != 0)
324
3679632
    CHECK_EQ(b, ret / a);
325
326
3679633
  return ret;
327
}
328
329
// These should be used in our code as opposed to the native
330
// versions as they abstract out some platform and or
331
// compiler version specific functionality.
332
// malloc(0) and realloc(ptr, 0) have implementation-defined behavior in
333
// that the standard allows them to either return a unique pointer or a
334
// nullptr for zero-sized allocation requests.  Normalize by always using
335
// a nullptr.
336
template <typename T>
337
3148029
T* UncheckedRealloc(T* pointer, size_t n) {
338
3148029
  size_t full_size = MultiplyWithOverflowCheck(sizeof(T), n);
339
340


3148030
  if (full_size == 0) {
341
126867
    free(pointer);
342
126867
    return nullptr;
343
  }
344
345
3021163
  void* allocated = realloc(pointer, full_size);
346
347


3021163
  if (UNLIKELY(allocated == nullptr)) {
348
    // Tell V8 that memory is low and retry.
349
    LowMemoryNotification();
350
    allocated = realloc(pointer, full_size);
351
  }
352
353
3021163
  return static_cast<T*>(allocated);
354
}
355
356
// As per spec realloc behaves like malloc if passed nullptr.
357
template <typename T>
358
2157451
inline T* UncheckedMalloc(size_t n) {
359


2157451
  if (n == 0) n = 1;
360
2157451
  return UncheckedRealloc<T>(nullptr, n);
361
}
362
363
template <typename T>
364
60018
inline T* UncheckedCalloc(size_t n) {
365
60018
  if (n == 0) n = 1;
366
60018
  MultiplyWithOverflowCheck(sizeof(T), n);
367
60018
  return static_cast<T*>(calloc(n, sizeof(T)));
368
}
369
370
template <typename T>
371
413346
inline T* Realloc(T* pointer, size_t n) {
372
413346
  T* ret = UncheckedRealloc(pointer, n);
373




413346
  CHECK_IMPLIES(n > 0, ret != nullptr);
374
413346
  return ret;
375
}
376
377
template <typename T>
378
113
inline T* Malloc(size_t n) {
379
113
  T* ret = UncheckedMalloc<T>(n);
380






113
  CHECK_IMPLIES(n > 0, ret != nullptr);
381
113
  return ret;
382
}
383
384
template <typename T>
385
inline T* Calloc(size_t n) {
386
  T* ret = UncheckedCalloc<T>(n);
387
  CHECK_IMPLIES(n > 0, ret != nullptr);
388
  return ret;
389
}
390
391
// Shortcuts for char*.
392
12
inline char* Malloc(size_t n) { return Malloc<char>(n); }
393
inline char* Calloc(size_t n) { return Calloc<char>(n); }
394
2157313
inline char* UncheckedMalloc(size_t n) { return UncheckedMalloc<char>(n); }
395
60018
inline char* UncheckedCalloc(size_t n) { return UncheckedCalloc<char>(n); }
396
397
// This is a helper in the .cc file so including util-inl.h doesn't include more
398
// headers than we really need to.
399
void ThrowErrStringTooLong(v8::Isolate* isolate);
400
401
2841418
v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
402
                                    const std::string& str,
403
                                    v8::Isolate* isolate) {
404
3978977
  if (isolate == nullptr) isolate = context->GetIsolate();
405
2841413
  if (UNLIKELY(str.size() >= static_cast<size_t>(v8::String::kMaxLength))) {
406
    // V8 only has a TODO comment about adding an exception when the maximum
407
    // string size is exceeded.
408
    ThrowErrStringTooLong(isolate);
409
    return v8::MaybeLocal<v8::Value>();
410
  }
411
412
  return v8::String::NewFromUtf8(
413
2841421
             isolate, str.data(), v8::NewStringType::kNormal, str.size())
414
5682854
      .FromMaybe(v8::Local<v8::String>());
415
}
416
417
template <typename T>
418
155558
v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
419
                                    const std::vector<T>& vec,
420
                                    v8::Isolate* isolate) {
421
226711
  if (isolate == nullptr) isolate = context->GetIsolate();
422
155558
  v8::EscapableHandleScope handle_scope(isolate);
423
424
311116
  MaybeStackBuffer<v8::Local<v8::Value>, 128> arr(vec.size());
425
155558
  arr.SetLength(vec.size());
426
1775028
  for (size_t i = 0; i < vec.size(); ++i) {
427
3238940
    if (!ToV8Value(context, vec[i], isolate).ToLocal(&arr[i]))
428
      return v8::MaybeLocal<v8::Value>();
429
  }
430
431
311116
  return handle_scope.Escape(v8::Array::New(isolate, arr.out(), arr.length()));
432
}
433
434
template <typename T, typename U>
435
4965
v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
436
                                    const std::unordered_map<T, U>& map,
437
                                    v8::Isolate* isolate) {
438
9930
  if (isolate == nullptr) isolate = context->GetIsolate();
439
4965
  v8::EscapableHandleScope handle_scope(isolate);
440
441
4965
  v8::Local<v8::Map> ret = v8::Map::New(isolate);
442
89370
  for (const auto& item : map) {
443
    v8::Local<v8::Value> first, second;
444


590835
    if (!ToV8Value(context, item.first, isolate).ToLocal(&first) ||
445
253215
        !ToV8Value(context, item.second, isolate).ToLocal(&second) ||
446
253215
        ret->Set(context, first, second).IsEmpty()) {
447
      return v8::MaybeLocal<v8::Value>();
448
    }
449
  }
450
451
4965
  return handle_scope.Escape(ret);
452
}
453
454
template <typename T, typename >
455
2
v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
456
                                    const T& number,
457
                                    v8::Isolate* isolate) {
458
2
  if (isolate == nullptr) isolate = context->GetIsolate();
459
460
  using Limits = std::numeric_limits<T>;
461
  // Choose Uint32, Int32, or Double depending on range checks.
462
  // These checks should all collapse at compile time.
463

6
  if (static_cast<uint32_t>(Limits::max()) <=
464
2
          std::numeric_limits<uint32_t>::max() &&
465
2
      static_cast<uint32_t>(Limits::min()) >=
466
2
          std::numeric_limits<uint32_t>::min() && Limits::is_exact) {
467
4
    return v8::Integer::NewFromUnsigned(isolate, static_cast<uint32_t>(number));
468
  }
469
470
  if (static_cast<int32_t>(Limits::max()) <=
471
          std::numeric_limits<int32_t>::max() &&
472
      static_cast<int32_t>(Limits::min()) >=
473
          std::numeric_limits<int32_t>::min() && Limits::is_exact) {
474
    return v8::Integer::New(isolate, static_cast<int32_t>(number));
475
  }
476
477
  return v8::Number::New(isolate, static_cast<double>(number));
478
}
479
480
228939
SlicedArguments::SlicedArguments(
481
228939
    const v8::FunctionCallbackInfo<v8::Value>& args, size_t start) {
482
228939
  const size_t length = static_cast<size_t>(args.Length());
483
457878
  if (start >= length) return;
484
228692
  const size_t size = length - start;
485
486
228692
  AllocateSufficientStorage(size);
487
668733
  for (size_t i = 0; i < size; ++i)
488
880082
    (*this)[i] = args[i + start];
489
}
490
491
template <typename T, size_t S>
492
1196127
ArrayBufferViewContents<T, S>::ArrayBufferViewContents(
493
1196127
    v8::Local<v8::Value> value) {
494

1196127
  CHECK(value->IsArrayBufferView());
495
1196127
  Read(value.As<v8::ArrayBufferView>());
496
1196127
}
497
498
template <typename T, size_t S>
499
511694
ArrayBufferViewContents<T, S>::ArrayBufferViewContents(
500
511694
    v8::Local<v8::Object> value) {
501
511694
  CHECK(value->IsArrayBufferView());
502
511694
  Read(value.As<v8::ArrayBufferView>());
503
511694
}
504
505
template <typename T, size_t S>
506
177007
ArrayBufferViewContents<T, S>::ArrayBufferViewContents(
507
177007
    v8::Local<v8::ArrayBufferView> abv) {
508
177007
  Read(abv);
509
177007
}
510
511
template <typename T, size_t S>
512
1885996
void ArrayBufferViewContents<T, S>::Read(v8::Local<v8::ArrayBufferView> abv) {
513
  static_assert(sizeof(T) == 1, "Only supports one-byte data at the moment");
514
1885996
  length_ = abv->ByteLength();
515



2826009
  if (length_ > sizeof(stack_storage_) || abv->HasBuffer()) {
516
5587506
    data_ = static_cast<T*>(abv->Buffer()->GetContents().Data()) +
517
1862502
        abv->ByteOffset();
518
  } else {
519
46988
    abv->CopyContents(stack_storage_, sizeof(stack_storage_));
520
23494
    data_ = stack_storage_;
521
  }
522
1885996
}
523
524
}  // namespace node
525
526
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
527
528
#endif  // SRC_UTIL_INL_H_