Node.js  v8.x
Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine
util-inl.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_INL_H_
23 #define SRC_UTIL_INL_H_
24 
25 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
26 
27 #include "util.h"
28 #include <cstring>
29 
30 #if defined(_MSC_VER)
31 #include <intrin.h>
32 #define BSWAP_2(x) _byteswap_ushort(x)
33 #define BSWAP_4(x) _byteswap_ulong(x)
34 #define BSWAP_8(x) _byteswap_uint64(x)
35 #else
36 #define BSWAP_2(x) ((x) << 8) | ((x) >> 8)
37 #define BSWAP_4(x) \
38  (((x) & 0xFF) << 24) | \
39  (((x) & 0xFF00) << 8) | \
40  (((x) >> 8) & 0xFF00) | \
41  (((x) >> 24) & 0xFF)
42 #define BSWAP_8(x) \
43  (((x) & 0xFF00000000000000ull) >> 56) | \
44  (((x) & 0x00FF000000000000ull) >> 40) | \
45  (((x) & 0x0000FF0000000000ull) >> 24) | \
46  (((x) & 0x000000FF00000000ull) >> 8) | \
47  (((x) & 0x00000000FF000000ull) << 8) | \
48  (((x) & 0x0000000000FF0000ull) << 24) | \
49  (((x) & 0x000000000000FF00ull) << 40) | \
50  (((x) & 0x00000000000000FFull) << 56)
51 #endif
52 
53 namespace node {
54 
55 template <typename T>
56 ListNode<T>::ListNode() : prev_(this), next_(this) {}
57 
58 template <typename T>
59 ListNode<T>::~ListNode() {
60  Remove();
61 }
62 
63 template <typename T>
64 void ListNode<T>::Remove() {
65  prev_->next_ = next_;
66  next_->prev_ = prev_;
67  prev_ = this;
68  next_ = this;
69 }
70 
71 template <typename T>
72 bool ListNode<T>::IsEmpty() const {
73  return prev_ == this;
74 }
75 
76 template <typename T, ListNode<T> (T::*M)>
77 ListHead<T, M>::Iterator::Iterator(ListNode<T>* node) : node_(node) {}
78 
79 template <typename T, ListNode<T> (T::*M)>
80 T* ListHead<T, M>::Iterator::operator*() const {
81  return ContainerOf(M, node_);
82 }
83 
84 template <typename T, ListNode<T> (T::*M)>
85 const typename ListHead<T, M>::Iterator&
86 ListHead<T, M>::Iterator::operator++() {
87  node_ = node_->next_;
88  return *this;
89 }
90 
91 template <typename T, ListNode<T> (T::*M)>
92 bool ListHead<T, M>::Iterator::operator!=(const Iterator& that) const {
93  return node_ != that.node_;
94 }
95 
96 template <typename T, ListNode<T> (T::*M)>
97 ListHead<T, M>::~ListHead() {
98  while (IsEmpty() == false)
99  head_.next_->Remove();
100 }
101 
102 template <typename T, ListNode<T> (T::*M)>
103 void ListHead<T, M>::MoveBack(ListHead* that) {
104  if (IsEmpty())
105  return;
106  ListNode<T>* to = &that->head_;
107  head_.next_->prev_ = to->prev_;
108  to->prev_->next_ = head_.next_;
109  head_.prev_->next_ = to;
110  to->prev_ = head_.prev_;
111  head_.prev_ = &head_;
112  head_.next_ = &head_;
113 }
114 
115 template <typename T, ListNode<T> (T::*M)>
116 void ListHead<T, M>::PushBack(T* element) {
117  ListNode<T>* that = &(element->*M);
118  head_.prev_->next_ = that;
119  that->prev_ = head_.prev_;
120  that->next_ = &head_;
121  head_.prev_ = that;
122 }
123 
124 template <typename T, ListNode<T> (T::*M)>
125 void ListHead<T, M>::PushFront(T* element) {
126  ListNode<T>* that = &(element->*M);
127  head_.next_->prev_ = that;
128  that->prev_ = &head_;
129  that->next_ = head_.next_;
130  head_.next_ = that;
131 }
132 
133 template <typename T, ListNode<T> (T::*M)>
134 bool ListHead<T, M>::IsEmpty() const {
135  return head_.IsEmpty();
136 }
137 
138 template <typename T, ListNode<T> (T::*M)>
139 T* ListHead<T, M>::PopFront() {
140  if (IsEmpty())
141  return nullptr;
142  ListNode<T>* node = head_.next_;
143  node->Remove();
144  return ContainerOf(M, node);
145 }
146 
147 template <typename T, ListNode<T> (T::*M)>
148 typename ListHead<T, M>::Iterator ListHead<T, M>::begin() const {
149  return Iterator(head_.next_);
150 }
151 
152 template <typename T, ListNode<T> (T::*M)>
153 typename ListHead<T, M>::Iterator ListHead<T, M>::end() const {
154  return Iterator(const_cast<ListNode<T>*>(&head_));
155 }
156 
157 template <typename Inner, typename Outer>
158 ContainerOfHelper<Inner, Outer>::ContainerOfHelper(Inner Outer::*field,
159  Inner* pointer)
160  : pointer_(reinterpret_cast<Outer*>(
161  reinterpret_cast<uintptr_t>(pointer) -
162  reinterpret_cast<uintptr_t>(&(static_cast<Outer*>(0)->*field)))) {
163 }
164 
165 template <typename Inner, typename Outer>
166 template <typename TypeName>
167 ContainerOfHelper<Inner, Outer>::operator TypeName*() const {
168  return static_cast<TypeName*>(pointer_);
169 }
170 
171 template <typename Inner, typename Outer>
172 inline ContainerOfHelper<Inner, Outer> ContainerOf(Inner Outer::*field,
173  Inner* pointer) {
174  return ContainerOfHelper<Inner, Outer>(field, pointer);
175 }
176 
177 template <class TypeName>
178 inline v8::Local<TypeName> PersistentToLocal(
179  v8::Isolate* isolate,
180  const v8::Persistent<TypeName>& persistent) {
181  if (persistent.IsWeak()) {
182  return WeakPersistentToLocal(isolate, persistent);
183  } else {
184  return StrongPersistentToLocal(persistent);
185  }
186 }
187 
188 template <class TypeName>
189 inline v8::Local<TypeName> StrongPersistentToLocal(
190  const v8::Persistent<TypeName>& persistent) {
191  return *reinterpret_cast<v8::Local<TypeName>*>(
192  const_cast<v8::Persistent<TypeName>*>(&persistent));
193 }
194 
195 template <class TypeName>
196 inline v8::Local<TypeName> WeakPersistentToLocal(
197  v8::Isolate* isolate,
198  const v8::Persistent<TypeName>& persistent) {
199  return v8::Local<TypeName>::New(isolate, persistent);
200 }
201 
202 inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
203  const char* data,
204  int length) {
205  return v8::String::NewFromOneByte(isolate,
206  reinterpret_cast<const uint8_t*>(data),
207  v8::NewStringType::kNormal,
208  length).ToLocalChecked();
209 }
210 
211 inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
212  const signed char* data,
213  int length) {
214  return v8::String::NewFromOneByte(isolate,
215  reinterpret_cast<const uint8_t*>(data),
216  v8::NewStringType::kNormal,
217  length).ToLocalChecked();
218 }
219 
220 inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
221  const unsigned char* data,
222  int length) {
223  return v8::String::NewFromOneByte(isolate,
224  reinterpret_cast<const uint8_t*>(data),
225  v8::NewStringType::kNormal,
226  length).ToLocalChecked();
227 }
228 
229 template <typename TypeName>
230 void Wrap(v8::Local<v8::Object> object, TypeName* pointer) {
231  CHECK_EQ(false, object.IsEmpty());
232  CHECK_GT(object->InternalFieldCount(), 0);
233  object->SetAlignedPointerInInternalField(0, pointer);
234 }
235 
236 void ClearWrap(v8::Local<v8::Object> object) {
237  Wrap<void>(object, nullptr);
238 }
239 
240 template <typename TypeName>
241 TypeName* Unwrap(v8::Local<v8::Object> object) {
242  CHECK_EQ(false, object.IsEmpty());
243  CHECK_GT(object->InternalFieldCount(), 0);
244  void* pointer = object->GetAlignedPointerFromInternalField(0);
245  return static_cast<TypeName*>(pointer);
246 }
247 
248 void SwapBytes16(char* data, size_t nbytes) {
249  CHECK_EQ(nbytes % 2, 0);
250 
251 #if defined(_MSC_VER)
252  int align = reinterpret_cast<uintptr_t>(data) % sizeof(uint16_t);
253  if (align == 0) {
254  // MSVC has no strict aliasing, and is able to highly optimize this case.
255  uint16_t* data16 = reinterpret_cast<uint16_t*>(data);
256  size_t len16 = nbytes / sizeof(*data16);
257  for (size_t i = 0; i < len16; i++) {
258  data16[i] = BSWAP_2(data16[i]);
259  }
260  return;
261  }
262 #endif
263 
264  uint16_t temp;
265  for (size_t i = 0; i < nbytes; i += sizeof(temp)) {
266  memcpy(&temp, &data[i], sizeof(temp));
267  temp = BSWAP_2(temp);
268  memcpy(&data[i], &temp, sizeof(temp));
269  }
270 }
271 
272 void SwapBytes32(char* data, size_t nbytes) {
273  CHECK_EQ(nbytes % 4, 0);
274 
275 #if defined(_MSC_VER)
276  int align = reinterpret_cast<uintptr_t>(data) % sizeof(uint32_t);
277  // MSVC has no strict aliasing, and is able to highly optimize this case.
278  if (align == 0) {
279  uint32_t* data32 = reinterpret_cast<uint32_t*>(data);
280  size_t len32 = nbytes / sizeof(*data32);
281  for (size_t i = 0; i < len32; i++) {
282  data32[i] = BSWAP_4(data32[i]);
283  }
284  return;
285  }
286 #endif
287 
288  uint32_t temp;
289  for (size_t i = 0; i < nbytes; i += sizeof(temp)) {
290  memcpy(&temp, &data[i], sizeof(temp));
291  temp = BSWAP_4(temp);
292  memcpy(&data[i], &temp, sizeof(temp));
293  }
294 }
295 
296 void SwapBytes64(char* data, size_t nbytes) {
297  CHECK_EQ(nbytes % 8, 0);
298 
299 #if defined(_MSC_VER)
300  int align = reinterpret_cast<uintptr_t>(data) % sizeof(uint64_t);
301  if (align == 0) {
302  // MSVC has no strict aliasing, and is able to highly optimize this case.
303  uint64_t* data64 = reinterpret_cast<uint64_t*>(data);
304  size_t len64 = nbytes / sizeof(*data64);
305  for (size_t i = 0; i < len64; i++) {
306  data64[i] = BSWAP_8(data64[i]);
307  }
308  return;
309  }
310 #endif
311 
312  uint64_t temp;
313  for (size_t i = 0; i < nbytes; i += sizeof(temp)) {
314  memcpy(&temp, &data[i], sizeof(temp));
315  temp = BSWAP_8(temp);
316  memcpy(&data[i], &temp, sizeof(temp));
317  }
318 }
319 
320 char ToLower(char c) {
321  return c >= 'A' && c <= 'Z' ? c + ('a' - 'A') : c;
322 }
323 
324 bool StringEqualNoCase(const char* a, const char* b) {
325  do {
326  if (*a == '\0')
327  return *b == '\0';
328  if (*b == '\0')
329  return *a == '\0';
330  } while (ToLower(*a++) == ToLower(*b++));
331  return false;
332 }
333 
334 bool StringEqualNoCaseN(const char* a, const char* b, size_t length) {
335  for (size_t i = 0; i < length; i++) {
336  if (ToLower(a[i]) != ToLower(b[i]))
337  return false;
338  if (a[i] == '\0')
339  return true;
340  }
341  return true;
342 }
343 
344 inline size_t MultiplyWithOverflowCheck(size_t a, size_t b) {
345  size_t ret = a * b;
346  if (a != 0)
347  CHECK_EQ(b, ret / a);
348 
349  return ret;
350 }
351 
352 // These should be used in our code as opposed to the native
353 // versions as they abstract out some platform and or
354 // compiler version specific functionality.
355 // malloc(0) and realloc(ptr, 0) have implementation-defined behavior in
356 // that the standard allows them to either return a unique pointer or a
357 // nullptr for zero-sized allocation requests. Normalize by always using
358 // a nullptr.
359 template <typename T>
360 T* UncheckedRealloc(T* pointer, size_t n) {
361  size_t full_size = MultiplyWithOverflowCheck(sizeof(T), n);
362 
363  if (full_size == 0) {
364  free(pointer);
365  return nullptr;
366  }
367 
368  void* allocated = realloc(pointer, full_size);
369 
370  if (UNLIKELY(allocated == nullptr)) {
371  // Tell V8 that memory is low and retry.
373  allocated = realloc(pointer, full_size);
374  }
375 
376  return static_cast<T*>(allocated);
377 }
378 
379 // As per spec realloc behaves like malloc if passed nullptr.
380 template <typename T>
381 inline T* UncheckedMalloc(size_t n) {
382  if (n == 0) n = 1;
383  return UncheckedRealloc<T>(nullptr, n);
384 }
385 
386 template <typename T>
387 inline T* UncheckedCalloc(size_t n) {
388  if (n == 0) n = 1;
389  MultiplyWithOverflowCheck(sizeof(T), n);
390  return static_cast<T*>(calloc(n, sizeof(T)));
391 }
392 
393 template <typename T>
394 inline T* Realloc(T* pointer, size_t n) {
395  T* ret = UncheckedRealloc(pointer, n);
396  if (n > 0) CHECK_NE(ret, nullptr);
397  return ret;
398 }
399 
400 template <typename T>
401 inline T* Malloc(size_t n) {
402  T* ret = UncheckedMalloc<T>(n);
403  if (n > 0) CHECK_NE(ret, nullptr);
404  return ret;
405 }
406 
407 template <typename T>
408 inline T* Calloc(size_t n) {
409  T* ret = UncheckedCalloc<T>(n);
410  if (n > 0) CHECK_NE(ret, nullptr);
411  return ret;
412 }
413 
414 // Shortcuts for char*.
415 inline char* Malloc(size_t n) { return Malloc<char>(n); }
416 inline char* Calloc(size_t n) { return Calloc<char>(n); }
417 inline char* UncheckedMalloc(size_t n) { return UncheckedMalloc<char>(n); }
418 inline char* UncheckedCalloc(size_t n) { return UncheckedCalloc<char>(n); }
419 
420 } // namespace node
421 
422 #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
423 
424 #endif // SRC_UTIL_INL_H_
union node::cares_wrap::@8::CaresAsyncData::@0 data
dtrace a
Definition: v8ustack.d:531
MaybeLocal< Object > New(Isolate *isolate, Local< String > string, enum encoding enc)
Definition: node_buffer.cc:241
dtrace n
Definition: v8ustack.d:531
void LowMemoryNotification()
Definition: util.cc:100