GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage/nodes/benchmark/out/../src/util.h Lines: 62 63 98.4 %
Date: 2017-10-21 Branches: 45 78 57.7 %

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

3112067
    CHECK_LT(index, length());
296
3112067
    return buf_[index];
297
  }
298
299
  const T& operator[](size_t index) const {
300
    CHECK_LT(index, length());
301
    return buf_[index];
302
  }
303
304
6133072
  size_t length() const {
305
6133072
    return length_;
306
  }
307
308
  // Current maximum capacity of the buffer with which SetLength() can be used
309
  // without first calling AllocateSufficientStorage().
310
3559135
  size_t capacity() const {
311
3559135
    return IsAllocated() ? capacity_ :
312



3559135
                           IsInvalidated() ? 0 : kStackStorageSize;
313
  }
314
315
  // Make sure enough space for `storage` entries is available.
316
  // This method can be called multiple times throughout the lifetime of the
317
  // buffer, but once this has been called Invalidate() cannot be used.
318
  // Content of the buffer in the range [0, length()) is preserved.
319
1196323
  void AllocateSufficientStorage(size_t storage) {
320

1196323
    CHECK(!IsInvalidated());
321

1196323
    if (storage > capacity()) {
322
20098
      bool was_allocated = IsAllocated();
323

20098
      T* allocated_ptr = was_allocated ? buf_ : nullptr;
324
20098
      buf_ = Realloc(allocated_ptr, storage);
325
20098
      capacity_ = storage;
326



20098
      if (!was_allocated && length_ > 0)
327
        memcpy(buf_, buf_st_, length_ * sizeof(buf_[0]));
328
    }
329
330
1196323
    length_ = storage;
331
1196323
  }
332
333
1191730
  void SetLength(size_t length) {
334
    // capacity() returns how much memory is actually available.
335

1191730
    CHECK_LE(length, capacity());
336
1191730
    length_ = length;
337
1191730
  }
338
339
1160575
  void SetLengthAndZeroTerminate(size_t length) {
340
    // capacity() returns how much memory is actually available.
341

1160575
    CHECK_LE(length + 1, capacity());
342
1160575
    SetLength(length);
343
344
    // T() is 0 for integer types, nullptr for pointers, etc.
345
1160575
    buf_[length] = T();
346
1160575
  }
347
348
  // Make derefencing this object return nullptr.
349
  // This method can be called multiple times throughout the lifetime of the
350
  // buffer, but once this has been called AllocateSufficientStorage() cannot
351
  // be used.
352
4
  void Invalidate() {
353
4
    CHECK(!IsAllocated());
354
4
    length_ = 0;
355
4
    buf_ = nullptr;
356
4
  }
357
358
  // If the buffer is stored in the heap rather than on the stack.
359
4787561
  bool IsAllocated() const {
360



4787561
    return !IsInvalidated() && buf_ != buf_st_;
361
  }
362
363
  // If Invalidate() has been called.
364
9522663
  bool IsInvalidated() const {
365
9522663
    return buf_ == nullptr;
366
  }
367
368
  // Release ownership of the malloc'd buffer.
369
  // Note: This does not free the buffer.
370
2
  void Release() {
371

2
    CHECK(IsAllocated());
372
2
    buf_ = buf_st_;
373
2
    length_ = 0;
374
2
    capacity_ = 0;
375
2
  }
376
377
1208250
  MaybeStackBuffer() : length_(0), capacity_(0), buf_(buf_st_) {
378
    // Default to a zero-length, null-terminated buffer.
379
1208250
    buf_[0] = T();
380
1208250
  }
381
382
12272
  explicit MaybeStackBuffer(size_t storage) : MaybeStackBuffer() {
383
12272
    AllocateSufficientStorage(storage);
384
12272
  }
385
386
1208250
  ~MaybeStackBuffer() {
387

1208250
    if (IsAllocated())
388
20096
      free(buf_);
389
1208250
  }
390
391
 private:
392
  size_t length_;
393
  // capacity of the malloc'ed buf_
394
  size_t capacity_;
395
  T* buf_;
396
  T buf_st_[kStackStorageSize];
397
};
398
399
930720
class Utf8Value : public MaybeStackBuffer<char> {
400
 public:
401
  explicit Utf8Value(v8::Isolate* isolate, v8::Local<v8::Value> value);
402
};
403
404
408
class TwoByteValue : public MaybeStackBuffer<uint16_t> {
405
 public:
406
  explicit TwoByteValue(v8::Isolate* isolate, v8::Local<v8::Value> value);
407
};
408
409
230850
class BufferValue : public MaybeStackBuffer<char> {
410
 public:
411
  explicit BufferValue(v8::Isolate* isolate, v8::Local<v8::Value> value);
412
};
413
414
#define THROW_AND_RETURN_UNLESS_BUFFER(env, obj)                            \
415
  do {                                                                      \
416
    if (!Buffer::HasInstance(obj))                                          \
417
      return env->ThrowTypeError("argument should be a Buffer");            \
418
  } while (0)
419
420
#define SPREAD_BUFFER_ARG(val, name)                                          \
421
  CHECK((val)->IsArrayBufferView());                                          \
422
  v8::Local<v8::ArrayBufferView> name = (val).As<v8::ArrayBufferView>();      \
423
  v8::ArrayBuffer::Contents name##_c = name->Buffer()->GetContents();         \
424
  const size_t name##_offset = name->ByteOffset();                            \
425
  const size_t name##_length = name->ByteLength();                            \
426
  char* const name##_data =                                                   \
427
      static_cast<char*>(name##_c.Data()) + name##_offset;                    \
428
  if (name##_length > 0)                                                      \
429
    CHECK_NE(name##_data, nullptr);
430
431
432
}  // namespace node
433
434
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
435
436
#endif  // SRC_UTIL_H_