[V8] Introduce a QML compilation mode
[profile/ivi/qtjsbackend.git] / src / 3rdparty / v8 / src / utils.h
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 #ifndef V8_UTILS_H_
29 #define V8_UTILS_H_
30
31 #include <stdlib.h>
32 #include <string.h>
33 #include <climits>
34
35 #include "globals.h"
36 #include "checks.h"
37 #include "allocation.h"
38
39 namespace v8 {
40 namespace internal {
41
42 // ----------------------------------------------------------------------------
43 // General helper functions
44
45 #define IS_POWER_OF_TWO(x) (((x) & ((x) - 1)) == 0)
46
47 // Returns true iff x is a power of 2 (or zero). Cannot be used with the
48 // maximally negative value of the type T (the -1 overflows).
49 template <typename T>
50 inline bool IsPowerOf2(T x) {
51   return IS_POWER_OF_TWO(x);
52 }
53
54
55 // X must be a power of 2.  Returns the number of trailing zeros.
56 inline int WhichPowerOf2(uint32_t x) {
57   ASSERT(IsPowerOf2(x));
58   ASSERT(x != 0);
59   int bits = 0;
60 #ifdef DEBUG
61   int original_x = x;
62 #endif
63   if (x >= 0x10000) {
64     bits += 16;
65     x >>= 16;
66   }
67   if (x >= 0x100) {
68     bits += 8;
69     x >>= 8;
70   }
71   if (x >= 0x10) {
72     bits += 4;
73     x >>= 4;
74   }
75   switch (x) {
76     default: UNREACHABLE();
77     case 8: bits++;  // Fall through.
78     case 4: bits++;  // Fall through.
79     case 2: bits++;  // Fall through.
80     case 1: break;
81   }
82   ASSERT_EQ(1 << bits, original_x);
83   return bits;
84   return 0;
85 }
86
87
88 // Magic numbers for integer division.
89 // These are kind of 2's complement reciprocal of the divisors.
90 // Details and proofs can be found in:
91 // - Hacker's Delight, Henry S. Warren, Jr.
92 // - The PowerPC Compiler Writer’s Guide
93 // and probably many others.
94 // See details in the implementation of the algorithm in
95 // lithium-codegen-arm.cc : LCodeGen::TryEmitSignedIntegerDivisionByConstant().
96 struct DivMagicNumbers {
97   unsigned M;
98   unsigned s;
99 };
100
101 const DivMagicNumbers InvalidDivMagicNumber= {0, 0};
102 const DivMagicNumbers DivMagicNumberFor3   = {0x55555556, 0};
103 const DivMagicNumbers DivMagicNumberFor5   = {0x66666667, 1};
104 const DivMagicNumbers DivMagicNumberFor7   = {0x92492493, 2};
105 const DivMagicNumbers DivMagicNumberFor9   = {0x38e38e39, 1};
106 const DivMagicNumbers DivMagicNumberFor11  = {0x2e8ba2e9, 1};
107 const DivMagicNumbers DivMagicNumberFor25  = {0x51eb851f, 3};
108 const DivMagicNumbers DivMagicNumberFor125 = {0x10624dd3, 3};
109 const DivMagicNumbers DivMagicNumberFor625 = {0x68db8bad, 8};
110
111 const DivMagicNumbers DivMagicNumberFor(int32_t divisor);
112
113
114 // The C++ standard leaves the semantics of '>>' undefined for
115 // negative signed operands. Most implementations do the right thing,
116 // though.
117 inline int ArithmeticShiftRight(int x, int s) {
118   return x >> s;
119 }
120
121
122 // Compute the 0-relative offset of some absolute value x of type T.
123 // This allows conversion of Addresses and integral types into
124 // 0-relative int offsets.
125 template <typename T>
126 inline intptr_t OffsetFrom(T x) {
127   return x - static_cast<T>(0);
128 }
129
130
131 // Compute the absolute value of type T for some 0-relative offset x.
132 // This allows conversion of 0-relative int offsets into Addresses and
133 // integral types.
134 template <typename T>
135 inline T AddressFrom(intptr_t x) {
136   return static_cast<T>(static_cast<T>(0) + x);
137 }
138
139
140 // Return the largest multiple of m which is <= x.
141 template <typename T>
142 inline T RoundDown(T x, intptr_t m) {
143   ASSERT(IsPowerOf2(m));
144   return AddressFrom<T>(OffsetFrom(x) & -m);
145 }
146
147
148 // Return the smallest multiple of m which is >= x.
149 template <typename T>
150 inline T RoundUp(T x, intptr_t m) {
151   return RoundDown<T>(static_cast<T>(x + m - 1), m);
152 }
153
154
155 template <typename T>
156 int Compare(const T& a, const T& b) {
157   if (a == b)
158     return 0;
159   else if (a < b)
160     return -1;
161   else
162     return 1;
163 }
164
165
166 template <typename T>
167 int PointerValueCompare(const T* a, const T* b) {
168   return Compare<T>(*a, *b);
169 }
170
171
172 // Compare function to compare the object pointer value of two
173 // handlified objects. The handles are passed as pointers to the
174 // handles.
175 template<typename T> class Handle;  // Forward declaration.
176 template <typename T>
177 int HandleObjectPointerCompare(const Handle<T>* a, const Handle<T>* b) {
178   return Compare<T*>(*(*a), *(*b));
179 }
180
181
182 // Returns the smallest power of two which is >= x. If you pass in a
183 // number that is already a power of two, it is returned as is.
184 // Implementation is from "Hacker's Delight" by Henry S. Warren, Jr.,
185 // figure 3-3, page 48, where the function is called clp2.
186 inline uint32_t RoundUpToPowerOf2(uint32_t x) {
187   ASSERT(x <= 0x80000000u);
188   x = x - 1;
189   x = x | (x >> 1);
190   x = x | (x >> 2);
191   x = x | (x >> 4);
192   x = x | (x >> 8);
193   x = x | (x >> 16);
194   return x + 1;
195 }
196
197
198 inline uint32_t RoundDownToPowerOf2(uint32_t x) {
199   uint32_t rounded_up = RoundUpToPowerOf2(x);
200   if (rounded_up > x) return rounded_up >> 1;
201   return rounded_up;
202 }
203
204
205 template <typename T, typename U>
206 inline bool IsAligned(T value, U alignment) {
207   return (value & (alignment - 1)) == 0;
208 }
209
210
211 // Returns true if (addr + offset) is aligned.
212 inline bool IsAddressAligned(Address addr,
213                              intptr_t alignment,
214                              int offset = 0) {
215   intptr_t offs = OffsetFrom(addr + offset);
216   return IsAligned(offs, alignment);
217 }
218
219
220 // Returns the maximum of the two parameters.
221 template <typename T>
222 T Max(T a, T b) {
223   return a < b ? b : a;
224 }
225
226
227 // Returns the minimum of the two parameters.
228 template <typename T>
229 T Min(T a, T b) {
230   return a < b ? a : b;
231 }
232
233
234 inline int StrLength(const char* string) {
235   size_t length = strlen(string);
236   ASSERT(length == static_cast<size_t>(static_cast<int>(length)));
237   return static_cast<int>(length);
238 }
239
240
241 // ----------------------------------------------------------------------------
242 // BitField is a help template for encoding and decode bitfield with
243 // unsigned content.
244 template<class T, int shift, int size>
245 class BitField {
246  public:
247   // A uint32_t mask of bit field.  To use all bits of a uint32 in a
248   // bitfield without compiler warnings we have to compute 2^32 without
249   // using a shift count of 32.
250   static const uint32_t kMask = ((1U << shift) << size) - (1U << shift);
251
252   // Value for the field with all bits set.
253   static const T kMax = static_cast<T>((1U << size) - 1);
254
255   // Tells whether the provided value fits into the bit field.
256   static bool is_valid(T value) {
257     return (static_cast<uint32_t>(value) & ~static_cast<uint32_t>(kMax)) == 0;
258   }
259
260   // Returns a uint32_t with the bit field value encoded.
261   static uint32_t encode(T value) {
262     ASSERT(is_valid(value));
263     return static_cast<uint32_t>(value) << shift;
264   }
265
266   // Returns a uint32_t with the bit field value updated.
267   static uint32_t update(uint32_t previous, T value) {
268     return (previous & ~kMask) | encode(value);
269   }
270
271   // Extracts the bit field from the value.
272   static T decode(uint32_t value) {
273     return static_cast<T>((value & kMask) >> shift);
274   }
275 };
276
277
278 // ----------------------------------------------------------------------------
279 // Hash function.
280
281 static const uint32_t kZeroHashSeed = 0;
282
283 // Thomas Wang, Integer Hash Functions.
284 // http://www.concentric.net/~Ttwang/tech/inthash.htm
285 inline uint32_t ComputeIntegerHash(uint32_t key, uint32_t seed) {
286   uint32_t hash = key;
287   hash = hash ^ seed;
288   hash = ~hash + (hash << 15);  // hash = (hash << 15) - hash - 1;
289   hash = hash ^ (hash >> 12);
290   hash = hash + (hash << 2);
291   hash = hash ^ (hash >> 4);
292   hash = hash * 2057;  // hash = (hash + (hash << 3)) + (hash << 11);
293   hash = hash ^ (hash >> 16);
294   return hash;
295 }
296
297
298 inline uint32_t ComputeLongHash(uint64_t key) {
299   uint64_t hash = key;
300   hash = ~hash + (hash << 18);  // hash = (hash << 18) - hash - 1;
301   hash = hash ^ (hash >> 31);
302   hash = hash * 21;  // hash = (hash + (hash << 2)) + (hash << 4);
303   hash = hash ^ (hash >> 11);
304   hash = hash + (hash << 6);
305   hash = hash ^ (hash >> 22);
306   return (uint32_t) hash;
307 }
308
309
310 inline uint32_t ComputePointerHash(void* ptr) {
311   return ComputeIntegerHash(
312       static_cast<uint32_t>(reinterpret_cast<intptr_t>(ptr)),
313       v8::internal::kZeroHashSeed);
314 }
315
316
317 // ----------------------------------------------------------------------------
318 // Miscellaneous
319
320 // A static resource holds a static instance that can be reserved in
321 // a local scope using an instance of Access.  Attempts to re-reserve
322 // the instance will cause an error.
323 template <typename T>
324 class StaticResource {
325  public:
326   StaticResource() : is_reserved_(false)  {}
327
328  private:
329   template <typename S> friend class Access;
330   T instance_;
331   bool is_reserved_;
332 };
333
334
335 // Locally scoped access to a static resource.
336 template <typename T>
337 class Access {
338  public:
339   explicit Access(StaticResource<T>* resource)
340     : resource_(resource)
341     , instance_(&resource->instance_) {
342     ASSERT(!resource->is_reserved_);
343     resource->is_reserved_ = true;
344   }
345
346   ~Access() {
347     resource_->is_reserved_ = false;
348     resource_ = NULL;
349     instance_ = NULL;
350   }
351
352   T* value()  { return instance_; }
353   T* operator -> ()  { return instance_; }
354
355  private:
356   StaticResource<T>* resource_;
357   T* instance_;
358 };
359
360
361 template <typename T>
362 class Vector {
363  public:
364   Vector() : start_(NULL), length_(0) {}
365   Vector(T* data, int length) : start_(data), length_(length) {
366     ASSERT(length == 0 || (length > 0 && data != NULL));
367   }
368
369   static Vector<T> New(int length) {
370     return Vector<T>(NewArray<T>(length), length);
371   }
372
373   // Returns a vector using the same backing storage as this one,
374   // spanning from and including 'from', to but not including 'to'.
375   Vector<T> SubVector(int from, int to) {
376     ASSERT(to <= length_);
377     ASSERT(from < to);
378     ASSERT(0 <= from);
379     return Vector<T>(start() + from, to - from);
380   }
381
382   // Returns the length of the vector.
383   int length() const { return length_; }
384
385   // Returns whether or not the vector is empty.
386   bool is_empty() const { return length_ == 0; }
387
388   // Returns the pointer to the start of the data in the vector.
389   T* start() const { return start_; }
390
391   // Access individual vector elements - checks bounds in debug mode.
392   T& operator[](int index) const {
393     ASSERT(0 <= index && index < length_);
394     return start_[index];
395   }
396
397   const T& at(int index) const { return operator[](index); }
398
399   T& first() { return start_[0]; }
400
401   T& last() { return start_[length_ - 1]; }
402
403   // Returns a clone of this vector with a new backing store.
404   Vector<T> Clone() const {
405     T* result = NewArray<T>(length_);
406     for (int i = 0; i < length_; i++) result[i] = start_[i];
407     return Vector<T>(result, length_);
408   }
409
410   void Sort(int (*cmp)(const T*, const T*)) {
411     typedef int (*RawComparer)(const void*, const void*);
412     qsort(start(),
413           length(),
414           sizeof(T),
415           reinterpret_cast<RawComparer>(cmp));
416   }
417
418   void Sort() {
419     Sort(PointerValueCompare<T>);
420   }
421
422   void Truncate(int length) {
423     ASSERT(length <= length_);
424     length_ = length;
425   }
426
427   // Releases the array underlying this vector. Once disposed the
428   // vector is empty.
429   void Dispose() {
430     DeleteArray(start_);
431     start_ = NULL;
432     length_ = 0;
433   }
434
435   inline Vector<T> operator+(int offset) {
436     ASSERT(offset < length_);
437     return Vector<T>(start_ + offset, length_ - offset);
438   }
439
440   // Factory method for creating empty vectors.
441   static Vector<T> empty() { return Vector<T>(NULL, 0); }
442
443   template<typename S>
444   static Vector<T> cast(Vector<S> input) {
445     return Vector<T>(reinterpret_cast<T*>(input.start()),
446                      input.length() * sizeof(S) / sizeof(T));
447   }
448
449  protected:
450   void set_start(T* start) { start_ = start; }
451
452  private:
453   T* start_;
454   int length_;
455 };
456
457
458 // A pointer that can only be set once and doesn't allow NULL values.
459 template<typename T>
460 class SetOncePointer {
461  public:
462   SetOncePointer() : pointer_(NULL) { }
463
464   bool is_set() const { return pointer_ != NULL; }
465
466   T* get() const {
467     ASSERT(pointer_ != NULL);
468     return pointer_;
469   }
470
471   void set(T* value) {
472     ASSERT(pointer_ == NULL && value != NULL);
473     pointer_ = value;
474   }
475
476  private:
477   T* pointer_;
478 };
479
480
481 template <typename T, int kSize>
482 class EmbeddedVector : public Vector<T> {
483  public:
484   EmbeddedVector() : Vector<T>(buffer_, kSize) { }
485
486   explicit EmbeddedVector(T initial_value) : Vector<T>(buffer_, kSize) {
487     for (int i = 0; i < kSize; ++i) {
488       buffer_[i] = initial_value;
489     }
490   }
491
492   // When copying, make underlying Vector to reference our buffer.
493   EmbeddedVector(const EmbeddedVector& rhs)
494       : Vector<T>(rhs) {
495     memcpy(buffer_, rhs.buffer_, sizeof(T) * kSize);
496     set_start(buffer_);
497   }
498
499   EmbeddedVector& operator=(const EmbeddedVector& rhs) {
500     if (this == &rhs) return *this;
501     Vector<T>::operator=(rhs);
502     memcpy(buffer_, rhs.buffer_, sizeof(T) * kSize);
503     this->set_start(buffer_);
504     return *this;
505   }
506
507  private:
508   T buffer_[kSize];
509 };
510
511
512 template <typename T>
513 class ScopedVector : public Vector<T> {
514  public:
515   explicit ScopedVector(int length) : Vector<T>(NewArray<T>(length), length) { }
516   ~ScopedVector() {
517     DeleteArray(this->start());
518   }
519
520  private:
521   DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedVector);
522 };
523
524
525 inline Vector<const char> CStrVector(const char* data) {
526   return Vector<const char>(data, StrLength(data));
527 }
528
529 inline Vector<char> MutableCStrVector(char* data) {
530   return Vector<char>(data, StrLength(data));
531 }
532
533 inline Vector<char> MutableCStrVector(char* data, int max) {
534   int length = StrLength(data);
535   return Vector<char>(data, (length < max) ? length : max);
536 }
537
538
539 /*
540  * A class that collects values into a backing store.
541  * Specialized versions of the class can allow access to the backing store
542  * in different ways.
543  * There is no guarantee that the backing store is contiguous (and, as a
544  * consequence, no guarantees that consecutively added elements are adjacent
545  * in memory). The collector may move elements unless it has guaranteed not
546  * to.
547  */
548 template <typename T, int growth_factor = 2, int max_growth = 1 * MB>
549 class Collector {
550  public:
551   explicit Collector(int initial_capacity = kMinCapacity)
552       : index_(0), size_(0) {
553     current_chunk_ = Vector<T>::New(initial_capacity);
554   }
555
556   virtual ~Collector() {
557     // Free backing store (in reverse allocation order).
558     current_chunk_.Dispose();
559     for (int i = chunks_.length() - 1; i >= 0; i--) {
560       chunks_.at(i).Dispose();
561     }
562   }
563
564   // Add a single element.
565   inline void Add(T value) {
566     if (index_ >= current_chunk_.length()) {
567       Grow(1);
568     }
569     current_chunk_[index_] = value;
570     index_++;
571     size_++;
572   }
573
574   // Add a block of contiguous elements and return a Vector backed by the
575   // memory area.
576   // A basic Collector will keep this vector valid as long as the Collector
577   // is alive.
578   inline Vector<T> AddBlock(int size, T initial_value) {
579     ASSERT(size > 0);
580     if (size > current_chunk_.length() - index_) {
581       Grow(size);
582     }
583     T* position = current_chunk_.start() + index_;
584     index_ += size;
585     size_ += size;
586     for (int i = 0; i < size; i++) {
587       position[i] = initial_value;
588     }
589     return Vector<T>(position, size);
590   }
591
592
593   // Add a contiguous block of elements and return a vector backed
594   // by the added block.
595   // A basic Collector will keep this vector valid as long as the Collector
596   // is alive.
597   inline Vector<T> AddBlock(Vector<const T> source) {
598     if (source.length() > current_chunk_.length() - index_) {
599       Grow(source.length());
600     }
601     T* position = current_chunk_.start() + index_;
602     index_ += source.length();
603     size_ += source.length();
604     for (int i = 0; i < source.length(); i++) {
605       position[i] = source[i];
606     }
607     return Vector<T>(position, source.length());
608   }
609
610
611   // Write the contents of the collector into the provided vector.
612   void WriteTo(Vector<T> destination) {
613     ASSERT(size_ <= destination.length());
614     int position = 0;
615     for (int i = 0; i < chunks_.length(); i++) {
616       Vector<T> chunk = chunks_.at(i);
617       for (int j = 0; j < chunk.length(); j++) {
618         destination[position] = chunk[j];
619         position++;
620       }
621     }
622     for (int i = 0; i < index_; i++) {
623       destination[position] = current_chunk_[i];
624       position++;
625     }
626   }
627
628   // Allocate a single contiguous vector, copy all the collected
629   // elements to the vector, and return it.
630   // The caller is responsible for freeing the memory of the returned
631   // vector (e.g., using Vector::Dispose).
632   Vector<T> ToVector() {
633     Vector<T> new_store = Vector<T>::New(size_);
634     WriteTo(new_store);
635     return new_store;
636   }
637
638   // Resets the collector to be empty.
639   virtual void Reset();
640
641   // Total number of elements added to collector so far.
642   inline int size() { return size_; }
643
644  protected:
645   static const int kMinCapacity = 16;
646   List<Vector<T> > chunks_;
647   Vector<T> current_chunk_;  // Block of memory currently being written into.
648   int index_;  // Current index in current chunk.
649   int size_;  // Total number of elements in collector.
650
651   // Creates a new current chunk, and stores the old chunk in the chunks_ list.
652   void Grow(int min_capacity) {
653     ASSERT(growth_factor > 1);
654     int new_capacity;
655     int current_length = current_chunk_.length();
656     if (current_length < kMinCapacity) {
657       // The collector started out as empty.
658       new_capacity = min_capacity * growth_factor;
659       if (new_capacity < kMinCapacity) new_capacity = kMinCapacity;
660     } else {
661       int growth = current_length * (growth_factor - 1);
662       if (growth > max_growth) {
663         growth = max_growth;
664       }
665       new_capacity = current_length + growth;
666       if (new_capacity < min_capacity) {
667         new_capacity = min_capacity + growth;
668       }
669     }
670     NewChunk(new_capacity);
671     ASSERT(index_ + min_capacity <= current_chunk_.length());
672   }
673
674   // Before replacing the current chunk, give a subclass the option to move
675   // some of the current data into the new chunk. The function may update
676   // the current index_ value to represent data no longer in the current chunk.
677   // Returns the initial index of the new chunk (after copied data).
678   virtual void NewChunk(int new_capacity)  {
679     Vector<T> new_chunk = Vector<T>::New(new_capacity);
680     if (index_ > 0) {
681       chunks_.Add(current_chunk_.SubVector(0, index_));
682     } else {
683       current_chunk_.Dispose();
684     }
685     current_chunk_ = new_chunk;
686     index_ = 0;
687   }
688 };
689
690
691 /*
692  * A collector that allows sequences of values to be guaranteed to
693  * stay consecutive.
694  * If the backing store grows while a sequence is active, the current
695  * sequence might be moved, but after the sequence is ended, it will
696  * not move again.
697  * NOTICE: Blocks allocated using Collector::AddBlock(int) can move
698  * as well, if inside an active sequence where another element is added.
699  */
700 template <typename T, int growth_factor = 2, int max_growth = 1 * MB>
701 class SequenceCollector : public Collector<T, growth_factor, max_growth> {
702  public:
703   explicit SequenceCollector(int initial_capacity)
704       : Collector<T, growth_factor, max_growth>(initial_capacity),
705         sequence_start_(kNoSequence) { }
706
707   virtual ~SequenceCollector() {}
708
709   void StartSequence() {
710     ASSERT(sequence_start_ == kNoSequence);
711     sequence_start_ = this->index_;
712   }
713
714   Vector<T> EndSequence() {
715     ASSERT(sequence_start_ != kNoSequence);
716     int sequence_start = sequence_start_;
717     sequence_start_ = kNoSequence;
718     if (sequence_start == this->index_) return Vector<T>();
719     return this->current_chunk_.SubVector(sequence_start, this->index_);
720   }
721
722   // Drops the currently added sequence, and all collected elements in it.
723   void DropSequence() {
724     ASSERT(sequence_start_ != kNoSequence);
725     int sequence_length = this->index_ - sequence_start_;
726     this->index_ = sequence_start_;
727     this->size_ -= sequence_length;
728     sequence_start_ = kNoSequence;
729   }
730
731   virtual void Reset() {
732     sequence_start_ = kNoSequence;
733     this->Collector<T, growth_factor, max_growth>::Reset();
734   }
735
736  private:
737   static const int kNoSequence = -1;
738   int sequence_start_;
739
740   // Move the currently active sequence to the new chunk.
741   virtual void NewChunk(int new_capacity) {
742     if (sequence_start_ == kNoSequence) {
743       // Fall back on default behavior if no sequence has been started.
744       this->Collector<T, growth_factor, max_growth>::NewChunk(new_capacity);
745       return;
746     }
747     int sequence_length = this->index_ - sequence_start_;
748     Vector<T> new_chunk = Vector<T>::New(sequence_length + new_capacity);
749     ASSERT(sequence_length < new_chunk.length());
750     for (int i = 0; i < sequence_length; i++) {
751       new_chunk[i] = this->current_chunk_[sequence_start_ + i];
752     }
753     if (sequence_start_ > 0) {
754       this->chunks_.Add(this->current_chunk_.SubVector(0, sequence_start_));
755     } else {
756       this->current_chunk_.Dispose();
757     }
758     this->current_chunk_ = new_chunk;
759     this->index_ = sequence_length;
760     sequence_start_ = 0;
761   }
762 };
763
764
765 // Compare ASCII/16bit chars to ASCII/16bit chars.
766 template <typename lchar, typename rchar>
767 inline int CompareChars(const lchar* lhs, const rchar* rhs, int chars) {
768   const lchar* limit = lhs + chars;
769 #ifdef V8_HOST_CAN_READ_UNALIGNED
770   if (sizeof(*lhs) == sizeof(*rhs)) {
771     // Number of characters in a uintptr_t.
772     static const int kStepSize = sizeof(uintptr_t) / sizeof(*lhs);  // NOLINT
773     while (lhs <= limit - kStepSize) {
774       if (*reinterpret_cast<const uintptr_t*>(lhs) !=
775           *reinterpret_cast<const uintptr_t*>(rhs)) {
776         break;
777       }
778       lhs += kStepSize;
779       rhs += kStepSize;
780     }
781   }
782 #endif
783   while (lhs < limit) {
784     int r = static_cast<int>(*lhs) - static_cast<int>(*rhs);
785     if (r != 0) return r;
786     ++lhs;
787     ++rhs;
788   }
789   return 0;
790 }
791
792
793 // Calculate 10^exponent.
794 inline int TenToThe(int exponent) {
795   ASSERT(exponent <= 9);
796   ASSERT(exponent >= 1);
797   int answer = 10;
798   for (int i = 1; i < exponent; i++) answer *= 10;
799   return answer;
800 }
801
802
803 // The type-based aliasing rule allows the compiler to assume that pointers of
804 // different types (for some definition of different) never alias each other.
805 // Thus the following code does not work:
806 //
807 // float f = foo();
808 // int fbits = *(int*)(&f);
809 //
810 // The compiler 'knows' that the int pointer can't refer to f since the types
811 // don't match, so the compiler may cache f in a register, leaving random data
812 // in fbits.  Using C++ style casts makes no difference, however a pointer to
813 // char data is assumed to alias any other pointer.  This is the 'memcpy
814 // exception'.
815 //
816 // Bit_cast uses the memcpy exception to move the bits from a variable of one
817 // type of a variable of another type.  Of course the end result is likely to
818 // be implementation dependent.  Most compilers (gcc-4.2 and MSVC 2005)
819 // will completely optimize BitCast away.
820 //
821 // There is an additional use for BitCast.
822 // Recent gccs will warn when they see casts that may result in breakage due to
823 // the type-based aliasing rule.  If you have checked that there is no breakage
824 // you can use BitCast to cast one pointer type to another.  This confuses gcc
825 // enough that it can no longer see that you have cast one pointer type to
826 // another thus avoiding the warning.
827
828 // We need different implementations of BitCast for pointer and non-pointer
829 // values. We use partial specialization of auxiliary struct to work around
830 // issues with template functions overloading.
831 template <class Dest, class Source>
832 struct BitCastHelper {
833   STATIC_ASSERT(sizeof(Dest) == sizeof(Source));
834
835   INLINE(static Dest cast(const Source& source)) {
836     Dest dest;
837     memcpy(&dest, &source, sizeof(dest));
838     return dest;
839   }
840 };
841
842 template <class Dest, class Source>
843 struct BitCastHelper<Dest, Source*> {
844   INLINE(static Dest cast(Source* source)) {
845     return BitCastHelper<Dest, uintptr_t>::
846         cast(reinterpret_cast<uintptr_t>(source));
847   }
848 };
849
850 template <class Dest, class Source>
851 INLINE(Dest BitCast(const Source& source));
852
853 template <class Dest, class Source>
854 inline Dest BitCast(const Source& source) {
855   return BitCastHelper<Dest, Source>::cast(source);
856 }
857
858
859 template<typename ElementType, int NumElements>
860 class EmbeddedContainer {
861  public:
862   EmbeddedContainer() : elems_() { }
863
864   int length() { return NumElements; }
865   ElementType& operator[](int i) {
866     ASSERT(i < length());
867     return elems_[i];
868   }
869
870  private:
871   ElementType elems_[NumElements];
872 };
873
874
875 template<typename ElementType>
876 class EmbeddedContainer<ElementType, 0> {
877  public:
878   int length() { return 0; }
879   ElementType& operator[](int i) {
880     UNREACHABLE();
881     static ElementType t = 0;
882     return t;
883   }
884 };
885
886
887 // Helper class for building result strings in a character buffer. The
888 // purpose of the class is to use safe operations that checks the
889 // buffer bounds on all operations in debug mode.
890 // This simple base class does not allow formatted output.
891 class SimpleStringBuilder {
892  public:
893   // Create a string builder with a buffer of the given size. The
894   // buffer is allocated through NewArray<char> and must be
895   // deallocated by the caller of Finalize().
896   explicit SimpleStringBuilder(int size);
897
898   SimpleStringBuilder(char* buffer, int size)
899       : buffer_(buffer, size), position_(0) { }
900
901   ~SimpleStringBuilder() { if (!is_finalized()) Finalize(); }
902
903   int size() const { return buffer_.length(); }
904
905   // Get the current position in the builder.
906   int position() const {
907     ASSERT(!is_finalized());
908     return position_;
909   }
910
911   // Reset the position.
912   void Reset() { position_ = 0; }
913
914   // Add a single character to the builder. It is not allowed to add
915   // 0-characters; use the Finalize() method to terminate the string
916   // instead.
917   void AddCharacter(char c) {
918     ASSERT(c != '\0');
919     ASSERT(!is_finalized() && position_ < buffer_.length());
920     buffer_[position_++] = c;
921   }
922
923   // Add an entire string to the builder. Uses strlen() internally to
924   // compute the length of the input string.
925   void AddString(const char* s);
926
927   // Add the first 'n' characters of the given string 's' to the
928   // builder. The input string must have enough characters.
929   void AddSubstring(const char* s, int n);
930
931   // Add character padding to the builder. If count is non-positive,
932   // nothing is added to the builder.
933   void AddPadding(char c, int count);
934
935   // Add the decimal representation of the value.
936   void AddDecimalInteger(int value);
937
938   // Finalize the string by 0-terminating it and returning the buffer.
939   char* Finalize();
940
941  protected:
942   Vector<char> buffer_;
943   int position_;
944
945   bool is_finalized() const { return position_ < 0; }
946
947  private:
948   DISALLOW_IMPLICIT_CONSTRUCTORS(SimpleStringBuilder);
949 };
950
951
952 // A poor man's version of STL's bitset: A bit set of enums E (without explicit
953 // values), fitting into an integral type T.
954 template <class E, class T = int>
955 class EnumSet {
956  public:
957   explicit EnumSet(T bits = 0) : bits_(bits) {}
958   bool IsEmpty() const { return bits_ == 0; }
959   bool Contains(E element) const { return (bits_ & Mask(element)) != 0; }
960   bool ContainsAnyOf(const EnumSet& set) const {
961     return (bits_ & set.bits_) != 0;
962   }
963   void Add(E element) { bits_ |= Mask(element); }
964   void Add(const EnumSet& set) { bits_ |= set.bits_; }
965   void Remove(E element) { bits_ &= ~Mask(element); }
966   void Remove(const EnumSet& set) { bits_ &= ~set.bits_; }
967   void RemoveAll() { bits_ = 0; }
968   void Intersect(const EnumSet& set) { bits_ &= set.bits_; }
969   T ToIntegral() const { return bits_; }
970   bool operator==(const EnumSet& set) { return bits_ == set.bits_; }
971
972  private:
973   T Mask(E element) const {
974     // The strange typing in ASSERT is necessary to avoid stupid warnings, see:
975     // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43680
976     ASSERT(element < static_cast<int>(sizeof(T) * CHAR_BIT));
977     return 1 << element;
978   }
979
980   T bits_;
981 };
982
983 } }  // namespace v8::internal
984
985 #endif  // V8_UTILS_H_