blob: 525c6f87d3d96fbd8504a00474981675c1c1f74d [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"
16#include "src/base/logging.h"
17#include "src/base/macros.h"
18#include "src/base/platform/platform.h"
19#include "src/globals.h"
20#include "src/list.h"
21#include "src/vector.h"
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -080022
Steve Blocka7e24c12009-10-30 11:49:00 +000023namespace v8 {
24namespace internal {
25
26// ----------------------------------------------------------------------------
27// General helper functions
28
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010029
Ben Murdochb8a8cc12014-11-26 15:28:44 +000030// Same as strcmp, but can handle NULL arguments.
31inline bool CStringEquals(const char* s1, const char* s2) {
32 return (s1 == s2) || (s1 != NULL && s2 != NULL && strcmp(s1, s2) == 0);
Steve Blocka7e24c12009-10-30 11:49:00 +000033}
34
35
Kristian Monsen9dcf7e22010-06-28 14:14:28 +010036// X must be a power of 2. Returns the number of trailing zeros.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010037inline int WhichPowerOf2(uint32_t x) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000038 DCHECK(base::bits::IsPowerOfTwo32(x));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +010039 int bits = 0;
40#ifdef DEBUG
41 int original_x = x;
42#endif
43 if (x >= 0x10000) {
44 bits += 16;
45 x >>= 16;
46 }
47 if (x >= 0x100) {
48 bits += 8;
49 x >>= 8;
50 }
51 if (x >= 0x10) {
52 bits += 4;
53 x >>= 4;
54 }
55 switch (x) {
56 default: UNREACHABLE();
57 case 8: bits++; // Fall through.
58 case 4: bits++; // Fall through.
59 case 2: bits++; // Fall through.
60 case 1: break;
61 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000062 DCHECK_EQ(1 << bits, original_x);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +010063 return bits;
Kristian Monsen9dcf7e22010-06-28 14:14:28 +010064}
65
66
Ben Murdochb8a8cc12014-11-26 15:28:44 +000067inline int MostSignificantBit(uint32_t x) {
68 static const int msb4[] = {0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4};
69 int nibble = 0;
70 if (x & 0xffff0000) {
71 nibble += 16;
72 x >>= 16;
73 }
74 if (x & 0xff00) {
75 nibble += 8;
76 x >>= 8;
77 }
78 if (x & 0xf0) {
79 nibble += 4;
80 x >>= 4;
81 }
82 return nibble + msb4[x];
83}
84
85
Steve Blocka7e24c12009-10-30 11:49:00 +000086// The C++ standard leaves the semantics of '>>' undefined for
87// negative signed operands. Most implementations do the right thing,
88// though.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010089inline int ArithmeticShiftRight(int x, int s) {
Steve Blocka7e24c12009-10-30 11:49:00 +000090 return x >> s;
91}
92
93
Steve Blocka7e24c12009-10-30 11:49:00 +000094template <typename T>
Ben Murdoch3ef787d2012-04-12 10:51:47 +010095int Compare(const T& a, const T& b) {
Steve Blocka7e24c12009-10-30 11:49:00 +000096 if (a == b)
97 return 0;
98 else if (a < b)
99 return -1;
100 else
101 return 1;
102}
103
104
105template <typename T>
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100106int PointerValueCompare(const T* a, const T* b) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000107 return Compare<T>(*a, *b);
108}
109
110
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100111// Compare function to compare the object pointer value of two
112// handlified objects. The handles are passed as pointers to the
113// handles.
114template<typename T> class Handle; // Forward declaration.
115template <typename T>
116int HandleObjectPointerCompare(const Handle<T>* a, const Handle<T>* b) {
117 return Compare<T*>(*(*a), *(*b));
118}
119
120
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100121template <typename T, typename U>
122inline bool IsAligned(T value, U alignment) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000123 return (value & (alignment - 1)) == 0;
124}
125
126
127// Returns true if (addr + offset) is aligned.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100128inline bool IsAddressAligned(Address addr,
129 intptr_t alignment,
130 int offset = 0) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000131 intptr_t offs = OffsetFrom(addr + offset);
132 return IsAligned(offs, alignment);
133}
134
135
136// Returns the maximum of the two parameters.
137template <typename T>
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100138T Max(T a, T b) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000139 return a < b ? b : a;
140}
141
142
143// Returns the minimum of the two parameters.
144template <typename T>
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100145T Min(T a, T b) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000146 return a < b ? a : b;
147}
148
149
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000150// Returns the absolute value of its argument.
151template <typename T>
152T Abs(T a) {
153 return a < 0 ? -a : a;
Steve Blockd0582a62009-12-15 09:54:21 +0000154}
155
156
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000157// Floor(-0.0) == 0.0
158inline double Floor(double x) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400159#if V8_CC_MSVC
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000160 if (x == 0) return x; // Fix for issue 3477.
161#endif
162 return std::floor(x);
163}
164
165
166// TODO(svenpanne) Clean up the whole power-of-2 mess.
167inline int32_t WhichPowerOf2Abs(int32_t x) {
168 return (x == kMinInt) ? 31 : WhichPowerOf2(Abs(x));
169}
170
171
172// Obtains the unsigned type corresponding to T
173// available in C++11 as std::make_unsigned
174template<typename T>
175struct make_unsigned {
176 typedef T type;
177};
178
179
180// Template specializations necessary to have make_unsigned work
181template<> struct make_unsigned<int32_t> {
182 typedef uint32_t type;
183};
184
185
186template<> struct make_unsigned<int64_t> {
187 typedef uint64_t type;
188};
189
190
Steve Blocka7e24c12009-10-30 11:49:00 +0000191// ----------------------------------------------------------------------------
192// BitField is a help template for encoding and decode bitfield with
193// unsigned content.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000194
195template<class T, int shift, int size, class U>
196class BitFieldBase {
Steve Blocka7e24c12009-10-30 11:49:00 +0000197 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000198 // A type U mask of bit field. To use all bits of a type U of x bits
199 // in a bitfield without compiler warnings we have to compute 2^x
200 // without using a shift count of x in the computation.
201 static const U kOne = static_cast<U>(1U);
202 static const U kMask = ((kOne << shift) << size) - (kOne << shift);
203 static const U kShift = shift;
204 static const U kSize = size;
205 static const U kNext = kShift + kSize;
Ben Murdoch589d6972011-11-30 16:04:58 +0000206
207 // Value for the field with all bits set.
208 static const T kMax = static_cast<T>((1U << size) - 1);
209
Steve Blocka7e24c12009-10-30 11:49:00 +0000210 // Tells whether the provided value fits into the bit field.
211 static bool is_valid(T value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000212 return (static_cast<U>(value) & ~static_cast<U>(kMax)) == 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000213 }
214
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000215 // Returns a type U with the bit field value encoded.
216 static U encode(T value) {
217 DCHECK(is_valid(value));
218 return static_cast<U>(value) << shift;
Steve Blocka7e24c12009-10-30 11:49:00 +0000219 }
220
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000221 // Returns a type U with the bit field value updated.
222 static U update(U previous, T value) {
Ben Murdoch589d6972011-11-30 16:04:58 +0000223 return (previous & ~kMask) | encode(value);
Ben Murdoch257744e2011-11-30 15:57:28 +0000224 }
225
Steve Blocka7e24c12009-10-30 11:49:00 +0000226 // Extracts the bit field from the value.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000227 static T decode(U value) {
Ben Murdoch589d6972011-11-30 16:04:58 +0000228 return static_cast<T>((value & kMask) >> shift);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100229 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000230};
231
232
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400233template <class T, int shift, int size>
234class BitField8 : public BitFieldBase<T, shift, size, uint8_t> {};
235
236
237template <class T, int shift, int size>
238class BitField16 : public BitFieldBase<T, shift, size, uint16_t> {};
239
240
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000241template<class T, int shift, int size>
242class BitField : public BitFieldBase<T, shift, size, uint32_t> { };
243
244
245template<class T, int shift, int size>
246class BitField64 : public BitFieldBase<T, shift, size, uint64_t> { };
247
248
Steve Blocka7e24c12009-10-30 11:49:00 +0000249// ----------------------------------------------------------------------------
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400250// BitSetComputer is a help template for encoding and decoding information for
251// a variable number of items in an array.
252//
253// To encode boolean data in a smi array you would use:
254// typedef BitSetComputer<bool, 1, kSmiValueSize, uint32_t> BoolComputer;
255//
256template <class T, int kBitsPerItem, int kBitsPerWord, class U>
257class BitSetComputer {
258 public:
259 static const int kItemsPerWord = kBitsPerWord / kBitsPerItem;
260 static const int kMask = (1 << kBitsPerItem) - 1;
261
262 // The number of array elements required to embed T information for each item.
263 static int word_count(int items) {
264 if (items == 0) return 0;
265 return (items - 1) / kItemsPerWord + 1;
266 }
267
268 // The array index to look at for item.
269 static int index(int base_index, int item) {
270 return base_index + item / kItemsPerWord;
271 }
272
273 // Extract T data for a given item from data.
274 static T decode(U data, int item) {
275 return static_cast<T>((data >> shift(item)) & kMask);
276 }
277
278 // Return the encoding for a store of value for item in previous.
279 static U encode(U previous, int item, T value) {
280 int shift_value = shift(item);
281 int set_bits = (static_cast<int>(value) << shift_value);
282 return (previous & ~(kMask << shift_value)) | set_bits;
283 }
284
285 static int shift(int item) { return (item % kItemsPerWord) * kBitsPerItem; }
286};
287
288
289// ----------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +0000290// Hash function.
291
Ben Murdochc7cc0282012-03-05 14:35:55 +0000292static const uint32_t kZeroHashSeed = 0;
293
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800294// Thomas Wang, Integer Hash Functions.
295// http://www.concentric.net/~Ttwang/tech/inthash.htm
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100296inline uint32_t ComputeIntegerHash(uint32_t key, uint32_t seed) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800297 uint32_t hash = key;
Ben Murdochc7cc0282012-03-05 14:35:55 +0000298 hash = hash ^ seed;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800299 hash = ~hash + (hash << 15); // hash = (hash << 15) - hash - 1;
300 hash = hash ^ (hash >> 12);
301 hash = hash + (hash << 2);
302 hash = hash ^ (hash >> 4);
303 hash = hash * 2057; // hash = (hash + (hash << 3)) + (hash << 11);
304 hash = hash ^ (hash >> 16);
305 return hash;
306}
Steve Blocka7e24c12009-10-30 11:49:00 +0000307
308
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100309inline uint32_t ComputeLongHash(uint64_t key) {
310 uint64_t hash = key;
311 hash = ~hash + (hash << 18); // hash = (hash << 18) - hash - 1;
312 hash = hash ^ (hash >> 31);
313 hash = hash * 21; // hash = (hash + (hash << 2)) + (hash << 4);
314 hash = hash ^ (hash >> 11);
315 hash = hash + (hash << 6);
316 hash = hash ^ (hash >> 22);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000317 return static_cast<uint32_t>(hash);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100318}
319
320
321inline uint32_t ComputePointerHash(void* ptr) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000322 return ComputeIntegerHash(
Ben Murdochc7cc0282012-03-05 14:35:55 +0000323 static_cast<uint32_t>(reinterpret_cast<intptr_t>(ptr)),
324 v8::internal::kZeroHashSeed);
Ben Murdoch257744e2011-11-30 15:57:28 +0000325}
326
327
Steve Blocka7e24c12009-10-30 11:49:00 +0000328// ----------------------------------------------------------------------------
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000329// Generated memcpy/memmove
330
331// Initializes the codegen support that depends on CPU features. This is
332// called after CPU initialization.
333void init_memcopy_functions();
334
335#if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_X87)
336// Limit below which the extra overhead of the MemCopy function is likely
337// to outweigh the benefits of faster copying.
338const int kMinComplexMemCopy = 64;
339
340// Copy memory area. No restrictions.
341void MemMove(void* dest, const void* src, size_t size);
342typedef void (*MemMoveFunction)(void* dest, const void* src, size_t size);
343
344// Keep the distinction of "move" vs. "copy" for the benefit of other
345// architectures.
346V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
347 MemMove(dest, src, size);
348}
349#elif defined(V8_HOST_ARCH_ARM)
350typedef void (*MemCopyUint8Function)(uint8_t* dest, const uint8_t* src,
351 size_t size);
352extern MemCopyUint8Function memcopy_uint8_function;
353V8_INLINE void MemCopyUint8Wrapper(uint8_t* dest, const uint8_t* src,
354 size_t chars) {
355 memcpy(dest, src, chars);
356}
357// For values < 16, the assembler function is slower than the inlined C code.
358const int kMinComplexMemCopy = 16;
359V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
360 (*memcopy_uint8_function)(reinterpret_cast<uint8_t*>(dest),
361 reinterpret_cast<const uint8_t*>(src), size);
362}
363V8_INLINE void MemMove(void* dest, const void* src, size_t size) {
364 memmove(dest, src, size);
365}
366
367typedef void (*MemCopyUint16Uint8Function)(uint16_t* dest, const uint8_t* src,
368 size_t size);
369extern MemCopyUint16Uint8Function memcopy_uint16_uint8_function;
370void MemCopyUint16Uint8Wrapper(uint16_t* dest, const uint8_t* src,
371 size_t chars);
372// For values < 12, the assembler function is slower than the inlined C code.
373const int kMinComplexConvertMemCopy = 12;
374V8_INLINE void MemCopyUint16Uint8(uint16_t* dest, const uint8_t* src,
375 size_t size) {
376 (*memcopy_uint16_uint8_function)(dest, src, size);
377}
378#elif defined(V8_HOST_ARCH_MIPS)
379typedef void (*MemCopyUint8Function)(uint8_t* dest, const uint8_t* src,
380 size_t size);
381extern MemCopyUint8Function memcopy_uint8_function;
382V8_INLINE void MemCopyUint8Wrapper(uint8_t* dest, const uint8_t* src,
383 size_t chars) {
384 memcpy(dest, src, chars);
385}
386// For values < 16, the assembler function is slower than the inlined C code.
387const int kMinComplexMemCopy = 16;
388V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
389 (*memcopy_uint8_function)(reinterpret_cast<uint8_t*>(dest),
390 reinterpret_cast<const uint8_t*>(src), size);
391}
392V8_INLINE void MemMove(void* dest, const void* src, size_t size) {
393 memmove(dest, src, size);
394}
395#else
396// Copy memory area to disjoint memory area.
397V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
398 memcpy(dest, src, size);
399}
400V8_INLINE void MemMove(void* dest, const void* src, size_t size) {
401 memmove(dest, src, size);
402}
403const int kMinComplexMemCopy = 16 * kPointerSize;
404#endif // V8_TARGET_ARCH_IA32
405
406
407// ----------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +0000408// Miscellaneous
409
410// A static resource holds a static instance that can be reserved in
411// a local scope using an instance of Access. Attempts to re-reserve
412// the instance will cause an error.
413template <typename T>
414class StaticResource {
415 public:
416 StaticResource() : is_reserved_(false) {}
417
418 private:
419 template <typename S> friend class Access;
420 T instance_;
421 bool is_reserved_;
422};
423
424
425// Locally scoped access to a static resource.
426template <typename T>
427class Access {
428 public:
429 explicit Access(StaticResource<T>* resource)
430 : resource_(resource)
431 , instance_(&resource->instance_) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000432 DCHECK(!resource->is_reserved_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000433 resource->is_reserved_ = true;
434 }
435
436 ~Access() {
437 resource_->is_reserved_ = false;
438 resource_ = NULL;
439 instance_ = NULL;
440 }
441
442 T* value() { return instance_; }
443 T* operator -> () { return instance_; }
444
445 private:
446 StaticResource<T>* resource_;
447 T* instance_;
448};
449
450
Ben Murdochb0fe1622011-05-05 13:52:32 +0100451// A pointer that can only be set once and doesn't allow NULL values.
452template<typename T>
453class SetOncePointer {
454 public:
455 SetOncePointer() : pointer_(NULL) { }
456
457 bool is_set() const { return pointer_ != NULL; }
458
459 T* get() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000460 DCHECK(pointer_ != NULL);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100461 return pointer_;
462 }
463
464 void set(T* value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000465 DCHECK(pointer_ == NULL && value != NULL);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100466 pointer_ = value;
467 }
468
469 private:
470 T* pointer_;
471};
472
473
Steve Blocka7e24c12009-10-30 11:49:00 +0000474template <typename T, int kSize>
475class EmbeddedVector : public Vector<T> {
476 public:
477 EmbeddedVector() : Vector<T>(buffer_, kSize) { }
478
Ben Murdochb0fe1622011-05-05 13:52:32 +0100479 explicit EmbeddedVector(T initial_value) : Vector<T>(buffer_, kSize) {
480 for (int i = 0; i < kSize; ++i) {
481 buffer_[i] = initial_value;
482 }
483 }
484
Steve Blocka7e24c12009-10-30 11:49:00 +0000485 // When copying, make underlying Vector to reference our buffer.
486 EmbeddedVector(const EmbeddedVector& rhs)
487 : Vector<T>(rhs) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000488 MemCopy(buffer_, rhs.buffer_, sizeof(T) * kSize);
489 this->set_start(buffer_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000490 }
491
492 EmbeddedVector& operator=(const EmbeddedVector& rhs) {
493 if (this == &rhs) return *this;
494 Vector<T>::operator=(rhs);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000495 MemCopy(buffer_, rhs.buffer_, sizeof(T) * kSize);
Steve Block6ded16b2010-05-10 14:33:55 +0100496 this->set_start(buffer_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000497 return *this;
498 }
499
500 private:
501 T buffer_[kSize];
502};
503
504
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100505/*
506 * A class that collects values into a backing store.
507 * Specialized versions of the class can allow access to the backing store
508 * in different ways.
509 * There is no guarantee that the backing store is contiguous (and, as a
510 * consequence, no guarantees that consecutively added elements are adjacent
511 * in memory). The collector may move elements unless it has guaranteed not
512 * to.
513 */
514template <typename T, int growth_factor = 2, int max_growth = 1 * MB>
515class Collector {
516 public:
517 explicit Collector(int initial_capacity = kMinCapacity)
518 : index_(0), size_(0) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100519 current_chunk_ = Vector<T>::New(initial_capacity);
520 }
521
522 virtual ~Collector() {
523 // Free backing store (in reverse allocation order).
524 current_chunk_.Dispose();
525 for (int i = chunks_.length() - 1; i >= 0; i--) {
526 chunks_.at(i).Dispose();
527 }
528 }
529
530 // Add a single element.
531 inline void Add(T value) {
532 if (index_ >= current_chunk_.length()) {
533 Grow(1);
534 }
535 current_chunk_[index_] = value;
536 index_++;
537 size_++;
538 }
539
540 // Add a block of contiguous elements and return a Vector backed by the
541 // memory area.
542 // A basic Collector will keep this vector valid as long as the Collector
543 // is alive.
544 inline Vector<T> AddBlock(int size, T initial_value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000545 DCHECK(size > 0);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100546 if (size > current_chunk_.length() - index_) {
547 Grow(size);
548 }
549 T* position = current_chunk_.start() + index_;
550 index_ += size;
551 size_ += size;
552 for (int i = 0; i < size; i++) {
553 position[i] = initial_value;
554 }
555 return Vector<T>(position, size);
556 }
557
558
Steve Block9fac8402011-05-12 15:51:54 +0100559 // Add a contiguous block of elements and return a vector backed
560 // by the added block.
561 // A basic Collector will keep this vector valid as long as the Collector
562 // is alive.
563 inline Vector<T> AddBlock(Vector<const T> source) {
564 if (source.length() > current_chunk_.length() - index_) {
565 Grow(source.length());
566 }
567 T* position = current_chunk_.start() + index_;
568 index_ += source.length();
569 size_ += source.length();
570 for (int i = 0; i < source.length(); i++) {
571 position[i] = source[i];
572 }
573 return Vector<T>(position, source.length());
574 }
575
576
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100577 // Write the contents of the collector into the provided vector.
578 void WriteTo(Vector<T> destination) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000579 DCHECK(size_ <= destination.length());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100580 int position = 0;
581 for (int i = 0; i < chunks_.length(); i++) {
582 Vector<T> chunk = chunks_.at(i);
583 for (int j = 0; j < chunk.length(); j++) {
584 destination[position] = chunk[j];
585 position++;
586 }
587 }
588 for (int i = 0; i < index_; i++) {
589 destination[position] = current_chunk_[i];
590 position++;
591 }
592 }
593
594 // Allocate a single contiguous vector, copy all the collected
595 // elements to the vector, and return it.
596 // The caller is responsible for freeing the memory of the returned
597 // vector (e.g., using Vector::Dispose).
598 Vector<T> ToVector() {
599 Vector<T> new_store = Vector<T>::New(size_);
600 WriteTo(new_store);
601 return new_store;
602 }
603
604 // Resets the collector to be empty.
Ben Murdoch257744e2011-11-30 15:57:28 +0000605 virtual void Reset();
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100606
607 // Total number of elements added to collector so far.
608 inline int size() { return size_; }
609
610 protected:
611 static const int kMinCapacity = 16;
612 List<Vector<T> > chunks_;
613 Vector<T> current_chunk_; // Block of memory currently being written into.
614 int index_; // Current index in current chunk.
615 int size_; // Total number of elements in collector.
616
617 // Creates a new current chunk, and stores the old chunk in the chunks_ list.
618 void Grow(int min_capacity) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000619 DCHECK(growth_factor > 1);
Ben Murdoch589d6972011-11-30 16:04:58 +0000620 int new_capacity;
621 int current_length = current_chunk_.length();
622 if (current_length < kMinCapacity) {
623 // The collector started out as empty.
624 new_capacity = min_capacity * growth_factor;
625 if (new_capacity < kMinCapacity) new_capacity = kMinCapacity;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100626 } else {
Ben Murdoch589d6972011-11-30 16:04:58 +0000627 int growth = current_length * (growth_factor - 1);
628 if (growth > max_growth) {
629 growth = max_growth;
630 }
631 new_capacity = current_length + growth;
632 if (new_capacity < min_capacity) {
633 new_capacity = min_capacity + growth;
634 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100635 }
Ben Murdoch589d6972011-11-30 16:04:58 +0000636 NewChunk(new_capacity);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000637 DCHECK(index_ + min_capacity <= current_chunk_.length());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100638 }
639
640 // Before replacing the current chunk, give a subclass the option to move
641 // some of the current data into the new chunk. The function may update
642 // the current index_ value to represent data no longer in the current chunk.
643 // Returns the initial index of the new chunk (after copied data).
Ben Murdoch589d6972011-11-30 16:04:58 +0000644 virtual void NewChunk(int new_capacity) {
645 Vector<T> new_chunk = Vector<T>::New(new_capacity);
646 if (index_ > 0) {
647 chunks_.Add(current_chunk_.SubVector(0, index_));
648 } else {
649 current_chunk_.Dispose();
650 }
651 current_chunk_ = new_chunk;
652 index_ = 0;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100653 }
654};
655
656
657/*
658 * A collector that allows sequences of values to be guaranteed to
659 * stay consecutive.
660 * If the backing store grows while a sequence is active, the current
661 * sequence might be moved, but after the sequence is ended, it will
662 * not move again.
663 * NOTICE: Blocks allocated using Collector::AddBlock(int) can move
664 * as well, if inside an active sequence where another element is added.
665 */
666template <typename T, int growth_factor = 2, int max_growth = 1 * MB>
667class SequenceCollector : public Collector<T, growth_factor, max_growth> {
668 public:
669 explicit SequenceCollector(int initial_capacity)
670 : Collector<T, growth_factor, max_growth>(initial_capacity),
671 sequence_start_(kNoSequence) { }
672
673 virtual ~SequenceCollector() {}
674
675 void StartSequence() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000676 DCHECK(sequence_start_ == kNoSequence);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100677 sequence_start_ = this->index_;
678 }
679
680 Vector<T> EndSequence() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000681 DCHECK(sequence_start_ != kNoSequence);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100682 int sequence_start = sequence_start_;
683 sequence_start_ = kNoSequence;
684 if (sequence_start == this->index_) return Vector<T>();
685 return this->current_chunk_.SubVector(sequence_start, this->index_);
686 }
687
688 // Drops the currently added sequence, and all collected elements in it.
689 void DropSequence() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000690 DCHECK(sequence_start_ != kNoSequence);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100691 int sequence_length = this->index_ - sequence_start_;
692 this->index_ = sequence_start_;
693 this->size_ -= sequence_length;
694 sequence_start_ = kNoSequence;
695 }
696
697 virtual void Reset() {
698 sequence_start_ = kNoSequence;
699 this->Collector<T, growth_factor, max_growth>::Reset();
700 }
701
702 private:
703 static const int kNoSequence = -1;
704 int sequence_start_;
705
706 // Move the currently active sequence to the new chunk.
Ben Murdoch589d6972011-11-30 16:04:58 +0000707 virtual void NewChunk(int new_capacity) {
708 if (sequence_start_ == kNoSequence) {
709 // Fall back on default behavior if no sequence has been started.
710 this->Collector<T, growth_factor, max_growth>::NewChunk(new_capacity);
711 return;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100712 }
Ben Murdoch589d6972011-11-30 16:04:58 +0000713 int sequence_length = this->index_ - sequence_start_;
714 Vector<T> new_chunk = Vector<T>::New(sequence_length + new_capacity);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000715 DCHECK(sequence_length < new_chunk.length());
Ben Murdoch589d6972011-11-30 16:04:58 +0000716 for (int i = 0; i < sequence_length; i++) {
717 new_chunk[i] = this->current_chunk_[sequence_start_ + i];
718 }
719 if (sequence_start_ > 0) {
720 this->chunks_.Add(this->current_chunk_.SubVector(0, sequence_start_));
721 } else {
722 this->current_chunk_.Dispose();
723 }
724 this->current_chunk_ = new_chunk;
725 this->index_ = sequence_length;
726 sequence_start_ = 0;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100727 }
728};
729
730
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000731// Compare 8bit/16bit chars to 8bit/16bit chars.
Steve Block6ded16b2010-05-10 14:33:55 +0100732template <typename lchar, typename rchar>
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000733inline int CompareCharsUnsigned(const lchar* lhs,
734 const rchar* rhs,
735 int chars) {
Steve Block6ded16b2010-05-10 14:33:55 +0100736 const lchar* limit = lhs + chars;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000737 if (sizeof(*lhs) == sizeof(char) && sizeof(*rhs) == sizeof(char)) {
738 // memcmp compares byte-by-byte, yielding wrong results for two-byte
739 // strings on little-endian systems.
740 return memcmp(lhs, rhs, chars);
Steve Block6ded16b2010-05-10 14:33:55 +0100741 }
Steve Block6ded16b2010-05-10 14:33:55 +0100742 while (lhs < limit) {
743 int r = static_cast<int>(*lhs) - static_cast<int>(*rhs);
744 if (r != 0) return r;
745 ++lhs;
746 ++rhs;
747 }
748 return 0;
749}
750
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000751template<typename lchar, typename rchar>
752inline int CompareChars(const lchar* lhs, const rchar* rhs, int chars) {
753 DCHECK(sizeof(lchar) <= 2);
754 DCHECK(sizeof(rchar) <= 2);
755 if (sizeof(lchar) == 1) {
756 if (sizeof(rchar) == 1) {
757 return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs),
758 reinterpret_cast<const uint8_t*>(rhs),
759 chars);
760 } else {
761 return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs),
762 reinterpret_cast<const uint16_t*>(rhs),
763 chars);
764 }
765 } else {
766 if (sizeof(rchar) == 1) {
767 return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(lhs),
768 reinterpret_cast<const uint8_t*>(rhs),
769 chars);
770 } else {
771 return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(lhs),
772 reinterpret_cast<const uint16_t*>(rhs),
773 chars);
774 }
775 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800776}
Steve Blockd0582a62009-12-15 09:54:21 +0000777
Steve Block6ded16b2010-05-10 14:33:55 +0100778
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000779// Calculate 10^exponent.
780inline int TenToThe(int exponent) {
781 DCHECK(exponent <= 9);
782 DCHECK(exponent >= 1);
783 int answer = 10;
784 for (int i = 1; i < exponent; i++) answer *= 10;
785 return answer;
Iain Merrick75681382010-08-19 15:07:18 +0100786}
Steve Blocka7e24c12009-10-30 11:49:00 +0000787
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000788
789template<typename ElementType, int NumElements>
790class EmbeddedContainer {
791 public:
792 EmbeddedContainer() : elems_() { }
793
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000794 int length() const { return NumElements; }
795 const ElementType& operator[](int i) const {
796 DCHECK(i < length());
797 return elems_[i];
798 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000799 ElementType& operator[](int i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000800 DCHECK(i < length());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000801 return elems_[i];
802 }
803
804 private:
805 ElementType elems_[NumElements];
806};
807
808
809template<typename ElementType>
810class EmbeddedContainer<ElementType, 0> {
811 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000812 int length() const { return 0; }
813 const ElementType& operator[](int i) const {
814 UNREACHABLE();
815 static ElementType t = 0;
816 return t;
817 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000818 ElementType& operator[](int i) {
819 UNREACHABLE();
820 static ElementType t = 0;
821 return t;
822 }
823};
824
825
826// Helper class for building result strings in a character buffer. The
827// purpose of the class is to use safe operations that checks the
828// buffer bounds on all operations in debug mode.
829// This simple base class does not allow formatted output.
830class SimpleStringBuilder {
831 public:
832 // Create a string builder with a buffer of the given size. The
833 // buffer is allocated through NewArray<char> and must be
834 // deallocated by the caller of Finalize().
835 explicit SimpleStringBuilder(int size);
836
837 SimpleStringBuilder(char* buffer, int size)
838 : buffer_(buffer, size), position_(0) { }
839
840 ~SimpleStringBuilder() { if (!is_finalized()) Finalize(); }
841
842 int size() const { return buffer_.length(); }
843
844 // Get the current position in the builder.
845 int position() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000846 DCHECK(!is_finalized());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000847 return position_;
848 }
849
850 // Reset the position.
851 void Reset() { position_ = 0; }
852
853 // Add a single character to the builder. It is not allowed to add
854 // 0-characters; use the Finalize() method to terminate the string
855 // instead.
856 void AddCharacter(char c) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000857 DCHECK(c != '\0');
858 DCHECK(!is_finalized() && position_ < buffer_.length());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000859 buffer_[position_++] = c;
860 }
861
862 // Add an entire string to the builder. Uses strlen() internally to
863 // compute the length of the input string.
864 void AddString(const char* s);
865
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400866 // Add the first 'n' characters of the given 0-terminated string 's' to the
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000867 // builder. The input string must have enough characters.
868 void AddSubstring(const char* s, int n);
869
870 // Add character padding to the builder. If count is non-positive,
871 // nothing is added to the builder.
872 void AddPadding(char c, int count);
873
874 // Add the decimal representation of the value.
875 void AddDecimalInteger(int value);
876
877 // Finalize the string by 0-terminating it and returning the buffer.
878 char* Finalize();
879
880 protected:
881 Vector<char> buffer_;
882 int position_;
883
884 bool is_finalized() const { return position_ < 0; }
Ben Murdoch589d6972011-11-30 16:04:58 +0000885
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000886 private:
887 DISALLOW_IMPLICIT_CONSTRUCTORS(SimpleStringBuilder);
888};
889
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000890
891// A poor man's version of STL's bitset: A bit set of enums E (without explicit
892// values), fitting into an integral type T.
893template <class E, class T = int>
894class EnumSet {
895 public:
896 explicit EnumSet(T bits = 0) : bits_(bits) {}
897 bool IsEmpty() const { return bits_ == 0; }
898 bool Contains(E element) const { return (bits_ & Mask(element)) != 0; }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100899 bool ContainsAnyOf(const EnumSet& set) const {
900 return (bits_ & set.bits_) != 0;
901 }
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000902 void Add(E element) { bits_ |= Mask(element); }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100903 void Add(const EnumSet& set) { bits_ |= set.bits_; }
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000904 void Remove(E element) { bits_ &= ~Mask(element); }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100905 void Remove(const EnumSet& set) { bits_ &= ~set.bits_; }
906 void RemoveAll() { bits_ = 0; }
907 void Intersect(const EnumSet& set) { bits_ &= set.bits_; }
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000908 T ToIntegral() const { return bits_; }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100909 bool operator==(const EnumSet& set) { return bits_ == set.bits_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000910 bool operator!=(const EnumSet& set) { return bits_ != set.bits_; }
911 EnumSet<E, T> operator|(const EnumSet& set) const {
912 return EnumSet<E, T>(bits_ | set.bits_);
913 }
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000914
915 private:
916 T Mask(E element) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000917 // The strange typing in DCHECK is necessary to avoid stupid warnings, see:
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000918 // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43680
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000919 DCHECK(static_cast<int>(element) < static_cast<int>(sizeof(T) * CHAR_BIT));
920 return static_cast<T>(1) << element;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000921 }
922
923 T bits_;
924};
925
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000926// Bit field extraction.
927inline uint32_t unsigned_bitextract_32(int msb, int lsb, uint32_t x) {
928 return (x >> lsb) & ((1 << (1 + msb - lsb)) - 1);
929}
930
931inline uint64_t unsigned_bitextract_64(int msb, int lsb, uint64_t x) {
932 return (x >> lsb) & ((static_cast<uint64_t>(1) << (1 + msb - lsb)) - 1);
933}
934
935inline int32_t signed_bitextract_32(int msb, int lsb, int32_t x) {
936 return (x << (31 - msb)) >> (lsb + 31 - msb);
937}
938
939inline int signed_bitextract_64(int msb, int lsb, int x) {
940 // TODO(jbramley): This is broken for big bitfields.
941 return (x << (63 - msb)) >> (lsb + 63 - msb);
942}
943
944// Check number width.
945inline bool is_intn(int64_t x, unsigned n) {
946 DCHECK((0 < n) && (n < 64));
947 int64_t limit = static_cast<int64_t>(1) << (n - 1);
948 return (-limit <= x) && (x < limit);
949}
950
951inline bool is_uintn(int64_t x, unsigned n) {
952 DCHECK((0 < n) && (n < (sizeof(x) * kBitsPerByte)));
953 return !(x >> n);
954}
955
956template <class T>
957inline T truncate_to_intn(T x, unsigned n) {
958 DCHECK((0 < n) && (n < (sizeof(x) * kBitsPerByte)));
959 return (x & ((static_cast<T>(1) << n) - 1));
960}
961
962#define INT_1_TO_63_LIST(V) \
963V(1) V(2) V(3) V(4) V(5) V(6) V(7) V(8) \
964V(9) V(10) V(11) V(12) V(13) V(14) V(15) V(16) \
965V(17) V(18) V(19) V(20) V(21) V(22) V(23) V(24) \
966V(25) V(26) V(27) V(28) V(29) V(30) V(31) V(32) \
967V(33) V(34) V(35) V(36) V(37) V(38) V(39) V(40) \
968V(41) V(42) V(43) V(44) V(45) V(46) V(47) V(48) \
969V(49) V(50) V(51) V(52) V(53) V(54) V(55) V(56) \
970V(57) V(58) V(59) V(60) V(61) V(62) V(63)
971
972#define DECLARE_IS_INT_N(N) \
973inline bool is_int##N(int64_t x) { return is_intn(x, N); }
974#define DECLARE_IS_UINT_N(N) \
975template <class T> \
976inline bool is_uint##N(T x) { return is_uintn(x, N); }
977#define DECLARE_TRUNCATE_TO_INT_N(N) \
978template <class T> \
979inline T truncate_to_int##N(T x) { return truncate_to_intn(x, N); }
980INT_1_TO_63_LIST(DECLARE_IS_INT_N)
981INT_1_TO_63_LIST(DECLARE_IS_UINT_N)
982INT_1_TO_63_LIST(DECLARE_TRUNCATE_TO_INT_N)
983#undef DECLARE_IS_INT_N
984#undef DECLARE_IS_UINT_N
985#undef DECLARE_TRUNCATE_TO_INT_N
986
987class TypeFeedbackId {
988 public:
989 explicit TypeFeedbackId(int id) : id_(id) { }
990 int ToInt() const { return id_; }
991
992 static TypeFeedbackId None() { return TypeFeedbackId(kNoneId); }
993 bool IsNone() const { return id_ == kNoneId; }
994
995 private:
996 static const int kNoneId = -1;
997
998 int id_;
999};
1000
1001
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001002template <int dummy_parameter>
1003class VectorSlot {
1004 public:
1005 explicit VectorSlot(int id) : id_(id) {}
1006 int ToInt() const { return id_; }
1007
1008 static VectorSlot Invalid() { return VectorSlot(kInvalidSlot); }
1009 bool IsInvalid() const { return id_ == kInvalidSlot; }
1010
1011 VectorSlot next() const {
1012 DCHECK(id_ != kInvalidSlot);
1013 return VectorSlot(id_ + 1);
1014 }
1015
1016 bool operator==(const VectorSlot& other) const { return id_ == other.id_; }
1017
1018 private:
1019 static const int kInvalidSlot = -1;
1020
1021 int id_;
1022};
1023
1024
1025typedef VectorSlot<0> FeedbackVectorSlot;
1026typedef VectorSlot<1> FeedbackVectorICSlot;
1027
1028
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001029class BailoutId {
1030 public:
1031 explicit BailoutId(int id) : id_(id) { }
1032 int ToInt() const { return id_; }
1033
1034 static BailoutId None() { return BailoutId(kNoneId); }
1035 static BailoutId FunctionEntry() { return BailoutId(kFunctionEntryId); }
1036 static BailoutId Declarations() { return BailoutId(kDeclarationsId); }
1037 static BailoutId FirstUsable() { return BailoutId(kFirstUsableId); }
1038 static BailoutId StubEntry() { return BailoutId(kStubEntryId); }
1039
1040 bool IsNone() const { return id_ == kNoneId; }
1041 bool operator==(const BailoutId& other) const { return id_ == other.id_; }
1042 bool operator!=(const BailoutId& other) const { return id_ != other.id_; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001043 friend size_t hash_value(BailoutId);
1044 friend std::ostream& operator<<(std::ostream&, BailoutId);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001045
1046 private:
1047 static const int kNoneId = -1;
1048
1049 // Using 0 could disguise errors.
1050 static const int kFunctionEntryId = 2;
1051
1052 // This AST id identifies the point after the declarations have been visited.
1053 // We need it to capture the environment effects of declarations that emit
1054 // code (function declarations).
1055 static const int kDeclarationsId = 3;
1056
1057 // Every FunctionState starts with this id.
1058 static const int kFirstUsableId = 4;
1059
1060 // Every compiled stub starts with this id.
1061 static const int kStubEntryId = 5;
1062
1063 int id_;
1064};
1065
1066
1067template <class C>
1068class ContainerPointerWrapper {
1069 public:
1070 typedef typename C::iterator iterator;
1071 typedef typename C::reverse_iterator reverse_iterator;
1072 explicit ContainerPointerWrapper(C* container) : container_(container) {}
1073 iterator begin() { return container_->begin(); }
1074 iterator end() { return container_->end(); }
1075 reverse_iterator rbegin() { return container_->rbegin(); }
1076 reverse_iterator rend() { return container_->rend(); }
1077 private:
1078 C* container_;
1079};
1080
1081
1082// ----------------------------------------------------------------------------
1083// I/O support.
1084
1085#if __GNUC__ >= 4
1086// On gcc we can ask the compiler to check the types of %d-style format
1087// specifiers and their associated arguments. TODO(erikcorry) fix this
1088// so it works on MacOSX.
1089#if defined(__MACH__) && defined(__APPLE__)
1090#define PRINTF_CHECKING
1091#define FPRINTF_CHECKING
1092#define PRINTF_METHOD_CHECKING
1093#define FPRINTF_METHOD_CHECKING
1094#else // MacOsX.
1095#define PRINTF_CHECKING __attribute__ ((format (printf, 1, 2)))
1096#define FPRINTF_CHECKING __attribute__ ((format (printf, 2, 3)))
1097#define PRINTF_METHOD_CHECKING __attribute__ ((format (printf, 2, 3)))
1098#define FPRINTF_METHOD_CHECKING __attribute__ ((format (printf, 3, 4)))
1099#endif
1100#else
1101#define PRINTF_CHECKING
1102#define FPRINTF_CHECKING
1103#define PRINTF_METHOD_CHECKING
1104#define FPRINTF_METHOD_CHECKING
1105#endif
1106
1107// Our version of printf().
1108void PRINTF_CHECKING PrintF(const char* format, ...);
1109void FPRINTF_CHECKING PrintF(FILE* out, const char* format, ...);
1110
1111// Prepends the current process ID to the output.
1112void PRINTF_CHECKING PrintPID(const char* format, ...);
1113
1114// Safe formatting print. Ensures that str is always null-terminated.
1115// Returns the number of chars written, or -1 if output was truncated.
1116int FPRINTF_CHECKING SNPrintF(Vector<char> str, const char* format, ...);
1117int VSNPrintF(Vector<char> str, const char* format, va_list args);
1118
1119void StrNCpy(Vector<char> dest, const char* src, size_t n);
1120
1121// Our version of fflush.
1122void Flush(FILE* out);
1123
1124inline void Flush() {
1125 Flush(stdout);
1126}
1127
1128
1129// Read a line of characters after printing the prompt to stdout. The resulting
1130// char* needs to be disposed off with DeleteArray by the caller.
1131char* ReadLine(const char* prompt);
1132
1133
1134// Read and return the raw bytes in a file. the size of the buffer is returned
1135// in size.
1136// The returned buffer must be freed by the caller.
1137byte* ReadBytes(const char* filename, int* size, bool verbose = true);
1138
1139
1140// Append size chars from str to the file given by filename.
1141// The file is overwritten. Returns the number of chars written.
1142int AppendChars(const char* filename,
1143 const char* str,
1144 int size,
1145 bool verbose = true);
1146
1147
1148// Write size chars from str to the file given by filename.
1149// The file is overwritten. Returns the number of chars written.
1150int WriteChars(const char* filename,
1151 const char* str,
1152 int size,
1153 bool verbose = true);
1154
1155
1156// Write size bytes to the file given by filename.
1157// The file is overwritten. Returns the number of bytes written.
1158int WriteBytes(const char* filename,
1159 const byte* bytes,
1160 int size,
1161 bool verbose = true);
1162
1163
1164// Write the C code
1165// const char* <varname> = "<str>";
1166// const int <varname>_len = <len>;
1167// to the file given by filename. Only the first len chars are written.
1168int WriteAsCFile(const char* filename, const char* varname,
1169 const char* str, int size, bool verbose = true);
1170
1171
1172// ----------------------------------------------------------------------------
1173// Data structures
1174
1175template <typename T>
1176inline Vector< Handle<Object> > HandleVector(v8::internal::Handle<T>* elms,
1177 int length) {
1178 return Vector< Handle<Object> >(
1179 reinterpret_cast<v8::internal::Handle<Object>*>(elms), length);
1180}
1181
1182
1183// ----------------------------------------------------------------------------
1184// Memory
1185
1186// Copies words from |src| to |dst|. The data spans must not overlap.
1187template <typename T>
1188inline void CopyWords(T* dst, const T* src, size_t num_words) {
1189 STATIC_ASSERT(sizeof(T) == kPointerSize);
1190 // TODO(mvstanton): disabled because mac builds are bogus failing on this
1191 // assert. They are doing a signed comparison. Investigate in
1192 // the morning.
1193 // DCHECK(Min(dst, const_cast<T*>(src)) + num_words <=
1194 // Max(dst, const_cast<T*>(src)));
1195 DCHECK(num_words > 0);
1196
1197 // Use block copying MemCopy if the segment we're copying is
1198 // enough to justify the extra call/setup overhead.
1199 static const size_t kBlockCopyLimit = 16;
1200
1201 if (num_words < kBlockCopyLimit) {
1202 do {
1203 num_words--;
1204 *dst++ = *src++;
1205 } while (num_words > 0);
1206 } else {
1207 MemCopy(dst, src, num_words * kPointerSize);
1208 }
1209}
1210
1211
1212// Copies words from |src| to |dst|. No restrictions.
1213template <typename T>
1214inline void MoveWords(T* dst, const T* src, size_t num_words) {
1215 STATIC_ASSERT(sizeof(T) == kPointerSize);
1216 DCHECK(num_words > 0);
1217
1218 // Use block copying MemCopy if the segment we're copying is
1219 // enough to justify the extra call/setup overhead.
1220 static const size_t kBlockCopyLimit = 16;
1221
1222 if (num_words < kBlockCopyLimit &&
1223 ((dst < src) || (dst >= (src + num_words * kPointerSize)))) {
1224 T* end = dst + num_words;
1225 do {
1226 num_words--;
1227 *dst++ = *src++;
1228 } while (num_words > 0);
1229 } else {
1230 MemMove(dst, src, num_words * kPointerSize);
1231 }
1232}
1233
1234
1235// Copies data from |src| to |dst|. The data spans must not overlap.
1236template <typename T>
1237inline void CopyBytes(T* dst, const T* src, size_t num_bytes) {
1238 STATIC_ASSERT(sizeof(T) == 1);
1239 DCHECK(Min(dst, const_cast<T*>(src)) + num_bytes <=
1240 Max(dst, const_cast<T*>(src)));
1241 if (num_bytes == 0) return;
1242
1243 // Use block copying MemCopy if the segment we're copying is
1244 // enough to justify the extra call/setup overhead.
1245 static const int kBlockCopyLimit = kMinComplexMemCopy;
1246
1247 if (num_bytes < static_cast<size_t>(kBlockCopyLimit)) {
1248 do {
1249 num_bytes--;
1250 *dst++ = *src++;
1251 } while (num_bytes > 0);
1252 } else {
1253 MemCopy(dst, src, num_bytes);
1254 }
1255}
1256
1257
1258template <typename T, typename U>
1259inline void MemsetPointer(T** dest, U* value, int counter) {
1260#ifdef DEBUG
1261 T* a = NULL;
1262 U* b = NULL;
1263 a = b; // Fake assignment to check assignability.
1264 USE(a);
1265#endif // DEBUG
1266#if V8_HOST_ARCH_IA32
1267#define STOS "stosl"
1268#elif V8_HOST_ARCH_X64
1269#if V8_HOST_ARCH_32_BIT
1270#define STOS "addr32 stosl"
1271#else
1272#define STOS "stosq"
1273#endif
1274#endif
1275#if defined(__native_client__)
1276 // This STOS sequence does not validate for x86_64 Native Client.
1277 // Here we #undef STOS to force use of the slower C version.
1278 // TODO(bradchen): Profile V8 and implement a faster REP STOS
1279 // here if the profile indicates it matters.
1280#undef STOS
1281#endif
1282
1283#if defined(MEMORY_SANITIZER)
1284 // MemorySanitizer does not understand inline assembly.
1285#undef STOS
1286#endif
1287
1288#if defined(__GNUC__) && defined(STOS)
1289 asm volatile(
1290 "cld;"
1291 "rep ; " STOS
1292 : "+&c" (counter), "+&D" (dest)
1293 : "a" (value)
1294 : "memory", "cc");
1295#else
1296 for (int i = 0; i < counter; i++) {
1297 dest[i] = value;
1298 }
1299#endif
1300
1301#undef STOS
1302}
1303
1304
1305// Simple support to read a file into a 0-terminated C-string.
1306// The returned buffer must be freed by the caller.
1307// On return, *exits tells whether the file existed.
1308Vector<const char> ReadFile(const char* filename,
1309 bool* exists,
1310 bool verbose = true);
1311Vector<const char> ReadFile(FILE* file,
1312 bool* exists,
1313 bool verbose = true);
1314
1315
1316template <typename sourcechar, typename sinkchar>
1317INLINE(static void CopyCharsUnsigned(sinkchar* dest,
1318 const sourcechar* src,
1319 int chars));
1320#if defined(V8_HOST_ARCH_ARM)
1321INLINE(void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, int chars));
1322INLINE(void CopyCharsUnsigned(uint16_t* dest, const uint8_t* src, int chars));
1323INLINE(void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, int chars));
1324#elif defined(V8_HOST_ARCH_MIPS)
1325INLINE(void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, int chars));
1326INLINE(void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, int chars));
1327#endif
1328
1329// Copy from 8bit/16bit chars to 8bit/16bit chars.
1330template <typename sourcechar, typename sinkchar>
1331INLINE(void CopyChars(sinkchar* dest, const sourcechar* src, int chars));
1332
1333template<typename sourcechar, typename sinkchar>
1334void CopyChars(sinkchar* dest, const sourcechar* src, int chars) {
1335 DCHECK(sizeof(sourcechar) <= 2);
1336 DCHECK(sizeof(sinkchar) <= 2);
1337 if (sizeof(sinkchar) == 1) {
1338 if (sizeof(sourcechar) == 1) {
1339 CopyCharsUnsigned(reinterpret_cast<uint8_t*>(dest),
1340 reinterpret_cast<const uint8_t*>(src),
1341 chars);
1342 } else {
1343 CopyCharsUnsigned(reinterpret_cast<uint8_t*>(dest),
1344 reinterpret_cast<const uint16_t*>(src),
1345 chars);
1346 }
1347 } else {
1348 if (sizeof(sourcechar) == 1) {
1349 CopyCharsUnsigned(reinterpret_cast<uint16_t*>(dest),
1350 reinterpret_cast<const uint8_t*>(src),
1351 chars);
1352 } else {
1353 CopyCharsUnsigned(reinterpret_cast<uint16_t*>(dest),
1354 reinterpret_cast<const uint16_t*>(src),
1355 chars);
1356 }
1357 }
1358}
1359
1360template <typename sourcechar, typename sinkchar>
1361void CopyCharsUnsigned(sinkchar* dest, const sourcechar* src, int chars) {
1362 sinkchar* limit = dest + chars;
1363 if ((sizeof(*dest) == sizeof(*src)) &&
1364 (chars >= static_cast<int>(kMinComplexMemCopy / sizeof(*dest)))) {
1365 MemCopy(dest, src, chars * sizeof(*dest));
1366 } else {
1367 while (dest < limit) *dest++ = static_cast<sinkchar>(*src++);
1368 }
1369}
1370
1371
1372#if defined(V8_HOST_ARCH_ARM)
1373void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, int chars) {
1374 switch (static_cast<unsigned>(chars)) {
1375 case 0:
1376 break;
1377 case 1:
1378 *dest = *src;
1379 break;
1380 case 2:
1381 memcpy(dest, src, 2);
1382 break;
1383 case 3:
1384 memcpy(dest, src, 3);
1385 break;
1386 case 4:
1387 memcpy(dest, src, 4);
1388 break;
1389 case 5:
1390 memcpy(dest, src, 5);
1391 break;
1392 case 6:
1393 memcpy(dest, src, 6);
1394 break;
1395 case 7:
1396 memcpy(dest, src, 7);
1397 break;
1398 case 8:
1399 memcpy(dest, src, 8);
1400 break;
1401 case 9:
1402 memcpy(dest, src, 9);
1403 break;
1404 case 10:
1405 memcpy(dest, src, 10);
1406 break;
1407 case 11:
1408 memcpy(dest, src, 11);
1409 break;
1410 case 12:
1411 memcpy(dest, src, 12);
1412 break;
1413 case 13:
1414 memcpy(dest, src, 13);
1415 break;
1416 case 14:
1417 memcpy(dest, src, 14);
1418 break;
1419 case 15:
1420 memcpy(dest, src, 15);
1421 break;
1422 default:
1423 MemCopy(dest, src, chars);
1424 break;
1425 }
1426}
1427
1428
1429void CopyCharsUnsigned(uint16_t* dest, const uint8_t* src, int chars) {
1430 if (chars >= kMinComplexConvertMemCopy) {
1431 MemCopyUint16Uint8(dest, src, chars);
1432 } else {
1433 MemCopyUint16Uint8Wrapper(dest, src, chars);
1434 }
1435}
1436
1437
1438void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, int chars) {
1439 switch (static_cast<unsigned>(chars)) {
1440 case 0:
1441 break;
1442 case 1:
1443 *dest = *src;
1444 break;
1445 case 2:
1446 memcpy(dest, src, 4);
1447 break;
1448 case 3:
1449 memcpy(dest, src, 6);
1450 break;
1451 case 4:
1452 memcpy(dest, src, 8);
1453 break;
1454 case 5:
1455 memcpy(dest, src, 10);
1456 break;
1457 case 6:
1458 memcpy(dest, src, 12);
1459 break;
1460 case 7:
1461 memcpy(dest, src, 14);
1462 break;
1463 default:
1464 MemCopy(dest, src, chars * sizeof(*dest));
1465 break;
1466 }
1467}
1468
1469
1470#elif defined(V8_HOST_ARCH_MIPS)
1471void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, int chars) {
1472 if (chars < kMinComplexMemCopy) {
1473 memcpy(dest, src, chars);
1474 } else {
1475 MemCopy(dest, src, chars);
1476 }
1477}
1478
1479void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, int chars) {
1480 if (chars < kMinComplexMemCopy) {
1481 memcpy(dest, src, chars * sizeof(*dest));
1482 } else {
1483 MemCopy(dest, src, chars * sizeof(*dest));
1484 }
1485}
1486#endif
1487
1488
1489class StringBuilder : public SimpleStringBuilder {
1490 public:
1491 explicit StringBuilder(int size) : SimpleStringBuilder(size) { }
1492 StringBuilder(char* buffer, int size) : SimpleStringBuilder(buffer, size) { }
1493
1494 // Add formatted contents to the builder just like printf().
1495 void AddFormatted(const char* format, ...);
1496
1497 // Add formatted contents like printf based on a va_list.
1498 void AddFormattedList(const char* format, va_list list);
1499 private:
1500 DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
1501};
1502
1503
1504bool DoubleToBoolean(double d);
1505
1506template <typename Stream>
1507bool StringToArrayIndex(Stream* stream, uint32_t* index) {
1508 uint16_t ch = stream->GetNext();
1509
1510 // If the string begins with a '0' character, it must only consist
1511 // of it to be a legal array index.
1512 if (ch == '0') {
1513 *index = 0;
1514 return !stream->HasMore();
1515 }
1516
1517 // Convert string to uint32 array index; character by character.
1518 int d = ch - '0';
1519 if (d < 0 || d > 9) return false;
1520 uint32_t result = d;
1521 while (stream->HasMore()) {
1522 d = stream->GetNext() - '0';
1523 if (d < 0 || d > 9) return false;
1524 // Check that the new result is below the 32 bit limit.
1525 if (result > 429496729U - ((d > 5) ? 1 : 0)) return false;
1526 result = (result * 10) + d;
1527 }
1528
1529 *index = result;
1530 return true;
1531}
1532
1533
1534// Returns current value of top of the stack. Works correctly with ASAN.
1535DISABLE_ASAN
1536inline uintptr_t GetCurrentStackPosition() {
1537 // Takes the address of the limit variable in order to find out where
1538 // the top of stack is right now.
1539 uintptr_t limit = reinterpret_cast<uintptr_t>(&limit);
1540 return limit;
1541}
1542
1543} // namespace internal
1544} // namespace v8
Steve Block6ded16b2010-05-10 14:33:55 +01001545
Steve Blocka7e24c12009-10-30 11:49:00 +00001546#endif // V8_UTILS_H_