blob: 2991815e576310cdf112297087b6526d24c96459 [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;
64 return 0;
65}
66
67
Ben Murdochb8a8cc12014-11-26 15:28:44 +000068inline int MostSignificantBit(uint32_t x) {
69 static const int msb4[] = {0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4};
70 int nibble = 0;
71 if (x & 0xffff0000) {
72 nibble += 16;
73 x >>= 16;
74 }
75 if (x & 0xff00) {
76 nibble += 8;
77 x >>= 8;
78 }
79 if (x & 0xf0) {
80 nibble += 4;
81 x >>= 4;
82 }
83 return nibble + msb4[x];
84}
85
86
Steve Blocka7e24c12009-10-30 11:49:00 +000087// The C++ standard leaves the semantics of '>>' undefined for
88// negative signed operands. Most implementations do the right thing,
89// though.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010090inline int ArithmeticShiftRight(int x, int s) {
Steve Blocka7e24c12009-10-30 11:49:00 +000091 return x >> s;
92}
93
94
Steve Blocka7e24c12009-10-30 11:49:00 +000095template <typename T>
Ben Murdoch3ef787d2012-04-12 10:51:47 +010096int Compare(const T& a, const T& b) {
Steve Blocka7e24c12009-10-30 11:49:00 +000097 if (a == b)
98 return 0;
99 else if (a < b)
100 return -1;
101 else
102 return 1;
103}
104
105
106template <typename T>
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100107int PointerValueCompare(const T* a, const T* b) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000108 return Compare<T>(*a, *b);
109}
110
111
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100112// Compare function to compare the object pointer value of two
113// handlified objects. The handles are passed as pointers to the
114// handles.
115template<typename T> class Handle; // Forward declaration.
116template <typename T>
117int HandleObjectPointerCompare(const Handle<T>* a, const Handle<T>* b) {
118 return Compare<T*>(*(*a), *(*b));
119}
120
121
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100122template <typename T, typename U>
123inline bool IsAligned(T value, U alignment) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000124 return (value & (alignment - 1)) == 0;
125}
126
127
128// Returns true if (addr + offset) is aligned.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100129inline bool IsAddressAligned(Address addr,
130 intptr_t alignment,
131 int offset = 0) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000132 intptr_t offs = OffsetFrom(addr + offset);
133 return IsAligned(offs, alignment);
134}
135
136
137// Returns the maximum of the two parameters.
138template <typename T>
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100139T Max(T a, T b) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000140 return a < b ? b : a;
141}
142
143
144// Returns the minimum of the two parameters.
145template <typename T>
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100146T Min(T a, T b) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000147 return a < b ? a : b;
148}
149
150
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000151// Returns the absolute value of its argument.
152template <typename T>
153T Abs(T a) {
154 return a < 0 ? -a : a;
Steve Blockd0582a62009-12-15 09:54:21 +0000155}
156
157
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000158// Floor(-0.0) == 0.0
159inline double Floor(double x) {
160#ifdef _MSC_VER
161 if (x == 0) return x; // Fix for issue 3477.
162#endif
163 return std::floor(x);
164}
165
166
167// TODO(svenpanne) Clean up the whole power-of-2 mess.
168inline int32_t WhichPowerOf2Abs(int32_t x) {
169 return (x == kMinInt) ? 31 : WhichPowerOf2(Abs(x));
170}
171
172
173// Obtains the unsigned type corresponding to T
174// available in C++11 as std::make_unsigned
175template<typename T>
176struct make_unsigned {
177 typedef T type;
178};
179
180
181// Template specializations necessary to have make_unsigned work
182template<> struct make_unsigned<int32_t> {
183 typedef uint32_t type;
184};
185
186
187template<> struct make_unsigned<int64_t> {
188 typedef uint64_t type;
189};
190
191
Steve Blocka7e24c12009-10-30 11:49:00 +0000192// ----------------------------------------------------------------------------
193// BitField is a help template for encoding and decode bitfield with
194// unsigned content.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000195
196template<class T, int shift, int size, class U>
197class BitFieldBase {
Steve Blocka7e24c12009-10-30 11:49:00 +0000198 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000199 // A type U mask of bit field. To use all bits of a type U of x bits
200 // in a bitfield without compiler warnings we have to compute 2^x
201 // without using a shift count of x in the computation.
202 static const U kOne = static_cast<U>(1U);
203 static const U kMask = ((kOne << shift) << size) - (kOne << shift);
204 static const U kShift = shift;
205 static const U kSize = size;
206 static const U kNext = kShift + kSize;
Ben Murdoch589d6972011-11-30 16:04:58 +0000207
208 // Value for the field with all bits set.
209 static const T kMax = static_cast<T>((1U << size) - 1);
210
Steve Blocka7e24c12009-10-30 11:49:00 +0000211 // Tells whether the provided value fits into the bit field.
212 static bool is_valid(T value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000213 return (static_cast<U>(value) & ~static_cast<U>(kMax)) == 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000214 }
215
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000216 // Returns a type U with the bit field value encoded.
217 static U encode(T value) {
218 DCHECK(is_valid(value));
219 return static_cast<U>(value) << shift;
Steve Blocka7e24c12009-10-30 11:49:00 +0000220 }
221
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000222 // Returns a type U with the bit field value updated.
223 static U update(U previous, T value) {
Ben Murdoch589d6972011-11-30 16:04:58 +0000224 return (previous & ~kMask) | encode(value);
Ben Murdoch257744e2011-11-30 15:57:28 +0000225 }
226
Steve Blocka7e24c12009-10-30 11:49:00 +0000227 // Extracts the bit field from the value.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000228 static T decode(U value) {
Ben Murdoch589d6972011-11-30 16:04:58 +0000229 return static_cast<T>((value & kMask) >> shift);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100230 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000231};
232
233
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000234template<class T, int shift, int size>
235class BitField : public BitFieldBase<T, shift, size, uint32_t> { };
236
237
238template<class T, int shift, int size>
239class BitField64 : public BitFieldBase<T, shift, size, uint64_t> { };
240
241
Steve Blocka7e24c12009-10-30 11:49:00 +0000242// ----------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +0000243// Hash function.
244
Ben Murdochc7cc0282012-03-05 14:35:55 +0000245static const uint32_t kZeroHashSeed = 0;
246
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800247// Thomas Wang, Integer Hash Functions.
248// http://www.concentric.net/~Ttwang/tech/inthash.htm
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100249inline uint32_t ComputeIntegerHash(uint32_t key, uint32_t seed) {
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800250 uint32_t hash = key;
Ben Murdochc7cc0282012-03-05 14:35:55 +0000251 hash = hash ^ seed;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800252 hash = ~hash + (hash << 15); // hash = (hash << 15) - hash - 1;
253 hash = hash ^ (hash >> 12);
254 hash = hash + (hash << 2);
255 hash = hash ^ (hash >> 4);
256 hash = hash * 2057; // hash = (hash + (hash << 3)) + (hash << 11);
257 hash = hash ^ (hash >> 16);
258 return hash;
259}
Steve Blocka7e24c12009-10-30 11:49:00 +0000260
261
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100262inline uint32_t ComputeLongHash(uint64_t key) {
263 uint64_t hash = key;
264 hash = ~hash + (hash << 18); // hash = (hash << 18) - hash - 1;
265 hash = hash ^ (hash >> 31);
266 hash = hash * 21; // hash = (hash + (hash << 2)) + (hash << 4);
267 hash = hash ^ (hash >> 11);
268 hash = hash + (hash << 6);
269 hash = hash ^ (hash >> 22);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000270 return static_cast<uint32_t>(hash);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100271}
272
273
274inline uint32_t ComputePointerHash(void* ptr) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000275 return ComputeIntegerHash(
Ben Murdochc7cc0282012-03-05 14:35:55 +0000276 static_cast<uint32_t>(reinterpret_cast<intptr_t>(ptr)),
277 v8::internal::kZeroHashSeed);
Ben Murdoch257744e2011-11-30 15:57:28 +0000278}
279
280
Steve Blocka7e24c12009-10-30 11:49:00 +0000281// ----------------------------------------------------------------------------
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000282// Generated memcpy/memmove
283
284// Initializes the codegen support that depends on CPU features. This is
285// called after CPU initialization.
286void init_memcopy_functions();
287
288#if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_X87)
289// Limit below which the extra overhead of the MemCopy function is likely
290// to outweigh the benefits of faster copying.
291const int kMinComplexMemCopy = 64;
292
293// Copy memory area. No restrictions.
294void MemMove(void* dest, const void* src, size_t size);
295typedef void (*MemMoveFunction)(void* dest, const void* src, size_t size);
296
297// Keep the distinction of "move" vs. "copy" for the benefit of other
298// architectures.
299V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
300 MemMove(dest, src, size);
301}
302#elif defined(V8_HOST_ARCH_ARM)
303typedef void (*MemCopyUint8Function)(uint8_t* dest, const uint8_t* src,
304 size_t size);
305extern MemCopyUint8Function memcopy_uint8_function;
306V8_INLINE void MemCopyUint8Wrapper(uint8_t* dest, const uint8_t* src,
307 size_t chars) {
308 memcpy(dest, src, chars);
309}
310// For values < 16, the assembler function is slower than the inlined C code.
311const int kMinComplexMemCopy = 16;
312V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
313 (*memcopy_uint8_function)(reinterpret_cast<uint8_t*>(dest),
314 reinterpret_cast<const uint8_t*>(src), size);
315}
316V8_INLINE void MemMove(void* dest, const void* src, size_t size) {
317 memmove(dest, src, size);
318}
319
320typedef void (*MemCopyUint16Uint8Function)(uint16_t* dest, const uint8_t* src,
321 size_t size);
322extern MemCopyUint16Uint8Function memcopy_uint16_uint8_function;
323void MemCopyUint16Uint8Wrapper(uint16_t* dest, const uint8_t* src,
324 size_t chars);
325// For values < 12, the assembler function is slower than the inlined C code.
326const int kMinComplexConvertMemCopy = 12;
327V8_INLINE void MemCopyUint16Uint8(uint16_t* dest, const uint8_t* src,
328 size_t size) {
329 (*memcopy_uint16_uint8_function)(dest, src, size);
330}
331#elif defined(V8_HOST_ARCH_MIPS)
332typedef void (*MemCopyUint8Function)(uint8_t* dest, const uint8_t* src,
333 size_t size);
334extern MemCopyUint8Function memcopy_uint8_function;
335V8_INLINE void MemCopyUint8Wrapper(uint8_t* dest, const uint8_t* src,
336 size_t chars) {
337 memcpy(dest, src, chars);
338}
339// For values < 16, the assembler function is slower than the inlined C code.
340const int kMinComplexMemCopy = 16;
341V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
342 (*memcopy_uint8_function)(reinterpret_cast<uint8_t*>(dest),
343 reinterpret_cast<const uint8_t*>(src), size);
344}
345V8_INLINE void MemMove(void* dest, const void* src, size_t size) {
346 memmove(dest, src, size);
347}
348#else
349// Copy memory area to disjoint memory area.
350V8_INLINE void MemCopy(void* dest, const void* src, size_t size) {
351 memcpy(dest, src, size);
352}
353V8_INLINE void MemMove(void* dest, const void* src, size_t size) {
354 memmove(dest, src, size);
355}
356const int kMinComplexMemCopy = 16 * kPointerSize;
357#endif // V8_TARGET_ARCH_IA32
358
359
360// ----------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +0000361// Miscellaneous
362
363// A static resource holds a static instance that can be reserved in
364// a local scope using an instance of Access. Attempts to re-reserve
365// the instance will cause an error.
366template <typename T>
367class StaticResource {
368 public:
369 StaticResource() : is_reserved_(false) {}
370
371 private:
372 template <typename S> friend class Access;
373 T instance_;
374 bool is_reserved_;
375};
376
377
378// Locally scoped access to a static resource.
379template <typename T>
380class Access {
381 public:
382 explicit Access(StaticResource<T>* resource)
383 : resource_(resource)
384 , instance_(&resource->instance_) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000385 DCHECK(!resource->is_reserved_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000386 resource->is_reserved_ = true;
387 }
388
389 ~Access() {
390 resource_->is_reserved_ = false;
391 resource_ = NULL;
392 instance_ = NULL;
393 }
394
395 T* value() { return instance_; }
396 T* operator -> () { return instance_; }
397
398 private:
399 StaticResource<T>* resource_;
400 T* instance_;
401};
402
403
Ben Murdochb0fe1622011-05-05 13:52:32 +0100404// A pointer that can only be set once and doesn't allow NULL values.
405template<typename T>
406class SetOncePointer {
407 public:
408 SetOncePointer() : pointer_(NULL) { }
409
410 bool is_set() const { return pointer_ != NULL; }
411
412 T* get() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000413 DCHECK(pointer_ != NULL);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100414 return pointer_;
415 }
416
417 void set(T* value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000418 DCHECK(pointer_ == NULL && value != NULL);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100419 pointer_ = value;
420 }
421
422 private:
423 T* pointer_;
424};
425
426
Steve Blocka7e24c12009-10-30 11:49:00 +0000427template <typename T, int kSize>
428class EmbeddedVector : public Vector<T> {
429 public:
430 EmbeddedVector() : Vector<T>(buffer_, kSize) { }
431
Ben Murdochb0fe1622011-05-05 13:52:32 +0100432 explicit EmbeddedVector(T initial_value) : Vector<T>(buffer_, kSize) {
433 for (int i = 0; i < kSize; ++i) {
434 buffer_[i] = initial_value;
435 }
436 }
437
Steve Blocka7e24c12009-10-30 11:49:00 +0000438 // When copying, make underlying Vector to reference our buffer.
439 EmbeddedVector(const EmbeddedVector& rhs)
440 : Vector<T>(rhs) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000441 MemCopy(buffer_, rhs.buffer_, sizeof(T) * kSize);
442 this->set_start(buffer_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000443 }
444
445 EmbeddedVector& operator=(const EmbeddedVector& rhs) {
446 if (this == &rhs) return *this;
447 Vector<T>::operator=(rhs);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000448 MemCopy(buffer_, rhs.buffer_, sizeof(T) * kSize);
Steve Block6ded16b2010-05-10 14:33:55 +0100449 this->set_start(buffer_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000450 return *this;
451 }
452
453 private:
454 T buffer_[kSize];
455};
456
457
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100458/*
459 * A class that collects values into a backing store.
460 * Specialized versions of the class can allow access to the backing store
461 * in different ways.
462 * There is no guarantee that the backing store is contiguous (and, as a
463 * consequence, no guarantees that consecutively added elements are adjacent
464 * in memory). The collector may move elements unless it has guaranteed not
465 * to.
466 */
467template <typename T, int growth_factor = 2, int max_growth = 1 * MB>
468class Collector {
469 public:
470 explicit Collector(int initial_capacity = kMinCapacity)
471 : index_(0), size_(0) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100472 current_chunk_ = Vector<T>::New(initial_capacity);
473 }
474
475 virtual ~Collector() {
476 // Free backing store (in reverse allocation order).
477 current_chunk_.Dispose();
478 for (int i = chunks_.length() - 1; i >= 0; i--) {
479 chunks_.at(i).Dispose();
480 }
481 }
482
483 // Add a single element.
484 inline void Add(T value) {
485 if (index_ >= current_chunk_.length()) {
486 Grow(1);
487 }
488 current_chunk_[index_] = value;
489 index_++;
490 size_++;
491 }
492
493 // Add a block of contiguous elements and return a Vector backed by the
494 // memory area.
495 // A basic Collector will keep this vector valid as long as the Collector
496 // is alive.
497 inline Vector<T> AddBlock(int size, T initial_value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000498 DCHECK(size > 0);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100499 if (size > current_chunk_.length() - index_) {
500 Grow(size);
501 }
502 T* position = current_chunk_.start() + index_;
503 index_ += size;
504 size_ += size;
505 for (int i = 0; i < size; i++) {
506 position[i] = initial_value;
507 }
508 return Vector<T>(position, size);
509 }
510
511
Steve Block9fac8402011-05-12 15:51:54 +0100512 // Add a contiguous block of elements and return a vector backed
513 // by the added block.
514 // A basic Collector will keep this vector valid as long as the Collector
515 // is alive.
516 inline Vector<T> AddBlock(Vector<const T> source) {
517 if (source.length() > current_chunk_.length() - index_) {
518 Grow(source.length());
519 }
520 T* position = current_chunk_.start() + index_;
521 index_ += source.length();
522 size_ += source.length();
523 for (int i = 0; i < source.length(); i++) {
524 position[i] = source[i];
525 }
526 return Vector<T>(position, source.length());
527 }
528
529
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100530 // Write the contents of the collector into the provided vector.
531 void WriteTo(Vector<T> destination) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000532 DCHECK(size_ <= destination.length());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100533 int position = 0;
534 for (int i = 0; i < chunks_.length(); i++) {
535 Vector<T> chunk = chunks_.at(i);
536 for (int j = 0; j < chunk.length(); j++) {
537 destination[position] = chunk[j];
538 position++;
539 }
540 }
541 for (int i = 0; i < index_; i++) {
542 destination[position] = current_chunk_[i];
543 position++;
544 }
545 }
546
547 // Allocate a single contiguous vector, copy all the collected
548 // elements to the vector, and return it.
549 // The caller is responsible for freeing the memory of the returned
550 // vector (e.g., using Vector::Dispose).
551 Vector<T> ToVector() {
552 Vector<T> new_store = Vector<T>::New(size_);
553 WriteTo(new_store);
554 return new_store;
555 }
556
557 // Resets the collector to be empty.
Ben Murdoch257744e2011-11-30 15:57:28 +0000558 virtual void Reset();
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100559
560 // Total number of elements added to collector so far.
561 inline int size() { return size_; }
562
563 protected:
564 static const int kMinCapacity = 16;
565 List<Vector<T> > chunks_;
566 Vector<T> current_chunk_; // Block of memory currently being written into.
567 int index_; // Current index in current chunk.
568 int size_; // Total number of elements in collector.
569
570 // Creates a new current chunk, and stores the old chunk in the chunks_ list.
571 void Grow(int min_capacity) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000572 DCHECK(growth_factor > 1);
Ben Murdoch589d6972011-11-30 16:04:58 +0000573 int new_capacity;
574 int current_length = current_chunk_.length();
575 if (current_length < kMinCapacity) {
576 // The collector started out as empty.
577 new_capacity = min_capacity * growth_factor;
578 if (new_capacity < kMinCapacity) new_capacity = kMinCapacity;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100579 } else {
Ben Murdoch589d6972011-11-30 16:04:58 +0000580 int growth = current_length * (growth_factor - 1);
581 if (growth > max_growth) {
582 growth = max_growth;
583 }
584 new_capacity = current_length + growth;
585 if (new_capacity < min_capacity) {
586 new_capacity = min_capacity + growth;
587 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100588 }
Ben Murdoch589d6972011-11-30 16:04:58 +0000589 NewChunk(new_capacity);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000590 DCHECK(index_ + min_capacity <= current_chunk_.length());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100591 }
592
593 // Before replacing the current chunk, give a subclass the option to move
594 // some of the current data into the new chunk. The function may update
595 // the current index_ value to represent data no longer in the current chunk.
596 // Returns the initial index of the new chunk (after copied data).
Ben Murdoch589d6972011-11-30 16:04:58 +0000597 virtual void NewChunk(int new_capacity) {
598 Vector<T> new_chunk = Vector<T>::New(new_capacity);
599 if (index_ > 0) {
600 chunks_.Add(current_chunk_.SubVector(0, index_));
601 } else {
602 current_chunk_.Dispose();
603 }
604 current_chunk_ = new_chunk;
605 index_ = 0;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100606 }
607};
608
609
610/*
611 * A collector that allows sequences of values to be guaranteed to
612 * stay consecutive.
613 * If the backing store grows while a sequence is active, the current
614 * sequence might be moved, but after the sequence is ended, it will
615 * not move again.
616 * NOTICE: Blocks allocated using Collector::AddBlock(int) can move
617 * as well, if inside an active sequence where another element is added.
618 */
619template <typename T, int growth_factor = 2, int max_growth = 1 * MB>
620class SequenceCollector : public Collector<T, growth_factor, max_growth> {
621 public:
622 explicit SequenceCollector(int initial_capacity)
623 : Collector<T, growth_factor, max_growth>(initial_capacity),
624 sequence_start_(kNoSequence) { }
625
626 virtual ~SequenceCollector() {}
627
628 void StartSequence() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000629 DCHECK(sequence_start_ == kNoSequence);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100630 sequence_start_ = this->index_;
631 }
632
633 Vector<T> EndSequence() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000634 DCHECK(sequence_start_ != kNoSequence);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100635 int sequence_start = sequence_start_;
636 sequence_start_ = kNoSequence;
637 if (sequence_start == this->index_) return Vector<T>();
638 return this->current_chunk_.SubVector(sequence_start, this->index_);
639 }
640
641 // Drops the currently added sequence, and all collected elements in it.
642 void DropSequence() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000643 DCHECK(sequence_start_ != kNoSequence);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100644 int sequence_length = this->index_ - sequence_start_;
645 this->index_ = sequence_start_;
646 this->size_ -= sequence_length;
647 sequence_start_ = kNoSequence;
648 }
649
650 virtual void Reset() {
651 sequence_start_ = kNoSequence;
652 this->Collector<T, growth_factor, max_growth>::Reset();
653 }
654
655 private:
656 static const int kNoSequence = -1;
657 int sequence_start_;
658
659 // Move the currently active sequence to the new chunk.
Ben Murdoch589d6972011-11-30 16:04:58 +0000660 virtual void NewChunk(int new_capacity) {
661 if (sequence_start_ == kNoSequence) {
662 // Fall back on default behavior if no sequence has been started.
663 this->Collector<T, growth_factor, max_growth>::NewChunk(new_capacity);
664 return;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100665 }
Ben Murdoch589d6972011-11-30 16:04:58 +0000666 int sequence_length = this->index_ - sequence_start_;
667 Vector<T> new_chunk = Vector<T>::New(sequence_length + new_capacity);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000668 DCHECK(sequence_length < new_chunk.length());
Ben Murdoch589d6972011-11-30 16:04:58 +0000669 for (int i = 0; i < sequence_length; i++) {
670 new_chunk[i] = this->current_chunk_[sequence_start_ + i];
671 }
672 if (sequence_start_ > 0) {
673 this->chunks_.Add(this->current_chunk_.SubVector(0, sequence_start_));
674 } else {
675 this->current_chunk_.Dispose();
676 }
677 this->current_chunk_ = new_chunk;
678 this->index_ = sequence_length;
679 sequence_start_ = 0;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100680 }
681};
682
683
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000684// Compare 8bit/16bit chars to 8bit/16bit chars.
Steve Block6ded16b2010-05-10 14:33:55 +0100685template <typename lchar, typename rchar>
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000686inline int CompareCharsUnsigned(const lchar* lhs,
687 const rchar* rhs,
688 int chars) {
Steve Block6ded16b2010-05-10 14:33:55 +0100689 const lchar* limit = lhs + chars;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000690 if (sizeof(*lhs) == sizeof(char) && sizeof(*rhs) == sizeof(char)) {
691 // memcmp compares byte-by-byte, yielding wrong results for two-byte
692 // strings on little-endian systems.
693 return memcmp(lhs, rhs, chars);
Steve Block6ded16b2010-05-10 14:33:55 +0100694 }
Steve Block6ded16b2010-05-10 14:33:55 +0100695 while (lhs < limit) {
696 int r = static_cast<int>(*lhs) - static_cast<int>(*rhs);
697 if (r != 0) return r;
698 ++lhs;
699 ++rhs;
700 }
701 return 0;
702}
703
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000704template<typename lchar, typename rchar>
705inline int CompareChars(const lchar* lhs, const rchar* rhs, int chars) {
706 DCHECK(sizeof(lchar) <= 2);
707 DCHECK(sizeof(rchar) <= 2);
708 if (sizeof(lchar) == 1) {
709 if (sizeof(rchar) == 1) {
710 return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs),
711 reinterpret_cast<const uint8_t*>(rhs),
712 chars);
713 } else {
714 return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs),
715 reinterpret_cast<const uint16_t*>(rhs),
716 chars);
717 }
718 } else {
719 if (sizeof(rchar) == 1) {
720 return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(lhs),
721 reinterpret_cast<const uint8_t*>(rhs),
722 chars);
723 } else {
724 return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(lhs),
725 reinterpret_cast<const uint16_t*>(rhs),
726 chars);
727 }
728 }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800729}
Steve Blockd0582a62009-12-15 09:54:21 +0000730
Steve Block6ded16b2010-05-10 14:33:55 +0100731
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000732// Calculate 10^exponent.
733inline int TenToThe(int exponent) {
734 DCHECK(exponent <= 9);
735 DCHECK(exponent >= 1);
736 int answer = 10;
737 for (int i = 1; i < exponent; i++) answer *= 10;
738 return answer;
Iain Merrick75681382010-08-19 15:07:18 +0100739}
Steve Blocka7e24c12009-10-30 11:49:00 +0000740
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000741
742template<typename ElementType, int NumElements>
743class EmbeddedContainer {
744 public:
745 EmbeddedContainer() : elems_() { }
746
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000747 int length() const { return NumElements; }
748 const ElementType& operator[](int i) const {
749 DCHECK(i < length());
750 return elems_[i];
751 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000752 ElementType& operator[](int i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000753 DCHECK(i < length());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000754 return elems_[i];
755 }
756
757 private:
758 ElementType elems_[NumElements];
759};
760
761
762template<typename ElementType>
763class EmbeddedContainer<ElementType, 0> {
764 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000765 int length() const { return 0; }
766 const ElementType& operator[](int i) const {
767 UNREACHABLE();
768 static ElementType t = 0;
769 return t;
770 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000771 ElementType& operator[](int i) {
772 UNREACHABLE();
773 static ElementType t = 0;
774 return t;
775 }
776};
777
778
779// Helper class for building result strings in a character buffer. The
780// purpose of the class is to use safe operations that checks the
781// buffer bounds on all operations in debug mode.
782// This simple base class does not allow formatted output.
783class SimpleStringBuilder {
784 public:
785 // Create a string builder with a buffer of the given size. The
786 // buffer is allocated through NewArray<char> and must be
787 // deallocated by the caller of Finalize().
788 explicit SimpleStringBuilder(int size);
789
790 SimpleStringBuilder(char* buffer, int size)
791 : buffer_(buffer, size), position_(0) { }
792
793 ~SimpleStringBuilder() { if (!is_finalized()) Finalize(); }
794
795 int size() const { return buffer_.length(); }
796
797 // Get the current position in the builder.
798 int position() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000799 DCHECK(!is_finalized());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000800 return position_;
801 }
802
803 // Reset the position.
804 void Reset() { position_ = 0; }
805
806 // Add a single character to the builder. It is not allowed to add
807 // 0-characters; use the Finalize() method to terminate the string
808 // instead.
809 void AddCharacter(char c) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000810 DCHECK(c != '\0');
811 DCHECK(!is_finalized() && position_ < buffer_.length());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000812 buffer_[position_++] = c;
813 }
814
815 // Add an entire string to the builder. Uses strlen() internally to
816 // compute the length of the input string.
817 void AddString(const char* s);
818
819 // Add the first 'n' characters of the given string 's' to the
820 // builder. The input string must have enough characters.
821 void AddSubstring(const char* s, int n);
822
823 // Add character padding to the builder. If count is non-positive,
824 // nothing is added to the builder.
825 void AddPadding(char c, int count);
826
827 // Add the decimal representation of the value.
828 void AddDecimalInteger(int value);
829
830 // Finalize the string by 0-terminating it and returning the buffer.
831 char* Finalize();
832
833 protected:
834 Vector<char> buffer_;
835 int position_;
836
837 bool is_finalized() const { return position_ < 0; }
Ben Murdoch589d6972011-11-30 16:04:58 +0000838
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000839 private:
840 DISALLOW_IMPLICIT_CONSTRUCTORS(SimpleStringBuilder);
841};
842
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000843
844// A poor man's version of STL's bitset: A bit set of enums E (without explicit
845// values), fitting into an integral type T.
846template <class E, class T = int>
847class EnumSet {
848 public:
849 explicit EnumSet(T bits = 0) : bits_(bits) {}
850 bool IsEmpty() const { return bits_ == 0; }
851 bool Contains(E element) const { return (bits_ & Mask(element)) != 0; }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100852 bool ContainsAnyOf(const EnumSet& set) const {
853 return (bits_ & set.bits_) != 0;
854 }
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000855 void Add(E element) { bits_ |= Mask(element); }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100856 void Add(const EnumSet& set) { bits_ |= set.bits_; }
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000857 void Remove(E element) { bits_ &= ~Mask(element); }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100858 void Remove(const EnumSet& set) { bits_ &= ~set.bits_; }
859 void RemoveAll() { bits_ = 0; }
860 void Intersect(const EnumSet& set) { bits_ &= set.bits_; }
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000861 T ToIntegral() const { return bits_; }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100862 bool operator==(const EnumSet& set) { return bits_ == set.bits_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000863 bool operator!=(const EnumSet& set) { return bits_ != set.bits_; }
864 EnumSet<E, T> operator|(const EnumSet& set) const {
865 return EnumSet<E, T>(bits_ | set.bits_);
866 }
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000867
868 private:
869 T Mask(E element) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000870 // The strange typing in DCHECK is necessary to avoid stupid warnings, see:
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000871 // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43680
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000872 DCHECK(static_cast<int>(element) < static_cast<int>(sizeof(T) * CHAR_BIT));
873 return static_cast<T>(1) << element;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000874 }
875
876 T bits_;
877};
878
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000879// Bit field extraction.
880inline uint32_t unsigned_bitextract_32(int msb, int lsb, uint32_t x) {
881 return (x >> lsb) & ((1 << (1 + msb - lsb)) - 1);
882}
883
884inline uint64_t unsigned_bitextract_64(int msb, int lsb, uint64_t x) {
885 return (x >> lsb) & ((static_cast<uint64_t>(1) << (1 + msb - lsb)) - 1);
886}
887
888inline int32_t signed_bitextract_32(int msb, int lsb, int32_t x) {
889 return (x << (31 - msb)) >> (lsb + 31 - msb);
890}
891
892inline int signed_bitextract_64(int msb, int lsb, int x) {
893 // TODO(jbramley): This is broken for big bitfields.
894 return (x << (63 - msb)) >> (lsb + 63 - msb);
895}
896
897// Check number width.
898inline bool is_intn(int64_t x, unsigned n) {
899 DCHECK((0 < n) && (n < 64));
900 int64_t limit = static_cast<int64_t>(1) << (n - 1);
901 return (-limit <= x) && (x < limit);
902}
903
904inline bool is_uintn(int64_t x, unsigned n) {
905 DCHECK((0 < n) && (n < (sizeof(x) * kBitsPerByte)));
906 return !(x >> n);
907}
908
909template <class T>
910inline T truncate_to_intn(T x, unsigned n) {
911 DCHECK((0 < n) && (n < (sizeof(x) * kBitsPerByte)));
912 return (x & ((static_cast<T>(1) << n) - 1));
913}
914
915#define INT_1_TO_63_LIST(V) \
916V(1) V(2) V(3) V(4) V(5) V(6) V(7) V(8) \
917V(9) V(10) V(11) V(12) V(13) V(14) V(15) V(16) \
918V(17) V(18) V(19) V(20) V(21) V(22) V(23) V(24) \
919V(25) V(26) V(27) V(28) V(29) V(30) V(31) V(32) \
920V(33) V(34) V(35) V(36) V(37) V(38) V(39) V(40) \
921V(41) V(42) V(43) V(44) V(45) V(46) V(47) V(48) \
922V(49) V(50) V(51) V(52) V(53) V(54) V(55) V(56) \
923V(57) V(58) V(59) V(60) V(61) V(62) V(63)
924
925#define DECLARE_IS_INT_N(N) \
926inline bool is_int##N(int64_t x) { return is_intn(x, N); }
927#define DECLARE_IS_UINT_N(N) \
928template <class T> \
929inline bool is_uint##N(T x) { return is_uintn(x, N); }
930#define DECLARE_TRUNCATE_TO_INT_N(N) \
931template <class T> \
932inline T truncate_to_int##N(T x) { return truncate_to_intn(x, N); }
933INT_1_TO_63_LIST(DECLARE_IS_INT_N)
934INT_1_TO_63_LIST(DECLARE_IS_UINT_N)
935INT_1_TO_63_LIST(DECLARE_TRUNCATE_TO_INT_N)
936#undef DECLARE_IS_INT_N
937#undef DECLARE_IS_UINT_N
938#undef DECLARE_TRUNCATE_TO_INT_N
939
940class TypeFeedbackId {
941 public:
942 explicit TypeFeedbackId(int id) : id_(id) { }
943 int ToInt() const { return id_; }
944
945 static TypeFeedbackId None() { return TypeFeedbackId(kNoneId); }
946 bool IsNone() const { return id_ == kNoneId; }
947
948 private:
949 static const int kNoneId = -1;
950
951 int id_;
952};
953
954
955class BailoutId {
956 public:
957 explicit BailoutId(int id) : id_(id) { }
958 int ToInt() const { return id_; }
959
960 static BailoutId None() { return BailoutId(kNoneId); }
961 static BailoutId FunctionEntry() { return BailoutId(kFunctionEntryId); }
962 static BailoutId Declarations() { return BailoutId(kDeclarationsId); }
963 static BailoutId FirstUsable() { return BailoutId(kFirstUsableId); }
964 static BailoutId StubEntry() { return BailoutId(kStubEntryId); }
965
966 bool IsNone() const { return id_ == kNoneId; }
967 bool operator==(const BailoutId& other) const { return id_ == other.id_; }
968 bool operator!=(const BailoutId& other) const { return id_ != other.id_; }
969
970 private:
971 static const int kNoneId = -1;
972
973 // Using 0 could disguise errors.
974 static const int kFunctionEntryId = 2;
975
976 // This AST id identifies the point after the declarations have been visited.
977 // We need it to capture the environment effects of declarations that emit
978 // code (function declarations).
979 static const int kDeclarationsId = 3;
980
981 // Every FunctionState starts with this id.
982 static const int kFirstUsableId = 4;
983
984 // Every compiled stub starts with this id.
985 static const int kStubEntryId = 5;
986
987 int id_;
988};
989
990
991template <class C>
992class ContainerPointerWrapper {
993 public:
994 typedef typename C::iterator iterator;
995 typedef typename C::reverse_iterator reverse_iterator;
996 explicit ContainerPointerWrapper(C* container) : container_(container) {}
997 iterator begin() { return container_->begin(); }
998 iterator end() { return container_->end(); }
999 reverse_iterator rbegin() { return container_->rbegin(); }
1000 reverse_iterator rend() { return container_->rend(); }
1001 private:
1002 C* container_;
1003};
1004
1005
1006// ----------------------------------------------------------------------------
1007// I/O support.
1008
1009#if __GNUC__ >= 4
1010// On gcc we can ask the compiler to check the types of %d-style format
1011// specifiers and their associated arguments. TODO(erikcorry) fix this
1012// so it works on MacOSX.
1013#if defined(__MACH__) && defined(__APPLE__)
1014#define PRINTF_CHECKING
1015#define FPRINTF_CHECKING
1016#define PRINTF_METHOD_CHECKING
1017#define FPRINTF_METHOD_CHECKING
1018#else // MacOsX.
1019#define PRINTF_CHECKING __attribute__ ((format (printf, 1, 2)))
1020#define FPRINTF_CHECKING __attribute__ ((format (printf, 2, 3)))
1021#define PRINTF_METHOD_CHECKING __attribute__ ((format (printf, 2, 3)))
1022#define FPRINTF_METHOD_CHECKING __attribute__ ((format (printf, 3, 4)))
1023#endif
1024#else
1025#define PRINTF_CHECKING
1026#define FPRINTF_CHECKING
1027#define PRINTF_METHOD_CHECKING
1028#define FPRINTF_METHOD_CHECKING
1029#endif
1030
1031// Our version of printf().
1032void PRINTF_CHECKING PrintF(const char* format, ...);
1033void FPRINTF_CHECKING PrintF(FILE* out, const char* format, ...);
1034
1035// Prepends the current process ID to the output.
1036void PRINTF_CHECKING PrintPID(const char* format, ...);
1037
1038// Safe formatting print. Ensures that str is always null-terminated.
1039// Returns the number of chars written, or -1 if output was truncated.
1040int FPRINTF_CHECKING SNPrintF(Vector<char> str, const char* format, ...);
1041int VSNPrintF(Vector<char> str, const char* format, va_list args);
1042
1043void StrNCpy(Vector<char> dest, const char* src, size_t n);
1044
1045// Our version of fflush.
1046void Flush(FILE* out);
1047
1048inline void Flush() {
1049 Flush(stdout);
1050}
1051
1052
1053// Read a line of characters after printing the prompt to stdout. The resulting
1054// char* needs to be disposed off with DeleteArray by the caller.
1055char* ReadLine(const char* prompt);
1056
1057
1058// Read and return the raw bytes in a file. the size of the buffer is returned
1059// in size.
1060// The returned buffer must be freed by the caller.
1061byte* ReadBytes(const char* filename, int* size, bool verbose = true);
1062
1063
1064// Append size chars from str to the file given by filename.
1065// The file is overwritten. Returns the number of chars written.
1066int AppendChars(const char* filename,
1067 const char* str,
1068 int size,
1069 bool verbose = true);
1070
1071
1072// Write size chars from str to the file given by filename.
1073// The file is overwritten. Returns the number of chars written.
1074int WriteChars(const char* filename,
1075 const char* str,
1076 int size,
1077 bool verbose = true);
1078
1079
1080// Write size bytes to the file given by filename.
1081// The file is overwritten. Returns the number of bytes written.
1082int WriteBytes(const char* filename,
1083 const byte* bytes,
1084 int size,
1085 bool verbose = true);
1086
1087
1088// Write the C code
1089// const char* <varname> = "<str>";
1090// const int <varname>_len = <len>;
1091// to the file given by filename. Only the first len chars are written.
1092int WriteAsCFile(const char* filename, const char* varname,
1093 const char* str, int size, bool verbose = true);
1094
1095
1096// ----------------------------------------------------------------------------
1097// Data structures
1098
1099template <typename T>
1100inline Vector< Handle<Object> > HandleVector(v8::internal::Handle<T>* elms,
1101 int length) {
1102 return Vector< Handle<Object> >(
1103 reinterpret_cast<v8::internal::Handle<Object>*>(elms), length);
1104}
1105
1106
1107// ----------------------------------------------------------------------------
1108// Memory
1109
1110// Copies words from |src| to |dst|. The data spans must not overlap.
1111template <typename T>
1112inline void CopyWords(T* dst, const T* src, size_t num_words) {
1113 STATIC_ASSERT(sizeof(T) == kPointerSize);
1114 // TODO(mvstanton): disabled because mac builds are bogus failing on this
1115 // assert. They are doing a signed comparison. Investigate in
1116 // the morning.
1117 // DCHECK(Min(dst, const_cast<T*>(src)) + num_words <=
1118 // Max(dst, const_cast<T*>(src)));
1119 DCHECK(num_words > 0);
1120
1121 // Use block copying MemCopy if the segment we're copying is
1122 // enough to justify the extra call/setup overhead.
1123 static const size_t kBlockCopyLimit = 16;
1124
1125 if (num_words < kBlockCopyLimit) {
1126 do {
1127 num_words--;
1128 *dst++ = *src++;
1129 } while (num_words > 0);
1130 } else {
1131 MemCopy(dst, src, num_words * kPointerSize);
1132 }
1133}
1134
1135
1136// Copies words from |src| to |dst|. No restrictions.
1137template <typename T>
1138inline void MoveWords(T* dst, const T* src, size_t num_words) {
1139 STATIC_ASSERT(sizeof(T) == kPointerSize);
1140 DCHECK(num_words > 0);
1141
1142 // Use block copying MemCopy if the segment we're copying is
1143 // enough to justify the extra call/setup overhead.
1144 static const size_t kBlockCopyLimit = 16;
1145
1146 if (num_words < kBlockCopyLimit &&
1147 ((dst < src) || (dst >= (src + num_words * kPointerSize)))) {
1148 T* end = dst + num_words;
1149 do {
1150 num_words--;
1151 *dst++ = *src++;
1152 } while (num_words > 0);
1153 } else {
1154 MemMove(dst, src, num_words * kPointerSize);
1155 }
1156}
1157
1158
1159// Copies data from |src| to |dst|. The data spans must not overlap.
1160template <typename T>
1161inline void CopyBytes(T* dst, const T* src, size_t num_bytes) {
1162 STATIC_ASSERT(sizeof(T) == 1);
1163 DCHECK(Min(dst, const_cast<T*>(src)) + num_bytes <=
1164 Max(dst, const_cast<T*>(src)));
1165 if (num_bytes == 0) return;
1166
1167 // Use block copying MemCopy if the segment we're copying is
1168 // enough to justify the extra call/setup overhead.
1169 static const int kBlockCopyLimit = kMinComplexMemCopy;
1170
1171 if (num_bytes < static_cast<size_t>(kBlockCopyLimit)) {
1172 do {
1173 num_bytes--;
1174 *dst++ = *src++;
1175 } while (num_bytes > 0);
1176 } else {
1177 MemCopy(dst, src, num_bytes);
1178 }
1179}
1180
1181
1182template <typename T, typename U>
1183inline void MemsetPointer(T** dest, U* value, int counter) {
1184#ifdef DEBUG
1185 T* a = NULL;
1186 U* b = NULL;
1187 a = b; // Fake assignment to check assignability.
1188 USE(a);
1189#endif // DEBUG
1190#if V8_HOST_ARCH_IA32
1191#define STOS "stosl"
1192#elif V8_HOST_ARCH_X64
1193#if V8_HOST_ARCH_32_BIT
1194#define STOS "addr32 stosl"
1195#else
1196#define STOS "stosq"
1197#endif
1198#endif
1199#if defined(__native_client__)
1200 // This STOS sequence does not validate for x86_64 Native Client.
1201 // Here we #undef STOS to force use of the slower C version.
1202 // TODO(bradchen): Profile V8 and implement a faster REP STOS
1203 // here if the profile indicates it matters.
1204#undef STOS
1205#endif
1206
1207#if defined(MEMORY_SANITIZER)
1208 // MemorySanitizer does not understand inline assembly.
1209#undef STOS
1210#endif
1211
1212#if defined(__GNUC__) && defined(STOS)
1213 asm volatile(
1214 "cld;"
1215 "rep ; " STOS
1216 : "+&c" (counter), "+&D" (dest)
1217 : "a" (value)
1218 : "memory", "cc");
1219#else
1220 for (int i = 0; i < counter; i++) {
1221 dest[i] = value;
1222 }
1223#endif
1224
1225#undef STOS
1226}
1227
1228
1229// Simple support to read a file into a 0-terminated C-string.
1230// The returned buffer must be freed by the caller.
1231// On return, *exits tells whether the file existed.
1232Vector<const char> ReadFile(const char* filename,
1233 bool* exists,
1234 bool verbose = true);
1235Vector<const char> ReadFile(FILE* file,
1236 bool* exists,
1237 bool verbose = true);
1238
1239
1240template <typename sourcechar, typename sinkchar>
1241INLINE(static void CopyCharsUnsigned(sinkchar* dest,
1242 const sourcechar* src,
1243 int chars));
1244#if defined(V8_HOST_ARCH_ARM)
1245INLINE(void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, int chars));
1246INLINE(void CopyCharsUnsigned(uint16_t* dest, const uint8_t* src, int chars));
1247INLINE(void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, int chars));
1248#elif defined(V8_HOST_ARCH_MIPS)
1249INLINE(void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, int chars));
1250INLINE(void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, int chars));
1251#endif
1252
1253// Copy from 8bit/16bit chars to 8bit/16bit chars.
1254template <typename sourcechar, typename sinkchar>
1255INLINE(void CopyChars(sinkchar* dest, const sourcechar* src, int chars));
1256
1257template<typename sourcechar, typename sinkchar>
1258void CopyChars(sinkchar* dest, const sourcechar* src, int chars) {
1259 DCHECK(sizeof(sourcechar) <= 2);
1260 DCHECK(sizeof(sinkchar) <= 2);
1261 if (sizeof(sinkchar) == 1) {
1262 if (sizeof(sourcechar) == 1) {
1263 CopyCharsUnsigned(reinterpret_cast<uint8_t*>(dest),
1264 reinterpret_cast<const uint8_t*>(src),
1265 chars);
1266 } else {
1267 CopyCharsUnsigned(reinterpret_cast<uint8_t*>(dest),
1268 reinterpret_cast<const uint16_t*>(src),
1269 chars);
1270 }
1271 } else {
1272 if (sizeof(sourcechar) == 1) {
1273 CopyCharsUnsigned(reinterpret_cast<uint16_t*>(dest),
1274 reinterpret_cast<const uint8_t*>(src),
1275 chars);
1276 } else {
1277 CopyCharsUnsigned(reinterpret_cast<uint16_t*>(dest),
1278 reinterpret_cast<const uint16_t*>(src),
1279 chars);
1280 }
1281 }
1282}
1283
1284template <typename sourcechar, typename sinkchar>
1285void CopyCharsUnsigned(sinkchar* dest, const sourcechar* src, int chars) {
1286 sinkchar* limit = dest + chars;
1287 if ((sizeof(*dest) == sizeof(*src)) &&
1288 (chars >= static_cast<int>(kMinComplexMemCopy / sizeof(*dest)))) {
1289 MemCopy(dest, src, chars * sizeof(*dest));
1290 } else {
1291 while (dest < limit) *dest++ = static_cast<sinkchar>(*src++);
1292 }
1293}
1294
1295
1296#if defined(V8_HOST_ARCH_ARM)
1297void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, int chars) {
1298 switch (static_cast<unsigned>(chars)) {
1299 case 0:
1300 break;
1301 case 1:
1302 *dest = *src;
1303 break;
1304 case 2:
1305 memcpy(dest, src, 2);
1306 break;
1307 case 3:
1308 memcpy(dest, src, 3);
1309 break;
1310 case 4:
1311 memcpy(dest, src, 4);
1312 break;
1313 case 5:
1314 memcpy(dest, src, 5);
1315 break;
1316 case 6:
1317 memcpy(dest, src, 6);
1318 break;
1319 case 7:
1320 memcpy(dest, src, 7);
1321 break;
1322 case 8:
1323 memcpy(dest, src, 8);
1324 break;
1325 case 9:
1326 memcpy(dest, src, 9);
1327 break;
1328 case 10:
1329 memcpy(dest, src, 10);
1330 break;
1331 case 11:
1332 memcpy(dest, src, 11);
1333 break;
1334 case 12:
1335 memcpy(dest, src, 12);
1336 break;
1337 case 13:
1338 memcpy(dest, src, 13);
1339 break;
1340 case 14:
1341 memcpy(dest, src, 14);
1342 break;
1343 case 15:
1344 memcpy(dest, src, 15);
1345 break;
1346 default:
1347 MemCopy(dest, src, chars);
1348 break;
1349 }
1350}
1351
1352
1353void CopyCharsUnsigned(uint16_t* dest, const uint8_t* src, int chars) {
1354 if (chars >= kMinComplexConvertMemCopy) {
1355 MemCopyUint16Uint8(dest, src, chars);
1356 } else {
1357 MemCopyUint16Uint8Wrapper(dest, src, chars);
1358 }
1359}
1360
1361
1362void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, int chars) {
1363 switch (static_cast<unsigned>(chars)) {
1364 case 0:
1365 break;
1366 case 1:
1367 *dest = *src;
1368 break;
1369 case 2:
1370 memcpy(dest, src, 4);
1371 break;
1372 case 3:
1373 memcpy(dest, src, 6);
1374 break;
1375 case 4:
1376 memcpy(dest, src, 8);
1377 break;
1378 case 5:
1379 memcpy(dest, src, 10);
1380 break;
1381 case 6:
1382 memcpy(dest, src, 12);
1383 break;
1384 case 7:
1385 memcpy(dest, src, 14);
1386 break;
1387 default:
1388 MemCopy(dest, src, chars * sizeof(*dest));
1389 break;
1390 }
1391}
1392
1393
1394#elif defined(V8_HOST_ARCH_MIPS)
1395void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, int chars) {
1396 if (chars < kMinComplexMemCopy) {
1397 memcpy(dest, src, chars);
1398 } else {
1399 MemCopy(dest, src, chars);
1400 }
1401}
1402
1403void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, int chars) {
1404 if (chars < kMinComplexMemCopy) {
1405 memcpy(dest, src, chars * sizeof(*dest));
1406 } else {
1407 MemCopy(dest, src, chars * sizeof(*dest));
1408 }
1409}
1410#endif
1411
1412
1413class StringBuilder : public SimpleStringBuilder {
1414 public:
1415 explicit StringBuilder(int size) : SimpleStringBuilder(size) { }
1416 StringBuilder(char* buffer, int size) : SimpleStringBuilder(buffer, size) { }
1417
1418 // Add formatted contents to the builder just like printf().
1419 void AddFormatted(const char* format, ...);
1420
1421 // Add formatted contents like printf based on a va_list.
1422 void AddFormattedList(const char* format, va_list list);
1423 private:
1424 DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
1425};
1426
1427
1428bool DoubleToBoolean(double d);
1429
1430template <typename Stream>
1431bool StringToArrayIndex(Stream* stream, uint32_t* index) {
1432 uint16_t ch = stream->GetNext();
1433
1434 // If the string begins with a '0' character, it must only consist
1435 // of it to be a legal array index.
1436 if (ch == '0') {
1437 *index = 0;
1438 return !stream->HasMore();
1439 }
1440
1441 // Convert string to uint32 array index; character by character.
1442 int d = ch - '0';
1443 if (d < 0 || d > 9) return false;
1444 uint32_t result = d;
1445 while (stream->HasMore()) {
1446 d = stream->GetNext() - '0';
1447 if (d < 0 || d > 9) return false;
1448 // Check that the new result is below the 32 bit limit.
1449 if (result > 429496729U - ((d > 5) ? 1 : 0)) return false;
1450 result = (result * 10) + d;
1451 }
1452
1453 *index = result;
1454 return true;
1455}
1456
1457
1458// Returns current value of top of the stack. Works correctly with ASAN.
1459DISABLE_ASAN
1460inline uintptr_t GetCurrentStackPosition() {
1461 // Takes the address of the limit variable in order to find out where
1462 // the top of stack is right now.
1463 uintptr_t limit = reinterpret_cast<uintptr_t>(&limit);
1464 return limit;
1465}
1466
1467} // namespace internal
1468} // namespace v8
Steve Block6ded16b2010-05-10 14:33:55 +01001469
Steve Blocka7e24c12009-10-30 11:49:00 +00001470#endif // V8_UTILS_H_