GCC Code Coverage Report
Directory: ../src/ Exec Total Coverage
File: /home/node-core-coverage/node-core-coverage/workdir/node/out/../src/util.h Lines: 30 30 100.0 %
Date: 2016-11-30 Branches: 85 130 65.4 %

Line Branch Exec Source
1
#ifndef SRC_UTIL_H_
2
#define SRC_UTIL_H_
3
4
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
5
6
#include "v8.h"
7
8
#include <assert.h>
9
#include <signal.h>
10
#include <stddef.h>
11
#include <stdio.h>
12
#include <stdlib.h>
13
14
#include <type_traits>  // std::remove_reference
15
16
namespace node {
17
18
// These should be used in our code as opposed to the native
19
// versions as they abstract out some platform and or
20
// compiler version specific functionality
21
// malloc(0) and realloc(ptr, 0) have implementation-defined behavior in
22
// that the standard allows them to either return a unique pointer or a
23
// nullptr for zero-sized allocation requests.  Normalize by always using
24
// a nullptr.
25
template <typename T>
26
inline T* UncheckedRealloc(T* pointer, size_t n);
27
template <typename T>
28
inline T* UncheckedMalloc(size_t n);
29
template <typename T>
30
inline T* UncheckedCalloc(size_t n);
31
32
// Same things, but aborts immediately instead of returning nullptr when
33
// no memory is available.
34
template <typename T>
35
inline T* Realloc(T* pointer, size_t n);
36
template <typename T>
37
inline T* Malloc(size_t n);
38
template <typename T>
39
inline T* Calloc(size_t n);
40
41
inline char* Malloc(size_t n);
42
inline char* Calloc(size_t n);
43
inline char* UncheckedMalloc(size_t n);
44
inline char* UncheckedCalloc(size_t n);
45
46
// Used by the allocation functions when allocation fails.
47
// Thin wrapper around v8::Isolate::LowMemoryNotification() that checks
48
// whether V8 is initialized.
49
void LowMemoryNotification();
50
51
#ifdef __GNUC__
52
#define NO_RETURN __attribute__((noreturn))
53
#else
54
#define NO_RETURN
55
#endif
56
57
// The slightly odd function signature for Assert() is to ease
58
// instruction cache pressure in calls from ASSERT and CHECK.
59
NO_RETURN void Abort();
60
NO_RETURN void Assert(const char* const (*args)[4]);
61
void DumpBacktrace(FILE* fp);
62
63
template <typename T> using remove_reference = std::remove_reference<T>;
64
65
#define FIXED_ONE_BYTE_STRING(isolate, string)                                \
66
  (node::OneByteString((isolate), (string), sizeof(string) - 1))
67
68
#define DISALLOW_COPY_AND_ASSIGN(TypeName)                                    \
69
  void operator=(const TypeName&) = delete;                                   \
70
  void operator=(TypeName&&) = delete;                                        \
71
  TypeName(const TypeName&) = delete;                                         \
72
  TypeName(TypeName&&) = delete
73
74
// Windows 8+ does not like abort() in Release mode
75
#ifdef _WIN32
76
#define ABORT_NO_BACKTRACE() raise(SIGABRT)
77
#else
78
#define ABORT_NO_BACKTRACE() abort()
79
#endif
80
81
#define ABORT() node::Abort()
82
83
#ifdef __GNUC__
84
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
85
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
86
#define PRETTY_FUNCTION_NAME __PRETTY_FUNCTION__
87
#else
88
#define LIKELY(expr) expr
89
#define UNLIKELY(expr) expr
90
#define PRETTY_FUNCTION_NAME ""
91
#endif
92
93
#define STRINGIFY_(x) #x
94
#define STRINGIFY(x) STRINGIFY_(x)
95
96
#define CHECK(expr)                                                           \
97
  do {                                                                        \
98
    if (UNLIKELY(!(expr))) {                                                  \
99
      static const char* const args[] = { __FILE__, STRINGIFY(__LINE__),      \
100
                                          #expr, PRETTY_FUNCTION_NAME };      \
101
      node::Assert(&args);                                                    \
102
    }                                                                         \
103
  } while (0)
104
105
// FIXME(bnoordhuis) cctests don't link in node::Abort() and node::Assert().
106
#ifdef GTEST_DONT_DEFINE_ASSERT_EQ
107
#undef ABORT
108
#undef CHECK
109
#define ABORT ABORT_NO_BACKTRACE
110
#define CHECK assert
111
#endif
112
113
#ifdef NDEBUG
114
#define ASSERT(expr)
115
#else
116
#define ASSERT(expr) CHECK(expr)
117
#endif
118
119
#define ASSERT_EQ(a, b) ASSERT((a) == (b))
120
#define ASSERT_GE(a, b) ASSERT((a) >= (b))
121
#define ASSERT_GT(a, b) ASSERT((a) > (b))
122
#define ASSERT_LE(a, b) ASSERT((a) <= (b))
123
#define ASSERT_LT(a, b) ASSERT((a) < (b))
124
#define ASSERT_NE(a, b) ASSERT((a) != (b))
125
126
#define CHECK_EQ(a, b) CHECK((a) == (b))
127
#define CHECK_GE(a, b) CHECK((a) >= (b))
128
#define CHECK_GT(a, b) CHECK((a) > (b))
129
#define CHECK_LE(a, b) CHECK((a) <= (b))
130
#define CHECK_LT(a, b) CHECK((a) < (b))
131
#define CHECK_NE(a, b) CHECK((a) != (b))
132
133
#define UNREACHABLE() ABORT()
134
135
#define ASSIGN_OR_RETURN_UNWRAP(ptr, obj, ...)                                \
136
  do {                                                                        \
137
    *ptr =                                                                    \
138
        Unwrap<typename node::remove_reference<decltype(**ptr)>::type>(obj);  \
139
    if (*ptr == nullptr)                                                      \
140
      return __VA_ARGS__;                                                     \
141
  } while (0)
142
143
// TAILQ-style intrusive list node.
144
template <typename T>
145
class ListNode;
146
147
// TAILQ-style intrusive list head.
148
template <typename T, ListNode<T> (T::*M)>
149
class ListHead;
150
151
template <typename T>
152
class ListNode {
153
 public:
154
  inline ListNode();
155
  inline ~ListNode();
156
  inline void Remove();
157
  inline bool IsEmpty() const;
158
159
 private:
160
  template <typename U, ListNode<U> (U::*M)> friend class ListHead;
161
  ListNode* prev_;
162
  ListNode* next_;
163
  DISALLOW_COPY_AND_ASSIGN(ListNode);
164
};
165
166
template <typename T, ListNode<T> (T::*M)>
167
class ListHead {
168
 public:
169
  class Iterator {
170
   public:
171
    inline T* operator*() const;
172
    inline const Iterator& operator++();
173
    inline bool operator!=(const Iterator& that) const;
174
175
   private:
176
    friend class ListHead;
177
    inline explicit Iterator(ListNode<T>* node);
178
    ListNode<T>* node_;
179
  };
180
181
14416
  inline ListHead() = default;
182
  inline ~ListHead();
183
  inline void MoveBack(ListHead* that);
184
  inline void PushBack(T* element);
185
  inline void PushFront(T* element);
186
  inline bool IsEmpty() const;
187
  inline T* PopFront();
188
  inline Iterator begin() const;
189
  inline Iterator end() const;
190
191
 private:
192
  ListNode<T> head_;
193
  DISALLOW_COPY_AND_ASSIGN(ListHead);
194
};
195
196
// The helper is for doing safe downcasts from base types to derived types.
197
template <typename Inner, typename Outer>
198
class ContainerOfHelper {
199
 public:
200
  inline ContainerOfHelper(Inner Outer::*field, Inner* pointer);
201
  template <typename TypeName>
202
  inline operator TypeName*() const;
203
 private:
204
  Outer* const pointer_;
205
};
206
207
// Calculate the address of the outer (i.e. embedding) struct from
208
// the interior pointer to a data member.
209
template <typename Inner, typename Outer>
210
inline ContainerOfHelper<Inner, Outer> ContainerOf(Inner Outer::*field,
211
                                                   Inner* pointer);
212
213
// If persistent.IsWeak() == false, then do not call persistent.Reset()
214
// while the returned Local<T> is still in scope, it will destroy the
215
// reference to the object.
216
template <class TypeName>
217
inline v8::Local<TypeName> PersistentToLocal(
218
    v8::Isolate* isolate,
219
    const v8::Persistent<TypeName>& persistent);
220
221
// Unchecked conversion from a non-weak Persistent<T> to Local<TLocal<T>,
222
// use with care!
223
//
224
// Do not call persistent.Reset() while the returned Local<T> is still in
225
// scope, it will destroy the reference to the object.
226
template <class TypeName>
227
inline v8::Local<TypeName> StrongPersistentToLocal(
228
    const v8::Persistent<TypeName>& persistent);
229
230
template <class TypeName>
231
inline v8::Local<TypeName> WeakPersistentToLocal(
232
    v8::Isolate* isolate,
233
    const v8::Persistent<TypeName>& persistent);
234
235
// Convenience wrapper around v8::String::NewFromOneByte().
236
inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
237
                                           const char* data,
238
                                           int length = -1);
239
240
// For the people that compile with -funsigned-char.
241
inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
242
                                           const signed char* data,
243
                                           int length = -1);
244
245
inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
246
                                           const unsigned char* data,
247
                                           int length = -1);
248
249
inline void Wrap(v8::Local<v8::Object> object, void* pointer);
250
251
inline void ClearWrap(v8::Local<v8::Object> object);
252
253
template <typename TypeName>
254
inline TypeName* Unwrap(v8::Local<v8::Object> object);
255
256
// Swaps bytes in place. nbytes is the number of bytes to swap and must be a
257
// multiple of the word size (checked by function).
258
inline void SwapBytes16(char* data, size_t nbytes);
259
inline void SwapBytes32(char* data, size_t nbytes);
260
inline void SwapBytes64(char* data, size_t nbytes);
261
262
// tolower() is locale-sensitive.  Use ToLower() instead.
263
inline char ToLower(char c);
264
265
// strcasecmp() is locale-sensitive.  Use StringEqualNoCase() instead.
266
inline bool StringEqualNoCase(const char* a, const char* b);
267
268
// strncasecmp() is locale-sensitive.  Use StringEqualNoCaseN() instead.
269
inline bool StringEqualNoCaseN(const char* a, const char* b, size_t length);
270
271
// Allocates an array of member type T. For up to kStackStorageSize items,
272
// the stack is used, otherwise malloc().
273
template <typename T, size_t kStackStorageSize = 1024>
274
class MaybeStackBuffer {
275
 public:
276
  const T* out() const {
277
    return buf_;
278
  }
279
280
  T* out() {
281
    return buf_;
282
  }
283
284
  // operator* for compatibility with `v8::String::(Utf8)Value`
285
  T* operator*() {
286
    return buf_;
287
  }
288
289
  const T* operator*() const {
290
    return buf_;
291
  }
292
293
  T& operator[](size_t index) {
294


113537
    CHECK_LT(index, length());
295
87876
    return buf_[index];
296
  }
297
298
  const T& operator[](size_t index) const {
299
    CHECK_LT(index, length());
300
    return buf_[index];
301
  }
302
303
  size_t length() const {
304
    return length_;
305
  }
306
307
  // Call to make sure enough space for `storage` entries is available.
308
  // There can only be 1 call to AllocateSufficientStorage or Invalidate
309
  // per instance.
310
  void AllocateSufficientStorage(size_t storage) {
311




360446
    if (storage <= kStackStorageSize) {
312
348749
      buf_ = buf_st_;
313
    } else {
314
283
      buf_ = Malloc<T>(storage);
315
    }
316
317
    // Remember how much was allocated to check against that in SetLength().
318
360446
    length_ = storage;
319
  }
320
321
  void SetLength(size_t length) {
322
    // length_ stores how much memory was allocated.
323

346348
    CHECK_LE(length, length_);
324
346348
    length_ = length;
325
  }
326
327
345917
  void SetLengthAndZeroTerminate(size_t length) {
328
    // length_ stores how much memory was allocated.
329

345917
    CHECK_LE(length + 1, length_);
330
691834
    SetLength(length);
331
332
    // T() is 0 for integer types, nullptr for pointers, etc.
333
345917
    buf_[length] = T();
334
345917
  }
335
336
  // Make derefencing this object return nullptr.
337
  // Calling this is mutually exclusive with calling
338
  // AllocateSufficientStorage.
339
  void Invalidate() {
340
4
    CHECK_EQ(buf_, buf_st_);
341
4
    length_ = 0;
342
4
    buf_ = nullptr;
343
  }
344
345
  bool IsAllocated() {
346
5
    return buf_ != buf_st_;
347
  }
348
349
  void Release() {
350
2
    buf_ = buf_st_;
351
2
    length_ = 0;
352
  }
353
354
361481
  MaybeStackBuffer() : length_(0), buf_(buf_st_) {
355
    // Default to a zero-length, null-terminated buffer.
356
361481
    buf_[0] = T();
357
  }
358
359
11417
  explicit MaybeStackBuffer(size_t storage) : MaybeStackBuffer() {
360
11417
    AllocateSufficientStorage(storage);
361
  }
362
363
  ~MaybeStackBuffer() {
364























361481
    if (buf_ != buf_st_)
365
285
      free(buf_);
366
361481
  }
367
368
 private:
369
  size_t length_;
370
  T* buf_;
371
  T buf_st_[kStackStorageSize];
372
};
373
374
471094
class Utf8Value : public MaybeStackBuffer<char> {
375
 public:
376
  explicit Utf8Value(v8::Isolate* isolate, v8::Local<v8::Value> value);
377
};
378
379
134
class TwoByteValue : public MaybeStackBuffer<uint16_t> {
380
 public:
381
  explicit TwoByteValue(v8::Isolate* isolate, v8::Local<v8::Value> value);
382
};
383
384
209151
class BufferValue : public MaybeStackBuffer<char> {
385
 public:
386
  explicit BufferValue(v8::Isolate* isolate, v8::Local<v8::Value> value);
387
};
388
389
#define THROW_AND_RETURN_UNLESS_BUFFER(env, obj)                            \
390
  do {                                                                      \
391
    if (!Buffer::HasInstance(obj))                                          \
392
      return env->ThrowTypeError("argument should be a Buffer");            \
393
  } while (0)
394
395
#define SPREAD_BUFFER_ARG(val, name)                                          \
396
  CHECK((val)->IsUint8Array());                                               \
397
  Local<v8::Uint8Array> name = (val).As<v8::Uint8Array>();                    \
398
  v8::ArrayBuffer::Contents name##_c = name->Buffer()->GetContents();         \
399
  const size_t name##_offset = name->ByteOffset();                            \
400
  const size_t name##_length = name->ByteLength();                            \
401
  char* const name##_data =                                                   \
402
      static_cast<char*>(name##_c.Data()) + name##_offset;                    \
403
  if (name##_length > 0)                                                      \
404
    CHECK_NE(name##_data, nullptr);
405
406
407
}  // namespace node
408
409
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
410
411
#endif  // SRC_UTIL_H_