Home | History | Annotate | Download | only in src
      1 // Copyright 2006-2008 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 
     34 #include "globals.h"
     35 #include "checks.h"
     36 #include "allocation.h"
     37 
     38 namespace v8 {
     39 namespace internal {
     40 
     41 // ----------------------------------------------------------------------------
     42 // General helper functions
     43 
     44 #define IS_POWER_OF_TWO(x) (((x) & ((x) - 1)) == 0)
     45 
     46 // Returns true iff x is a power of 2 (or zero). Cannot be used with the
     47 // maximally negative value of the type T (the -1 overflows).
     48 template <typename T>
     49 static inline bool IsPowerOf2(T x) {
     50   return IS_POWER_OF_TWO(x);
     51 }
     52 
     53 
     54 // X must be a power of 2.  Returns the number of trailing zeros.
     55 template <typename T>
     56 static inline int WhichPowerOf2(T x) {
     57   ASSERT(IsPowerOf2(x));
     58   ASSERT(x != 0);
     59   if (x < 0) return 31;
     60   int bits = 0;
     61 #ifdef DEBUG
     62   int original_x = x;
     63 #endif
     64   if (x >= 0x10000) {
     65     bits += 16;
     66     x >>= 16;
     67   }
     68   if (x >= 0x100) {
     69     bits += 8;
     70     x >>= 8;
     71   }
     72   if (x >= 0x10) {
     73     bits += 4;
     74     x >>= 4;
     75   }
     76   switch (x) {
     77     default: UNREACHABLE();
     78     case 8: bits++;  // Fall through.
     79     case 4: bits++;  // Fall through.
     80     case 2: bits++;  // Fall through.
     81     case 1: break;
     82   }
     83   ASSERT_EQ(1 << bits, original_x);
     84   return bits;
     85   return 0;
     86 }
     87 
     88 
     89 // The C++ standard leaves the semantics of '>>' undefined for
     90 // negative signed operands. Most implementations do the right thing,
     91 // though.
     92 static inline int ArithmeticShiftRight(int x, int s) {
     93   return x >> s;
     94 }
     95 
     96 
     97 // Compute the 0-relative offset of some absolute value x of type T.
     98 // This allows conversion of Addresses and integral types into
     99 // 0-relative int offsets.
    100 template <typename T>
    101 static inline intptr_t OffsetFrom(T x) {
    102   return x - static_cast<T>(0);
    103 }
    104 
    105 
    106 // Compute the absolute value of type T for some 0-relative offset x.
    107 // This allows conversion of 0-relative int offsets into Addresses and
    108 // integral types.
    109 template <typename T>
    110 static inline T AddressFrom(intptr_t x) {
    111   return static_cast<T>(static_cast<T>(0) + x);
    112 }
    113 
    114 
    115 // Return the largest multiple of m which is <= x.
    116 template <typename T>
    117 static inline T RoundDown(T x, int m) {
    118   ASSERT(IsPowerOf2(m));
    119   return AddressFrom<T>(OffsetFrom(x) & -m);
    120 }
    121 
    122 
    123 // Return the smallest multiple of m which is >= x.
    124 template <typename T>
    125 static inline T RoundUp(T x, int m) {
    126   return RoundDown(x + m - 1, m);
    127 }
    128 
    129 
    130 template <typename T>
    131 static int Compare(const T& a, const T& b) {
    132   if (a == b)
    133     return 0;
    134   else if (a < b)
    135     return -1;
    136   else
    137     return 1;
    138 }
    139 
    140 
    141 template <typename T>
    142 static int PointerValueCompare(const T* a, const T* b) {
    143   return Compare<T>(*a, *b);
    144 }
    145 
    146 
    147 // Returns the smallest power of two which is >= x. If you pass in a
    148 // number that is already a power of two, it is returned as is.
    149 // Implementation is from "Hacker's Delight" by Henry S. Warren, Jr.,
    150 // figure 3-3, page 48, where the function is called clp2.
    151 static inline uint32_t RoundUpToPowerOf2(uint32_t x) {
    152   ASSERT(x <= 0x80000000u);
    153   x = x - 1;
    154   x = x | (x >> 1);
    155   x = x | (x >> 2);
    156   x = x | (x >> 4);
    157   x = x | (x >> 8);
    158   x = x | (x >> 16);
    159   return x + 1;
    160 }
    161 
    162 
    163 
    164 template <typename T>
    165 static inline bool IsAligned(T value, T alignment) {
    166   ASSERT(IsPowerOf2(alignment));
    167   return (value & (alignment - 1)) == 0;
    168 }
    169 
    170 
    171 // Returns true if (addr + offset) is aligned.
    172 static inline bool IsAddressAligned(Address addr,
    173                                     intptr_t alignment,
    174                                     int offset) {
    175   intptr_t offs = OffsetFrom(addr + offset);
    176   return IsAligned(offs, alignment);
    177 }
    178 
    179 
    180 // Returns the maximum of the two parameters.
    181 template <typename T>
    182 static T Max(T a, T b) {
    183   return a < b ? b : a;
    184 }
    185 
    186 
    187 // Returns the minimum of the two parameters.
    188 template <typename T>
    189 static T Min(T a, T b) {
    190   return a < b ? a : b;
    191 }
    192 
    193 
    194 inline int StrLength(const char* string) {
    195   size_t length = strlen(string);
    196   ASSERT(length == static_cast<size_t>(static_cast<int>(length)));
    197   return static_cast<int>(length);
    198 }
    199 
    200 
    201 // ----------------------------------------------------------------------------
    202 // BitField is a help template for encoding and decode bitfield with
    203 // unsigned content.
    204 template<class T, int shift, int size>
    205 class BitField {
    206  public:
    207   // Tells whether the provided value fits into the bit field.
    208   static bool is_valid(T value) {
    209     return (static_cast<uint32_t>(value) & ~((1U << (size)) - 1)) == 0;
    210   }
    211 
    212   // Returns a uint32_t mask of bit field.
    213   static uint32_t mask() {
    214     // To use all bits of a uint32 in a bitfield without compiler warnings we
    215     // have to compute 2^32 without using a shift count of 32.
    216     return ((1U << shift) << size) - (1U << shift);
    217   }
    218 
    219   // Returns a uint32_t with the bit field value encoded.
    220   static uint32_t encode(T value) {
    221     ASSERT(is_valid(value));
    222     return static_cast<uint32_t>(value) << shift;
    223   }
    224 
    225   // Extracts the bit field from the value.
    226   static T decode(uint32_t value) {
    227     return static_cast<T>((value & mask()) >> shift);
    228   }
    229 
    230   // Value for the field with all bits set.
    231   static T max() {
    232     return decode(mask());
    233   }
    234 };
    235 
    236 
    237 // ----------------------------------------------------------------------------
    238 // Hash function.
    239 
    240 // Thomas Wang, Integer Hash Functions.
    241 // http://www.concentric.net/~Ttwang/tech/inthash.htm
    242 static inline uint32_t ComputeIntegerHash(uint32_t key) {
    243   uint32_t hash = key;
    244   hash = ~hash + (hash << 15);  // hash = (hash << 15) - hash - 1;
    245   hash = hash ^ (hash >> 12);
    246   hash = hash + (hash << 2);
    247   hash = hash ^ (hash >> 4);
    248   hash = hash * 2057;  // hash = (hash + (hash << 3)) + (hash << 11);
    249   hash = hash ^ (hash >> 16);
    250   return hash;
    251 }
    252 
    253 
    254 // ----------------------------------------------------------------------------
    255 // Miscellaneous
    256 
    257 // A static resource holds a static instance that can be reserved in
    258 // a local scope using an instance of Access.  Attempts to re-reserve
    259 // the instance will cause an error.
    260 template <typename T>
    261 class StaticResource {
    262  public:
    263   StaticResource() : is_reserved_(false)  {}
    264 
    265  private:
    266   template <typename S> friend class Access;
    267   T instance_;
    268   bool is_reserved_;
    269 };
    270 
    271 
    272 // Locally scoped access to a static resource.
    273 template <typename T>
    274 class Access {
    275  public:
    276   explicit Access(StaticResource<T>* resource)
    277     : resource_(resource)
    278     , instance_(&resource->instance_) {
    279     ASSERT(!resource->is_reserved_);
    280     resource->is_reserved_ = true;
    281   }
    282 
    283   ~Access() {
    284     resource_->is_reserved_ = false;
    285     resource_ = NULL;
    286     instance_ = NULL;
    287   }
    288 
    289   T* value()  { return instance_; }
    290   T* operator -> ()  { return instance_; }
    291 
    292  private:
    293   StaticResource<T>* resource_;
    294   T* instance_;
    295 };
    296 
    297 
    298 template <typename T>
    299 class Vector {
    300  public:
    301   Vector() : start_(NULL), length_(0) {}
    302   Vector(T* data, int length) : start_(data), length_(length) {
    303     ASSERT(length == 0 || (length > 0 && data != NULL));
    304   }
    305 
    306   static Vector<T> New(int length) {
    307     return Vector<T>(NewArray<T>(length), length);
    308   }
    309 
    310   // Returns a vector using the same backing storage as this one,
    311   // spanning from and including 'from', to but not including 'to'.
    312   Vector<T> SubVector(int from, int to) {
    313     ASSERT(to <= length_);
    314     ASSERT(from < to);
    315     ASSERT(0 <= from);
    316     return Vector<T>(start() + from, to - from);
    317   }
    318 
    319   // Returns the length of the vector.
    320   int length() const { return length_; }
    321 
    322   // Returns whether or not the vector is empty.
    323   bool is_empty() const { return length_ == 0; }
    324 
    325   // Returns the pointer to the start of the data in the vector.
    326   T* start() const { return start_; }
    327 
    328   // Access individual vector elements - checks bounds in debug mode.
    329   T& operator[](int index) const {
    330     ASSERT(0 <= index && index < length_);
    331     return start_[index];
    332   }
    333 
    334   const T& at(int index) const { return operator[](index); }
    335 
    336   T& first() { return start_[0]; }
    337 
    338   T& last() { return start_[length_ - 1]; }
    339 
    340   // Returns a clone of this vector with a new backing store.
    341   Vector<T> Clone() const {
    342     T* result = NewArray<T>(length_);
    343     for (int i = 0; i < length_; i++) result[i] = start_[i];
    344     return Vector<T>(result, length_);
    345   }
    346 
    347   void Sort(int (*cmp)(const T*, const T*)) {
    348     typedef int (*RawComparer)(const void*, const void*);
    349     qsort(start(),
    350           length(),
    351           sizeof(T),
    352           reinterpret_cast<RawComparer>(cmp));
    353   }
    354 
    355   void Sort() {
    356     Sort(PointerValueCompare<T>);
    357   }
    358 
    359   void Truncate(int length) {
    360     ASSERT(length <= length_);
    361     length_ = length;
    362   }
    363 
    364   // Releases the array underlying this vector. Once disposed the
    365   // vector is empty.
    366   void Dispose() {
    367     DeleteArray(start_);
    368     start_ = NULL;
    369     length_ = 0;
    370   }
    371 
    372   inline Vector<T> operator+(int offset) {
    373     ASSERT(offset < length_);
    374     return Vector<T>(start_ + offset, length_ - offset);
    375   }
    376 
    377   // Factory method for creating empty vectors.
    378   static Vector<T> empty() { return Vector<T>(NULL, 0); }
    379 
    380   template<typename S>
    381   static Vector<T> cast(Vector<S> input) {
    382     return Vector<T>(reinterpret_cast<T*>(input.start()),
    383                      input.length() * sizeof(S) / sizeof(T));
    384   }
    385 
    386  protected:
    387   void set_start(T* start) { start_ = start; }
    388 
    389  private:
    390   T* start_;
    391   int length_;
    392 };
    393 
    394 
    395 // A pointer that can only be set once and doesn't allow NULL values.
    396 template<typename T>
    397 class SetOncePointer {
    398  public:
    399   SetOncePointer() : pointer_(NULL) { }
    400 
    401   bool is_set() const { return pointer_ != NULL; }
    402 
    403   T* get() const {
    404     ASSERT(pointer_ != NULL);
    405     return pointer_;
    406   }
    407 
    408   void set(T* value) {
    409     ASSERT(pointer_ == NULL && value != NULL);
    410     pointer_ = value;
    411   }
    412 
    413  private:
    414   T* pointer_;
    415 };
    416 
    417 
    418 template <typename T, int kSize>
    419 class EmbeddedVector : public Vector<T> {
    420  public:
    421   EmbeddedVector() : Vector<T>(buffer_, kSize) { }
    422 
    423   explicit EmbeddedVector(T initial_value) : Vector<T>(buffer_, kSize) {
    424     for (int i = 0; i < kSize; ++i) {
    425       buffer_[i] = initial_value;
    426     }
    427   }
    428 
    429   // When copying, make underlying Vector to reference our buffer.
    430   EmbeddedVector(const EmbeddedVector& rhs)
    431       : Vector<T>(rhs) {
    432     memcpy(buffer_, rhs.buffer_, sizeof(T) * kSize);
    433     set_start(buffer_);
    434   }
    435 
    436   EmbeddedVector& operator=(const EmbeddedVector& rhs) {
    437     if (this == &rhs) return *this;
    438     Vector<T>::operator=(rhs);
    439     memcpy(buffer_, rhs.buffer_, sizeof(T) * kSize);
    440     this->set_start(buffer_);
    441     return *this;
    442   }
    443 
    444  private:
    445   T buffer_[kSize];
    446 };
    447 
    448 
    449 template <typename T>
    450 class ScopedVector : public Vector<T> {
    451  public:
    452   explicit ScopedVector(int length) : Vector<T>(NewArray<T>(length), length) { }
    453   ~ScopedVector() {
    454     DeleteArray(this->start());
    455   }
    456 
    457  private:
    458   DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedVector);
    459 };
    460 
    461 
    462 inline Vector<const char> CStrVector(const char* data) {
    463   return Vector<const char>(data, StrLength(data));
    464 }
    465 
    466 inline Vector<char> MutableCStrVector(char* data) {
    467   return Vector<char>(data, StrLength(data));
    468 }
    469 
    470 inline Vector<char> MutableCStrVector(char* data, int max) {
    471   int length = StrLength(data);
    472   return Vector<char>(data, (length < max) ? length : max);
    473 }
    474 
    475 
    476 /*
    477  * A class that collects values into a backing store.
    478  * Specialized versions of the class can allow access to the backing store
    479  * in different ways.
    480  * There is no guarantee that the backing store is contiguous (and, as a
    481  * consequence, no guarantees that consecutively added elements are adjacent
    482  * in memory). The collector may move elements unless it has guaranteed not
    483  * to.
    484  */
    485 template <typename T, int growth_factor = 2, int max_growth = 1 * MB>
    486 class Collector {
    487  public:
    488   explicit Collector(int initial_capacity = kMinCapacity)
    489       : index_(0), size_(0) {
    490     if (initial_capacity < kMinCapacity) {
    491       initial_capacity = kMinCapacity;
    492     }
    493     current_chunk_ = Vector<T>::New(initial_capacity);
    494   }
    495 
    496   virtual ~Collector() {
    497     // Free backing store (in reverse allocation order).
    498     current_chunk_.Dispose();
    499     for (int i = chunks_.length() - 1; i >= 0; i--) {
    500       chunks_.at(i).Dispose();
    501     }
    502   }
    503 
    504   // Add a single element.
    505   inline void Add(T value) {
    506     if (index_ >= current_chunk_.length()) {
    507       Grow(1);
    508     }
    509     current_chunk_[index_] = value;
    510     index_++;
    511     size_++;
    512   }
    513 
    514   // Add a block of contiguous elements and return a Vector backed by the
    515   // memory area.
    516   // A basic Collector will keep this vector valid as long as the Collector
    517   // is alive.
    518   inline Vector<T> AddBlock(int size, T initial_value) {
    519     ASSERT(size > 0);
    520     if (size > current_chunk_.length() - index_) {
    521       Grow(size);
    522     }
    523     T* position = current_chunk_.start() + index_;
    524     index_ += size;
    525     size_ += size;
    526     for (int i = 0; i < size; i++) {
    527       position[i] = initial_value;
    528     }
    529     return Vector<T>(position, size);
    530   }
    531 
    532 
    533   // Add a contiguous block of elements and return a vector backed
    534   // by the added block.
    535   // A basic Collector will keep this vector valid as long as the Collector
    536   // is alive.
    537   inline Vector<T> AddBlock(Vector<const T> source) {
    538     if (source.length() > current_chunk_.length() - index_) {
    539       Grow(source.length());
    540     }
    541     T* position = current_chunk_.start() + index_;
    542     index_ += source.length();
    543     size_ += source.length();
    544     for (int i = 0; i < source.length(); i++) {
    545       position[i] = source[i];
    546     }
    547     return Vector<T>(position, source.length());
    548   }
    549 
    550 
    551   // Write the contents of the collector into the provided vector.
    552   void WriteTo(Vector<T> destination) {
    553     ASSERT(size_ <= destination.length());
    554     int position = 0;
    555     for (int i = 0; i < chunks_.length(); i++) {
    556       Vector<T> chunk = chunks_.at(i);
    557       for (int j = 0; j < chunk.length(); j++) {
    558         destination[position] = chunk[j];
    559         position++;
    560       }
    561     }
    562     for (int i = 0; i < index_; i++) {
    563       destination[position] = current_chunk_[i];
    564       position++;
    565     }
    566   }
    567 
    568   // Allocate a single contiguous vector, copy all the collected
    569   // elements to the vector, and return it.
    570   // The caller is responsible for freeing the memory of the returned
    571   // vector (e.g., using Vector::Dispose).
    572   Vector<T> ToVector() {
    573     Vector<T> new_store = Vector<T>::New(size_);
    574     WriteTo(new_store);
    575     return new_store;
    576   }
    577 
    578   // Resets the collector to be empty.
    579   virtual void Reset() {
    580     for (int i = chunks_.length() - 1; i >= 0; i--) {
    581       chunks_.at(i).Dispose();
    582     }
    583     chunks_.Rewind(0);
    584     index_ = 0;
    585     size_ = 0;
    586   }
    587 
    588   // Total number of elements added to collector so far.
    589   inline int size() { return size_; }
    590 
    591  protected:
    592   static const int kMinCapacity = 16;
    593   List<Vector<T> > chunks_;
    594   Vector<T> current_chunk_;  // Block of memory currently being written into.
    595   int index_;  // Current index in current chunk.
    596   int size_;  // Total number of elements in collector.
    597 
    598   // Creates a new current chunk, and stores the old chunk in the chunks_ list.
    599   void Grow(int min_capacity) {
    600     ASSERT(growth_factor > 1);
    601     int growth = current_chunk_.length() * (growth_factor - 1);
    602     if (growth > max_growth) {
    603       growth = max_growth;
    604     }
    605     int new_capacity = current_chunk_.length() + growth;
    606     if (new_capacity < min_capacity) {
    607       new_capacity = min_capacity + growth;
    608     }
    609     Vector<T> new_chunk = Vector<T>::New(new_capacity);
    610     int new_index = PrepareGrow(new_chunk);
    611     if (index_ > 0) {
    612       chunks_.Add(current_chunk_.SubVector(0, index_));
    613     } else {
    614       // Can happen if the call to PrepareGrow moves everything into
    615       // the new chunk.
    616       current_chunk_.Dispose();
    617     }
    618     current_chunk_ = new_chunk;
    619     index_ = new_index;
    620     ASSERT(index_ + min_capacity <= current_chunk_.length());
    621   }
    622 
    623   // Before replacing the current chunk, give a subclass the option to move
    624   // some of the current data into the new chunk. The function may update
    625   // the current index_ value to represent data no longer in the current chunk.
    626   // Returns the initial index of the new chunk (after copied data).
    627   virtual int PrepareGrow(Vector<T> new_chunk)  {
    628     return 0;
    629   }
    630 };
    631 
    632 
    633 /*
    634  * A collector that allows sequences of values to be guaranteed to
    635  * stay consecutive.
    636  * If the backing store grows while a sequence is active, the current
    637  * sequence might be moved, but after the sequence is ended, it will
    638  * not move again.
    639  * NOTICE: Blocks allocated using Collector::AddBlock(int) can move
    640  * as well, if inside an active sequence where another element is added.
    641  */
    642 template <typename T, int growth_factor = 2, int max_growth = 1 * MB>
    643 class SequenceCollector : public Collector<T, growth_factor, max_growth> {
    644  public:
    645   explicit SequenceCollector(int initial_capacity)
    646       : Collector<T, growth_factor, max_growth>(initial_capacity),
    647         sequence_start_(kNoSequence) { }
    648 
    649   virtual ~SequenceCollector() {}
    650 
    651   void StartSequence() {
    652     ASSERT(sequence_start_ == kNoSequence);
    653     sequence_start_ = this->index_;
    654   }
    655 
    656   Vector<T> EndSequence() {
    657     ASSERT(sequence_start_ != kNoSequence);
    658     int sequence_start = sequence_start_;
    659     sequence_start_ = kNoSequence;
    660     if (sequence_start == this->index_) return Vector<T>();
    661     return this->current_chunk_.SubVector(sequence_start, this->index_);
    662   }
    663 
    664   // Drops the currently added sequence, and all collected elements in it.
    665   void DropSequence() {
    666     ASSERT(sequence_start_ != kNoSequence);
    667     int sequence_length = this->index_ - sequence_start_;
    668     this->index_ = sequence_start_;
    669     this->size_ -= sequence_length;
    670     sequence_start_ = kNoSequence;
    671   }
    672 
    673   virtual void Reset() {
    674     sequence_start_ = kNoSequence;
    675     this->Collector<T, growth_factor, max_growth>::Reset();
    676   }
    677 
    678  private:
    679   static const int kNoSequence = -1;
    680   int sequence_start_;
    681 
    682   // Move the currently active sequence to the new chunk.
    683   virtual int PrepareGrow(Vector<T> new_chunk) {
    684     if (sequence_start_ != kNoSequence) {
    685       int sequence_length = this->index_ - sequence_start_;
    686       // The new chunk is always larger than the current chunk, so there
    687       // is room for the copy.
    688       ASSERT(sequence_length < new_chunk.length());
    689       for (int i = 0; i < sequence_length; i++) {
    690         new_chunk[i] = this->current_chunk_[sequence_start_ + i];
    691       }
    692       this->index_ = sequence_start_;
    693       sequence_start_ = 0;
    694       return sequence_length;
    695     }
    696     return 0;
    697   }
    698 };
    699 
    700 
    701 // Compare ASCII/16bit chars to ASCII/16bit chars.
    702 template <typename lchar, typename rchar>
    703 static inline int CompareChars(const lchar* lhs, const rchar* rhs, int chars) {
    704   const lchar* limit = lhs + chars;
    705 #ifdef V8_HOST_CAN_READ_UNALIGNED
    706   if (sizeof(*lhs) == sizeof(*rhs)) {
    707     // Number of characters in a uintptr_t.
    708     static const int kStepSize = sizeof(uintptr_t) / sizeof(*lhs);  // NOLINT
    709     while (lhs <= limit - kStepSize) {
    710       if (*reinterpret_cast<const uintptr_t*>(lhs) !=
    711           *reinterpret_cast<const uintptr_t*>(rhs)) {
    712         break;
    713       }
    714       lhs += kStepSize;
    715       rhs += kStepSize;
    716     }
    717   }
    718 #endif
    719   while (lhs < limit) {
    720     int r = static_cast<int>(*lhs) - static_cast<int>(*rhs);
    721     if (r != 0) return r;
    722     ++lhs;
    723     ++rhs;
    724   }
    725   return 0;
    726 }
    727 
    728 
    729 // Calculate 10^exponent.
    730 static inline int TenToThe(int exponent) {
    731   ASSERT(exponent <= 9);
    732   ASSERT(exponent >= 1);
    733   int answer = 10;
    734   for (int i = 1; i < exponent; i++) answer *= 10;
    735   return answer;
    736 }
    737 
    738 
    739 // The type-based aliasing rule allows the compiler to assume that pointers of
    740 // different types (for some definition of different) never alias each other.
    741 // Thus the following code does not work:
    742 //
    743 // float f = foo();
    744 // int fbits = *(int*)(&f);
    745 //
    746 // The compiler 'knows' that the int pointer can't refer to f since the types
    747 // don't match, so the compiler may cache f in a register, leaving random data
    748 // in fbits.  Using C++ style casts makes no difference, however a pointer to
    749 // char data is assumed to alias any other pointer.  This is the 'memcpy
    750 // exception'.
    751 //
    752 // Bit_cast uses the memcpy exception to move the bits from a variable of one
    753 // type of a variable of another type.  Of course the end result is likely to
    754 // be implementation dependent.  Most compilers (gcc-4.2 and MSVC 2005)
    755 // will completely optimize BitCast away.
    756 //
    757 // There is an additional use for BitCast.
    758 // Recent gccs will warn when they see casts that may result in breakage due to
    759 // the type-based aliasing rule.  If you have checked that there is no breakage
    760 // you can use BitCast to cast one pointer type to another.  This confuses gcc
    761 // enough that it can no longer see that you have cast one pointer type to
    762 // another thus avoiding the warning.
    763 
    764 // We need different implementations of BitCast for pointer and non-pointer
    765 // values. We use partial specialization of auxiliary struct to work around
    766 // issues with template functions overloading.
    767 template <class Dest, class Source>
    768 struct BitCastHelper {
    769   STATIC_ASSERT(sizeof(Dest) == sizeof(Source));
    770 
    771   INLINE(static Dest cast(const Source& source)) {
    772     Dest dest;
    773     memcpy(&dest, &source, sizeof(dest));
    774     return dest;
    775   }
    776 };
    777 
    778 template <class Dest, class Source>
    779 struct BitCastHelper<Dest, Source*> {
    780   INLINE(static Dest cast(Source* source)) {
    781     return BitCastHelper<Dest, uintptr_t>::
    782         cast(reinterpret_cast<uintptr_t>(source));
    783   }
    784 };
    785 
    786 template <class Dest, class Source>
    787 INLINE(Dest BitCast(const Source& source));
    788 
    789 template <class Dest, class Source>
    790 inline Dest BitCast(const Source& source) {
    791   return BitCastHelper<Dest, Source>::cast(source);
    792 }
    793 
    794 } }  // namespace v8::internal
    795 
    796 #endif  // V8_UTILS_H_
    797