GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage/nodes/benchmark/out/../src/util.h Lines: 102 102 100.0 %
Date: 2019-01-07 12:15:22 Branches: 69 106 65.1 %

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_H_
23
#define SRC_UTIL_H_
24
25
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
26
27
#include "node_persistent.h"
28
#include "v8.h"
29
30
#include <assert.h>
31
#include <signal.h>
32
#include <stddef.h>
33
#include <stdio.h>
34
#include <stdlib.h>
35
#include <string.h>
36
37
#include <functional>  // std::function
38
#include <limits>
39
#include <set>
40
#include <string>
41
#include <array>
42
#include <unordered_map>
43
44
namespace node {
45
46
// These should be used in our code as opposed to the native
47
// versions as they abstract out some platform and or
48
// compiler version specific functionality
49
// malloc(0) and realloc(ptr, 0) have implementation-defined behavior in
50
// that the standard allows them to either return a unique pointer or a
51
// nullptr for zero-sized allocation requests.  Normalize by always using
52
// a nullptr.
53
template <typename T>
54
inline T* UncheckedRealloc(T* pointer, size_t n);
55
template <typename T>
56
inline T* UncheckedMalloc(size_t n);
57
template <typename T>
58
inline T* UncheckedCalloc(size_t n);
59
60
// Same things, but aborts immediately instead of returning nullptr when
61
// no memory is available.
62
template <typename T>
63
inline T* Realloc(T* pointer, size_t n);
64
template <typename T>
65
inline T* Malloc(size_t n);
66
template <typename T>
67
inline T* Calloc(size_t n);
68
69
inline char* Malloc(size_t n);
70
inline char* Calloc(size_t n);
71
inline char* UncheckedMalloc(size_t n);
72
inline char* UncheckedCalloc(size_t n);
73
74
template <typename T>
75
inline T MultiplyWithOverflowCheck(T a, T b);
76
77
// Used by the allocation functions when allocation fails.
78
// Thin wrapper around v8::Isolate::LowMemoryNotification() that checks
79
// whether V8 is initialized.
80
void LowMemoryNotification();
81
82
// The slightly odd function signature for Assert() is to ease
83
// instruction cache pressure in calls from CHECK.
84
[[noreturn]] void Abort();
85
[[noreturn]] void Assert(const char* const (*args)[4]);
86
void DumpBacktrace(FILE* fp);
87
88
#define DISALLOW_COPY_AND_ASSIGN(TypeName)                                    \
89
  TypeName(const TypeName&) = delete;                                         \
90
  TypeName& operator=(const TypeName&) = delete
91
92
// Windows 8+ does not like abort() in Release mode
93
#ifdef _WIN32
94
#define ABORT_NO_BACKTRACE() _exit(134)
95
#else
96
#define ABORT_NO_BACKTRACE() abort()
97
#endif
98
99
#define ABORT() node::Abort()
100
101
#ifdef __GNUC__
102
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
103
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
104
#define PRETTY_FUNCTION_NAME __PRETTY_FUNCTION__
105
#else
106
#define LIKELY(expr) expr
107
#define UNLIKELY(expr) expr
108
#define PRETTY_FUNCTION_NAME ""
109
#endif
110
111
#define STRINGIFY_(x) #x
112
#define STRINGIFY(x) STRINGIFY_(x)
113
114
#define CHECK(expr)                                                           \
115
  do {                                                                        \
116
    if (UNLIKELY(!(expr))) {                                                  \
117
      static const char* const args[] = { __FILE__, STRINGIFY(__LINE__),      \
118
                                          #expr, PRETTY_FUNCTION_NAME };      \
119
      node::Assert(&args);                                                    \
120
    }                                                                         \
121
  } while (0)
122
123
#define CHECK_EQ(a, b) CHECK((a) == (b))
124
#define CHECK_GE(a, b) CHECK((a) >= (b))
125
#define CHECK_GT(a, b) CHECK((a) > (b))
126
#define CHECK_LE(a, b) CHECK((a) <= (b))
127
#define CHECK_LT(a, b) CHECK((a) < (b))
128
#define CHECK_NE(a, b) CHECK((a) != (b))
129
#define CHECK_NULL(val) CHECK((val) == nullptr)
130
#define CHECK_NOT_NULL(val) CHECK((val) != nullptr)
131
#define CHECK_IMPLIES(a, b) CHECK(!(a) || (b))
132
133
#ifdef DEBUG
134
  #define DCHECK(expr) CHECK(expr)
135
  #define DCHECK_EQ(a, b) CHECK((a) == (b))
136
  #define DCHECK_GE(a, b) CHECK((a) >= (b))
137
  #define DCHECK_GT(a, b) CHECK((a) > (b))
138
  #define DCHECK_LE(a, b) CHECK((a) <= (b))
139
  #define DCHECK_LT(a, b) CHECK((a) < (b))
140
  #define DCHECK_NE(a, b) CHECK((a) != (b))
141
  #define DCHECK_NULL(val) CHECK((val) == nullptr)
142
  #define DCHECK_NOT_NULL(val) CHECK((val) != nullptr)
143
  #define DCHECK_IMPLIES(a, b) CHECK(!(a) || (b))
144
#else
145
  #define DCHECK(expr)
146
  #define DCHECK_EQ(a, b)
147
  #define DCHECK_GE(a, b)
148
  #define DCHECK_GT(a, b)
149
  #define DCHECK_LE(a, b)
150
  #define DCHECK_LT(a, b)
151
  #define DCHECK_NE(a, b)
152
  #define DCHECK_NULL(val)
153
  #define DCHECK_NOT_NULL(val)
154
  #define DCHECK_IMPLIES(a, b)
155
#endif
156
157
158
#define UNREACHABLE() ABORT()
159
160
// TAILQ-style intrusive list node.
161
template <typename T>
162
class ListNode;
163
164
// TAILQ-style intrusive list head.
165
template <typename T, ListNode<T> (T::*M)>
166
class ListHead;
167
168
template <typename T>
169
class ListNode {
170
 public:
171
  inline ListNode();
172
  inline ~ListNode();
173
  inline void Remove();
174
  inline bool IsEmpty() const;
175
176
 private:
177
  template <typename U, ListNode<U> (U::*M)> friend class ListHead;
178
  friend int GenDebugSymbols();
179
  ListNode* prev_;
180
  ListNode* next_;
181
  DISALLOW_COPY_AND_ASSIGN(ListNode);
182
};
183
184
template <typename T, ListNode<T> (T::*M)>
185
class ListHead {
186
 public:
187
  class Iterator {
188
   public:
189
    inline T* operator*() const;
190
    inline const Iterator& operator++();
191
    inline bool operator!=(const Iterator& that) const;
192
193
   private:
194
    friend class ListHead;
195
    inline explicit Iterator(ListNode<T>* node);
196
    ListNode<T>* node_;
197
  };
198
199
7371
  inline ListHead() = default;
200
  inline ~ListHead();
201
  inline void PushBack(T* element);
202
  inline void PushFront(T* element);
203
  inline bool IsEmpty() const;
204
  inline T* PopFront();
205
  inline Iterator begin() const;
206
  inline Iterator end() const;
207
208
 private:
209
  friend int GenDebugSymbols();
210
  ListNode<T> head_;
211
  DISALLOW_COPY_AND_ASSIGN(ListHead);
212
};
213
214
// The helper is for doing safe downcasts from base types to derived types.
215
template <typename Inner, typename Outer>
216
class ContainerOfHelper {
217
 public:
218
  inline ContainerOfHelper(Inner Outer::*field, Inner* pointer);
219
  template <typename TypeName>
220
  inline operator TypeName*() const;
221
 private:
222
  Outer* const pointer_;
223
};
224
225
// Calculate the address of the outer (i.e. embedding) struct from
226
// the interior pointer to a data member.
227
template <typename Inner, typename Outer>
228
constexpr ContainerOfHelper<Inner, Outer> ContainerOf(Inner Outer::*field,
229
                                                      Inner* pointer);
230
231
// Convenience wrapper around v8::String::NewFromOneByte().
232
inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
233
                                           const char* data,
234
                                           int length = -1);
235
236
// For the people that compile with -funsigned-char.
237
inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
238
                                           const signed char* data,
239
                                           int length = -1);
240
241
inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
242
                                           const unsigned char* data,
243
                                           int length = -1);
244
245
// Used to be a macro, hence the uppercase name.
246
template <int N>
247
775099
inline v8::Local<v8::String> FIXED_ONE_BYTE_STRING(
248
    v8::Isolate* isolate,
249
    const char(&data)[N]) {
250
775099
  return OneByteString(isolate, data, N - 1);
251
}
252
253
template <std::size_t N>
254
17957
inline v8::Local<v8::String> FIXED_ONE_BYTE_STRING(
255
    v8::Isolate* isolate,
256
    const std::array<char, N>& arr) {
257
17957
  return OneByteString(isolate, arr.data(), N - 1);
258
}
259
260
261
262
// Swaps bytes in place. nbytes is the number of bytes to swap and must be a
263
// multiple of the word size (checked by function).
264
inline void SwapBytes16(char* data, size_t nbytes);
265
inline void SwapBytes32(char* data, size_t nbytes);
266
inline void SwapBytes64(char* data, size_t nbytes);
267
268
// tolower() is locale-sensitive.  Use ToLower() instead.
269
inline char ToLower(char c);
270
inline std::string ToLower(const std::string& in);
271
272
// strcasecmp() is locale-sensitive.  Use StringEqualNoCase() instead.
273
inline bool StringEqualNoCase(const char* a, const char* b);
274
275
// strncasecmp() is locale-sensitive.  Use StringEqualNoCaseN() instead.
276
inline bool StringEqualNoCaseN(const char* a, const char* b, size_t length);
277
278
// Allocates an array of member type T. For up to kStackStorageSize items,
279
// the stack is used, otherwise malloc().
280
template <typename T, size_t kStackStorageSize = 1024>
281
class MaybeStackBuffer {
282
 public:
283
  const T* out() const {
284
    return buf_;
285
  }
286
287
1500016
  T* out() {
288
1500016
    return buf_;
289
  }
290
291
  // operator* for compatibility with `v8::String::(Utf8)Value`
292
1764748
  T* operator*() {
293
1764748
    return buf_;
294
  }
295
296
7390
  const T* operator*() const {
297
7390
    return buf_;
298
  }
299
300
431081
  T& operator[](size_t index) {
301

431081
    CHECK_LT(index, length());
302
431081
    return buf_[index];
303
  }
304
305
  const T& operator[](size_t index) const {
306
    CHECK_LT(index, length());
307
    return buf_[index];
308
  }
309
310
638194
  size_t length() const {
311
638194
    return length_;
312
  }
313
314
  // Current maximum capacity of the buffer with which SetLength() can be used
315
  // without first calling AllocateSufficientStorage().
316
4484497
  size_t capacity() const {
317
4484497
    return IsAllocated() ? capacity_ :
318




4484506
                           IsInvalidated() ? 0 : kStackStorageSize;
319
  }
320
321
  // Make sure enough space for `storage` entries is available.
322
  // This method can be called multiple times throughout the lifetime of the
323
  // buffer, but once this has been called Invalidate() cannot be used.
324
  // Content of the buffer in the range [0, length()) is preserved.
325
1560518
  void AllocateSufficientStorage(size_t storage) {
326


1560518
    CHECK(!IsInvalidated());
327


1560518
    if (storage > capacity()) {
328
1666
      bool was_allocated = IsAllocated();
329


1666
      T* allocated_ptr = was_allocated ? buf_ : nullptr;
330
1666
      buf_ = Realloc(allocated_ptr, storage);
331
1666
      capacity_ = storage;
332




1666
      if (!was_allocated && length_ > 0)
333
2
        memcpy(buf_, buf_st_, length_ * sizeof(buf_[0]));
334
    }
335
336
1560523
    length_ = storage;
337
1560523
  }
338
339
1506021
  void SetLength(size_t length) {
340
    // capacity() returns how much memory is actually available.
341

1506021
    CHECK_LE(length, capacity());
342
1506021
    length_ = length;
343
1506021
  }
344
345
1411213
  void SetLengthAndZeroTerminate(size_t length) {
346
    // capacity() returns how much memory is actually available.
347

1411213
    CHECK_LE(length + 1, capacity());
348
1411218
    SetLength(length);
349
350
    // T() is 0 for integer types, nullptr for pointers, etc.
351
1411217
    buf_[length] = T();
352
1411217
  }
353
354
  // Make derefencing this object return nullptr.
355
  // This method can be called multiple times throughout the lifetime of the
356
  // buffer, but once this has been called AllocateSufficientStorage() cannot
357
  // be used.
358
2
  void Invalidate() {
359
2
    CHECK(!IsAllocated());
360
2
    length_ = 0;
361
2
    buf_ = nullptr;
362
2
  }
363
364
  // If the buffer is stored in the heap rather than on the stack.
365
6214624
  bool IsAllocated() const {
366




6214624
    return !IsInvalidated() && buf_ != buf_st_;
367
  }
368
369
  // If Invalidate() has been called.
370
12256925
  bool IsInvalidated() const {
371
12256925
    return buf_ == nullptr;
372
  }
373
374
  // Release ownership of the malloc'd buffer.
375
  // Note: This does not free the buffer.
376
4
  void Release() {
377

4
    CHECK(IsAllocated());
378
4
    buf_ = buf_st_;
379
4
    length_ = 0;
380
4
    capacity_ = 0;
381
4
  }
382
383
12829489
  MaybeStackBuffer() : length_(0), capacity_(0), buf_(buf_st_) {
384
    // Default to a zero-length, null-terminated buffer.
385
1814144
    buf_[0] = T();
386
1727409
  }
387
388
99192
  explicit MaybeStackBuffer(size_t storage) : MaybeStackBuffer() {
389
99192
    AllocateSufficientStorage(storage);
390
99192
  }
391
392
1727403
  ~MaybeStackBuffer() {
393


1727403
    if (IsAllocated())
394
1660
      free(buf_);
395
1727406
  }
396
397
 private:
398
  size_t length_;
399
  // capacity of the malloc'ed buf_
400
  size_t capacity_;
401
  T* buf_;
402
  T buf_st_[kStackStorageSize];
403
};
404
405
1210402
class Utf8Value : public MaybeStackBuffer<char> {
406
 public:
407
  explicit Utf8Value(v8::Isolate* isolate, v8::Local<v8::Value> value);
408
};
409
410
535
class TwoByteValue : public MaybeStackBuffer<uint16_t> {
411
 public:
412
  explicit TwoByteValue(v8::Isolate* isolate, v8::Local<v8::Value> value);
413
};
414
415
200365
class BufferValue : public MaybeStackBuffer<char> {
416
 public:
417
  explicit BufferValue(v8::Isolate* isolate, v8::Local<v8::Value> value);
418
};
419
420
#define SPREAD_BUFFER_ARG(val, name)                                          \
421
  CHECK((val)->IsArrayBufferView());                                          \
422
  v8::Local<v8::ArrayBufferView> name = (val).As<v8::ArrayBufferView>();      \
423
  v8::ArrayBuffer::Contents name##_c = name->Buffer()->GetContents();         \
424
  const size_t name##_offset = name->ByteOffset();                            \
425
  const size_t name##_length = name->ByteLength();                            \
426
  char* const name##_data =                                                   \
427
      static_cast<char*>(name##_c.Data()) + name##_offset;                    \
428
  if (name##_length > 0)                                                      \
429
    CHECK_NE(name##_data, nullptr);
430
431
// Use this when a variable or parameter is unused in order to explicitly
432
// silence a compiler warning about that.
433
34343
template <typename T> inline void USE(T&&) {}
434
435
// Run a function when exiting the current scope.
436
struct OnScopeLeave {
437
  std::function<void()> fn_;
438
439
43011
  explicit OnScopeLeave(std::function<void()> fn) : fn_(fn) {}
440
43007
  ~OnScopeLeave() { fn_(); }
441
};
442
443
// Simple RAII wrapper for contiguous data that uses malloc()/free().
444
template <typename T>
445
struct MallocedBuffer {
446
  T* data;
447
  size_t size;
448
449
2095
  T* release() {
450
2095
    T* ret = data;
451
2095
    data = nullptr;
452
2095
    return ret;
453
  }
454
455
46
  void Truncate(size_t new_size) {
456
46
    CHECK(new_size <= size);
457
46
    size = new_size;
458
46
  }
459
460
8936
  inline bool is_empty() const { return data == nullptr; }
461
462
38312
  MallocedBuffer() : data(nullptr), size(0) {}
463
13694
  explicit MallocedBuffer(size_t size) : data(Malloc<T>(size)), size(size) {}
464
8880
  MallocedBuffer(T* data, size_t size) : data(data), size(size) {}
465
64897
  MallocedBuffer(MallocedBuffer&& other) : data(other.data), size(other.size) {
466
64897
    other.data = nullptr;
467
64897
  }
468
31120
  MallocedBuffer& operator=(MallocedBuffer&& other) {
469
31120
    this->~MallocedBuffer();
470
31139
    return *new(this) MallocedBuffer(std::move(other));
471
  }
472
125776
  ~MallocedBuffer() {
473
125776
    free(data);
474
125776
  }
475
  MallocedBuffer(const MallocedBuffer&) = delete;
476
  MallocedBuffer& operator=(const MallocedBuffer&) = delete;
477
};
478
479
template <typename T>
480
117
class NonCopyableMaybe {
481
 public:
482
1
  NonCopyableMaybe() : empty_(true) {}
483
116
  explicit NonCopyableMaybe(T&& value)
484
      : empty_(false),
485
116
        value_(std::move(value)) {}
486
487
117
  bool IsEmpty() const {
488
117
    return empty_;
489
  }
490
491
116
  T&& Release() {
492
116
    CHECK_EQ(empty_, false);
493
116
    empty_ = true;
494
116
    return std::move(value_);
495
  }
496
497
 private:
498
  bool empty_;
499
  T value_;
500
};
501
502
// Test whether some value can be called with ().
503
template <typename T, typename = void>
504
struct is_callable : std::is_function<T> { };
505
506
template <typename T>
507
struct is_callable<T, typename std::enable_if<
508
    std::is_same<decltype(void(&T::operator())), void>::value
509
    >::type> : std::true_type { };
510
511
template <typename T, void (*function)(T*)>
512
struct FunctionDeleter {
513
51231
  void operator()(T* pointer) const { function(pointer); }
514
  typedef std::unique_ptr<T, FunctionDeleter> Pointer;
515
};
516
517
template <typename T, void (*function)(T*)>
518
using DeleteFnPtr = typename FunctionDeleter<T, function>::Pointer;
519
520
std::set<std::string> ParseCommaSeparatedSet(const std::string& in);
521
522
inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
523
                                           const std::string& str,
524
                                           v8::Isolate* isolate = nullptr);
525
template <typename T, typename test_for_number =
526
    typename std::enable_if<std::numeric_limits<T>::is_specialized, bool>::type>
527
inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
528
                                           const T& number,
529
                                           v8::Isolate* isolate = nullptr);
530
template <typename T>
531
inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
532
                                           const std::vector<T>& vec,
533
                                           v8::Isolate* isolate = nullptr);
534
template <typename T, typename U>
535
inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
536
                                           const std::unordered_map<T, U>& map,
537
                                           v8::Isolate* isolate = nullptr);
538
539
// These macros expects a `Isolate* isolate` and a `Local<Context> context`
540
// to be in the scope.
541
#define READONLY_PROPERTY(obj, name, value)                                    \
542
  do {                                                                         \
543
    obj->DefineOwnProperty(                                                    \
544
           context, FIXED_ONE_BYTE_STRING(isolate, name), value, v8::ReadOnly) \
545
        .FromJust();                                                           \
546
  } while (0)
547
548
#define READONLY_DONT_ENUM_PROPERTY(obj, name, var)                            \
549
  do {                                                                         \
550
    obj->DefineOwnProperty(                                                    \
551
           context,                                                            \
552
           OneByteString(isolate, name),                                       \
553
           var,                                                                \
554
           static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum))    \
555
        .FromJust();                                                           \
556
  } while (0)
557
558
#define READONLY_FALSE_PROPERTY(obj, name)                                     \
559
  READONLY_PROPERTY(obj, name, v8::False(isolate))
560
561
#define READONLY_TRUE_PROPERTY(obj, name)                                      \
562
  READONLY_PROPERTY(obj, name, v8::True(isolate))
563
564
#define READONLY_STRING_PROPERTY(obj, name, str)                               \
565
  READONLY_PROPERTY(obj, name, ToV8Value(context, str).ToLocalChecked())
566
567
}  // namespace node
568
569
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
570
571
#endif  // SRC_UTIL_H_