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: 118 123 95.9 %
Date: 2019-09-15 22:29:17 Branches: 61 114 53.5 %

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

3683905
    CHECK_LT(index, length());
342
3683905
    return buf_[index];
343
  }
344
345
10267
  const T& operator[](size_t index) const {
346
10267
    CHECK_LT(index, length());
347
10267
    return buf_[index];
348
  }
349
350
5162674
  size_t length() const {
351
5162674
    return length_;
352
  }
353
354
  // Current maximum capacity of the buffer with which SetLength() can be used
355
  // without first calling AllocateSufficientStorage().
356
20243258
  size_t capacity() const {
357
20243258
    return IsAllocated() ? capacity_ :
358




20243263
                           IsInvalidated() ? 0 : kStackStorageSize;
359
  }
360
361
  // Make sure enough space for `storage` entries is available.
362
  // This method can be called multiple times throughout the lifetime of the
363
  // buffer, but once this has been called Invalidate() cannot be used.
364
  // Content of the buffer in the range [0, length()) is preserved.
365
7210480
  void AllocateSufficientStorage(size_t storage) {
366


7210480
    CHECK(!IsInvalidated());
367


7210478
    if (storage > capacity()) {
368
413008
      bool was_allocated = IsAllocated();
369


413008
      T* allocated_ptr = was_allocated ? buf_ : nullptr;
370
413008
      buf_ = Realloc(allocated_ptr, storage);
371
413008
      capacity_ = storage;
372




413008
      if (!was_allocated && length_ > 0)
373
        memcpy(buf_, buf_st_, length_ * sizeof(buf_[0]));
374
    }
375
376
7210481
    length_ = storage;
377
7210481
  }
378
379
6800835
  void SetLength(size_t length) {
380
    // capacity() returns how much memory is actually available.
381

6800835
    CHECK_LE(length, capacity());
382
6800835
    length_ = length;
383
6800835
  }
384
385
6217790
  void SetLengthAndZeroTerminate(size_t length) {
386
    // capacity() returns how much memory is actually available.
387

6217790
    CHECK_LE(length + 1, capacity());
388
6217792
    SetLength(length);
389
390
    // T() is 0 for integer types, nullptr for pointers, etc.
391
6217792
    buf_[length] = T();
392
6217792
  }
393
394
  // Make derefencing this object return nullptr.
395
  // This method can be called multiple times throughout the lifetime of the
396
  // buffer, but once this has been called AllocateSufficientStorage() cannot
397
  // be used.
398
  void Invalidate() {
399
    CHECK(!IsAllocated());
400
    length_ = 0;
401
    buf_ = nullptr;
402
  }
403
404
  // If the buffer is stored in the heap rather than on the stack.
405
29011729
  bool IsAllocated() const {
406




29011729
    return !IsInvalidated() && buf_ != buf_st_;
407
  }
408
409
  // If Invalidate() has been called.
410
56045126
  bool IsInvalidated() const {
411
56045126
    return buf_ == nullptr;
412
  }
413
414
  // Release ownership of the malloc'd buffer.
415
  // Note: This does not free the buffer.
416
2
  void Release() {
417

2
    CHECK(IsAllocated());
418
2
    buf_ = buf_st_;
419
2
    length_ = 0;
420
2
    capacity_ = 0;
421
2
  }
422
423
270461725
  MaybeStackBuffer() : length_(0), capacity_(0), buf_(buf_st_) {
424
    // Default to a zero-length, null-terminated buffer.
425
8797238
    buf_[0] = T();
426
8354407
  }
427
428
291295
  explicit MaybeStackBuffer(size_t storage) : MaybeStackBuffer() {
429
291295
    AllocateSufficientStorage(storage);
430
291295
  }
431
432
8354395
  ~MaybeStackBuffer() {
433


8354395
    if (IsAllocated())
434
413006
      free(buf_);
435
8354396
  }
436
437
 private:
438
  size_t length_;
439
  // capacity of the malloc'ed buf_
440
  size_t capacity_;
441
  T* buf_;
442
  T buf_st_[kStackStorageSize];
443
};
444
445
// Provides access to an ArrayBufferView's storage, either the original,
446
// or for small data, a copy of it. This object's lifetime is bound to the
447
// original ArrayBufferView's lifetime.
448
template <typename T, size_t kStackStorageSize = 64>
449
class ArrayBufferViewContents {
450
 public:
451
1799
  ArrayBufferViewContents() = default;
452
453
  explicit inline ArrayBufferViewContents(v8::Local<v8::Value> value);
454
  explicit inline ArrayBufferViewContents(v8::Local<v8::Object> value);
455
  explicit inline ArrayBufferViewContents(v8::Local<v8::ArrayBufferView> abv);
456
  inline void Read(v8::Local<v8::ArrayBufferView> abv);
457
458
1534737
  inline const T* data() const { return data_; }
459
4334463
  inline size_t length() const { return length_; }
460
461
 private:
462
  T stack_storage_[kStackStorageSize];
463
  T* data_ = nullptr;
464
  size_t length_ = 0;
465
};
466
467
5963267
class Utf8Value : public MaybeStackBuffer<char> {
468
 public:
469
  explicit Utf8Value(v8::Isolate* isolate, v8::Local<v8::Value> value);
470
};
471
472
1549
class TwoByteValue : public MaybeStackBuffer<uint16_t> {
473
 public:
474
  explicit TwoByteValue(v8::Isolate* isolate, v8::Local<v8::Value> value);
475
};
476
477
253362
class BufferValue : public MaybeStackBuffer<char> {
478
 public:
479
  explicit BufferValue(v8::Isolate* isolate, v8::Local<v8::Value> value);
480
};
481
482
#define SPREAD_BUFFER_ARG(val, name)                                          \
483
  CHECK((val)->IsArrayBufferView());                                          \
484
  v8::Local<v8::ArrayBufferView> name = (val).As<v8::ArrayBufferView>();      \
485
  v8::ArrayBuffer::Contents name##_c = name->Buffer()->GetContents();         \
486
  const size_t name##_offset = name->ByteOffset();                            \
487
  const size_t name##_length = name->ByteLength();                            \
488
  char* const name##_data =                                                   \
489
      static_cast<char*>(name##_c.Data()) + name##_offset;                    \
490
  if (name##_length > 0)                                                      \
491
    CHECK_NE(name##_data, nullptr);
492
493
// Use this when a variable or parameter is unused in order to explicitly
494
// silence a compiler warning about that.
495
74609
template <typename T> inline void USE(T&&) {}
496
497
// Run a function when exiting the current scope.
498
struct OnScopeLeave {
499
  std::function<void()> fn_;
500
501
151732
  explicit OnScopeLeave(std::function<void()> fn) : fn_(std::move(fn)) {}
502
151726
  ~OnScopeLeave() { fn_(); }
503
};
504
505
// Simple RAII wrapper for contiguous data that uses malloc()/free().
506
template <typename T>
507
struct MallocedBuffer {
508
  T* data;
509
  size_t size;
510
511
6
  T* release() {
512
6
    T* ret = data;
513
6
    data = nullptr;
514
6
    return ret;
515
  }
516
517
  void Truncate(size_t new_size) {
518
    CHECK(new_size <= size);
519
    size = new_size;
520
  }
521
522
41119
  inline bool is_empty() const { return data == nullptr; }
523
524
174466
  MallocedBuffer() : data(nullptr), size(0) {}
525
4
  explicit MallocedBuffer(size_t size) : data(Malloc<T>(size)), size(size) {}
526
41213
  MallocedBuffer(T* data, size_t size) : data(data), size(size) {}
527
370423
  MallocedBuffer(MallocedBuffer&& other) : data(other.data), size(other.size) {
528
370423
    other.data = nullptr;
529
370423
  }
530
92563
  MallocedBuffer& operator=(MallocedBuffer&& other) {
531
92563
    this->~MallocedBuffer();
532
92594
    return *new(this) MallocedBuffer(std::move(other));
533
  }
534
585604
  ~MallocedBuffer() {
535
585604
    free(data);
536
585604
  }
537
  MallocedBuffer(const MallocedBuffer&) = delete;
538
  MallocedBuffer& operator=(const MallocedBuffer&) = delete;
539
};
540
541
template <typename T>
542
1270
class NonCopyableMaybe {
543
 public:
544
1
  NonCopyableMaybe() : empty_(true) {}
545
1269
  explicit NonCopyableMaybe(T&& value)
546
      : empty_(false),
547
1269
        value_(std::move(value)) {}
548
549
1270
  bool IsEmpty() const {
550
1270
    return empty_;
551
  }
552
553
1269
  T&& Release() {
554
1269
    CHECK_EQ(empty_, false);
555
1269
    empty_ = true;
556
1269
    return std::move(value_);
557
  }
558
559
 private:
560
  bool empty_;
561
  T value_;
562
};
563
564
// Test whether some value can be called with ().
565
template <typename T, typename = void>
566
struct is_callable : std::is_function<T> { };
567
568
template <typename T>
569
struct is_callable<T, typename std::enable_if<
570
    std::is_same<decltype(void(&T::operator())), void>::value
571
    >::type> : std::true_type { };
572
573
template <typename T, void (*function)(T*)>
574
struct FunctionDeleter {
575
486593
  void operator()(T* pointer) const { function(pointer); }
576
  typedef std::unique_ptr<T, FunctionDeleter> Pointer;
577
};
578
579
template <typename T, void (*function)(T*)>
580
using DeleteFnPtr = typename FunctionDeleter<T, function>::Pointer;
581
582
std::vector<std::string> SplitString(const std::string& in, char delim);
583
584
inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
585
                                           const std::string& str,
586
                                           v8::Isolate* isolate = nullptr);
587
template <typename T, typename test_for_number =
588
    typename std::enable_if<std::numeric_limits<T>::is_specialized, bool>::type>
589
inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
590
                                           const T& number,
591
                                           v8::Isolate* isolate = nullptr);
592
template <typename T>
593
inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
594
                                           const std::vector<T>& vec,
595
                                           v8::Isolate* isolate = nullptr);
596
template <typename T, typename U>
597
inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
598
                                           const std::unordered_map<T, U>& map,
599
                                           v8::Isolate* isolate = nullptr);
600
601
// These macros expects a `Isolate* isolate` and a `Local<Context> context`
602
// to be in the scope.
603
#define READONLY_PROPERTY(obj, name, value)                                    \
604
  do {                                                                         \
605
    obj->DefineOwnProperty(                                                    \
606
           context, FIXED_ONE_BYTE_STRING(isolate, name), value, v8::ReadOnly) \
607
        .Check();                                                              \
608
  } while (0)
609
610
#define READONLY_DONT_ENUM_PROPERTY(obj, name, var)                            \
611
  do {                                                                         \
612
    obj->DefineOwnProperty(                                                    \
613
           context,                                                            \
614
           OneByteString(isolate, name),                                       \
615
           var,                                                                \
616
           static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum))    \
617
        .Check();                                                              \
618
  } while (0)
619
620
#define READONLY_FALSE_PROPERTY(obj, name)                                     \
621
  READONLY_PROPERTY(obj, name, v8::False(isolate))
622
623
#define READONLY_TRUE_PROPERTY(obj, name)                                      \
624
  READONLY_PROPERTY(obj, name, v8::True(isolate))
625
626
#define READONLY_STRING_PROPERTY(obj, name, str)                               \
627
  READONLY_PROPERTY(obj, name, ToV8Value(context, str).ToLocalChecked())
628
629
// Variation on NODE_DEFINE_CONSTANT that sets a String value.
630
#define NODE_DEFINE_STRING_CONSTANT(target, name, constant)                    \
631
  do {                                                                         \
632
    v8::Isolate* isolate = target->GetIsolate();                               \
633
    v8::Local<v8::String> constant_name =                                      \
634
        v8::String::NewFromUtf8(isolate, name, v8::NewStringType::kNormal)     \
635
            .ToLocalChecked();                                                 \
636
    v8::Local<v8::String> constant_value =                                     \
637
        v8::String::NewFromUtf8(isolate, constant, v8::NewStringType::kNormal) \
638
            .ToLocalChecked();                                                 \
639
    v8::PropertyAttribute constant_attributes =                                \
640
        static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete);     \
641
    target                                                                     \
642
        ->DefineOwnProperty(isolate->GetCurrentContext(),                      \
643
                            constant_name,                                     \
644
                            constant_value,                                    \
645
                            constant_attributes)                               \
646
        .Check();                                                              \
647
  } while (0)
648
649
enum Endianness {
650
  kLittleEndian,  // _Not_ LITTLE_ENDIAN, clashes with endian.h.
651
  kBigEndian
652
};
653
654
8187
inline enum Endianness GetEndianness() {
655
  // Constant-folded by the compiler.
656
  const union {
657
    uint8_t u8[2];
658
    uint16_t u16;
659
8187
  } u = {{1, 0}};
660
8187
  return u.u16 == 1 ? kLittleEndian : kBigEndian;
661
}
662
663
1
inline bool IsLittleEndian() {
664
1
  return GetEndianness() == kLittleEndian;
665
}
666
667
8186
inline bool IsBigEndian() {
668
8186
  return GetEndianness() == kBigEndian;
669
}
670
671
template <typename T, size_t N>
672
3321656
constexpr size_t arraysize(const T (&)[N]) {
673
3321656
  return N;
674
}
675
676
// Round up a to the next highest multiple of b.
677
template <typename T>
678
1193881
constexpr T RoundUp(T a, T b) {
679
1193881
  return a % b != 0 ? a + b - (a % b) : a;
680
}
681
682
#ifdef __GNUC__
683
#define MUST_USE_RESULT __attribute__((warn_unused_result))
684
#else
685
#define MUST_USE_RESULT
686
#endif
687
688
234776
class SlicedArguments : public MaybeStackBuffer<v8::Local<v8::Value>> {
689
 public:
690
  inline explicit SlicedArguments(
691
      const v8::FunctionCallbackInfo<v8::Value>& args, size_t start = 0);
692
};
693
694
// Convert a v8::PersistentBase, e.g. v8::Global, to a Local, with an extra
695
// optimization for strong persistent handles.
696
class PersistentToLocal {
697
 public:
698
  // If persistent.IsWeak() == false, then do not call persistent.Reset()
699
  // while the returned Local<T> is still in scope, it will destroy the
700
  // reference to the object.
701
  template <class TypeName>
702
36641256
  static inline v8::Local<TypeName> Default(
703
      v8::Isolate* isolate,
704
      const v8::PersistentBase<TypeName>& persistent) {
705

36641256
    if (persistent.IsWeak()) {
706
33643217
      return PersistentToLocal::Weak(isolate, persistent);
707
    } else {
708
2998039
      return PersistentToLocal::Strong(persistent);
709
    }
710
  }
711
712
  // Unchecked conversion from a non-weak Persistent<T> to Local<T>,
713
  // use with care!
714
  //
715
  // Do not call persistent.Reset() while the returned Local<T> is still in
716
  // scope, it will destroy the reference to the object.
717
  template <class TypeName>
718
28885370
  static inline v8::Local<TypeName> Strong(
719
      const v8::PersistentBase<TypeName>& persistent) {
720
    return *reinterpret_cast<v8::Local<TypeName>*>(
721
28885370
        const_cast<v8::PersistentBase<TypeName>*>(&persistent));
722
  }
723
724
  template <class TypeName>
725
33643217
  static inline v8::Local<TypeName> Weak(
726
      v8::Isolate* isolate,
727
      const v8::PersistentBase<TypeName>& persistent) {
728
33643217
    return v8::Local<TypeName>::New(isolate, persistent);
729
  }
730
};
731
732
}  // namespace node
733
734
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
735
736
#endif  // SRC_UTIL_H_