blob: 9b94a2feb1de6a7e9fcc8910ec3008e93f4a3bca [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
5#ifndef V8_UTILS_H_
6#define V8_UTILS_H_
7
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008#include <limits.h>
Steve Blocka7e24c12009-10-30 11:49:00 +00009#include <stdlib.h>
Steve Block6ded16b2010-05-10 14:33:55 +010010#include <string.h>
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011#include <cmath>
Steve Blocka7e24c12009-10-30 11:49:00 +000012
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013#include "include/v8.h"
14#include "src/allocation.h"
15#include "src/base/bits.h"
Ben Murdochc5610432016-08-08 18:44:38 +010016#include "src/base/compiler-specific.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017#include "src/base/logging.h"
18#include "src/base/macros.h"
19#include "src/base/platform/platform.h"
20#include "src/globals.h"
21#include "src/list.h"
22#include "src/vector.h"
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -080023
Steve Blocka7e24c12009-10-30 11:49:00 +000024namespace v8 {
25namespace internal {
26
27// ----------------------------------------------------------------------------
28// General helper functions
29
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000030// Returns the value (0 .. 15) of a hexadecimal character c.
31// If c is not a legal hexadecimal character, returns a value < 0.
32inline int HexValue(uc32 c) {
33 c -= '0';
34 if (static_cast<unsigned>(c) <= 9) return c;
35 c = (c | 0x20) - ('a' - '0'); // detect 0x11..0x16 and 0x31..0x36.
36 if (static_cast<unsigned>(c) <= 5) return c + 10;
37 return -1;
38}
39
Ben Murdochc5610432016-08-08 18:44:38 +010040inline char HexCharOfValue(int value) {
41 DCHECK(0 <= value && value <= 16);
42 if (value < 10) return value + '0';
43 return value - 10 + 'A';
44}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000045
46inline int BoolToInt(bool b) { return b ? 1 : 0; }
47
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010048
Ben Murdochb8a8cc12014-11-26 15:28:44 +000049// Same as strcmp, but can handle NULL arguments.
50inline bool CStringEquals(const char* s1, const char* s2) {
51 return (s1 == s2) || (s1 != NULL && s2 != NULL && strcmp(s1, s2) == 0);
Steve Blocka7e24c12009-10-30 11:49:00 +000052}
53
54
Kristian Monsen9dcf7e22010-06-28 14:14:28 +010055// X must be a power of 2. Returns the number of trailing zeros.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010056inline int WhichPowerOf2(uint32_t x) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000057 DCHECK(base::bits::IsPowerOfTwo32(x));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +010058 int bits = 0;
59#ifdef DEBUG
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000060 uint32_t original_x = x;
Kristian Monsen9dcf7e22010-06-28 14:14:28 +010061#endif
62 if (x >= 0x10000) {
63 bits += 16;
64 x >>= 16;
65 }
66 if (x >= 0x100) {
67 bits += 8;
68 x >>= 8;
69 }
70 if (x >= 0x10) {
71 bits += 4;
72 x >>= 4;
73 }
74 switch (x) {
75 default: UNREACHABLE();
76 case 8: bits++; // Fall through.
77 case 4: bits++; // Fall through.
78 case 2: bits++; // Fall through.
79 case 1: break;
80 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000081 DCHECK_EQ(static_cast<uint32_t>(1) << bits, original_x);
82 return bits;
83}
84
85
86// X must be a power of 2. Returns the number of trailing zeros.
87inline int WhichPowerOf2_64(uint64_t x) {
88 DCHECK(base::bits::IsPowerOfTwo64(x));
89 int bits = 0;
90#ifdef DEBUG
91 uint64_t original_x = x;
92#endif
93 if (x >= 0x100000000L) {
94 bits += 32;
95 x >>= 32;
96 }
97 if (x >= 0x10000) {
98 bits += 16;
99 x >>= 16;
100 }
101 if (x >= 0x100) {
102 bits += 8;
103 x >>= 8;
104 }
105 if (x >= 0x10) {
106 bits += 4;
107 x >>= 4;
108 }
109 switch (x) {
110 default: UNREACHABLE();
111 case 8: bits++; // Fall through.
112 case 4: bits++; // Fall through.
113 case 2: bits++; // Fall through.
114 case 1: break;
115 }
116 DCHECK_EQ(static_cast<uint64_t>(1) << bits, original_x);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100117 return bits;
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100118}
119
120
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000121inline int MostSignificantBit(uint32_t x) {
122 static const int msb4[] = {0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4};
123 int nibble = 0;
124 if (x & 0xffff0000) {
125 nibble += 16;
126 x >>= 16;
127 }
128 if (x & 0xff00) {
129 nibble += 8;
130 x >>= 8;
131 }
132 if (x & 0xf0) {
133 nibble += 4;
134 x >>= 4;
135 }
136 return nibble + msb4[x];
137}
138
139
Steve Blocka7e24c12009-10-30 11:49:00 +0000140// The C++ standard leaves the semantics of '>>' undefined for
141// negative signed operands. Most implementations do the right thing,
142// though.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100143inline int ArithmeticShiftRight(int x, int s) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000144 return x >> s;
145}
146
147
Steve Blocka7e24c12009-10-30 11:49:00 +0000148template <typename T>
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100149int Compare(const T& a, const T& b) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000150 if (a == b)
151 return 0;
152 else if (a < b)
153 return -1;
154 else
155 return 1;
156}
157
158
159template <typename T>
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100160int PointerValueCompare(const T* a, const T* b) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000161 return Compare<T>(*a, *b);
162}
163
164
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100165// Compare function to compare the object pointer value of two
166// handlified objects. The handles are passed as pointers to the
167// handles.
168template<typename T> class Handle; // Forward declaration.
169template <typename T>
170int HandleObjectPointerCompare(const Handle<T>* a, const Handle<T>* b) {
171 return Compare<T*>(*(*a), *(*b));
172}
173
174
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100175template <typename T, typename U>
176inline bool IsAligned(T value, U alignment) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000177 return (value & (alignment - 1)) == 0;
178}
179
180
181// Returns true if (addr + offset) is aligned.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100182inline bool IsAddressAligned(Address addr,
183 intptr_t alignment,
184 int offset = 0) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000185 intptr_t offs = OffsetFrom(addr + offset);
186 return IsAligned(offs, alignment);
187}
188
189
190// Returns the maximum of the two parameters.
191template <typename T>
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100192T Max(T a, T b) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000193 return a < b ? b : a;
194}
195
196
197// Returns the minimum of the two parameters.
198template <typename T>
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100199T Min(T a, T b) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000200 return a < b ? a : b;
201}
202
203
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000204// Returns the absolute value of its argument.
205template <typename T>
206T Abs(T a) {
207 return a < 0 ? -a : a;
Steve Blockd0582a62009-12-15 09:54:21 +0000208}
209
210
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000211// Floor(-0.0) == 0.0
212inline double Floor(double x) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400213#if V8_CC_MSVC
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000214 if (x == 0) return x; // Fix for issue 3477.
215#endif
216 return std::floor(x);
217}
218
Ben Murdochda12d292016-06-02 14:46:10 +0100219inline double Pow(double x, double y) {
220#if (defined(__MINGW64_VERSION_MAJOR) && \
221 (!defined(__MINGW64_VERSION_RC) || __MINGW64_VERSION_RC < 1)) || \
222 defined(V8_OS_AIX)
223 // MinGW64 and AIX have a custom implementation for pow. This handles certain
224 // special cases that are different.
225 if ((x == 0.0 || std::isinf(x)) && y != 0.0 && std::isfinite(y)) {
226 double f;
227 double result = ((x == 0.0) ^ (y > 0)) ? V8_INFINITY : 0;
228 /* retain sign if odd integer exponent */
229 return ((std::modf(y, &f) == 0.0) && (static_cast<int64_t>(y) & 1))
230 ? copysign(result, x)
231 : result;
232 }
233
234 if (x == 2.0) {
235 int y_int = static_cast<int>(y);
236 if (y == y_int) {
237 return std::ldexp(1.0, y_int);
238 }
239 }
240#endif
241 return std::pow(x, y);
242}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000243
244// TODO(svenpanne) Clean up the whole power-of-2 mess.
245inline int32_t WhichPowerOf2Abs(int32_t x) {
246 return (x == kMinInt) ? 31 : WhichPowerOf2(Abs(x));
247}
248
249
250// Obtains the unsigned type corresponding to T
251// available in C++11 as std::make_unsigned
252template<typename T>
253struct make_unsigned {
254 typedef T type;
255};
256
257
258// Template specializations necessary to have make_unsigned work
259template<> struct make_unsigned<int32_t> {
260 typedef uint32_t type;
261};
262
263
264template<> struct make_unsigned<int64_t> {
265 typedef uint64_t type;
266};
267
268
Steve Blocka7e24c12009-10-30 11:49:00 +0000269// ----------------------------------------------------------------------------
270// BitField is a help template for encoding and decode bitfield with
271// unsigned content.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000272
273template<class T, int shift, int size, class U>
274class BitFieldBase {
Steve Blocka7e24c12009-10-30 11:49:00 +0000275 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000276 // A type U mask of bit field. To use all bits of a type U of x bits
277 // in a bitfield without compiler warnings we have to compute 2^x
278 // without using a shift count of x in the computation.
279 static const U kOne = static_cast<U>(1U);
280 static const U kMask = ((kOne << shift) << size) - (kOne << shift);
281 static const U kShift = shift;
282 static const U kSize = size;
283 static const U kNext = kShift + kSize;
Ben Murdoch589d6972011-11-30 16:04:58 +0000284
285 // Value for the field with all bits set.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000286 static const T kMax = static_cast<T>((kOne << size) - 1);
Ben Murdoch589d6972011-11-30 16:04:58 +0000287
Steve Blocka7e24c12009-10-30 11:49:00 +0000288 // Tells whether the provided value fits into the bit field.
289 static bool is_valid(T value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000290 return (static_cast<U>(value) & ~static_cast<U>(kMax)) == 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000291 }
292
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000293 // Returns a type U with the bit field value encoded.
294 static U encode(T value) {
295 DCHECK(is_valid(value));
296 return static_cast<U>(value) << shift;
Steve Blocka7e24c12009-10-30 11:49:00 +0000297 }
298
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000299 // Returns a type U with the bit field value updated.
300 static U update(U previous, T value) {
Ben Murdoch589d6972011-11-30 16:04:58 +0000301 return (previous & ~kMask) | encode(value);
Ben Murdoch257744e2011-11-30 15:57:28 +0000302 }
303
Steve Blocka7e24c12009-10-30 11:49:00 +0000304 // Extracts the bit field from the value.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000305 static T decode(U value) {
Ben Murdoch589d6972011-11-30 16:04:58 +0000306 return static_cast<T>((value & kMask) >> shift);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100307 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000308};
309
310
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400311template <class T, int shift, int size>
312class BitField8 : public BitFieldBase<T, shift, size, uint8_t> {};
313
314
315template <class T, int shift, int size>
316class BitField16 : public BitFieldBase<T, shift, size, uint16_t> {};
317
318
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000319template<class T, int shift, int size>
320class BitField : public BitFieldBase<T, shift, size, uint32_t> { };
321
322
323template<class T, int shift, int size>
324class BitField64 : public BitFieldBase<T, shift, size, uint64_t> { };
325
326
Steve Blocka7e24c12009-10-30 11:49:00 +0000327// ----------------------------------------------------------------------------
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400328// BitSetComputer is a help template for encoding and decoding information for
329// a variable number of items in an array.
330//
331// To encode boolean data in a smi array you would use:
332// typedef BitSetComputer<bool, 1, kSmiValueSize, uint32_t> BoolComputer;
333//
334template <class T, int kBitsPerItem, int kBitsPerWord, class U>
335class BitSetComputer {
336 public:
337 static const int kItemsPerWord = kBitsPerWord / kBitsPerItem;
338 static const int kMask = (1 << kBitsPerItem) - 1;
339
340 // The number of array elements required to embed T information for each item.
341 static int word_count(int items) {
342 if (items == 0) return 0;
343 return (items - 1) / kItemsPerWord + 1;
344 }
345
346 // The array index to look at for item.
347 static int index(int base_index, int item) {
348 return base_index + item / kItemsPerWord;
349 }
350
351 // Extract T data for a given item from data.
352 static T decode(U data, int item) {
353 return static_cast<T>((data >> shift(item)) & kMask);
354 }
355
356 // Return the encoding for a store of value for item in previous.
357 static U encode(U previous, int item, T value) {
358 int shift_value = shift(item);
359 int set_bits = (static_cast<int>(value) << shift_value);
360 return (previous & ~(kMask << shift_value)) | set_bits;
361 }
362
363 static int shift(int item) { return (item % kItemsPerWord) * kBitsPerItem; }
364};
365
366
367// ----------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +0000368// Hash function.
369
Ben Murdochc7cc0282012-03-05 14:35:55 +0000370static const uint32_t kZeroHashSeed = 0;
371
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800372// Thomas Wang, Integer Hash Functions.
373// http://www.concentric.net/~Ttwang/tech/inthash.htm
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100374inline uint32_t ComputeIntegerHash(uint32_t key, uint32_t seed) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800375 uint32_t hash = key;
Ben Murdochc7cc0282012-03-05 14:35:55 +0000376 hash = hash ^ seed;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800377 hash = ~hash + (hash << 15); // hash = (hash << 15) - hash - 1;
378 hash = hash ^ (hash >> 12);
379 hash = hash + (hash << 2);
380 hash = hash ^ (hash >> 4);
381 hash = hash * 2057; // hash = (hash + (hash << 3)) + (hash << 11);
382 hash = hash ^ (hash >> 16);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000383 return hash & 0x3fffffff;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800384}
Steve Blocka7e24c12009-10-30 11:49:00 +0000385
386
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100387inline uint32_t ComputeLongHash(uint64_t key) {
388 uint64_t hash = key;
389 hash = ~hash + (hash << 18); // hash = (hash << 18) - hash - 1;
390 hash = hash ^ (hash >> 31);
391 hash = hash * 21; // hash = (hash + (hash << 2)) + (hash << 4);
392 hash = hash ^ (hash >> 11);
393 hash = hash + (hash << 6);
394 hash = hash ^ (hash >> 22);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000395 return static_cast<uint32_t>(hash);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100396}
397
398
399inline uint32_t ComputePointerHash(void* ptr) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000400 return ComputeIntegerHash(
Ben Murdochc7cc0282012-03-05 14:35:55 +0000401 static_cast<uint32_t>(reinterpret_cast<intptr_t>(ptr)),
402 v8::internal::kZeroHashSeed);
Ben Murdoch257744e2011-11-30 15:57:28 +0000403}
404
405
Steve Blocka7e24c12009-10-30 11:49:00 +0000406// ----------------------------------------------------------------------------
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000407// Generated memcpy/memmove
408
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000409// Initializes the codegen support that depends on CPU features.
410void init_memcopy_functions(Isolate* isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000411
412#if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_X87)
413// Limit below which the extra overhead of the MemCopy function is likely
414// to outweigh the benefits of faster copying.
415const int kMinComplexMemCopy = 64;
416
417// Copy memory area. No restrictions.
418void MemMove(void* dest, const void* src, size_t size);
419typedef void (*MemMoveFunction)(void* dest, const void* src, size_t size);
420
421// Keep the distinction of "move" vs. "copy" for the benefit of other
422// architectures.
423V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
424 MemMove(dest, src, size);
425}
426#elif defined(V8_HOST_ARCH_ARM)
427typedef void (*MemCopyUint8Function)(uint8_t* dest, const uint8_t* src,
428 size_t size);
429extern MemCopyUint8Function memcopy_uint8_function;
430V8_INLINE void MemCopyUint8Wrapper(uint8_t* dest, const uint8_t* src,
431 size_t chars) {
432 memcpy(dest, src, chars);
433}
434// For values < 16, the assembler function is slower than the inlined C code.
435const int kMinComplexMemCopy = 16;
436V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
437 (*memcopy_uint8_function)(reinterpret_cast<uint8_t*>(dest),
438 reinterpret_cast<const uint8_t*>(src), size);
439}
440V8_INLINE void MemMove(void* dest, const void* src, size_t size) {
441 memmove(dest, src, size);
442}
443
444typedef void (*MemCopyUint16Uint8Function)(uint16_t* dest, const uint8_t* src,
445 size_t size);
446extern MemCopyUint16Uint8Function memcopy_uint16_uint8_function;
447void MemCopyUint16Uint8Wrapper(uint16_t* dest, const uint8_t* src,
448 size_t chars);
449// For values < 12, the assembler function is slower than the inlined C code.
450const int kMinComplexConvertMemCopy = 12;
451V8_INLINE void MemCopyUint16Uint8(uint16_t* dest, const uint8_t* src,
452 size_t size) {
453 (*memcopy_uint16_uint8_function)(dest, src, size);
454}
455#elif defined(V8_HOST_ARCH_MIPS)
456typedef void (*MemCopyUint8Function)(uint8_t* dest, const uint8_t* src,
457 size_t size);
458extern MemCopyUint8Function memcopy_uint8_function;
459V8_INLINE void MemCopyUint8Wrapper(uint8_t* dest, const uint8_t* src,
460 size_t chars) {
461 memcpy(dest, src, chars);
462}
463// For values < 16, the assembler function is slower than the inlined C code.
464const int kMinComplexMemCopy = 16;
465V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
466 (*memcopy_uint8_function)(reinterpret_cast<uint8_t*>(dest),
467 reinterpret_cast<const uint8_t*>(src), size);
468}
469V8_INLINE void MemMove(void* dest, const void* src, size_t size) {
470 memmove(dest, src, size);
471}
472#else
473// Copy memory area to disjoint memory area.
474V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
475 memcpy(dest, src, size);
476}
477V8_INLINE void MemMove(void* dest, const void* src, size_t size) {
478 memmove(dest, src, size);
479}
480const int kMinComplexMemCopy = 16 * kPointerSize;
481#endif // V8_TARGET_ARCH_IA32
482
483
484// ----------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +0000485// Miscellaneous
486
487// A static resource holds a static instance that can be reserved in
488// a local scope using an instance of Access. Attempts to re-reserve
489// the instance will cause an error.
490template <typename T>
491class StaticResource {
492 public:
493 StaticResource() : is_reserved_(false) {}
494
495 private:
496 template <typename S> friend class Access;
497 T instance_;
498 bool is_reserved_;
499};
500
501
502// Locally scoped access to a static resource.
503template <typename T>
504class Access {
505 public:
506 explicit Access(StaticResource<T>* resource)
507 : resource_(resource)
508 , instance_(&resource->instance_) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000509 DCHECK(!resource->is_reserved_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000510 resource->is_reserved_ = true;
511 }
512
513 ~Access() {
514 resource_->is_reserved_ = false;
515 resource_ = NULL;
516 instance_ = NULL;
517 }
518
519 T* value() { return instance_; }
520 T* operator -> () { return instance_; }
521
522 private:
523 StaticResource<T>* resource_;
524 T* instance_;
525};
526
527
Ben Murdochb0fe1622011-05-05 13:52:32 +0100528// A pointer that can only be set once and doesn't allow NULL values.
529template<typename T>
530class SetOncePointer {
531 public:
532 SetOncePointer() : pointer_(NULL) { }
533
534 bool is_set() const { return pointer_ != NULL; }
535
536 T* get() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000537 DCHECK(pointer_ != NULL);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100538 return pointer_;
539 }
540
541 void set(T* value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000542 DCHECK(pointer_ == NULL && value != NULL);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100543 pointer_ = value;
544 }
545
546 private:
547 T* pointer_;
548};
549
550
Steve Blocka7e24c12009-10-30 11:49:00 +0000551template <typename T, int kSize>
552class EmbeddedVector : public Vector<T> {
553 public:
554 EmbeddedVector() : Vector<T>(buffer_, kSize) { }
555
Ben Murdochb0fe1622011-05-05 13:52:32 +0100556 explicit EmbeddedVector(T initial_value) : Vector<T>(buffer_, kSize) {
557 for (int i = 0; i < kSize; ++i) {
558 buffer_[i] = initial_value;
559 }
560 }
561
Steve Blocka7e24c12009-10-30 11:49:00 +0000562 // When copying, make underlying Vector to reference our buffer.
563 EmbeddedVector(const EmbeddedVector& rhs)
564 : Vector<T>(rhs) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000565 MemCopy(buffer_, rhs.buffer_, sizeof(T) * kSize);
566 this->set_start(buffer_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000567 }
568
569 EmbeddedVector& operator=(const EmbeddedVector& rhs) {
570 if (this == &rhs) return *this;
571 Vector<T>::operator=(rhs);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000572 MemCopy(buffer_, rhs.buffer_, sizeof(T) * kSize);
Steve Block6ded16b2010-05-10 14:33:55 +0100573 this->set_start(buffer_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000574 return *this;
575 }
576
577 private:
578 T buffer_[kSize];
579};
580
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000581// Compare 8bit/16bit chars to 8bit/16bit chars.
Steve Block6ded16b2010-05-10 14:33:55 +0100582template <typename lchar, typename rchar>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000583inline int CompareCharsUnsigned(const lchar* lhs, const rchar* rhs,
584 size_t chars) {
Steve Block6ded16b2010-05-10 14:33:55 +0100585 const lchar* limit = lhs + chars;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000586 if (sizeof(*lhs) == sizeof(char) && sizeof(*rhs) == sizeof(char)) {
587 // memcmp compares byte-by-byte, yielding wrong results for two-byte
588 // strings on little-endian systems.
589 return memcmp(lhs, rhs, chars);
Steve Block6ded16b2010-05-10 14:33:55 +0100590 }
Steve Block6ded16b2010-05-10 14:33:55 +0100591 while (lhs < limit) {
592 int r = static_cast<int>(*lhs) - static_cast<int>(*rhs);
593 if (r != 0) return r;
594 ++lhs;
595 ++rhs;
596 }
597 return 0;
598}
599
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000600template <typename lchar, typename rchar>
601inline int CompareChars(const lchar* lhs, const rchar* rhs, size_t chars) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000602 DCHECK(sizeof(lchar) <= 2);
603 DCHECK(sizeof(rchar) <= 2);
604 if (sizeof(lchar) == 1) {
605 if (sizeof(rchar) == 1) {
606 return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs),
607 reinterpret_cast<const uint8_t*>(rhs),
608 chars);
609 } else {
610 return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs),
611 reinterpret_cast<const uint16_t*>(rhs),
612 chars);
613 }
614 } else {
615 if (sizeof(rchar) == 1) {
616 return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(lhs),
617 reinterpret_cast<const uint8_t*>(rhs),
618 chars);
619 } else {
620 return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(lhs),
621 reinterpret_cast<const uint16_t*>(rhs),
622 chars);
623 }
624 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800625}
Steve Blockd0582a62009-12-15 09:54:21 +0000626
Steve Block6ded16b2010-05-10 14:33:55 +0100627
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000628// Calculate 10^exponent.
629inline int TenToThe(int exponent) {
630 DCHECK(exponent <= 9);
631 DCHECK(exponent >= 1);
632 int answer = 10;
633 for (int i = 1; i < exponent; i++) answer *= 10;
634 return answer;
Iain Merrick75681382010-08-19 15:07:18 +0100635}
Steve Blocka7e24c12009-10-30 11:49:00 +0000636
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000637
638template<typename ElementType, int NumElements>
639class EmbeddedContainer {
640 public:
641 EmbeddedContainer() : elems_() { }
642
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000643 int length() const { return NumElements; }
644 const ElementType& operator[](int i) const {
645 DCHECK(i < length());
646 return elems_[i];
647 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000648 ElementType& operator[](int i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000649 DCHECK(i < length());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000650 return elems_[i];
651 }
652
653 private:
654 ElementType elems_[NumElements];
655};
656
657
658template<typename ElementType>
659class EmbeddedContainer<ElementType, 0> {
660 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000661 int length() const { return 0; }
662 const ElementType& operator[](int i) const {
663 UNREACHABLE();
664 static ElementType t = 0;
665 return t;
666 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000667 ElementType& operator[](int i) {
668 UNREACHABLE();
669 static ElementType t = 0;
670 return t;
671 }
672};
673
674
675// Helper class for building result strings in a character buffer. The
676// purpose of the class is to use safe operations that checks the
677// buffer bounds on all operations in debug mode.
678// This simple base class does not allow formatted output.
679class SimpleStringBuilder {
680 public:
681 // Create a string builder with a buffer of the given size. The
682 // buffer is allocated through NewArray<char> and must be
683 // deallocated by the caller of Finalize().
684 explicit SimpleStringBuilder(int size);
685
686 SimpleStringBuilder(char* buffer, int size)
687 : buffer_(buffer, size), position_(0) { }
688
689 ~SimpleStringBuilder() { if (!is_finalized()) Finalize(); }
690
691 int size() const { return buffer_.length(); }
692
693 // Get the current position in the builder.
694 int position() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000695 DCHECK(!is_finalized());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000696 return position_;
697 }
698
699 // Reset the position.
700 void Reset() { position_ = 0; }
701
702 // Add a single character to the builder. It is not allowed to add
703 // 0-characters; use the Finalize() method to terminate the string
704 // instead.
705 void AddCharacter(char c) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000706 DCHECK(c != '\0');
707 DCHECK(!is_finalized() && position_ < buffer_.length());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000708 buffer_[position_++] = c;
709 }
710
711 // Add an entire string to the builder. Uses strlen() internally to
712 // compute the length of the input string.
713 void AddString(const char* s);
714
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400715 // Add the first 'n' characters of the given 0-terminated string 's' to the
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000716 // builder. The input string must have enough characters.
717 void AddSubstring(const char* s, int n);
718
719 // Add character padding to the builder. If count is non-positive,
720 // nothing is added to the builder.
721 void AddPadding(char c, int count);
722
723 // Add the decimal representation of the value.
724 void AddDecimalInteger(int value);
725
726 // Finalize the string by 0-terminating it and returning the buffer.
727 char* Finalize();
728
729 protected:
730 Vector<char> buffer_;
731 int position_;
732
733 bool is_finalized() const { return position_ < 0; }
Ben Murdoch589d6972011-11-30 16:04:58 +0000734
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000735 private:
736 DISALLOW_IMPLICIT_CONSTRUCTORS(SimpleStringBuilder);
737};
738
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000739
740// A poor man's version of STL's bitset: A bit set of enums E (without explicit
741// values), fitting into an integral type T.
742template <class E, class T = int>
743class EnumSet {
744 public:
745 explicit EnumSet(T bits = 0) : bits_(bits) {}
746 bool IsEmpty() const { return bits_ == 0; }
747 bool Contains(E element) const { return (bits_ & Mask(element)) != 0; }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100748 bool ContainsAnyOf(const EnumSet& set) const {
749 return (bits_ & set.bits_) != 0;
750 }
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000751 void Add(E element) { bits_ |= Mask(element); }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100752 void Add(const EnumSet& set) { bits_ |= set.bits_; }
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000753 void Remove(E element) { bits_ &= ~Mask(element); }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100754 void Remove(const EnumSet& set) { bits_ &= ~set.bits_; }
755 void RemoveAll() { bits_ = 0; }
756 void Intersect(const EnumSet& set) { bits_ &= set.bits_; }
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000757 T ToIntegral() const { return bits_; }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100758 bool operator==(const EnumSet& set) { return bits_ == set.bits_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000759 bool operator!=(const EnumSet& set) { return bits_ != set.bits_; }
760 EnumSet<E, T> operator|(const EnumSet& set) const {
761 return EnumSet<E, T>(bits_ | set.bits_);
762 }
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000763
764 private:
765 T Mask(E element) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000766 // The strange typing in DCHECK is necessary to avoid stupid warnings, see:
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000767 // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43680
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000768 DCHECK(static_cast<int>(element) < static_cast<int>(sizeof(T) * CHAR_BIT));
769 return static_cast<T>(1) << element;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000770 }
771
772 T bits_;
773};
774
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000775// Bit field extraction.
776inline uint32_t unsigned_bitextract_32(int msb, int lsb, uint32_t x) {
777 return (x >> lsb) & ((1 << (1 + msb - lsb)) - 1);
778}
779
780inline uint64_t unsigned_bitextract_64(int msb, int lsb, uint64_t x) {
781 return (x >> lsb) & ((static_cast<uint64_t>(1) << (1 + msb - lsb)) - 1);
782}
783
784inline int32_t signed_bitextract_32(int msb, int lsb, int32_t x) {
785 return (x << (31 - msb)) >> (lsb + 31 - msb);
786}
787
788inline int signed_bitextract_64(int msb, int lsb, int x) {
789 // TODO(jbramley): This is broken for big bitfields.
790 return (x << (63 - msb)) >> (lsb + 63 - msb);
791}
792
793// Check number width.
794inline bool is_intn(int64_t x, unsigned n) {
795 DCHECK((0 < n) && (n < 64));
796 int64_t limit = static_cast<int64_t>(1) << (n - 1);
797 return (-limit <= x) && (x < limit);
798}
799
800inline bool is_uintn(int64_t x, unsigned n) {
801 DCHECK((0 < n) && (n < (sizeof(x) * kBitsPerByte)));
802 return !(x >> n);
803}
804
805template <class T>
806inline T truncate_to_intn(T x, unsigned n) {
807 DCHECK((0 < n) && (n < (sizeof(x) * kBitsPerByte)));
808 return (x & ((static_cast<T>(1) << n) - 1));
809}
810
811#define INT_1_TO_63_LIST(V) \
812V(1) V(2) V(3) V(4) V(5) V(6) V(7) V(8) \
813V(9) V(10) V(11) V(12) V(13) V(14) V(15) V(16) \
814V(17) V(18) V(19) V(20) V(21) V(22) V(23) V(24) \
815V(25) V(26) V(27) V(28) V(29) V(30) V(31) V(32) \
816V(33) V(34) V(35) V(36) V(37) V(38) V(39) V(40) \
817V(41) V(42) V(43) V(44) V(45) V(46) V(47) V(48) \
818V(49) V(50) V(51) V(52) V(53) V(54) V(55) V(56) \
819V(57) V(58) V(59) V(60) V(61) V(62) V(63)
820
821#define DECLARE_IS_INT_N(N) \
822inline bool is_int##N(int64_t x) { return is_intn(x, N); }
823#define DECLARE_IS_UINT_N(N) \
824template <class T> \
825inline bool is_uint##N(T x) { return is_uintn(x, N); }
826#define DECLARE_TRUNCATE_TO_INT_N(N) \
827template <class T> \
828inline T truncate_to_int##N(T x) { return truncate_to_intn(x, N); }
829INT_1_TO_63_LIST(DECLARE_IS_INT_N)
830INT_1_TO_63_LIST(DECLARE_IS_UINT_N)
831INT_1_TO_63_LIST(DECLARE_TRUNCATE_TO_INT_N)
832#undef DECLARE_IS_INT_N
833#undef DECLARE_IS_UINT_N
834#undef DECLARE_TRUNCATE_TO_INT_N
835
836class TypeFeedbackId {
837 public:
838 explicit TypeFeedbackId(int id) : id_(id) { }
839 int ToInt() const { return id_; }
840
841 static TypeFeedbackId None() { return TypeFeedbackId(kNoneId); }
842 bool IsNone() const { return id_ == kNoneId; }
843
844 private:
845 static const int kNoneId = -1;
846
847 int id_;
848};
849
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000850inline bool operator<(TypeFeedbackId lhs, TypeFeedbackId rhs) {
851 return lhs.ToInt() < rhs.ToInt();
852}
853inline bool operator>(TypeFeedbackId lhs, TypeFeedbackId rhs) {
854 return lhs.ToInt() > rhs.ToInt();
855}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000856
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000857
858class FeedbackVectorSlot {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400859 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000860 FeedbackVectorSlot() : id_(kInvalidSlot) {}
861 explicit FeedbackVectorSlot(int id) : id_(id) {}
862
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400863 int ToInt() const { return id_; }
864
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000865 static FeedbackVectorSlot Invalid() { return FeedbackVectorSlot(); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400866 bool IsInvalid() const { return id_ == kInvalidSlot; }
867
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000868 bool operator==(FeedbackVectorSlot that) const {
869 return this->id_ == that.id_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400870 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000871 bool operator!=(FeedbackVectorSlot that) const { return !(*this == that); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400872
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000873 friend size_t hash_value(FeedbackVectorSlot slot) { return slot.ToInt(); }
874 friend std::ostream& operator<<(std::ostream& os, FeedbackVectorSlot);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400875
876 private:
877 static const int kInvalidSlot = -1;
878
879 int id_;
880};
881
882
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000883class BailoutId {
884 public:
885 explicit BailoutId(int id) : id_(id) { }
886 int ToInt() const { return id_; }
887
888 static BailoutId None() { return BailoutId(kNoneId); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000889 static BailoutId ScriptContext() { return BailoutId(kScriptContextId); }
890 static BailoutId FunctionContext() { return BailoutId(kFunctionContextId); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000891 static BailoutId FunctionEntry() { return BailoutId(kFunctionEntryId); }
892 static BailoutId Declarations() { return BailoutId(kDeclarationsId); }
893 static BailoutId FirstUsable() { return BailoutId(kFirstUsableId); }
894 static BailoutId StubEntry() { return BailoutId(kStubEntryId); }
895
896 bool IsNone() const { return id_ == kNoneId; }
897 bool operator==(const BailoutId& other) const { return id_ == other.id_; }
898 bool operator!=(const BailoutId& other) const { return id_ != other.id_; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400899 friend size_t hash_value(BailoutId);
900 friend std::ostream& operator<<(std::ostream&, BailoutId);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000901
902 private:
903 static const int kNoneId = -1;
904
905 // Using 0 could disguise errors.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000906 static const int kScriptContextId = 1;
907 static const int kFunctionContextId = 2;
908 static const int kFunctionEntryId = 3;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000909
910 // This AST id identifies the point after the declarations have been visited.
911 // We need it to capture the environment effects of declarations that emit
912 // code (function declarations).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000913 static const int kDeclarationsId = 4;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000914
915 // Every FunctionState starts with this id.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000916 static const int kFirstUsableId = 5;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000917
918 // Every compiled stub starts with this id.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000919 static const int kStubEntryId = 6;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000920
921 int id_;
922};
923
Ben Murdoch097c5b22016-05-18 11:27:45 +0100924class TokenDispenserForFinally {
925 public:
926 int GetBreakContinueToken() { return next_token_++; }
927 static const int kFallThroughToken = 0;
928 static const int kThrowToken = 1;
929 static const int kReturnToken = 2;
930
931 static const int kFirstBreakContinueToken = 3;
932 static const int kInvalidToken = -1;
933
934 private:
935 int next_token_ = kFirstBreakContinueToken;
936};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000937
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000938// ----------------------------------------------------------------------------
939// I/O support.
940
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000941// Our version of printf().
Ben Murdochc5610432016-08-08 18:44:38 +0100942void PRINTF_FORMAT(1, 2) PrintF(const char* format, ...);
943void PRINTF_FORMAT(2, 3) PrintF(FILE* out, const char* format, ...);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000944
945// Prepends the current process ID to the output.
Ben Murdochc5610432016-08-08 18:44:38 +0100946void PRINTF_FORMAT(1, 2) PrintPID(const char* format, ...);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000947
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000948// Prepends the current process ID and given isolate pointer to the output.
Ben Murdochc5610432016-08-08 18:44:38 +0100949void PRINTF_FORMAT(2, 3) PrintIsolate(void* isolate, const char* format, ...);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000950
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000951// Safe formatting print. Ensures that str is always null-terminated.
952// Returns the number of chars written, or -1 if output was truncated.
Ben Murdochc5610432016-08-08 18:44:38 +0100953int PRINTF_FORMAT(2, 3) SNPrintF(Vector<char> str, const char* format, ...);
954int PRINTF_FORMAT(2, 0)
955 VSNPrintF(Vector<char> str, const char* format, va_list args);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000956
957void StrNCpy(Vector<char> dest, const char* src, size_t n);
958
959// Our version of fflush.
960void Flush(FILE* out);
961
962inline void Flush() {
963 Flush(stdout);
964}
965
966
967// Read a line of characters after printing the prompt to stdout. The resulting
968// char* needs to be disposed off with DeleteArray by the caller.
969char* ReadLine(const char* prompt);
970
971
972// Read and return the raw bytes in a file. the size of the buffer is returned
973// in size.
974// The returned buffer must be freed by the caller.
975byte* ReadBytes(const char* filename, int* size, bool verbose = true);
976
977
978// Append size chars from str to the file given by filename.
979// The file is overwritten. Returns the number of chars written.
980int AppendChars(const char* filename,
981 const char* str,
982 int size,
983 bool verbose = true);
984
985
986// Write size chars from str to the file given by filename.
987// The file is overwritten. Returns the number of chars written.
988int WriteChars(const char* filename,
989 const char* str,
990 int size,
991 bool verbose = true);
992
993
994// Write size bytes to the file given by filename.
995// The file is overwritten. Returns the number of bytes written.
996int WriteBytes(const char* filename,
997 const byte* bytes,
998 int size,
999 bool verbose = true);
1000
1001
1002// Write the C code
1003// const char* <varname> = "<str>";
1004// const int <varname>_len = <len>;
1005// to the file given by filename. Only the first len chars are written.
1006int WriteAsCFile(const char* filename, const char* varname,
1007 const char* str, int size, bool verbose = true);
1008
1009
1010// ----------------------------------------------------------------------------
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001011// Memory
1012
1013// Copies words from |src| to |dst|. The data spans must not overlap.
1014template <typename T>
1015inline void CopyWords(T* dst, const T* src, size_t num_words) {
1016 STATIC_ASSERT(sizeof(T) == kPointerSize);
1017 // TODO(mvstanton): disabled because mac builds are bogus failing on this
1018 // assert. They are doing a signed comparison. Investigate in
1019 // the morning.
1020 // DCHECK(Min(dst, const_cast<T*>(src)) + num_words <=
1021 // Max(dst, const_cast<T*>(src)));
1022 DCHECK(num_words > 0);
1023
1024 // Use block copying MemCopy if the segment we're copying is
1025 // enough to justify the extra call/setup overhead.
1026 static const size_t kBlockCopyLimit = 16;
1027
1028 if (num_words < kBlockCopyLimit) {
1029 do {
1030 num_words--;
1031 *dst++ = *src++;
1032 } while (num_words > 0);
1033 } else {
1034 MemCopy(dst, src, num_words * kPointerSize);
1035 }
1036}
1037
1038
1039// Copies words from |src| to |dst|. No restrictions.
1040template <typename T>
1041inline void MoveWords(T* dst, const T* src, size_t num_words) {
1042 STATIC_ASSERT(sizeof(T) == kPointerSize);
1043 DCHECK(num_words > 0);
1044
1045 // Use block copying MemCopy if the segment we're copying is
1046 // enough to justify the extra call/setup overhead.
1047 static const size_t kBlockCopyLimit = 16;
1048
1049 if (num_words < kBlockCopyLimit &&
1050 ((dst < src) || (dst >= (src + num_words * kPointerSize)))) {
1051 T* end = dst + num_words;
1052 do {
1053 num_words--;
1054 *dst++ = *src++;
1055 } while (num_words > 0);
1056 } else {
1057 MemMove(dst, src, num_words * kPointerSize);
1058 }
1059}
1060
1061
1062// Copies data from |src| to |dst|. The data spans must not overlap.
1063template <typename T>
1064inline void CopyBytes(T* dst, const T* src, size_t num_bytes) {
1065 STATIC_ASSERT(sizeof(T) == 1);
1066 DCHECK(Min(dst, const_cast<T*>(src)) + num_bytes <=
1067 Max(dst, const_cast<T*>(src)));
1068 if (num_bytes == 0) return;
1069
1070 // Use block copying MemCopy if the segment we're copying is
1071 // enough to justify the extra call/setup overhead.
1072 static const int kBlockCopyLimit = kMinComplexMemCopy;
1073
1074 if (num_bytes < static_cast<size_t>(kBlockCopyLimit)) {
1075 do {
1076 num_bytes--;
1077 *dst++ = *src++;
1078 } while (num_bytes > 0);
1079 } else {
1080 MemCopy(dst, src, num_bytes);
1081 }
1082}
1083
1084
1085template <typename T, typename U>
1086inline void MemsetPointer(T** dest, U* value, int counter) {
1087#ifdef DEBUG
1088 T* a = NULL;
1089 U* b = NULL;
1090 a = b; // Fake assignment to check assignability.
1091 USE(a);
1092#endif // DEBUG
1093#if V8_HOST_ARCH_IA32
1094#define STOS "stosl"
1095#elif V8_HOST_ARCH_X64
1096#if V8_HOST_ARCH_32_BIT
1097#define STOS "addr32 stosl"
1098#else
1099#define STOS "stosq"
1100#endif
1101#endif
1102#if defined(__native_client__)
1103 // This STOS sequence does not validate for x86_64 Native Client.
1104 // Here we #undef STOS to force use of the slower C version.
1105 // TODO(bradchen): Profile V8 and implement a faster REP STOS
1106 // here if the profile indicates it matters.
1107#undef STOS
1108#endif
1109
1110#if defined(MEMORY_SANITIZER)
1111 // MemorySanitizer does not understand inline assembly.
1112#undef STOS
1113#endif
1114
1115#if defined(__GNUC__) && defined(STOS)
1116 asm volatile(
1117 "cld;"
1118 "rep ; " STOS
1119 : "+&c" (counter), "+&D" (dest)
1120 : "a" (value)
1121 : "memory", "cc");
1122#else
1123 for (int i = 0; i < counter; i++) {
1124 dest[i] = value;
1125 }
1126#endif
1127
1128#undef STOS
1129}
1130
1131
1132// Simple support to read a file into a 0-terminated C-string.
1133// The returned buffer must be freed by the caller.
1134// On return, *exits tells whether the file existed.
1135Vector<const char> ReadFile(const char* filename,
1136 bool* exists,
1137 bool verbose = true);
1138Vector<const char> ReadFile(FILE* file,
1139 bool* exists,
1140 bool verbose = true);
1141
1142
1143template <typename sourcechar, typename sinkchar>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001144INLINE(static void CopyCharsUnsigned(sinkchar* dest, const sourcechar* src,
1145 size_t chars));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001146#if defined(V8_HOST_ARCH_ARM)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001147INLINE(void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, size_t chars));
1148INLINE(void CopyCharsUnsigned(uint16_t* dest, const uint8_t* src,
1149 size_t chars));
1150INLINE(void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src,
1151 size_t chars));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001152#elif defined(V8_HOST_ARCH_MIPS)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001153INLINE(void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, size_t chars));
1154INLINE(void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src,
1155 size_t chars));
Ben Murdochda12d292016-06-02 14:46:10 +01001156#elif defined(V8_HOST_ARCH_PPC) || defined(V8_HOST_ARCH_S390)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001157INLINE(void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, size_t chars));
1158INLINE(void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src,
1159 size_t chars));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001160#endif
1161
1162// Copy from 8bit/16bit chars to 8bit/16bit chars.
1163template <typename sourcechar, typename sinkchar>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001164INLINE(void CopyChars(sinkchar* dest, const sourcechar* src, size_t chars));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001165
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001166template <typename sourcechar, typename sinkchar>
1167void CopyChars(sinkchar* dest, const sourcechar* src, size_t chars) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001168 DCHECK(sizeof(sourcechar) <= 2);
1169 DCHECK(sizeof(sinkchar) <= 2);
1170 if (sizeof(sinkchar) == 1) {
1171 if (sizeof(sourcechar) == 1) {
1172 CopyCharsUnsigned(reinterpret_cast<uint8_t*>(dest),
1173 reinterpret_cast<const uint8_t*>(src),
1174 chars);
1175 } else {
1176 CopyCharsUnsigned(reinterpret_cast<uint8_t*>(dest),
1177 reinterpret_cast<const uint16_t*>(src),
1178 chars);
1179 }
1180 } else {
1181 if (sizeof(sourcechar) == 1) {
1182 CopyCharsUnsigned(reinterpret_cast<uint16_t*>(dest),
1183 reinterpret_cast<const uint8_t*>(src),
1184 chars);
1185 } else {
1186 CopyCharsUnsigned(reinterpret_cast<uint16_t*>(dest),
1187 reinterpret_cast<const uint16_t*>(src),
1188 chars);
1189 }
1190 }
1191}
1192
1193template <typename sourcechar, typename sinkchar>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001194void CopyCharsUnsigned(sinkchar* dest, const sourcechar* src, size_t chars) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001195 sinkchar* limit = dest + chars;
1196 if ((sizeof(*dest) == sizeof(*src)) &&
1197 (chars >= static_cast<int>(kMinComplexMemCopy / sizeof(*dest)))) {
1198 MemCopy(dest, src, chars * sizeof(*dest));
1199 } else {
1200 while (dest < limit) *dest++ = static_cast<sinkchar>(*src++);
1201 }
1202}
1203
1204
1205#if defined(V8_HOST_ARCH_ARM)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001206void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, size_t chars) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001207 switch (static_cast<unsigned>(chars)) {
1208 case 0:
1209 break;
1210 case 1:
1211 *dest = *src;
1212 break;
1213 case 2:
1214 memcpy(dest, src, 2);
1215 break;
1216 case 3:
1217 memcpy(dest, src, 3);
1218 break;
1219 case 4:
1220 memcpy(dest, src, 4);
1221 break;
1222 case 5:
1223 memcpy(dest, src, 5);
1224 break;
1225 case 6:
1226 memcpy(dest, src, 6);
1227 break;
1228 case 7:
1229 memcpy(dest, src, 7);
1230 break;
1231 case 8:
1232 memcpy(dest, src, 8);
1233 break;
1234 case 9:
1235 memcpy(dest, src, 9);
1236 break;
1237 case 10:
1238 memcpy(dest, src, 10);
1239 break;
1240 case 11:
1241 memcpy(dest, src, 11);
1242 break;
1243 case 12:
1244 memcpy(dest, src, 12);
1245 break;
1246 case 13:
1247 memcpy(dest, src, 13);
1248 break;
1249 case 14:
1250 memcpy(dest, src, 14);
1251 break;
1252 case 15:
1253 memcpy(dest, src, 15);
1254 break;
1255 default:
1256 MemCopy(dest, src, chars);
1257 break;
1258 }
1259}
1260
1261
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001262void CopyCharsUnsigned(uint16_t* dest, const uint8_t* src, size_t chars) {
1263 if (chars >= static_cast<size_t>(kMinComplexConvertMemCopy)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001264 MemCopyUint16Uint8(dest, src, chars);
1265 } else {
1266 MemCopyUint16Uint8Wrapper(dest, src, chars);
1267 }
1268}
1269
1270
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001271void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, size_t chars) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001272 switch (static_cast<unsigned>(chars)) {
1273 case 0:
1274 break;
1275 case 1:
1276 *dest = *src;
1277 break;
1278 case 2:
1279 memcpy(dest, src, 4);
1280 break;
1281 case 3:
1282 memcpy(dest, src, 6);
1283 break;
1284 case 4:
1285 memcpy(dest, src, 8);
1286 break;
1287 case 5:
1288 memcpy(dest, src, 10);
1289 break;
1290 case 6:
1291 memcpy(dest, src, 12);
1292 break;
1293 case 7:
1294 memcpy(dest, src, 14);
1295 break;
1296 default:
1297 MemCopy(dest, src, chars * sizeof(*dest));
1298 break;
1299 }
1300}
1301
1302
1303#elif defined(V8_HOST_ARCH_MIPS)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001304void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, size_t chars) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001305 if (chars < kMinComplexMemCopy) {
1306 memcpy(dest, src, chars);
1307 } else {
1308 MemCopy(dest, src, chars);
1309 }
1310}
1311
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001312void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, size_t chars) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001313 if (chars < kMinComplexMemCopy) {
1314 memcpy(dest, src, chars * sizeof(*dest));
1315 } else {
1316 MemCopy(dest, src, chars * sizeof(*dest));
1317 }
1318}
Ben Murdochda12d292016-06-02 14:46:10 +01001319#elif defined(V8_HOST_ARCH_PPC) || defined(V8_HOST_ARCH_S390)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001320#define CASE(n) \
1321 case n: \
1322 memcpy(dest, src, n); \
1323 break
1324void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, size_t chars) {
1325 switch (static_cast<unsigned>(chars)) {
1326 case 0:
1327 break;
1328 case 1:
1329 *dest = *src;
1330 break;
1331 CASE(2);
1332 CASE(3);
1333 CASE(4);
1334 CASE(5);
1335 CASE(6);
1336 CASE(7);
1337 CASE(8);
1338 CASE(9);
1339 CASE(10);
1340 CASE(11);
1341 CASE(12);
1342 CASE(13);
1343 CASE(14);
1344 CASE(15);
1345 CASE(16);
1346 CASE(17);
1347 CASE(18);
1348 CASE(19);
1349 CASE(20);
1350 CASE(21);
1351 CASE(22);
1352 CASE(23);
1353 CASE(24);
1354 CASE(25);
1355 CASE(26);
1356 CASE(27);
1357 CASE(28);
1358 CASE(29);
1359 CASE(30);
1360 CASE(31);
1361 CASE(32);
1362 CASE(33);
1363 CASE(34);
1364 CASE(35);
1365 CASE(36);
1366 CASE(37);
1367 CASE(38);
1368 CASE(39);
1369 CASE(40);
1370 CASE(41);
1371 CASE(42);
1372 CASE(43);
1373 CASE(44);
1374 CASE(45);
1375 CASE(46);
1376 CASE(47);
1377 CASE(48);
1378 CASE(49);
1379 CASE(50);
1380 CASE(51);
1381 CASE(52);
1382 CASE(53);
1383 CASE(54);
1384 CASE(55);
1385 CASE(56);
1386 CASE(57);
1387 CASE(58);
1388 CASE(59);
1389 CASE(60);
1390 CASE(61);
1391 CASE(62);
1392 CASE(63);
1393 CASE(64);
1394 default:
1395 memcpy(dest, src, chars);
1396 break;
1397 }
1398}
1399#undef CASE
1400
1401#define CASE(n) \
1402 case n: \
1403 memcpy(dest, src, n * 2); \
1404 break
1405void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, size_t chars) {
1406 switch (static_cast<unsigned>(chars)) {
1407 case 0:
1408 break;
1409 case 1:
1410 *dest = *src;
1411 break;
1412 CASE(2);
1413 CASE(3);
1414 CASE(4);
1415 CASE(5);
1416 CASE(6);
1417 CASE(7);
1418 CASE(8);
1419 CASE(9);
1420 CASE(10);
1421 CASE(11);
1422 CASE(12);
1423 CASE(13);
1424 CASE(14);
1425 CASE(15);
1426 CASE(16);
1427 CASE(17);
1428 CASE(18);
1429 CASE(19);
1430 CASE(20);
1431 CASE(21);
1432 CASE(22);
1433 CASE(23);
1434 CASE(24);
1435 CASE(25);
1436 CASE(26);
1437 CASE(27);
1438 CASE(28);
1439 CASE(29);
1440 CASE(30);
1441 CASE(31);
1442 CASE(32);
1443 default:
1444 memcpy(dest, src, chars * 2);
1445 break;
1446 }
1447}
1448#undef CASE
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001449#endif
1450
1451
1452class StringBuilder : public SimpleStringBuilder {
1453 public:
1454 explicit StringBuilder(int size) : SimpleStringBuilder(size) { }
1455 StringBuilder(char* buffer, int size) : SimpleStringBuilder(buffer, size) { }
1456
1457 // Add formatted contents to the builder just like printf().
Ben Murdochc5610432016-08-08 18:44:38 +01001458 void PRINTF_FORMAT(2, 3) AddFormatted(const char* format, ...);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001459
1460 // Add formatted contents like printf based on a va_list.
Ben Murdochc5610432016-08-08 18:44:38 +01001461 void PRINTF_FORMAT(2, 0) AddFormattedList(const char* format, va_list list);
1462
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001463 private:
1464 DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
1465};
1466
1467
1468bool DoubleToBoolean(double d);
1469
1470template <typename Stream>
1471bool StringToArrayIndex(Stream* stream, uint32_t* index) {
1472 uint16_t ch = stream->GetNext();
1473
1474 // If the string begins with a '0' character, it must only consist
1475 // of it to be a legal array index.
1476 if (ch == '0') {
1477 *index = 0;
1478 return !stream->HasMore();
1479 }
1480
1481 // Convert string to uint32 array index; character by character.
1482 int d = ch - '0';
1483 if (d < 0 || d > 9) return false;
1484 uint32_t result = d;
1485 while (stream->HasMore()) {
1486 d = stream->GetNext() - '0';
1487 if (d < 0 || d > 9) return false;
1488 // Check that the new result is below the 32 bit limit.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001489 if (result > 429496729U - ((d + 3) >> 3)) return false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001490 result = (result * 10) + d;
1491 }
1492
1493 *index = result;
1494 return true;
1495}
1496
1497
1498// Returns current value of top of the stack. Works correctly with ASAN.
1499DISABLE_ASAN
1500inline uintptr_t GetCurrentStackPosition() {
1501 // Takes the address of the limit variable in order to find out where
1502 // the top of stack is right now.
1503 uintptr_t limit = reinterpret_cast<uintptr_t>(&limit);
1504 return limit;
1505}
1506
Ben Murdoch097c5b22016-05-18 11:27:45 +01001507template <typename V>
1508static inline V ReadUnalignedValue(const void* p) {
1509#if !(V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64)
1510 return *reinterpret_cast<const V*>(p);
1511#else
1512 V r;
1513 memmove(&r, p, sizeof(V));
1514 return r;
1515#endif // V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
1516}
1517
1518template <typename V>
1519static inline void WriteUnalignedValue(void* p, V value) {
1520#if !(V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64)
1521 *(reinterpret_cast<V*>(p)) = value;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001522#else // V8_TARGET_ARCH_MIPS
Ben Murdoch097c5b22016-05-18 11:27:45 +01001523 memmove(p, &value, sizeof(V));
1524#endif // V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
1525}
1526
Ben Murdoch61f157c2016-09-16 13:49:30 +01001527static inline double ReadFloatValue(const void* p) {
1528 return ReadUnalignedValue<float>(p);
1529}
1530
Ben Murdoch097c5b22016-05-18 11:27:45 +01001531static inline double ReadDoubleValue(const void* p) {
1532 return ReadUnalignedValue<double>(p);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001533}
1534
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001535static inline void WriteDoubleValue(void* p, double value) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001536 WriteUnalignedValue(p, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001537}
1538
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001539static inline uint16_t ReadUnalignedUInt16(const void* p) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001540 return ReadUnalignedValue<uint16_t>(p);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001541}
1542
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001543static inline void WriteUnalignedUInt16(void* p, uint16_t value) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001544 WriteUnalignedValue(p, value);
1545}
1546
Ben Murdochda12d292016-06-02 14:46:10 +01001547static inline uint32_t ReadUnalignedUInt32(const void* p) {
1548 return ReadUnalignedValue<uint32_t>(p);
1549}
1550
Ben Murdoch097c5b22016-05-18 11:27:45 +01001551static inline void WriteUnalignedUInt32(void* p, uint32_t value) {
1552 WriteUnalignedValue(p, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001553}
1554
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001555} // namespace internal
1556} // namespace v8
Steve Block6ded16b2010-05-10 14:33:55 +01001557
Steve Blocka7e24c12009-10-30 11:49:00 +00001558#endif // V8_UTILS_H_