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-13 22:28:58 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
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
#define DISALLOW_COPY_AND_ASSIGN(TypeName)                                    \
100
  TypeName(const TypeName&) = delete;                                         \
101
  TypeName& operator=(const TypeName&) = delete
102
103
// Windows 8+ does not like abort() in Release mode
104
#ifdef _WIN32
105
#define ABORT_NO_BACKTRACE() _exit(134)
106
#else
107
#define ABORT_NO_BACKTRACE() abort()
108
#endif
109
110
#define ABORT() node::Abort()
111
112
#ifdef __GNUC__
113
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
114
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
115
#define PRETTY_FUNCTION_NAME __PRETTY_FUNCTION__
116
#else
117
#define LIKELY(expr) expr
118
#define UNLIKELY(expr) expr
119
#define PRETTY_FUNCTION_NAME ""
120
#endif
121
122
#define STRINGIFY_(x) #x
123
#define STRINGIFY(x) STRINGIFY_(x)
124
125
#define CHECK(expr)                                                           \
126
  do {                                                                        \
127
    if (UNLIKELY(!(expr))) {                                                  \
128
      /* Make sure that this struct does not end up in inline code, but    */ \
129
      /* rather in a read-only data section when modifying this code.      */ \
130
      static const node::AssertionInfo args = {                               \
131
        __FILE__ ":" STRINGIFY(__LINE__), #expr, PRETTY_FUNCTION_NAME         \
132
      };                                                                      \
133
      node::Assert(args);                                                     \
134
    }                                                                         \
135
  } while (0)
136
137
#define CHECK_EQ(a, b) CHECK((a) == (b))
138
#define CHECK_GE(a, b) CHECK((a) >= (b))
139
#define CHECK_GT(a, b) CHECK((a) > (b))
140
#define CHECK_LE(a, b) CHECK((a) <= (b))
141
#define CHECK_LT(a, b) CHECK((a) < (b))
142
#define CHECK_NE(a, b) CHECK((a) != (b))
143
#define CHECK_NULL(val) CHECK((val) == nullptr)
144
#define CHECK_NOT_NULL(val) CHECK((val) != nullptr)
145
#define CHECK_IMPLIES(a, b) CHECK(!(a) || (b))
146
147
#ifdef DEBUG
148
  #define DCHECK(expr) CHECK(expr)
149
  #define DCHECK_EQ(a, b) CHECK((a) == (b))
150
  #define DCHECK_GE(a, b) CHECK((a) >= (b))
151
  #define DCHECK_GT(a, b) CHECK((a) > (b))
152
  #define DCHECK_LE(a, b) CHECK((a) <= (b))
153
  #define DCHECK_LT(a, b) CHECK((a) < (b))
154
  #define DCHECK_NE(a, b) CHECK((a) != (b))
155
  #define DCHECK_NULL(val) CHECK((val) == nullptr)
156
  #define DCHECK_NOT_NULL(val) CHECK((val) != nullptr)
157
  #define DCHECK_IMPLIES(a, b) CHECK(!(a) || (b))
158
#else
159
  #define DCHECK(expr)
160
  #define DCHECK_EQ(a, b)
161
  #define DCHECK_GE(a, b)
162
  #define DCHECK_GT(a, b)
163
  #define DCHECK_LE(a, b)
164
  #define DCHECK_LT(a, b)
165
  #define DCHECK_NE(a, b)
166
  #define DCHECK_NULL(val)
167
  #define DCHECK_NOT_NULL(val)
168
  #define DCHECK_IMPLIES(a, b)
169
#endif
170
171
172
#define UNREACHABLE() ABORT()
173
174
// TAILQ-style intrusive list node.
175
template <typename T>
176
class ListNode;
177
178
// TAILQ-style intrusive list head.
179
template <typename T, ListNode<T> (T::*M)>
180
class ListHead;
181
182
template <typename T>
183
class ListNode {
184
 public:
185
  inline ListNode();
186
  inline ~ListNode();
187
  inline void Remove();
188
  inline bool IsEmpty() const;
189
190
 private:
191
  template <typename U, ListNode<U> (U::*M)> friend class ListHead;
192
  friend int GenDebugSymbols();
193
  ListNode* prev_;
194
  ListNode* next_;
195
  DISALLOW_COPY_AND_ASSIGN(ListNode);
196
};
197
198
template <typename T, ListNode<T> (T::*M)>
199
class ListHead {
200
 public:
201
  class Iterator {
202
   public:
203
    inline T* operator*() const;
204
    inline const Iterator& operator++();
205
    inline bool operator!=(const Iterator& that) const;
206
207
   private:
208
    friend class ListHead;
209
    inline explicit Iterator(ListNode<T>* node);
210
    ListNode<T>* node_;
211
  };
212
213
8834
  inline ListHead() = default;
214
  inline ~ListHead();
215
  inline void PushBack(T* element);
216
  inline void PushFront(T* element);
217
  inline bool IsEmpty() const;
218
  inline T* PopFront();
219
  inline Iterator begin() const;
220
  inline Iterator end() const;
221
222
 private:
223
  friend int GenDebugSymbols();
224
  ListNode<T> head_;
225
  DISALLOW_COPY_AND_ASSIGN(ListHead);
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
1182934
inline v8::Local<v8::String> FIXED_ONE_BYTE_STRING(
262
    v8::Isolate* isolate,
263
    const char(&data)[N]) {
264
1182934
  return OneByteString(isolate, data, N - 1);
265
}
266
267
template <std::size_t N>
268
18768
inline v8::Local<v8::String> FIXED_ONE_BYTE_STRING(
269
    v8::Isolate* isolate,
270
    const std::array<char, N>& arr) {
271
18768
  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
// strcasecmp() is locale-sensitive.  Use StringEqualNoCase() instead.
287
inline bool StringEqualNoCase(const char* a, const char* b);
288
289
// strncasecmp() is locale-sensitive.  Use StringEqualNoCaseN() instead.
290
inline bool StringEqualNoCaseN(const char* a, const char* b, size_t length);
291
292
// Allocates an array of member type T. For up to kStackStorageSize items,
293
// the stack is used, otherwise malloc().
294
template <typename T, size_t kStackStorageSize = 1024>
295
class MaybeStackBuffer {
296
 public:
297
  const T* out() const {
298
    return buf_;
299
  }
300
301
3639829
  T* out() {
302
3639829
    return buf_;
303
  }
304
305
  // operator* for compatibility with `v8::String::(Utf8)Value`
306
4865942
  T* operator*() {
307
4865942
    return buf_;
308
  }
309
310
7764
  const T* operator*() const {
311
7764
    return buf_;
312
  }
313
314
1795042
  T& operator[](size_t index) {
315

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




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


3580726
    CHECK(!IsInvalidated());
341


3580729
    if (storage > capacity()) {
342
2021
      bool was_allocated = IsAllocated();
343


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




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

3375722
    CHECK_LE(length, capacity());
356
3375725
    length_ = length;
357
3375725
  }
358
359
3220272
  void SetLengthAndZeroTerminate(size_t length) {
360
    // capacity() returns how much memory is actually available.
361

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




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

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


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