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: 108 113 95.6 %
Date: 2019-02-23 22:23:05 Branches: 60 108 55.6 %

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

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




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


3016635
    CHECK(!IsInvalidated());
342


3016639
    if (storage > capacity()) {
343
1799
      bool was_allocated = IsAllocated();
344


1799
      T* allocated_ptr = was_allocated ? buf_ : nullptr;
345
1799
      buf_ = Realloc(allocated_ptr, storage);
346
1799
      capacity_ = storage;
347




1799
      if (!was_allocated && length_ > 0)
348
        memcpy(buf_, buf_st_, length_ * sizeof(buf_[0]));
349
    }
350
351
3016639
    length_ = storage;
352
3016639
  }
353
354
2821546
  void SetLength(size_t length) {
355
    // capacity() returns how much memory is actually available.
356

2821546
    CHECK_LE(length, capacity());
357
2821547
    length_ = length;
358
2821547
  }
359
360
2666002
  void SetLengthAndZeroTerminate(size_t length) {
361
    // capacity() returns how much memory is actually available.
362

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




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

2
    CHECK(IsAllocated());
393
2
    buf_ = buf_st_;
394
2
    length_ = 0;
395
2
    capacity_ = 0;
396
2
  }
397
398
152538216
  MaybeStackBuffer() : length_(0), capacity_(0), buf_(buf_st_) {
399
    // Default to a zero-length, null-terminated buffer.
400
3473012
    buf_[0] = T();
401
3203560
  }
402
403
172214
  explicit MaybeStackBuffer(size_t storage) : MaybeStackBuffer() {
404
172214
    AllocateSufficientStorage(storage);
405
172214
  }
406
407
4880302
  ~MaybeStackBuffer() {
408


4880302
    if (IsAllocated())
409
414258
      free(buf_);
410
4880301
  }
411
412
 private:
413
  size_t length_;
414
  // capacity of the malloc'ed buf_
415
  size_t capacity_;
416
  T* buf_;
417
  T buf_st_[kStackStorageSize];
418
};
419
420
3675720
class Utf8Value : public MaybeStackBuffer<char> {
421
 public:
422
  explicit Utf8Value(v8::Isolate* isolate, v8::Local<v8::Value> value);
423
};
424
425
13983
class TwoByteValue : public MaybeStackBuffer<uint16_t> {
426
 public:
427
  explicit TwoByteValue(v8::Isolate* isolate, v8::Local<v8::Value> value);
428
};
429
430
225864
class BufferValue : public MaybeStackBuffer<char> {
431
 public:
432
  explicit BufferValue(v8::Isolate* isolate, v8::Local<v8::Value> value);
433
};
434
435
#define SPREAD_BUFFER_ARG(val, name)                                          \
436
  CHECK((val)->IsArrayBufferView());                                          \
437
  v8::Local<v8::ArrayBufferView> name = (val).As<v8::ArrayBufferView>();      \
438
  v8::ArrayBuffer::Contents name##_c = name->Buffer()->GetContents();         \
439
  const size_t name##_offset = name->ByteOffset();                            \
440
  const size_t name##_length = name->ByteLength();                            \
441
  char* const name##_data =                                                   \
442
      static_cast<char*>(name##_c.Data()) + name##_offset;                    \
443
  if (name##_length > 0)                                                      \
444
    CHECK_NE(name##_data, nullptr);
445
446
// Use this when a variable or parameter is unused in order to explicitly
447
// silence a compiler warning about that.
448
40218
template <typename T> inline void USE(T&&) {}
449
450
// Run a function when exiting the current scope.
451
struct OnScopeLeave {
452
  std::function<void()> fn_;
453
454
105502
  explicit OnScopeLeave(std::function<void()> fn) : fn_(std::move(fn)) {}
455
105498
  ~OnScopeLeave() { fn_(); }
456
};
457
458
// Simple RAII wrapper for contiguous data that uses malloc()/free().
459
template <typename T>
460
struct MallocedBuffer {
461
  T* data;
462
  size_t size;
463
464
6418
  T* release() {
465
6418
    T* ret = data;
466
6418
    data = nullptr;
467
6418
    return ret;
468
  }
469
470
50
  void Truncate(size_t new_size) {
471
50
    CHECK(new_size <= size);
472
50
    size = new_size;
473
50
  }
474
475
8172
  inline bool is_empty() const { return data == nullptr; }
476
477
46994
  MallocedBuffer() : data(nullptr), size(0) {}
478
28482
  explicit MallocedBuffer(size_t size) : data(Malloc<T>(size)), size(size) {}
479
8110
  MallocedBuffer(T* data, size_t size) : data(data), size(size) {}
480
71036
  MallocedBuffer(MallocedBuffer&& other) : data(other.data), size(other.size) {
481
71036
    other.data = nullptr;
482
71036
  }
483
40257
  MallocedBuffer& operator=(MallocedBuffer&& other) {
484
40257
    this->~MallocedBuffer();
485
40257
    return *new(this) MallocedBuffer(std::move(other));
486
  }
487
154614
  ~MallocedBuffer() {
488
154614
    free(data);
489
154614
  }
490
  MallocedBuffer(const MallocedBuffer&) = delete;
491
  MallocedBuffer& operator=(const MallocedBuffer&) = delete;
492
};
493
494
template <typename T>
495
360
class NonCopyableMaybe {
496
 public:
497
1
  NonCopyableMaybe() : empty_(true) {}
498
359
  explicit NonCopyableMaybe(T&& value)
499
      : empty_(false),
500
359
        value_(std::move(value)) {}
501
502
360
  bool IsEmpty() const {
503
360
    return empty_;
504
  }
505
506
359
  T&& Release() {
507
359
    CHECK_EQ(empty_, false);
508
359
    empty_ = true;
509
359
    return std::move(value_);
510
  }
511
512
 private:
513
  bool empty_;
514
  T value_;
515
};
516
517
// Test whether some value can be called with ().
518
template <typename T, typename = void>
519
struct is_callable : std::is_function<T> { };
520
521
template <typename T>
522
struct is_callable<T, typename std::enable_if<
523
    std::is_same<decltype(void(&T::operator())), void>::value
524
    >::type> : std::true_type { };
525
526
template <typename T, void (*function)(T*)>
527
struct FunctionDeleter {
528
61614
  void operator()(T* pointer) const { function(pointer); }
529
  typedef std::unique_ptr<T, FunctionDeleter> Pointer;
530
};
531
532
template <typename T, void (*function)(T*)>
533
using DeleteFnPtr = typename FunctionDeleter<T, function>::Pointer;
534
535
std::vector<std::string> SplitString(const std::string& in, char delim);
536
537
inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
538
                                           const std::string& str,
539
                                           v8::Isolate* isolate = nullptr);
540
template <typename T, typename test_for_number =
541
    typename std::enable_if<std::numeric_limits<T>::is_specialized, bool>::type>
542
inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
543
                                           const T& number,
544
                                           v8::Isolate* isolate = nullptr);
545
template <typename T>
546
inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
547
                                           const std::vector<T>& vec,
548
                                           v8::Isolate* isolate = nullptr);
549
template <typename T, typename U>
550
inline v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
551
                                           const std::unordered_map<T, U>& map,
552
                                           v8::Isolate* isolate = nullptr);
553
554
// These macros expects a `Isolate* isolate` and a `Local<Context> context`
555
// to be in the scope.
556
#define READONLY_PROPERTY(obj, name, value)                                    \
557
  do {                                                                         \
558
    obj->DefineOwnProperty(                                                    \
559
           context, FIXED_ONE_BYTE_STRING(isolate, name), value, v8::ReadOnly) \
560
        .FromJust();                                                           \
561
  } while (0)
562
563
#define READONLY_DONT_ENUM_PROPERTY(obj, name, var)                            \
564
  do {                                                                         \
565
    obj->DefineOwnProperty(                                                    \
566
           context,                                                            \
567
           OneByteString(isolate, name),                                       \
568
           var,                                                                \
569
           static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum))    \
570
        .FromJust();                                                           \
571
  } while (0)
572
573
#define READONLY_FALSE_PROPERTY(obj, name)                                     \
574
  READONLY_PROPERTY(obj, name, v8::False(isolate))
575
576
#define READONLY_TRUE_PROPERTY(obj, name)                                      \
577
  READONLY_PROPERTY(obj, name, v8::True(isolate))
578
579
#define READONLY_STRING_PROPERTY(obj, name, str)                               \
580
  READONLY_PROPERTY(obj, name, ToV8Value(context, str).ToLocalChecked())
581
582
// Variation on NODE_DEFINE_CONSTANT that sets a String value.
583
#define NODE_DEFINE_STRING_CONSTANT(target, name, constant)                    \
584
  do {                                                                         \
585
    v8::Isolate* isolate = target->GetIsolate();                               \
586
    v8::Local<v8::String> constant_name =                                      \
587
        v8::String::NewFromUtf8(isolate, name, v8::NewStringType::kNormal)     \
588
            .ToLocalChecked();                                                 \
589
    v8::Local<v8::String> constant_value =                                     \
590
        v8::String::NewFromUtf8(isolate, constant, v8::NewStringType::kNormal) \
591
            .ToLocalChecked();                                                 \
592
    v8::PropertyAttribute constant_attributes =                                \
593
        static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete);     \
594
    target                                                                     \
595
        ->DefineOwnProperty(isolate->GetCurrentContext(),                      \
596
                            constant_name,                                     \
597
                            constant_value,                                    \
598
                            constant_attributes)                               \
599
        .FromJust();                                                           \
600
  } while (0)
601
602
enum Endianness {
603
  kLittleEndian,  // _Not_ LITTLE_ENDIAN, clashes with endian.h.
604
  kBigEndian
605
};
606
607
7961
inline enum Endianness GetEndianness() {
608
  // Constant-folded by the compiler.
609
  const union {
610
    uint8_t u8[2];
611
    uint16_t u16;
612
7961
  } u = {{1, 0}};
613
7961
  return u.u16 == 1 ? kLittleEndian : kBigEndian;
614
}
615
616
1
inline bool IsLittleEndian() {
617
1
  return GetEndianness() == kLittleEndian;
618
}
619
620
7960
inline bool IsBigEndian() {
621
7960
  return GetEndianness() == kBigEndian;
622
}
623
624
template <typename T, size_t N>
625
2771035
constexpr size_t arraysize(const T (&)[N]) {
626
2771035
  return N;
627
}
628
629
// Round up a to the next highest multiple of b.
630
template <typename T>
631
286337
constexpr T RoundUp(T a, T b) {
632
286337
  return a % b != 0 ? a + b - (a % b) : a;
633
}
634
635
#ifdef __GNUC__
636
#define MUST_USE_RESULT __attribute__((warn_unused_result))
637
#else
638
#define MUST_USE_RESULT
639
#endif
640
641
128174
class SlicedArguments : public MaybeStackBuffer<v8::Local<v8::Value>> {
642
 public:
643
  inline explicit SlicedArguments(
644
      const v8::FunctionCallbackInfo<v8::Value>& args, size_t start = 0);
645
};
646
647
}  // namespace node
648
649
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
650
651
#endif  // SRC_UTIL_H_