Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / v8 / src / v8utils.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_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 #elif defined(V8_HOST_ARCH_MIPS)
270 INLINE(void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, int chars));
271 INLINE(void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, int chars));
272 #endif
273
274 // Copy from ASCII/16bit chars to ASCII/16bit chars.
275 template <typename sourcechar, typename sinkchar>
276 INLINE(void CopyChars(sinkchar* dest, const sourcechar* src, int chars));
277
278 template<typename sourcechar, typename sinkchar>
279 void CopyChars(sinkchar* dest, const sourcechar* src, int chars) {
280   ASSERT(sizeof(sourcechar) <= 2);
281   ASSERT(sizeof(sinkchar) <= 2);
282   if (sizeof(sinkchar) == 1) {
283     if (sizeof(sourcechar) == 1) {
284       CopyCharsUnsigned(reinterpret_cast<uint8_t*>(dest),
285                         reinterpret_cast<const uint8_t*>(src),
286                         chars);
287     } else {
288       CopyCharsUnsigned(reinterpret_cast<uint8_t*>(dest),
289                         reinterpret_cast<const uint16_t*>(src),
290                         chars);
291     }
292   } else {
293     if (sizeof(sourcechar) == 1) {
294       CopyCharsUnsigned(reinterpret_cast<uint16_t*>(dest),
295                         reinterpret_cast<const uint8_t*>(src),
296                         chars);
297     } else {
298       CopyCharsUnsigned(reinterpret_cast<uint16_t*>(dest),
299                         reinterpret_cast<const uint16_t*>(src),
300                         chars);
301     }
302   }
303 }
304
305 template <typename sourcechar, typename sinkchar>
306 void CopyCharsUnsigned(sinkchar* dest, const sourcechar* src, int chars) {
307   sinkchar* limit = dest + chars;
308 #ifdef V8_HOST_CAN_READ_UNALIGNED
309   if (sizeof(*dest) == sizeof(*src)) {
310     if (chars >= static_cast<int>(OS::kMinComplexMemCopy / sizeof(*dest))) {
311       OS::MemCopy(dest, src, chars * sizeof(*dest));
312       return;
313     }
314     // Number of characters in a uintptr_t.
315     static const int kStepSize = sizeof(uintptr_t) / sizeof(*dest);  // NOLINT
316     ASSERT(dest + kStepSize > dest);  // Check for overflow.
317     while (dest + kStepSize <= limit) {
318       *reinterpret_cast<uintptr_t*>(dest) =
319           *reinterpret_cast<const uintptr_t*>(src);
320       dest += kStepSize;
321       src += kStepSize;
322     }
323   }
324 #endif
325   while (dest < limit) {
326     *dest++ = static_cast<sinkchar>(*src++);
327   }
328 }
329
330
331 #if defined(V8_HOST_ARCH_ARM)
332 void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, int chars) {
333   switch (static_cast<unsigned>(chars)) {
334     case 0:
335       break;
336     case 1:
337       *dest = *src;
338       break;
339     case 2:
340       memcpy(dest, src, 2);
341       break;
342     case 3:
343       memcpy(dest, src, 3);
344       break;
345     case 4:
346       memcpy(dest, src, 4);
347       break;
348     case 5:
349       memcpy(dest, src, 5);
350       break;
351     case 6:
352       memcpy(dest, src, 6);
353       break;
354     case 7:
355       memcpy(dest, src, 7);
356       break;
357     case 8:
358       memcpy(dest, src, 8);
359       break;
360     case 9:
361       memcpy(dest, src, 9);
362       break;
363     case 10:
364       memcpy(dest, src, 10);
365       break;
366     case 11:
367       memcpy(dest, src, 11);
368       break;
369     case 12:
370       memcpy(dest, src, 12);
371       break;
372     case 13:
373       memcpy(dest, src, 13);
374       break;
375     case 14:
376       memcpy(dest, src, 14);
377       break;
378     case 15:
379       memcpy(dest, src, 15);
380       break;
381     default:
382       OS::MemCopy(dest, src, chars);
383       break;
384   }
385 }
386
387
388 void CopyCharsUnsigned(uint16_t* dest, const uint8_t* src, int chars) {
389   if (chars >= OS::kMinComplexConvertMemCopy) {
390     OS::MemCopyUint16Uint8(dest, src, chars);
391   } else {
392     OS::MemCopyUint16Uint8Wrapper(dest, src, chars);
393   }
394 }
395
396
397 void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, int chars) {
398   switch (static_cast<unsigned>(chars)) {
399     case 0:
400       break;
401     case 1:
402       *dest = *src;
403       break;
404     case 2:
405       memcpy(dest, src, 4);
406       break;
407     case 3:
408       memcpy(dest, src, 6);
409       break;
410     case 4:
411       memcpy(dest, src, 8);
412       break;
413     case 5:
414       memcpy(dest, src, 10);
415       break;
416     case 6:
417       memcpy(dest, src, 12);
418       break;
419     case 7:
420       memcpy(dest, src, 14);
421       break;
422     default:
423       OS::MemCopy(dest, src, chars * sizeof(*dest));
424       break;
425   }
426 }
427
428
429 #elif defined(V8_HOST_ARCH_MIPS)
430 void CopyCharsUnsigned(uint8_t* dest, const uint8_t* src, int chars) {
431   if (chars < OS::kMinComplexMemCopy) {
432     memcpy(dest, src, chars);
433   } else {
434     OS::MemCopy(dest, src, chars);
435   }
436 }
437
438 void CopyCharsUnsigned(uint16_t* dest, const uint16_t* src, int chars) {
439   if (chars < OS::kMinComplexMemCopy) {
440     memcpy(dest, src, chars * sizeof(*dest));
441   } else {
442     OS::MemCopy(dest, src, chars * sizeof(*dest));
443   }
444 }
445 #endif
446
447
448 class StringBuilder : public SimpleStringBuilder {
449  public:
450   explicit StringBuilder(int size) : SimpleStringBuilder(size) { }
451   StringBuilder(char* buffer, int size) : SimpleStringBuilder(buffer, size) { }
452
453   // Add formatted contents to the builder just like printf().
454   void AddFormatted(const char* format, ...);
455
456   // Add formatted contents like printf based on a va_list.
457   void AddFormattedList(const char* format, va_list list);
458  private:
459   DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
460 };
461
462 } }  // namespace v8::internal
463
464 #endif  // V8_V8UTILS_H_