GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/util.h Lines: 138 138 100.0 %
Date: 2021-06-04 04:12:13 Branches: 77 132 58.3 %

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 "v8.h"
28
29
#include <climits>
30
#include <cstddef>
31
#include <cstdio>
32
#include <cstdlib>
33
#include <cstring>
34
35
#include <functional>  // std::function
36
#include <limits>
37
#include <set>
38
#include <string>
39
#include <array>
40
#include <unordered_map>
41
#include <utility>
42
43
#ifdef __GNUC__
44
#define MUST_USE_RESULT __attribute__((warn_unused_result))
45
#else
46
#define MUST_USE_RESULT
47
#endif
48
49
namespace node {
50
51
// Maybe remove kPathSeparator when cpp17 is ready
52
#ifdef _WIN32
53
    constexpr char kPathSeparator = '\\';
54
/* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */
55
#define PATH_MAX_BYTES (MAX_PATH * 4)
56
#else
57
    constexpr char kPathSeparator = '/';
58
#define PATH_MAX_BYTES (PATH_MAX)
59
#endif
60
61
// These should be used in our code as opposed to the native
62
// versions as they abstract out some platform and or
63
// compiler version specific functionality
64
// malloc(0) and realloc(ptr, 0) have implementation-defined behavior in
65
// that the standard allows them to either return a unique pointer or a
66
// nullptr for zero-sized allocation requests.  Normalize by always using
67
// a nullptr.
68
template <typename T>
69
inline T* UncheckedRealloc(T* pointer, size_t n);
70
template <typename T>
71
inline T* UncheckedMalloc(size_t n);
72
template <typename T>
73
inline T* UncheckedCalloc(size_t n);
74
75
// Same things, but aborts immediately instead of returning nullptr when
76
// no memory is available.
77
template <typename T>
78
inline T* Realloc(T* pointer, size_t n);
79
template <typename T>
80
inline T* Malloc(size_t n);
81
template <typename T>
82
inline T* Calloc(size_t n);
83
84
inline char* Malloc(size_t n);
85
inline char* Calloc(size_t n);
86
inline char* UncheckedMalloc(size_t n);
87
inline char* UncheckedCalloc(size_t n);
88
89
template <typename T>
90
inline T MultiplyWithOverflowCheck(T a, T b);
91
92
namespace per_process {
93
// Tells whether the per-process V8::Initialize() is called and
94
// if it is safe to call v8::Isolate::GetCurrent().
95
extern bool v8_initialized;
96
}  // namespace per_process
97
98
// Used by the allocation functions when allocation fails.
99
// Thin wrapper around v8::Isolate::LowMemoryNotification() that checks
100
// whether V8 is initialized.
101
void LowMemoryNotification();
102
103
// The reason that Assert() takes a struct argument instead of individual
104
// const char*s is to ease instruction cache pressure in calls from CHECK.
105
struct AssertionInfo {
106
  const char* file_line;  // filename:line
107
  const char* message;
108
  const char* function;
109
};
110
[[noreturn]] void Assert(const AssertionInfo& info);
111
[[noreturn]] void Abort();
112
void DumpBacktrace(FILE* fp);
113
114
// Windows 8+ does not like abort() in Release mode
115
#ifdef _WIN32
116
#define ABORT_NO_BACKTRACE() _exit(134)
117
#else
118
#define ABORT_NO_BACKTRACE() abort()
119
#endif
120
121
#define ABORT() node::Abort()
122
123
#define ERROR_AND_ABORT(expr)                                                 \
124
  do {                                                                        \
125
    /* Make sure that this struct does not end up in inline code, but      */ \
126
    /* rather in a read-only data section when modifying this code.        */ \
127
    static const node::AssertionInfo args = {                                 \
128
      __FILE__ ":" STRINGIFY(__LINE__), #expr, PRETTY_FUNCTION_NAME           \
129
    };                                                                        \
130
    node::Assert(args);                                                       \
131
  } while (0)
132
133
#ifdef __GNUC__
134
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
135
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
136
#define PRETTY_FUNCTION_NAME __PRETTY_FUNCTION__
137
#else
138
#define LIKELY(expr) expr
139
#define UNLIKELY(expr) expr
140
#define PRETTY_FUNCTION_NAME ""
141
#endif
142
143
#define STRINGIFY_(x) #x
144
#define STRINGIFY(x) STRINGIFY_(x)
145
146
#define CHECK(expr)                                                           \
147
  do {                                                                        \
148
    if (UNLIKELY(!(expr))) {                                                  \
149
      ERROR_AND_ABORT(expr);                                                  \
150
    }                                                                         \
151
  } while (0)
152
153
#define CHECK_EQ(a, b) CHECK((a) == (b))
154
#define CHECK_GE(a, b) CHECK((a) >= (b))
155
#define CHECK_GT(a, b) CHECK((a) > (b))
156
#define CHECK_LE(a, b) CHECK((a) <= (b))
157
#define CHECK_LT(a, b) CHECK((a) < (b))
158
#define CHECK_NE(a, b) CHECK((a) != (b))
159
#define CHECK_NULL(val) CHECK((val) == nullptr)
160
#define CHECK_NOT_NULL(val) CHECK((val) != nullptr)
161
#define CHECK_IMPLIES(a, b) CHECK(!(a) || (b))
162
163
#ifdef DEBUG
164
  #define DCHECK(expr) CHECK(expr)
165
  #define DCHECK_EQ(a, b) CHECK((a) == (b))
166
  #define DCHECK_GE(a, b) CHECK((a) >= (b))
167
  #define DCHECK_GT(a, b) CHECK((a) > (b))
168
  #define DCHECK_LE(a, b) CHECK((a) <= (b))
169
  #define DCHECK_LT(a, b) CHECK((a) < (b))
170
  #define DCHECK_NE(a, b) CHECK((a) != (b))
171
  #define DCHECK_NULL(val) CHECK((val) == nullptr)
172
  #define DCHECK_NOT_NULL(val) CHECK((val) != nullptr)
173
  #define DCHECK_IMPLIES(a, b) CHECK(!(a) || (b))
174
#else
175
  #define DCHECK(expr)
176
  #define DCHECK_EQ(a, b)
177
  #define DCHECK_GE(a, b)
178
  #define DCHECK_GT(a, b)
179
  #define DCHECK_LE(a, b)
180
  #define DCHECK_LT(a, b)
181
  #define DCHECK_NE(a, b)
182
  #define DCHECK_NULL(val)
183
  #define DCHECK_NOT_NULL(val)
184
  #define DCHECK_IMPLIES(a, b)
185
#endif
186
187
188
#define UNREACHABLE(...)                                                      \
189
  ERROR_AND_ABORT("Unreachable code reached" __VA_OPT__(": ") __VA_ARGS__)
190
191
// ECMA262 20.1.2.6 Number.MAX_SAFE_INTEGER (2^53-1)
192
constexpr int64_t kMaxSafeJsInteger = 9007199254740991;
193
194
inline bool IsSafeJsInt(v8::Local<v8::Value> v);
195
196
// TAILQ-style intrusive list node.
197
template <typename T>
198
class ListNode;
199
200
// TAILQ-style intrusive list head.
201
template <typename T, ListNode<T> (T::*M)>
202
class ListHead;
203
204
template <typename T>
205
class ListNode {
206
 public:
207
  inline ListNode();
208
  inline ~ListNode();
209
  inline void Remove();
210
  inline bool IsEmpty() const;
211
212
  ListNode(const ListNode&) = delete;
213
  ListNode& operator=(const ListNode&) = delete;
214
215
 private:
216
  template <typename U, ListNode<U> (U::*M)> friend class ListHead;
217
  friend int GenDebugSymbols();
218
  ListNode* prev_;
219
  ListNode* next_;
220
};
221
222
template <typename T, ListNode<T> (T::*M)>
223
class ListHead {
224
 public:
225
  class Iterator {
226
   public:
227
    inline T* operator*() const;
228
    inline const Iterator& operator++();
229
    inline bool operator!=(const Iterator& that) const;
230
231
   private:
232
    friend class ListHead;
233
    inline explicit Iterator(ListNode<T>* node);
234
    ListNode<T>* node_;
235
  };
236
237
10481
  inline ListHead() = default;
238
  inline ~ListHead();
239
  inline void PushBack(T* element);
240
  inline void PushFront(T* element);
241
  inline bool IsEmpty() const;
242
  inline T* PopFront();
243
  inline Iterator begin() const;
244
  inline Iterator end() const;
245
246
  ListHead(const ListHead&) = delete;
247
  ListHead& operator=(const ListHead&) = delete;
248
249
 private:
250
  friend int GenDebugSymbols();
251
  ListNode<T> head_;
252
};
253
254
// The helper is for doing safe downcasts from base types to derived types.
255
template <typename Inner, typename Outer>
256
class ContainerOfHelper {
257
 public:
258
  inline ContainerOfHelper(Inner Outer::*field, Inner* pointer);
259
  template <typename TypeName>
260
  inline operator TypeName*() const;
261
 private:
262
  Outer* const pointer_;
263
};
264
265
// Calculate the address of the outer (i.e. embedding) struct from
266
// the interior pointer to a data member.
267
template <typename Inner, typename Outer>
268
constexpr ContainerOfHelper<Inner, Outer> ContainerOf(Inner Outer::*field,
269
                                                      Inner* pointer);
270
271
// Convenience wrapper around v8::String::NewFromOneByte().
272
inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
273
                                           const char* data,
274
                                           int length = -1);
275
276
// For the people that compile with -funsigned-char.
277
inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
278
                                           const signed char* data,
279
                                           int length = -1);
280
281
inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
282
                                           const unsigned char* data,
283
                                           int length = -1);
284
285
// Used to be a macro, hence the uppercase name.
286
template <int N>
287
2768254
inline v8::Local<v8::String> FIXED_ONE_BYTE_STRING(
288
    v8::Isolate* isolate,
289
    const char(&data)[N]) {
290
2768254
  return OneByteString(isolate, data, N - 1);
291
}
292
293
template <std::size_t N>
294
424
inline v8::Local<v8::String> FIXED_ONE_BYTE_STRING(
295
    v8::Isolate* isolate,
296
    const std::array<char, N>& arr) {
297
424
  return OneByteString(isolate, arr.data(), N - 1);
298
}
299
300
301
302
// Swaps bytes in place. nbytes is the number of bytes to swap and must be a
303
// multiple of the word size (checked by function).
304
inline void SwapBytes16(char* data, size_t nbytes);
305
inline void SwapBytes32(char* data, size_t nbytes);
306
inline void SwapBytes64(char* data, size_t nbytes);
307
308
// tolower() is locale-sensitive.  Use ToLower() instead.
309
inline char ToLower(char c);
310
inline std::string ToLower(const std::string& in);
311
312
// toupper() is locale-sensitive.  Use ToUpper() instead.
313
inline char ToUpper(char c);
314
inline std::string ToUpper(const std::string& in);
315
316
// strcasecmp() is locale-sensitive.  Use StringEqualNoCase() instead.
317
inline bool StringEqualNoCase(const char* a, const char* b);
318
319
// strncasecmp() is locale-sensitive.  Use StringEqualNoCaseN() instead.
320
inline bool StringEqualNoCaseN(const char* a, const char* b, size_t length);
321
322
template <typename T, size_t N>
323
6567558
constexpr size_t arraysize(const T (&)[N]) {
324
6567558
  return N;
325
}
326
327
template <typename T, size_t N>
328
constexpr size_t strsize(const T (&)[N]) {
329
  return N - 1;
330
}
331
332
// Allocates an array of member type T. For up to kStackStorageSize items,
333
// the stack is used, otherwise malloc().
334
template <typename T, size_t kStackStorageSize = 1024>
335
class MaybeStackBuffer {
336
 public:
337
5657
  const T* out() const {
338
5657
    return buf_;
339
  }
340
341
3810665
  T* out() {
342
3810665
    return buf_;
343
  }
344
345
  // operator* for compatibility with `v8::String::(Utf8)Value`
346
5169841
  T* operator*() {
347
5169841
    return buf_;
348
  }
349
350
31483
  const T* operator*() const {
351
31483
    return buf_;
352
  }
353
354
2424523
  T& operator[](size_t index) {
355

2424523
    CHECK_LT(index, length());
356
2424523
    return buf_[index];
357
  }
358
359
10737
  const T& operator[](size_t index) const {
360
10737
    CHECK_LT(index, length());
361
10737
    return buf_[index];
362
  }
363
364
4727518
  size_t length() const {
365
4727518
    return length_;
366
  }
367
368
  // Current maximum capacity of the buffer with which SetLength() can be used
369
  // without first calling AllocateSufficientStorage().
370
11283270
  size_t capacity() const {
371
11283270
    return capacity_;
372
  }
373
374
  // Make sure enough space for `storage` entries is available.
375
  // This method can be called multiple times throughout the lifetime of the
376
  // buffer, but once this has been called Invalidate() cannot be used.
377
  // Content of the buffer in the range [0, length()) is preserved.
378
3970731
  void AllocateSufficientStorage(size_t storage) {
379


3970731
    CHECK(!IsInvalidated());
380


3970693
    if (storage > capacity()) {
381
121009
      bool was_allocated = IsAllocated();
382


121009
      T* allocated_ptr = was_allocated ? buf_ : nullptr;
383
121009
      buf_ = Realloc(allocated_ptr, storage);
384
121009
      capacity_ = storage;
385





121009
      if (!was_allocated && length_ > 0)
386
2
        memcpy(buf_, buf_st_, length_ * sizeof(buf_[0]));
387
    }
388
389
3970659
    length_ = storage;
390
3970659
  }
391
392
3790950
  void SetLength(size_t length) {
393
    // capacity() returns how much memory is actually available.
394

3790950
    CHECK_LE(length, capacity());
395
3790880
    length_ = length;
396
3790880
  }
397
398
3507081
  void SetLengthAndZeroTerminate(size_t length) {
399
    // capacity() returns how much memory is actually available.
400

3507081
    CHECK_LE(length + 1, capacity());
401
3507065
    SetLength(length);
402
403
    // T() is 0 for integer types, nullptr for pointers, etc.
404
3506973
    buf_[length] = T();
405
3506973
  }
406
407
  // Make dereferencing this object return nullptr.
408
  // This method can be called multiple times throughout the lifetime of the
409
  // buffer, but once this has been called AllocateSufficientStorage() cannot
410
  // be used.
411
2
  void Invalidate() {
412
2
    CHECK(!IsAllocated());
413
2
    capacity_ = 0;
414
2
    length_ = 0;
415
2
    buf_ = nullptr;
416
2
  }
417
418
  // If the buffer is stored in the heap rather than on the stack.
419
4801619
  bool IsAllocated() const {
420





4801619
    return !IsInvalidated() && buf_ != buf_st_;
421
  }
422
423
  // If Invalidate() has been called.
424
8772899
  bool IsInvalidated() const {
425
8772899
    return buf_ == nullptr;
426
  }
427
428
  // Release ownership of the malloc'd buffer.
429
  // Note: This does not free the buffer.
430
81
  void Release() {
431

81
    CHECK(IsAllocated());
432
81
    buf_ = buf_st_;
433
81
    length_ = 0;
434
81
    capacity_ = arraysize(buf_st_);
435
81
  }
436
437
4678535
  MaybeStackBuffer()
438

67231253
      : length_(0), capacity_(arraysize(buf_st_)), buf_(buf_st_) {
439
    // Default to a zero-length, null-terminated buffer.
440
5102355
    buf_[0] = T();
441
4678509
  }
442
443
364998
  explicit MaybeStackBuffer(size_t storage) : MaybeStackBuffer() {
444
365002
    AllocateSufficientStorage(storage);
445
365003
  }
446
447
4678513
  ~MaybeStackBuffer() {
448


4678513
    if (IsAllocated())
449
120926
      free(buf_);
450
4678469
  }
451
452
 private:
453
  size_t length_;
454
  // capacity of the malloc'ed buf_
455
  size_t capacity_;
456
  T* buf_;
457
  T buf_st_[kStackStorageSize];
458
};
459
460
// Provides access to an ArrayBufferView's storage, either the original,
461
// or for small data, a copy of it. This object's lifetime is bound to the
462
// original ArrayBufferView's lifetime.
463
template <typename T, size_t kStackStorageSize = 64>
464
class ArrayBufferViewContents {
465
 public:
466
600
  ArrayBufferViewContents() = default;
467
468
  explicit inline ArrayBufferViewContents(v8::Local<v8::Value> value);
469
  explicit inline ArrayBufferViewContents(v8::Local<v8::Object> value);
470
  explicit inline ArrayBufferViewContents(v8::Local<v8::ArrayBufferView> abv);
471
  inline void Read(v8::Local<v8::ArrayBufferView> abv);
472
473
149709
  inline const T* data() const { return data_; }
474
583840
  inline size_t length() const { return length_; }
475
476
 private:
477
  T stack_storage_[kStackStorageSize];
478
  T* data_ = nullptr;
479
  size_t length_ = 0;
480
};
481
482
2599467
class Utf8Value : public MaybeStackBuffer<char> {
483
 public:
484
  explicit Utf8Value(v8::Isolate* isolate, v8::Local<v8::Value> value);
485
486
843
  inline std::string ToString() const { return std::string(out(), length()); }
487
488
4814
  inline bool operator==(const char* a) const {
489
4814
    return strcmp(out(), a) == 0;
490
  }
491
};
492
493
602949
class TwoByteValue : public MaybeStackBuffer<uint16_t> {
494
 public:
495
  explicit TwoByteValue(v8::Isolate* isolate, v8::Local<v8::Value> value);
496
};
497
498
200992
class BufferValue : public MaybeStackBuffer<char> {
499
 public:
500
  explicit BufferValue(v8::Isolate* isolate, v8::Local<v8::Value> value);
501
502
  inline std::string ToString() const { return std::string(out(), length()); }
503
};
504
505
#define SPREAD_BUFFER_ARG(val, name)                                          \
506
  CHECK((val)->IsArrayBufferView());                                          \
507
  v8::Local<v8::ArrayBufferView> name = (val).As<v8::ArrayBufferView>();      \
508
  std::shared_ptr<v8::BackingStore> name##_bs =                               \
509
      name->Buffer()->GetBackingStore();                                      \
510
  const size_t name##_offset = name->ByteOffset();                            \
511
  const size_t name##_length = name->ByteLength();                            \
512
  char* const name##_data =                                                   \
513
      static_cast<char*>(name##_bs->Data()) + name##_offset;                  \
514
  if (name##_length > 0)                                                      \
515
    CHECK_NE(name##_data, nullptr);
516
517
// Use this when a variable or parameter is unused in order to explicitly
518
// silence a compiler warning about that.
519
3841458
template <typename T> inline void USE(T&&) {}
520
521
template <typename Fn>
522
struct OnScopeLeaveImpl {
523
  Fn fn_;
524
  bool active_;
525
526
1655214
  explicit OnScopeLeaveImpl(Fn&& fn) : fn_(std::move(fn)), active_(true) {}
527

1654753
  ~OnScopeLeaveImpl() { if (active_) fn_(); }
528
529
  OnScopeLeaveImpl(const OnScopeLeaveImpl& other) = delete;
530
  OnScopeLeaveImpl& operator=(const OnScopeLeaveImpl& other) = delete;
531
  OnScopeLeaveImpl(OnScopeLeaveImpl&& other)
532
    : fn_(std::move(other.fn_)), active_(other.active_) {
533
    other.active_ = false;
534
  }
535
  OnScopeLeaveImpl& operator=(OnScopeLeaveImpl&& other) {
536
    if (this == &other) return *this;
537
    this->~OnScopeLeave();
538
    new (this)OnScopeLeaveImpl(std::move(other));
539
    return *this;
540
  }
541
};
542
543
// Run a function when exiting the current scope. Used like this:
544
// auto on_scope_leave = OnScopeLeave([&] {
545
//   // ... run some code ...
546
// });
547
template <typename Fn>
548
1655195
inline MUST_USE_RESULT OnScopeLeaveImpl<Fn> OnScopeLeave(Fn&& fn) {
549
1655195
  return OnScopeLeaveImpl<Fn>{std::move(fn)};
550
}
551
552
// Simple RAII wrapper for contiguous data that uses malloc()/free().
553
template <typename T>
554
struct MallocedBuffer {
555
  T* data;
556
  size_t size;
557
558
  T* release() {
559
    T* ret = data;
560
    data = nullptr;
561
    return ret;
562
  }
563
564
  void Truncate(size_t new_size) {
565
    CHECK(new_size <= size);
566
    size = new_size;
567
  }
568
569
  void Realloc(size_t new_size) {
570
    Truncate(new_size);
571
    data = UncheckedRealloc(data, new_size);
572
  }
573
574
49372
  inline bool is_empty() const { return data == nullptr; }
575
576
83628
  MallocedBuffer() : data(nullptr), size(0) {}
577
23
  explicit MallocedBuffer(size_t size) : data(Malloc<T>(size)), size(size) {}
578
49414
  MallocedBuffer(T* data, size_t size) : data(data), size(size) {}
579
132989
  MallocedBuffer(MallocedBuffer&& other) : data(other.data), size(other.size) {
580
132989
    other.data = nullptr;
581
132989
  }
582
49424
  MallocedBuffer& operator=(MallocedBuffer&& other) {
583
49424
    this->~MallocedBuffer();
584
49423
    return *new(this) MallocedBuffer(std::move(other));
585
  }
586
265785
  ~MallocedBuffer() {
587
265785
    free(data);
588
265785
  }
589
  MallocedBuffer(const MallocedBuffer&) = delete;
590
  MallocedBuffer& operator=(const MallocedBuffer&) = delete;
591
};
592
593
template <typename T>
594
13131
class NonCopyableMaybe {
595
 public:
596
2451
  NonCopyableMaybe() : empty_(true) {}
597
2385
  explicit NonCopyableMaybe(T&& value)
598
      : empty_(false),
599
2385
        value_(std::move(value)) {}
600
601
2356
  bool IsEmpty() const {
602
2356
    return empty_;
603
  }
604
605
838
  const T* get() const {
606
838
    return empty_ ? nullptr : &value_;
607
  }
608
609
22
  const T* operator->() const {
610
22
    CHECK(!empty_);
611
22
    return &value_;
612
  }
613
614
2289
  T&& Release() {
615
2289
    CHECK_EQ(empty_, false);
616
2289
    empty_ = true;
617
2289
    return std::move(value_);
618
  }
619
620
 private:
621
  bool empty_;
622
  T value_;
623
};
624
625
// Test whether some value can be called with ().
626
template <typename T, typename = void>
627
struct is_callable : std::is_function<T> { };
628
629
template <typename T>
630
struct is_callable<T, typename std::enable_if<
631
    std::is_same<decltype(void(&T::operator())), void>::value
632
    >::type> : std::true_type { };
633
634
template <typename T, void (*function)(T*)>
635
struct FunctionDeleter {
636
94578
  void operator()(T* pointer) const { function(pointer); }
637
  typedef std::unique_ptr<T, FunctionDeleter> Pointer;
638
};
639
640
template <typename T, void (*function)(T*)>
641
using DeleteFnPtr = typename FunctionDeleter<T, function>::Pointer;
642
643
std::vector<std::string> SplitString(const std::string& in, char delim);
644
645
inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
646
                                           const std::string& str,
647
                                           v8::Isolate* isolate = nullptr);
648
template <typename T, typename test_for_number =
649
    typename std::enable_if<std::numeric_limits<T>::is_specialized, bool>::type>
650
inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
651
                                           const T& number,
652
                                           v8::Isolate* isolate = nullptr);
653
template <typename T>
654
inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
655
                                           const std::vector<T>& vec,
656
                                           v8::Isolate* isolate = nullptr);
657
template <typename T, typename U>
658
inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
659
                                           const std::unordered_map<T, U>& map,
660
                                           v8::Isolate* isolate = nullptr);
661
662
// These macros expects a `Isolate* isolate` and a `Local<Context> context`
663
// to be in the scope.
664
#define READONLY_PROPERTY(obj, name, value)                                    \
665
  do {                                                                         \
666
    obj->DefineOwnProperty(                                                    \
667
           context, FIXED_ONE_BYTE_STRING(isolate, name), value, v8::ReadOnly) \
668
        .Check();                                                              \
669
  } while (0)
670
671
#define READONLY_DONT_ENUM_PROPERTY(obj, name, var)                            \
672
  do {                                                                         \
673
    obj->DefineOwnProperty(                                                    \
674
           context,                                                            \
675
           OneByteString(isolate, name),                                       \
676
           var,                                                                \
677
           static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum))    \
678
        .Check();                                                              \
679
  } while (0)
680
681
#define READONLY_FALSE_PROPERTY(obj, name)                                     \
682
  READONLY_PROPERTY(obj, name, v8::False(isolate))
683
684
#define READONLY_TRUE_PROPERTY(obj, name)                                      \
685
  READONLY_PROPERTY(obj, name, v8::True(isolate))
686
687
#define READONLY_STRING_PROPERTY(obj, name, str)                               \
688
  READONLY_PROPERTY(obj, name, ToV8Value(context, str).ToLocalChecked())
689
690
// Variation on NODE_DEFINE_CONSTANT that sets a String value.
691
#define NODE_DEFINE_STRING_CONSTANT(target, name, constant)                    \
692
  do {                                                                         \
693
    v8::Isolate* isolate = target->GetIsolate();                               \
694
    v8::Local<v8::String> constant_name =                                      \
695
        v8::String::NewFromUtf8(isolate, name).ToLocalChecked();               \
696
    v8::Local<v8::String> constant_value =                                     \
697
        v8::String::NewFromUtf8(isolate, constant).ToLocalChecked();           \
698
    v8::PropertyAttribute constant_attributes =                                \
699
        static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete);     \
700
    target                                                                     \
701
        ->DefineOwnProperty(isolate->GetCurrentContext(),                      \
702
                            constant_name,                                     \
703
                            constant_value,                                    \
704
                            constant_attributes)                               \
705
        .Check();                                                              \
706
  } while (0)
707
708
enum Endianness {
709
  kLittleEndian,  // _Not_ LITTLE_ENDIAN, clashes with endian.h.
710
  kBigEndian
711
};
712
713
5977
inline enum Endianness GetEndianness() {
714
  // Constant-folded by the compiler.
715
  const union {
716
    uint8_t u8[2];
717
    uint16_t u16;
718
5977
  } u = {{1, 0}};
719
5977
  return u.u16 == 1 ? kLittleEndian : kBigEndian;
720
}
721
722
1
inline bool IsLittleEndian() {
723
1
  return GetEndianness() == kLittleEndian;
724
}
725
726
5975
inline bool IsBigEndian() {
727
5975
  return GetEndianness() == kBigEndian;
728
}
729
730
// Round up a to the next highest multiple of b.
731
template <typename T>
732
124547
constexpr T RoundUp(T a, T b) {
733
124547
  return a % b != 0 ? a + b - (a % b) : a;
734
}
735
736
// Align ptr to an `alignment`-bytes boundary.
737
template <typename T, typename U>
738
23647
constexpr T* AlignUp(T* ptr, U alignment) {
739
  return reinterpret_cast<T*>(
740
23647
      RoundUp(reinterpret_cast<uintptr_t>(ptr), alignment));
741
}
742
743
22913
class SlicedArguments : public MaybeStackBuffer<v8::Local<v8::Value>> {
744
 public:
745
  inline explicit SlicedArguments(
746
      const v8::FunctionCallbackInfo<v8::Value>& args, size_t start = 0);
747
};
748
749
// Convert a v8::PersistentBase, e.g. v8::Global, to a Local, with an extra
750
// optimization for strong persistent handles.
751
class PersistentToLocal {
752
 public:
753
  // If persistent.IsWeak() == false, then do not call persistent.Reset()
754
  // while the returned Local<T> is still in scope, it will destroy the
755
  // reference to the object.
756
  template <class TypeName>
757
4355495
  static inline v8::Local<TypeName> Default(
758
      v8::Isolate* isolate,
759
      const v8::PersistentBase<TypeName>& persistent) {
760

4355495
    if (persistent.IsWeak()) {
761
2274010
      return PersistentToLocal::Weak(isolate, persistent);
762
    } else {
763
2081485
      return PersistentToLocal::Strong(persistent);
764
    }
765
  }
766
767
  // Unchecked conversion from a non-weak Persistent<T> to Local<T>,
768
  // use with care!
769
  //
770
  // Do not call persistent.Reset() while the returned Local<T> is still in
771
  // scope, it will destroy the reference to the object.
772
  template <class TypeName>
773
12390929
  static inline v8::Local<TypeName> Strong(
774
      const v8::PersistentBase<TypeName>& persistent) {
775
    DCHECK(!persistent.IsWeak());
776
    return *reinterpret_cast<v8::Local<TypeName>*>(
777
12390929
        const_cast<v8::PersistentBase<TypeName>*>(&persistent));
778
  }
779
780
  template <class TypeName>
781
2279305
  static inline v8::Local<TypeName> Weak(
782
      v8::Isolate* isolate,
783
      const v8::PersistentBase<TypeName>& persistent) {
784
2279306
    return v8::Local<TypeName>::New(isolate, persistent);
785
  }
786
};
787
788
// Can be used as a key for std::unordered_map when lookup performance is more
789
// important than size and the keys are statically used to avoid redundant hash
790
// computations.
791
class FastStringKey {
792
 public:
793
  constexpr explicit FastStringKey(const char* name);
794
795
5240
  struct Hash {
796
    constexpr size_t operator()(const FastStringKey& key) const;
797
  };
798
  constexpr bool operator==(const FastStringKey& other) const;
799
800
  constexpr const char* c_str() const;
801
802
 private:
803
  static constexpr size_t HashImpl(const char* str);
804
805
  const char* name_;
806
  size_t cached_hash_;
807
};
808
809
// Like std::static_pointer_cast but for unique_ptr with the default deleter.
810
template <typename T, typename U>
811
10424
std::unique_ptr<T> static_unique_pointer_cast(std::unique_ptr<U>&& ptr) {
812
10424
  return std::unique_ptr<T>(static_cast<T*>(ptr.release()));
813
}
814
815
#define MAYBE_FIELD_PTR(ptr, field) ptr == nullptr ? nullptr : &(ptr->field)
816
}  // namespace node
817
818
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
819
820
#endif  // SRC_UTIL_H_