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: 177 191 92.7 %
Date: 2019-05-05 22:32:45 Branches: 105 172 61.0 %

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
#if defined(_MSC_VER)
31
#include <intrin.h>
32
#define BSWAP_2(x) _byteswap_ushort(x)
33
#define BSWAP_4(x) _byteswap_ulong(x)
34
#define BSWAP_8(x) _byteswap_uint64(x)
35
#else
36
#define BSWAP_2(x) ((x) << 8) | ((x) >> 8)
37
#define BSWAP_4(x)                                                            \
38
  (((x) & 0xFF) << 24) |                                                      \
39
  (((x) & 0xFF00) << 8) |                                                     \
40
  (((x) >> 8) & 0xFF00) |                                                     \
41
  (((x) >> 24) & 0xFF)
42
#define BSWAP_8(x)                                                            \
43
  (((x) & 0xFF00000000000000ull) >> 56) |                                     \
44
  (((x) & 0x00FF000000000000ull) >> 40) |                                     \
45
  (((x) & 0x0000FF0000000000ull) >> 24) |                                     \
46
  (((x) & 0x000000FF00000000ull) >> 8) |                                      \
47
  (((x) & 0x00000000FF000000ull) << 8) |                                      \
48
  (((x) & 0x0000000000FF0000ull) << 24) |                                     \
49
  (((x) & 0x000000000000FF00ull) << 40) |                                     \
50
  (((x) & 0x00000000000000FFull) << 56)
51
#endif
52
53
namespace node {
54
55
template <typename T>
56
144228
ListNode<T>::ListNode() : prev_(this), next_(this) {}
57
58
template <typename T>
59
142944
ListNode<T>::~ListNode() {
60
142944
  Remove();
61
142944
}
62
63
template <typename T>
64
145029
void ListNode<T>::Remove() {
65
145029
  prev_->next_ = next_;
66
145029
  next_->prev_ = prev_;
67
145029
  prev_ = this;
68
145029
  next_ = this;
69
145029
}
70
71
template <typename T>
72
24325
bool ListNode<T>::IsEmpty() const {
73
24325
  return prev_ == this;
74
}
75
76
template <typename T, ListNode<T> (T::*M)>
77
25942
ListHead<T, M>::Iterator::Iterator(ListNode<T>* node) : node_(node) {}
78
79
template <typename T, ListNode<T> (T::*M)>
80
2417
T* ListHead<T, M>::Iterator::operator*() const {
81
2417
  return ContainerOf(M, node_);
82
}
83
84
template <typename T, ListNode<T> (T::*M)>
85
const typename ListHead<T, M>::Iterator&
86
2417
ListHead<T, M>::Iterator::operator++() {
87
2417
  node_ = node_->next_;
88
2417
  return *this;
89
}
90
91
template <typename T, ListNode<T> (T::*M)>
92
15388
bool ListHead<T, M>::Iterator::operator!=(const Iterator& that) const {
93
15388
  return node_ != that.node_;
94
}
95
96
template <typename T, ListNode<T> (T::*M)>
97
8542
ListHead<T, M>::~ListHead() {
98

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

12344415
  return c >= 'A' && c <= 'Z' ? c + ('a' - 'A') : c;
268
}
269
270
508
std::string ToLower(const std::string& in) {
271
508
  std::string out(in.size(), 0);
272
6537
  for (size_t i = 0; i < in.size(); ++i)
273
6029
    out[i] = ToLower(in[i]);
274
508
  return out;
275
}
276
277
12288
char ToUpper(char c) {
278

12288
  return c >= 'a' && c <= 'z' ? (c - 'a') + 'A' : c;
279
}
280
281
std::string ToUpper(const std::string& in) {
282
  std::string out(in.size(), 0);
283
  for (size_t i = 0; i < in.size(); ++i)
284
    out[i] = ToUpper(in[i]);
285
  return out;
286
}
287
288
6617433
bool StringEqualNoCase(const char* a, const char* b) {
289
6168331
  do {
290
6617433
    if (*a == '\0')
291
449086
      return *b == '\0';
292
6168347
    if (*b == '\0')
293
16
      return *a == '\0';
294
6168331
  } while (ToLower(*a++) == ToLower(*b++));
295
4785238
  return false;
296
}
297
298
252
bool StringEqualNoCaseN(const char* a, const char* b, size_t length) {
299
941
  for (size_t i = 0; i < length; i++) {
300
862
    if (ToLower(a[i]) != ToLower(b[i]))
301
173
      return false;
302
689
    if (a[i] == '\0')
303
      return true;
304
  }
305
79
  return true;
306
}
307
308
template <typename T>
309
3304676
inline T MultiplyWithOverflowCheck(T a, T b) {
310
3304676
  auto ret = a * b;
311
3304676
  if (a != 0)
312
3304675
    CHECK_EQ(b, ret / a);
313
314
3304676
  return ret;
315
}
316
317
// These should be used in our code as opposed to the native
318
// versions as they abstract out some platform and or
319
// compiler version specific functionality.
320
// malloc(0) and realloc(ptr, 0) have implementation-defined behavior in
321
// that the standard allows them to either return a unique pointer or a
322
// nullptr for zero-sized allocation requests.  Normalize by always using
323
// a nullptr.
324
template <typename T>
325
3185967
T* UncheckedRealloc(T* pointer, size_t n) {
326
3185967
  size_t full_size = MultiplyWithOverflowCheck(sizeof(T), n);
327
328


3185966
  if (full_size == 0) {
329
117434
    free(pointer);
330
117434
    return nullptr;
331
  }
332
333
3068532
  void* allocated = realloc(pointer, full_size);
334
335


3068532
  if (UNLIKELY(allocated == nullptr)) {
336
    // Tell V8 that memory is low and retry.
337
    LowMemoryNotification();
338
    allocated = realloc(pointer, full_size);
339
  }
340
341
3068532
  return static_cast<T*>(allocated);
342
}
343
344
// As per spec realloc behaves like malloc if passed nullptr.
345
template <typename T>
346
2183625
inline T* UncheckedMalloc(size_t n) {
347


2183625
  if (n == 0) n = 1;
348
2183625
  return UncheckedRealloc<T>(nullptr, n);
349
}
350
351
template <typename T>
352
52760
inline T* UncheckedCalloc(size_t n) {
353
52760
  if (n == 0) n = 1;
354
52760
  MultiplyWithOverflowCheck(sizeof(T), n);
355
52760
  return static_cast<T*>(calloc(n, sizeof(T)));
356
}
357
358
template <typename T>
359
440340
inline T* Realloc(T* pointer, size_t n) {
360
440340
  T* ret = UncheckedRealloc(pointer, n);
361




440340
  CHECK_IMPLIES(n > 0, ret != nullptr);
362
440340
  return ret;
363
}
364
365
template <typename T>
366
105
inline T* Malloc(size_t n) {
367
105
  T* ret = UncheckedMalloc<T>(n);
368






105
  CHECK_IMPLIES(n > 0, ret != nullptr);
369
105
  return ret;
370
}
371
372
template <typename T>
373
inline T* Calloc(size_t n) {
374
  T* ret = UncheckedCalloc<T>(n);
375
  CHECK_IMPLIES(n > 0, ret != nullptr);
376
  return ret;
377
}
378
379
// Shortcuts for char*.
380
12
inline char* Malloc(size_t n) { return Malloc<char>(n); }
381
inline char* Calloc(size_t n) { return Calloc<char>(n); }
382
2183492
inline char* UncheckedMalloc(size_t n) { return UncheckedMalloc<char>(n); }
383
52760
inline char* UncheckedCalloc(size_t n) { return UncheckedCalloc<char>(n); }
384
385
// This is a helper in the .cc file so including util-inl.h doesn't include more
386
// headers than we really need to.
387
void ThrowErrStringTooLong(v8::Isolate* isolate);
388
389
2649491
v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
390
                                    const std::string& str,
391
                                    v8::Isolate* isolate) {
392
3611060
  if (isolate == nullptr) isolate = context->GetIsolate();
393
2649492
  if (UNLIKELY(str.size() >= static_cast<size_t>(v8::String::kMaxLength))) {
394
    // V8 only has a TODO comment about adding an exception when the maximum
395
    // string size is exceeded.
396
    ThrowErrStringTooLong(isolate);
397
    return v8::MaybeLocal<v8::Value>();
398
  }
399
400
  return v8::String::NewFromUtf8(
401
2649492
             isolate, str.data(), v8::NewStringType::kNormal, str.size())
402
5298985
      .FromMaybe(v8::Local<v8::String>());
403
}
404
405
template <typename T>
406
151565
v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
407
                                    const std::vector<T>& vec,
408
                                    v8::Isolate* isolate) {
409
224199
  if (isolate == nullptr) isolate = context->GetIsolate();
410
151565
  v8::EscapableHandleScope handle_scope(isolate);
411
412
303130
  MaybeStackBuffer<v8::Local<v8::Value>, 128> arr(vec.size());
413
151565
  arr.SetLength(vec.size());
414
1760807
  for (size_t i = 0; i < vec.size(); ++i) {
415
3218484
    if (!ToV8Value(context, vec[i], isolate).ToLocal(&arr[i]))
416
      return v8::MaybeLocal<v8::Value>();
417
  }
418
419
303130
  return handle_scope.Escape(v8::Array::New(isolate, arr.out(), arr.length()));
420
}
421
422
template <typename T, typename U>
423
4643
v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
424
                                    const std::unordered_map<T, U>& map,
425
                                    v8::Isolate* isolate) {
426
9286
  if (isolate == nullptr) isolate = context->GetIsolate();
427
4643
  v8::EscapableHandleScope handle_scope(isolate);
428
429
4643
  v8::Local<v8::Map> ret = v8::Map::New(isolate);
430
83574
  for (const auto& item : map) {
431
    v8::Local<v8::Value> first, second;
432


552517
    if (!ToV8Value(context, item.first, isolate).ToLocal(&first) ||
433
236793
        !ToV8Value(context, item.second, isolate).ToLocal(&second) ||
434
236793
        ret->Set(context, first, second).IsEmpty()) {
435
      return v8::MaybeLocal<v8::Value>();
436
    }
437
  }
438
439
4643
  return handle_scope.Escape(ret);
440
}
441
442
template <typename T, typename >
443
2
v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
444
                                    const T& number,
445
                                    v8::Isolate* isolate) {
446
2
  if (isolate == nullptr) isolate = context->GetIsolate();
447
448
  using Limits = std::numeric_limits<T>;
449
  // Choose Uint32, Int32, or Double depending on range checks.
450
  // These checks should all collapse at compile time.
451

6
  if (static_cast<uint32_t>(Limits::max()) <=
452
2
          std::numeric_limits<uint32_t>::max() &&
453
2
      static_cast<uint32_t>(Limits::min()) >=
454
2
          std::numeric_limits<uint32_t>::min() && Limits::is_exact) {
455
4
    return v8::Integer::NewFromUnsigned(isolate, static_cast<uint32_t>(number));
456
  }
457
458
  if (static_cast<int32_t>(Limits::max()) <=
459
          std::numeric_limits<int32_t>::max() &&
460
      static_cast<int32_t>(Limits::min()) >=
461
          std::numeric_limits<int32_t>::min() && Limits::is_exact) {
462
    return v8::Integer::New(isolate, static_cast<int32_t>(number));
463
  }
464
465
  return v8::Number::New(isolate, static_cast<double>(number));
466
}
467
468
146578
SlicedArguments::SlicedArguments(
469
146578
    const v8::FunctionCallbackInfo<v8::Value>& args, size_t start) {
470
146578
  const size_t length = static_cast<size_t>(args.Length());
471
293156
  if (start >= length) return;
472
146331
  const size_t size = length - start;
473
474
146331
  AllocateSufficientStorage(size);
475
503347
  for (size_t i = 0; i < size; ++i)
476
714032
    (*this)[i] = args[i + start];
477
}
478
479
template <typename T, size_t S>
480
6626
ArrayBufferViewContents<T, S>::ArrayBufferViewContents(
481
6626
    v8::Local<v8::Value> value) {
482

6626
  CHECK(value->IsArrayBufferView());
483
6626
  Read(value.As<v8::ArrayBufferView>());
484
6626
}
485
486
template <typename T, size_t S>
487
203966
ArrayBufferViewContents<T, S>::ArrayBufferViewContents(
488
203966
    v8::Local<v8::ArrayBufferView> abv) {
489
203966
  Read(abv);
490
203966
}
491
492
template <typename T, size_t S>
493
211760
void ArrayBufferViewContents<T, S>::Read(v8::Local<v8::ArrayBufferView> abv) {
494
  static_assert(sizeof(T) == 1, "Only supports one-byte data at the moment");
495
211760
  length_ = abv->ByteLength();
496



342652
  if (length_ > sizeof(stack_storage_) || abv->HasBuffer()) {
497
634020
    data_ = static_cast<T*>(abv->Buffer()->GetContents().Data()) +
498
211340
        abv->ByteOffset();
499
  } else {
500
840
    abv->CopyContents(stack_storage_, sizeof(stack_storage_));
501
420
    data_ = stack_storage_;
502
  }
503
211760
}
504
505
}  // namespace node
506
507
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
508
509
#endif  // SRC_UTIL_INL_H_