Home | History | Annotate | Download | only in src
      1 // Copyright 2010 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 // Our version of fflush.
     61 void Flush(FILE* out);
     62 
     63 inline void Flush() {
     64   Flush(stdout);
     65 }
     66 
     67 
     68 // Read a line of characters after printing the prompt to stdout. The resulting
     69 // char* needs to be disposed off with DeleteArray by the caller.
     70 char* ReadLine(const char* prompt);
     71 
     72 
     73 // Read and return the raw bytes in a file. the size of the buffer is returned
     74 // in size.
     75 // The returned buffer must be freed by the caller.
     76 byte* ReadBytes(const char* filename, int* size, bool verbose = true);
     77 
     78 
     79 // Append size chars from str to the file given by filename.
     80 // The file is overwritten. Returns the number of chars written.
     81 int AppendChars(const char* filename,
     82                 const char* str,
     83                 int size,
     84                 bool verbose = true);
     85 
     86 
     87 // Write size chars from str to the file given by filename.
     88 // The file is overwritten. Returns the number of chars written.
     89 int WriteChars(const char* filename,
     90                const char* str,
     91                int size,
     92                bool verbose = true);
     93 
     94 
     95 // Write size bytes to the file given by filename.
     96 // The file is overwritten. Returns the number of bytes written.
     97 int WriteBytes(const char* filename,
     98                const byte* bytes,
     99                int size,
    100                bool verbose = true);
    101 
    102 
    103 // Write the C code
    104 // const char* <varname> = "<str>";
    105 // const int <varname>_len = <len>;
    106 // to the file given by filename. Only the first len chars are written.
    107 int WriteAsCFile(const char* filename, const char* varname,
    108                  const char* str, int size, bool verbose = true);
    109 
    110 
    111 // Data structures
    112 
    113 template <typename T>
    114 inline Vector< Handle<Object> > HandleVector(v8::internal::Handle<T>* elms,
    115                                              int length) {
    116   return Vector< Handle<Object> >(
    117       reinterpret_cast<v8::internal::Handle<Object>*>(elms), length);
    118 }
    119 
    120 // Memory
    121 
    122 // Copies data from |src| to |dst|.  The data spans MUST not overlap.
    123 template <typename T>
    124 inline void CopyWords(T* dst, T* src, int num_words) {
    125   STATIC_ASSERT(sizeof(T) == kPointerSize);
    126   ASSERT(Min(dst, src) + num_words <= Max(dst, src));
    127   ASSERT(num_words > 0);
    128 
    129   // Use block copying memcpy if the segment we're copying is
    130   // enough to justify the extra call/setup overhead.
    131   static const int kBlockCopyLimit = 16;
    132 
    133   if (num_words >= kBlockCopyLimit) {
    134     memcpy(dst, src, num_words * kPointerSize);
    135   } else {
    136     int remaining = num_words;
    137     do {
    138       remaining--;
    139       *dst++ = *src++;
    140     } while (remaining > 0);
    141   }
    142 }
    143 
    144 
    145 template <typename T>
    146 static inline void MemsetPointer(T** dest, T* value, int counter) {
    147 #if defined(V8_HOST_ARCH_IA32)
    148 #define STOS "stosl"
    149 #elif defined(V8_HOST_ARCH_X64)
    150 #define STOS "stosq"
    151 #endif
    152 
    153 #if defined(__GNUC__) && defined(STOS)
    154   asm volatile(
    155       "cld;"
    156       "rep ; " STOS
    157       : "+&c" (counter), "+&D" (dest)
    158       : "a" (value)
    159       : "memory", "cc");
    160 #else
    161   for (int i = 0; i < counter; i++) {
    162     dest[i] = value;
    163   }
    164 #endif
    165 
    166 #undef STOS
    167 }
    168 
    169 
    170 // Simple wrapper that allows an ExternalString to refer to a
    171 // Vector<const char>. Doesn't assume ownership of the data.
    172 class AsciiStringAdapter: public v8::String::ExternalAsciiStringResource {
    173  public:
    174   explicit AsciiStringAdapter(Vector<const char> data) : data_(data) {}
    175 
    176   virtual const char* data() const { return data_.start(); }
    177 
    178   virtual size_t length() const { return data_.length(); }
    179 
    180  private:
    181   Vector<const char> data_;
    182 };
    183 
    184 
    185 // Simple support to read a file into a 0-terminated C-string.
    186 // The returned buffer must be freed by the caller.
    187 // On return, *exits tells whether the file existed.
    188 Vector<const char> ReadFile(const char* filename,
    189                             bool* exists,
    190                             bool verbose = true);
    191 
    192 
    193 // Helper class for building result strings in a character buffer. The
    194 // purpose of the class is to use safe operations that checks the
    195 // buffer bounds on all operations in debug mode.
    196 class StringBuilder {
    197  public:
    198   // Create a string builder with a buffer of the given size. The
    199   // buffer is allocated through NewArray<char> and must be
    200   // deallocated by the caller of Finalize().
    201   explicit StringBuilder(int size);
    202 
    203   StringBuilder(char* buffer, int size)
    204       : buffer_(buffer, size), position_(0) { }
    205 
    206   ~StringBuilder() { if (!is_finalized()) Finalize(); }
    207 
    208   int size() const { return buffer_.length(); }
    209 
    210   // Get the current position in the builder.
    211   int position() const {
    212     ASSERT(!is_finalized());
    213     return position_;
    214   }
    215 
    216   // Reset the position.
    217   void Reset() { position_ = 0; }
    218 
    219   // Add a single character to the builder. It is not allowed to add
    220   // 0-characters; use the Finalize() method to terminate the string
    221   // instead.
    222   void AddCharacter(char c) {
    223     ASSERT(c != '\0');
    224     ASSERT(!is_finalized() && position_ < buffer_.length());
    225     buffer_[position_++] = c;
    226   }
    227 
    228   // Add an entire string to the builder. Uses strlen() internally to
    229   // compute the length of the input string.
    230   void AddString(const char* s);
    231 
    232   // Add the first 'n' characters of the given string 's' to the
    233   // builder. The input string must have enough characters.
    234   void AddSubstring(const char* s, int n);
    235 
    236   // Add formatted contents to the builder just like printf().
    237   void AddFormatted(const char* format, ...);
    238 
    239   // Add formatted contents like printf based on a va_list.
    240   void AddFormattedList(const char* format, va_list list);
    241 
    242   // Add character padding to the builder. If count is non-positive,
    243   // nothing is added to the builder.
    244   void AddPadding(char c, int count);
    245 
    246   // Finalize the string by 0-terminating it and returning the buffer.
    247   char* Finalize();
    248 
    249  private:
    250   Vector<char> buffer_;
    251   int position_;
    252 
    253   bool is_finalized() const { return position_ < 0; }
    254 
    255   DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
    256 };
    257 
    258 
    259 // Copy from ASCII/16bit chars to ASCII/16bit chars.
    260 template <typename sourcechar, typename sinkchar>
    261 static inline void CopyChars(sinkchar* dest, const sourcechar* src, int chars) {
    262   sinkchar* limit = dest + chars;
    263 #ifdef V8_HOST_CAN_READ_UNALIGNED
    264   if (sizeof(*dest) == sizeof(*src)) {
    265     if (chars >= static_cast<int>(OS::kMinComplexMemCopy / sizeof(*dest))) {
    266       OS::MemCopy(dest, src, chars * sizeof(*dest));
    267       return;
    268     }
    269     // Number of characters in a uintptr_t.
    270     static const int kStepSize = sizeof(uintptr_t) / sizeof(*dest);  // NOLINT
    271     while (dest <= limit - kStepSize) {
    272       *reinterpret_cast<uintptr_t*>(dest) =
    273           *reinterpret_cast<const uintptr_t*>(src);
    274       dest += kStepSize;
    275       src += kStepSize;
    276     }
    277   }
    278 #endif
    279   while (dest < limit) {
    280     *dest++ = static_cast<sinkchar>(*src++);
    281   }
    282 }
    283 
    284 
    285 // A resource for using mmapped files to back external strings that are read
    286 // from files.
    287 class MemoryMappedExternalResource: public
    288     v8::String::ExternalAsciiStringResource {
    289  public:
    290   explicit MemoryMappedExternalResource(const char* filename);
    291   MemoryMappedExternalResource(const char* filename,
    292                                bool remove_file_on_cleanup);
    293   virtual ~MemoryMappedExternalResource();
    294 
    295   virtual const char* data() const { return data_; }
    296   virtual size_t length() const { return length_; }
    297 
    298   bool exists() const { return file_ != NULL; }
    299   bool is_empty() const { return length_ == 0; }
    300 
    301   bool EnsureIsAscii(bool abort_if_failed) const;
    302   bool EnsureIsAscii() const { return EnsureIsAscii(true); }
    303   bool IsAscii() const { return EnsureIsAscii(false); }
    304 
    305  private:
    306   void Init(const char* filename);
    307 
    308   char* filename_;
    309   OS::MemoryMappedFile* file_;
    310 
    311   const char* data_;
    312   size_t length_;
    313   bool remove_file_on_cleanup_;
    314 };
    315 
    316 
    317 } }  // namespace v8::internal
    318 
    319 #endif  // V8_V8UTILS_H_
    320