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