Node.js  v8.x
Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine
util.h
Go to the documentation of this file.
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.
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() raise(SIGABRT)
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  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  T* out() {
282  return buf_;
283  }
284 
285  // operator* for compatibility with `v8::String::(Utf8)Value`
286  T* operator*() {
287  return buf_;
288  }
289 
290  const T* operator*() const {
291  return buf_;
292  }
293 
294  T& operator[](size_t index) {
295  CHECK_LT(index, length());
296  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  size_t length() const {
305  return length_;
306  }
307 
308  // Current maximum capacity of the buffer with which SetLength() can be used
309  // without first calling AllocateSufficientStorage().
310  size_t capacity() const {
311  return IsAllocated() ? capacity_ :
312  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  void AllocateSufficientStorage(size_t storage) {
320  CHECK(!IsInvalidated());
321  if (storage > capacity()) {
322  bool was_allocated = IsAllocated();
323  T* allocated_ptr = was_allocated ? buf_ : nullptr;
324  buf_ = Realloc(allocated_ptr, storage);
325  capacity_ = storage;
326  if (!was_allocated && length_ > 0)
327  memcpy(buf_, buf_st_, length_ * sizeof(buf_[0]));
328  }
329 
330  length_ = storage;
331  }
332 
333  void SetLength(size_t length) {
334  // capacity() returns how much memory is actually available.
335  CHECK_LE(length, capacity());
336  length_ = length;
337  }
338 
339  void SetLengthAndZeroTerminate(size_t length) {
340  // capacity() returns how much memory is actually available.
341  CHECK_LE(length + 1, capacity());
342  SetLength(length);
343 
344  // T() is 0 for integer types, nullptr for pointers, etc.
345  buf_[length] = T();
346  }
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  void Invalidate() {
353  CHECK(!IsAllocated());
354  length_ = 0;
355  buf_ = nullptr;
356  }
357 
358  // If the buffer is stored in the heap rather than on the stack.
359  bool IsAllocated() const {
360  return !IsInvalidated() && buf_ != buf_st_;
361  }
362 
363  // If Invalidate() has been called.
364  bool IsInvalidated() const {
365  return buf_ == nullptr;
366  }
367 
368  // Release ownership of the malloc'd buffer.
369  // Note: This does not free the buffer.
370  void Release() {
371  CHECK(IsAllocated());
372  buf_ = buf_st_;
373  length_ = 0;
374  capacity_ = 0;
375  }
376 
377  MaybeStackBuffer() : length_(0), capacity_(0), buf_(buf_st_) {
378  // Default to a zero-length, null-terminated buffer.
379  buf_[0] = T();
380  }
381 
382  explicit MaybeStackBuffer(size_t storage) : MaybeStackBuffer() {
383  AllocateSufficientStorage(storage);
384  }
385 
386  ~MaybeStackBuffer() {
387  if (IsAllocated())
388  free(buf_);
389  }
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 class Utf8Value : public MaybeStackBuffer<char> {
400  public:
401  explicit Utf8Value(v8::Isolate* isolate, v8::Local<v8::Value> value);
402 };
403 
404 class TwoByteValue : public MaybeStackBuffer<uint16_t> {
405  public:
406  explicit TwoByteValue(v8::Isolate* isolate, v8::Local<v8::Value> value);
407 };
408 
409 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_
union node::cares_wrap::@8::CaresAsyncData::@0 data
NO_RETURN void Assert(const char *const (*args)[4])
Definition: node.cc:1908
dtrace a
Definition: v8ustack.d:531
void DumpBacktrace(FILE *fp)
dtrace n
Definition: v8ustack.d:531
NO_RETURN void Abort()
Definition: node.cc:1901
void LowMemoryNotification()
Definition: util.cc:100