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: 115 120 95.8 %
Date: 2019-05-05 22:32:45 Branches: 61 112 54.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 <csignal>
31
#include <cstddef>
32
#include <cstdio>
33
#include <cstdlib>
34
#include <cstring>
35
36
#include <functional>  // std::function
37
#include <limits>
38
#include <set>
39
#include <string>
40
#include <array>
41
#include <unordered_map>
42
#include <utility>
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
namespace per_process {
78
// Tells whether the per-process V8::Initialize() is called and
79
// if it is safe to call v8::Isolate::GetCurrent().
80
extern bool v8_initialized;
81
}  // namespace per_process
82
83
// Used by the allocation functions when allocation fails.
84
// Thin wrapper around v8::Isolate::LowMemoryNotification() that checks
85
// whether V8 is initialized.
86
void LowMemoryNotification();
87
88
// The reason that Assert() takes a struct argument instead of individual
89
// const char*s is to ease instruction cache pressure in calls from CHECK.
90
struct AssertionInfo {
91
  const char* file_line;  // filename:line
92
  const char* message;
93
  const char* function;
94
};
95
[[noreturn]] void Assert(const AssertionInfo& info);
96
[[noreturn]] void Abort();
97
void DumpBacktrace(FILE* fp);
98
99
// Windows 8+ does not like abort() in Release mode
100
#ifdef _WIN32
101
#define ABORT_NO_BACKTRACE() _exit(134)
102
#else
103
#define ABORT_NO_BACKTRACE() abort()
104
#endif
105
106
#define ABORT() node::Abort()
107
108
#ifdef __GNUC__
109
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
110
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
111
#define PRETTY_FUNCTION_NAME __PRETTY_FUNCTION__
112
#else
113
#define LIKELY(expr) expr
114
#define UNLIKELY(expr) expr
115
#define PRETTY_FUNCTION_NAME ""
116
#endif
117
118
#define STRINGIFY_(x) #x
119
#define STRINGIFY(x) STRINGIFY_(x)
120
121
#define CHECK(expr)                                                           \
122
  do {                                                                        \
123
    if (UNLIKELY(!(expr))) {                                                  \
124
      /* Make sure that this struct does not end up in inline code, but    */ \
125
      /* rather in a read-only data section when modifying this code.      */ \
126
      static const node::AssertionInfo args = {                               \
127
        __FILE__ ":" STRINGIFY(__LINE__), #expr, PRETTY_FUNCTION_NAME         \
128
      };                                                                      \
129
      node::Assert(args);                                                     \
130
    }                                                                         \
131
  } while (0)
132
133
#define CHECK_EQ(a, b) CHECK((a) == (b))
134
#define CHECK_GE(a, b) CHECK((a) >= (b))
135
#define CHECK_GT(a, b) CHECK((a) > (b))
136
#define CHECK_LE(a, b) CHECK((a) <= (b))
137
#define CHECK_LT(a, b) CHECK((a) < (b))
138
#define CHECK_NE(a, b) CHECK((a) != (b))
139
#define CHECK_NULL(val) CHECK((val) == nullptr)
140
#define CHECK_NOT_NULL(val) CHECK((val) != nullptr)
141
#define CHECK_IMPLIES(a, b) CHECK(!(a) || (b))
142
143
#ifdef DEBUG
144
  #define DCHECK(expr) CHECK(expr)
145
  #define DCHECK_EQ(a, b) CHECK((a) == (b))
146
  #define DCHECK_GE(a, b) CHECK((a) >= (b))
147
  #define DCHECK_GT(a, b) CHECK((a) > (b))
148
  #define DCHECK_LE(a, b) CHECK((a) <= (b))
149
  #define DCHECK_LT(a, b) CHECK((a) < (b))
150
  #define DCHECK_NE(a, b) CHECK((a) != (b))
151
  #define DCHECK_NULL(val) CHECK((val) == nullptr)
152
  #define DCHECK_NOT_NULL(val) CHECK((val) != nullptr)
153
  #define DCHECK_IMPLIES(a, b) CHECK(!(a) || (b))
154
#else
155
  #define DCHECK(expr)
156
  #define DCHECK_EQ(a, b)
157
  #define DCHECK_GE(a, b)
158
  #define DCHECK_GT(a, b)
159
  #define DCHECK_LE(a, b)
160
  #define DCHECK_LT(a, b)
161
  #define DCHECK_NE(a, b)
162
  #define DCHECK_NULL(val)
163
  #define DCHECK_NOT_NULL(val)
164
  #define DCHECK_IMPLIES(a, b)
165
#endif
166
167
168
#define UNREACHABLE() ABORT()
169
170
// TAILQ-style intrusive list node.
171
template <typename T>
172
class ListNode;
173
174
// TAILQ-style intrusive list head.
175
template <typename T, ListNode<T> (T::*M)>
176
class ListHead;
177
178
template <typename T>
179
class ListNode {
180
 public:
181
  inline ListNode();
182
  inline ~ListNode();
183
  inline void Remove();
184
  inline bool IsEmpty() const;
185
186
  ListNode(const ListNode&) = delete;
187
  ListNode& operator=(const ListNode&) = delete;
188
189
 private:
190
  template <typename U, ListNode<U> (U::*M)> friend class ListHead;
191
  friend int GenDebugSymbols();
192
  ListNode* prev_;
193
  ListNode* next_;
194
};
195
196
template <typename T, ListNode<T> (T::*M)>
197
class ListHead {
198
 public:
199
  class Iterator {
200
   public:
201
    inline T* operator*() const;
202
    inline const Iterator& operator++();
203
    inline bool operator!=(const Iterator& that) const;
204
205
   private:
206
    friend class ListHead;
207
    inline explicit Iterator(ListNode<T>* node);
208
    ListNode<T>* node_;
209
  };
210
211
9302
  inline ListHead() = default;
212
  inline ~ListHead();
213
  inline void PushBack(T* element);
214
  inline void PushFront(T* element);
215
  inline bool IsEmpty() const;
216
  inline T* PopFront();
217
  inline Iterator begin() const;
218
  inline Iterator end() const;
219
220
  ListHead(const ListHead&) = delete;
221
  ListHead& operator=(const ListHead&) = delete;
222
223
 private:
224
  friend int GenDebugSymbols();
225
  ListNode<T> head_;
226
};
227
228
// The helper is for doing safe downcasts from base types to derived types.
229
template <typename Inner, typename Outer>
230
class ContainerOfHelper {
231
 public:
232
  inline ContainerOfHelper(Inner Outer::*field, Inner* pointer);
233
  template <typename TypeName>
234
  inline operator TypeName*() const;
235
 private:
236
  Outer* const pointer_;
237
};
238
239
// Calculate the address of the outer (i.e. embedding) struct from
240
// the interior pointer to a data member.
241
template <typename Inner, typename Outer>
242
constexpr ContainerOfHelper<Inner, Outer> ContainerOf(Inner Outer::*field,
243
                                                      Inner* pointer);
244
245
// Convenience wrapper around v8::String::NewFromOneByte().
246
inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
247
                                           const char* data,
248
                                           int length = -1);
249
250
// For the people that compile with -funsigned-char.
251
inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
252
                                           const signed char* data,
253
                                           int length = -1);
254
255
inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
256
                                           const unsigned char* data,
257
                                           int length = -1);
258
259
// Used to be a macro, hence the uppercase name.
260
template <int N>
261
3154221
inline v8::Local<v8::String> FIXED_ONE_BYTE_STRING(
262
    v8::Isolate* isolate,
263
    const char(&data)[N]) {
264
3154221
  return OneByteString(isolate, data, N - 1);
265
}
266
267
template <std::size_t N>
268
19506
inline v8::Local<v8::String> FIXED_ONE_BYTE_STRING(
269
    v8::Isolate* isolate,
270
    const std::array<char, N>& arr) {
271
19506
  return OneByteString(isolate, arr.data(), N - 1);
272
}
273
274
275
276
// Swaps bytes in place. nbytes is the number of bytes to swap and must be a
277
// multiple of the word size (checked by function).
278
inline void SwapBytes16(char* data, size_t nbytes);
279
inline void SwapBytes32(char* data, size_t nbytes);
280
inline void SwapBytes64(char* data, size_t nbytes);
281
282
// tolower() is locale-sensitive.  Use ToLower() instead.
283
inline char ToLower(char c);
284
inline std::string ToLower(const std::string& in);
285
286
// toupper() is locale-sensitive.  Use ToUpper() instead.
287
inline char ToUpper(char c);
288
inline std::string ToUpper(const std::string& in);
289
290
// strcasecmp() is locale-sensitive.  Use StringEqualNoCase() instead.
291
inline bool StringEqualNoCase(const char* a, const char* b);
292
293
// strncasecmp() is locale-sensitive.  Use StringEqualNoCaseN() instead.
294
inline bool StringEqualNoCaseN(const char* a, const char* b, size_t length);
295
296
// Allocates an array of member type T. For up to kStackStorageSize items,
297
// the stack is used, otherwise malloc().
298
template <typename T, size_t kStackStorageSize = 1024>
299
class MaybeStackBuffer {
300
 public:
301
  const T* out() const {
302
    return buf_;
303
  }
304
305
5585015
  T* out() {
306
5585015
    return buf_;
307
  }
308
309
  // operator* for compatibility with `v8::String::(Utf8)Value`
310
4266814
  T* operator*() {
311
4266814
    return buf_;
312
  }
313
314
444109
  const T* operator*() const {
315
444109
    return buf_;
316
  }
317
318
2763188
  T& operator[](size_t index) {
319

2763188
    CHECK_LT(index, length());
320
2763188
    return buf_[index];
321
  }
322
323
  const T& operator[](size_t index) const {
324
    CHECK_LT(index, length());
325
    return buf_[index];
326
  }
327
328
3855060
  size_t length() const {
329
3855060
    return length_;
330
  }
331
332
  // Current maximum capacity of the buffer with which SetLength() can be used
333
  // without first calling AllocateSufficientStorage().
334
14225875
  size_t capacity() const {
335
14225875
    return IsAllocated() ? capacity_ :
336




14225893
                           IsInvalidated() ? 0 : kStackStorageSize;
337
  }
338
339
  // Make sure enough space for `storage` entries is available.
340
  // This method can be called multiple times throughout the lifetime of the
341
  // buffer, but once this has been called Invalidate() cannot be used.
342
  // Content of the buffer in the range [0, length()) is preserved.
343
5076040
  void AllocateSufficientStorage(size_t storage) {
344


5076040
    CHECK(!IsInvalidated());
345


5076045
    if (storage > capacity()) {
346
440340
      bool was_allocated = IsAllocated();
347


440340
      T* allocated_ptr = was_allocated ? buf_ : nullptr;
348
440340
      buf_ = Realloc(allocated_ptr, storage);
349
440340
      capacity_ = storage;
350




440340
      if (!was_allocated && length_ > 0)
351
        memcpy(buf_, buf_st_, length_ * sizeof(buf_[0]));
352
    }
353
354
5076047
    length_ = storage;
355
5076047
  }
356
357
4865887
  void SetLength(size_t length) {
358
    // capacity() returns how much memory is actually available.
359

4865887
    CHECK_LE(length, capacity());
360
4865887
    length_ = length;
361
4865887
  }
362
363
4268747
  void SetLengthAndZeroTerminate(size_t length) {
364
    // capacity() returns how much memory is actually available.
365

4268747
    CHECK_LE(length + 1, capacity());
366
4268758
    SetLength(length);
367
368
    // T() is 0 for integer types, nullptr for pointers, etc.
369
4268757
    buf_[length] = T();
370
4268757
  }
371
372
  // Make derefencing this object return nullptr.
373
  // This method can be called multiple times throughout the lifetime of the
374
  // buffer, but once this has been called AllocateSufficientStorage() cannot
375
  // be used.
376
  void Invalidate() {
377
    CHECK(!IsAllocated());
378
    length_ = 0;
379
    buf_ = nullptr;
380
  }
381
382
  // If the buffer is stored in the heap rather than on the stack.
383
19819168
  bool IsAllocated() const {
384




19819168
    return !IsInvalidated() && buf_ != buf_st_;
385
  }
386
387
  // If Invalidate() has been called.
388
38673858
  bool IsInvalidated() const {
389
38673858
    return buf_ == nullptr;
390
  }
391
392
  // Release ownership of the malloc'd buffer.
393
  // Note: This does not free the buffer.
394
2
  void Release() {
395

2
    CHECK(IsAllocated());
396
2
    buf_ = buf_st_;
397
2
    length_ = 0;
398
2
    capacity_ = 0;
399
2
  }
400
401
174648092
  MaybeStackBuffer() : length_(0), capacity_(0), buf_(buf_st_) {
402
    // Default to a zero-length, null-terminated buffer.
403
5450043
    buf_[0] = T();
404
5151900
  }
405
406
181786
  explicit MaybeStackBuffer(size_t storage) : MaybeStackBuffer() {
407
181786
    AllocateSufficientStorage(storage);
408
181786
  }
409
410
5151891
  ~MaybeStackBuffer() {
411


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

38013079
    if (persistent.IsWeak()) {
683
35955823
      return PersistentToLocal::Weak(isolate, persistent);
684
    } else {
685
2057256
      return PersistentToLocal::Strong(persistent);
686
    }
687
  }
688
689
  // Unchecked conversion from a non-weak Persistent<T> to Local<T>,
690
  // use with care!
691
  //
692
  // Do not call persistent.Reset() while the returned Local<T> is still in
693
  // scope, it will destroy the reference to the object.
694
  template <class TypeName>
695
24702437
  static inline v8::Local<TypeName> Strong(
696
      const v8::PersistentBase<TypeName>& persistent) {
697
    return *reinterpret_cast<v8::Local<TypeName>*>(
698
24702437
        const_cast<v8::PersistentBase<TypeName>*>(&persistent));
699
  }
700
701
  template <class TypeName>
702
35955823
  static inline v8::Local<TypeName> Weak(
703
      v8::Isolate* isolate,
704
      const v8::PersistentBase<TypeName>& persistent) {
705
35955823
    return v8::Local<TypeName>::New(isolate, persistent);
706
  }
707
};
708
709
}  // namespace node
710
711
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
712
713
#endif  // SRC_UTIL_H_