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