Home | History | Annotate | Download | only in src
      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_V8UTILS_H_
     29 #define V8_V8UTILS_H_
     30 
     31 #include "utils.h"
     32 #include "platform.h"  // For va_list on Solaris.
     33 
     34 namespace v8 {
     35 namespace internal {
     36 
     37 // ----------------------------------------------------------------------------
     38 // I/O support.
     39 
     40 #if __GNUC__ >= 4
     41 // On gcc we can ask the compiler to check the types of %d-style format
     42 // specifiers and their associated arguments.  TODO(erikcorry) fix this
     43 // so it works on MacOSX.
     44 #if defined(__MACH__) && defined(__APPLE__)
     45 #define PRINTF_CHECKING
     46 #define FPRINTF_CHECKING
     47 #else  // MacOsX.
     48 #define PRINTF_CHECKING __attribute__ ((format (printf, 1, 2)))
     49 #define FPRINTF_CHECKING __attribute__ ((format (printf, 2, 3)))
     50 #endif
     51 #else
     52 #define PRINTF_CHECKING
     53 #define FPRINTF_CHECKING
     54 #endif
     55 
     56 // Our version of printf().
     57 void PRINTF_CHECKING PrintF(const char* format, ...);
     58 void FPRINTF_CHECKING PrintF(FILE* out, const char* format, ...);
     59 
     60 // Prepends the current process ID to the output.
     61 void PRINTF_CHECKING PrintPID(const char* format, ...);
     62 
     63 // Our version of fflush.
     64 void Flush(FILE* out);
     65 
     66 inline void Flush() {
     67   Flush(stdout);
     68 }
     69 
     70 
     71 // Read a line of characters after printing the prompt to stdout. The resulting
     72 // char* needs to be disposed off with DeleteArray by the caller.
     73 char* ReadLine(const char* prompt);
     74 
     75 
     76 // Read and return the raw bytes in a file. the size of the buffer is returned
     77 // in size.
     78 // The returned buffer must be freed by the caller.
     79 byte* ReadBytes(const char* filename, int* size, bool verbose = true);
     80 
     81 
     82 // Append size chars from str to the file given by filename.
     83 // The file is overwritten. Returns the number of chars written.
     84 int AppendChars(const char* filename,
     85                 const char* str,
     86                 int size,
     87                 bool verbose = true);
     88 
     89 
     90 // Write size chars from str to the file given by filename.
     91 // The file is overwritten. Returns the number of chars written.
     92 int WriteChars(const char* filename,
     93                const char* str,
     94                int size,
     95                bool verbose = true);
     96 
     97 
     98 // Write size bytes to the file given by filename.
     99 // The file is overwritten. Returns the number of bytes written.
    100 int WriteBytes(const char* filename,
    101                const byte* bytes,
    102                int size,
    103                bool verbose = true);
    104 
    105 
    106 // Write the C code
    107 // const char* <varname> = "<str>";
    108 // const int <varname>_len = <len>;
    109 // to the file given by filename. Only the first len chars are written.
    110 int WriteAsCFile(const char* filename, const char* varname,
    111                  const char* str, int size, bool verbose = true);
    112 
    113 
    114 // ----------------------------------------------------------------------------
    115 // Data structures
    116 
    117 template <typename T>
    118 inline Vector< Handle<Object> > HandleVector(v8::internal::Handle<T>* elms,
    119                                              int length) {
    120   return Vector< Handle<Object> >(
    121       reinterpret_cast<v8::internal::Handle<Object>*>(elms), length);
    122 }
    123 
    124 
    125 // ----------------------------------------------------------------------------
    126 // Memory
    127 
    128 // Copies words from |src| to |dst|. The data spans must not overlap.
    129 template <typename T>
    130 inline void CopyWords(T* dst, const T* src, size_t num_words) {
    131   STATIC_ASSERT(sizeof(T) == kPointerSize);
    132   ASSERT(Min(dst, const_cast<T*>(src)) + num_words <=
    133          Max(dst, const_cast<T*>(src)));
    134   ASSERT(num_words > 0);
    135 
    136   // Use block copying OS::MemCopy if the segment we're copying is
    137   // enough to justify the extra call/setup overhead.
    138   static const size_t kBlockCopyLimit = 16;
    139 
    140   if (num_words < kBlockCopyLimit) {
    141     do {
    142       num_words--;
    143       *dst++ = *src++;
    144     } while (num_words > 0);
    145   } else {
    146     OS::MemCopy(dst, src, num_words * kPointerSize);
    147   }
    148 }
    149 
    150 
    151 // Copies words from |src| to |dst|. No restrictions.
    152 template <typename T>
    153 inline void MoveWords(T* dst, const T* src, size_t num_words) {
    154   STATIC_ASSERT(sizeof(T) == kPointerSize);
    155   ASSERT(num_words > 0);
    156 
    157   // Use block copying OS::MemCopy if the segment we're copying is
    158   // enough to justify the extra call/setup overhead.
    159   static const size_t kBlockCopyLimit = 16;
    160 
    161   if (num_words < kBlockCopyLimit &&
    162       ((dst < src) || (dst >= (src + num_words * kPointerSize)))) {
    163     T* end = dst + num_words;
    164     do {
    165       num_words--;
    166       *dst++ = *src++;
    167     } while (num_words > 0);
    168   } else {
    169     OS::MemMove(dst, src, num_words * kPointerSize);
    170   }
    171 }
    172 
    173 
    174 // Copies data from |src| to |dst|.  The data spans must not overlap.
    175 template <typename T>
    176 inline void CopyBytes(T* dst, const T* src, size_t num_bytes) {
    177   STATIC_ASSERT(sizeof(T) == 1);
    178   ASSERT(Min(dst, const_cast<T*>(src)) + num_bytes <=
    179          Max(dst, const_cast<T*>(src)));
    180   if (num_bytes == 0) return;
    181 
    182   // Use block copying OS::MemCopy if the segment we're copying is
    183   // enough to justify the extra call/setup overhead.
    184   static const int kBlockCopyLimit = OS::kMinComplexMemCopy;
    185 
    186   if (num_bytes < static_cast<size_t>(kBlockCopyLimit)) {
    187     do {
    188       num_bytes--;
    189       *dst++ = *src++;
    190     } while (num_bytes > 0);
    191   } else {
    192     OS::MemCopy(dst, src, num_bytes);
    193   }
    194 }
    195 
    196 
    197 template <typename T, typename U>
    198 inline void MemsetPointer(T** dest, U* value, int counter) {
    199 #ifdef DEBUG
    200   T* a = NULL;
    201   U* b = NULL;
    202   a = b;  // Fake assignment to check assignability.
    203   USE(a);
    204 #endif  // DEBUG
    205 #if V8_HOST_ARCH_IA32
    206 #define STOS "stosl"
    207 #elif V8_HOST_ARCH_X64
    208 #define STOS "stosq"
    209 #endif
    210 #if defined(__native_client__)
    211   // This STOS sequence does not validate for x86_64 Native Client.
    212   // Here we #undef STOS to force use of the slower C version.
    213   // TODO(bradchen): Profile V8 and implement a faster REP STOS
    214   // here if the profile indicates it matters.
    215 #undef STOS
    216 #endif
    217 
    218 #if defined(__GNUC__) && defined(STOS)
    219   asm volatile(
    220       "cld;"
    221       "rep ; " STOS
    222       : "+&c" (counter), "+&D" (dest)
    223       : "a" (value)
    224       : "memory", "cc");
    225 #else
    226   for (int i = 0; i < counter; i++) {
    227     dest[i] = value;
    228   }
    229 #endif
    230 
    231 #undef STOS
    232 }
    233 
    234 
    235 // Simple wrapper that allows an ExternalString to refer to a
    236 // Vector<const char>. Doesn't assume ownership of the data.
    237 class AsciiStringAdapter: public v8::String::ExternalAsciiStringResource {
    238  public:
    239   explicit AsciiStringAdapter(Vector<const char> data) : data_(data) {}
    240 
    241   virtual const char* data() const { return data_.start(); }
    242 
    243   virtual size_t length() const { return data_.length(); }
    244 
    245  private:
    246   Vector<const char> data_;
    247 };
    248 
    249 
    250 // Simple support to read a file into a 0-terminated C-string.
    251 // The returned buffer must be freed by the caller.
    252 // On return, *exits tells whether the file existed.
    253 Vector<const char> ReadFile(const char* filename,
    254                             bool* exists,
    255                             bool verbose = true);
    256 Vector<const char> ReadFile(FILE* file,
    257                             bool* exists,
    258                             bool verbose = true);
    259 
    260 
    261 template <typename sourcechar, typename sinkchar>
    262 INLINE(static void CopyCharsUnsigned(sinkchar* dest,
    263                                      const sourcechar* src,
    264                                      int chars));
    265 #if defined(V8_HOST_ARCH_ARM)
    266 INLINE(void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, int chars));
    267 INLINE(void CopyCharsUnsigned(uint16_t* dest, const uint8_t* src, int chars));
    268 INLINE(void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, int chars));
    269 #endif
    270 
    271 // Copy from ASCII/16bit chars to ASCII/16bit chars.
    272 template <typename sourcechar, typename sinkchar>
    273 INLINE(void CopyChars(sinkchar* dest, const sourcechar* src, int chars));
    274 
    275 template<typename sourcechar, typename sinkchar>
    276 void CopyChars(sinkchar* dest, const sourcechar* src, int chars) {
    277   ASSERT(sizeof(sourcechar) <= 2);
    278   ASSERT(sizeof(sinkchar) <= 2);
    279   if (sizeof(sinkchar) == 1) {
    280     if (sizeof(sourcechar) == 1) {
    281       CopyCharsUnsigned(reinterpret_cast<uint8_t*>(dest),
    282                         reinterpret_cast<const uint8_t*>(src),
    283                         chars);
    284     } else {
    285       CopyCharsUnsigned(reinterpret_cast<uint8_t*>(dest),
    286                         reinterpret_cast<const uint16_t*>(src),
    287                         chars);
    288     }
    289   } else {
    290     if (sizeof(sourcechar) == 1) {
    291       CopyCharsUnsigned(reinterpret_cast<uint16_t*>(dest),
    292                         reinterpret_cast<const uint8_t*>(src),
    293                         chars);
    294     } else {
    295       CopyCharsUnsigned(reinterpret_cast<uint16_t*>(dest),
    296                         reinterpret_cast<const uint16_t*>(src),
    297                         chars);
    298     }
    299   }
    300 }
    301 
    302 template <typename sourcechar, typename sinkchar>
    303 void CopyCharsUnsigned(sinkchar* dest, const sourcechar* src, int chars) {
    304   sinkchar* limit = dest + chars;
    305 #ifdef V8_HOST_CAN_READ_UNALIGNED
    306   if (sizeof(*dest) == sizeof(*src)) {
    307     if (chars >= static_cast<int>(OS::kMinComplexMemCopy / sizeof(*dest))) {
    308       OS::MemCopy(dest, src, chars * sizeof(*dest));
    309       return;
    310     }
    311     // Number of characters in a uintptr_t.
    312     static const int kStepSize = sizeof(uintptr_t) / sizeof(*dest);  // NOLINT
    313     ASSERT(dest + kStepSize > dest);  // Check for overflow.
    314     while (dest + kStepSize <= limit) {
    315       *reinterpret_cast<uintptr_t*>(dest) =
    316           *reinterpret_cast<const uintptr_t*>(src);
    317       dest += kStepSize;
    318       src += kStepSize;
    319     }
    320   }
    321 #endif
    322   while (dest < limit) {
    323     *dest++ = static_cast<sinkchar>(*src++);
    324   }
    325 }
    326 
    327 
    328 #if defined(V8_HOST_ARCH_ARM)
    329 void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, int chars) {
    330   switch (static_cast<unsigned>(chars)) {
    331     case 0:
    332       break;
    333     case 1:
    334       *dest = *src;
    335       break;
    336     case 2:
    337       memcpy(dest, src, 2);
    338       break;
    339     case 3:
    340       memcpy(dest, src, 3);
    341       break;
    342     case 4:
    343       memcpy(dest, src, 4);
    344       break;
    345     case 5:
    346       memcpy(dest, src, 5);
    347       break;
    348     case 6:
    349       memcpy(dest, src, 6);
    350       break;
    351     case 7:
    352       memcpy(dest, src, 7);
    353       break;
    354     case 8:
    355       memcpy(dest, src, 8);
    356       break;
    357     case 9:
    358       memcpy(dest, src, 9);
    359       break;
    360     case 10:
    361       memcpy(dest, src, 10);
    362       break;
    363     case 11:
    364       memcpy(dest, src, 11);
    365       break;
    366     case 12:
    367       memcpy(dest, src, 12);
    368       break;
    369     case 13:
    370       memcpy(dest, src, 13);
    371       break;
    372     case 14:
    373       memcpy(dest, src, 14);
    374       break;
    375     case 15:
    376       memcpy(dest, src, 15);
    377       break;
    378     default:
    379       OS::MemCopy(dest, src, chars);
    380       break;
    381   }
    382 }
    383 
    384 
    385 void CopyCharsUnsigned(uint16_t* dest, const uint8_t* src, int chars) {
    386   if (chars >= OS::kMinComplexConvertMemCopy) {
    387     OS::MemCopyUint16Uint8(dest, src, chars);
    388   } else {
    389     OS::MemCopyUint16Uint8Wrapper(dest, src, chars);
    390   }
    391 }
    392 
    393 
    394 void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, int chars) {
    395   switch (static_cast<unsigned>(chars)) {
    396     case 0:
    397       break;
    398     case 1:
    399       *dest = *src;
    400       break;
    401     case 2:
    402       memcpy(dest, src, 4);
    403       break;
    404     case 3:
    405       memcpy(dest, src, 6);
    406       break;
    407     case 4:
    408       memcpy(dest, src, 8);
    409       break;
    410     case 5:
    411       memcpy(dest, src, 10);
    412       break;
    413     case 6:
    414       memcpy(dest, src, 12);
    415       break;
    416     case 7:
    417       memcpy(dest, src, 14);
    418       break;
    419     default:
    420       OS::MemCopy(dest, src, chars * sizeof(*dest));
    421       break;
    422   }
    423 }
    424 #endif
    425 
    426 
    427 class StringBuilder : public SimpleStringBuilder {
    428  public:
    429   explicit StringBuilder(int size) : SimpleStringBuilder(size) { }
    430   StringBuilder(char* buffer, int size) : SimpleStringBuilder(buffer, size) { }
    431 
    432   // Add formatted contents to the builder just like printf().
    433   void AddFormatted(const char* format, ...);
    434 
    435   // Add formatted contents like printf based on a va_list.
    436   void AddFormattedList(const char* format, va_list list);
    437  private:
    438   DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
    439 };
    440 
    441 } }  // namespace v8::internal
    442 
    443 #endif  // V8_V8UTILS_H_
    444