• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <stdarg.h>
6 #include <sys/stat.h>
7 
8 #include "src/v8.h"
9 
10 #include "src/base/logging.h"
11 #include "src/base/platform/platform.h"
12 #include "src/utils.h"
13 
14 namespace v8 {
15 namespace internal {
16 
17 
SimpleStringBuilder(int size)18 SimpleStringBuilder::SimpleStringBuilder(int size) {
19   buffer_ = Vector<char>::New(size);
20   position_ = 0;
21 }
22 
23 
AddString(const char * s)24 void SimpleStringBuilder::AddString(const char* s) {
25   AddSubstring(s, StrLength(s));
26 }
27 
28 
AddSubstring(const char * s,int n)29 void SimpleStringBuilder::AddSubstring(const char* s, int n) {
30   DCHECK(!is_finalized() && position_ + n <= buffer_.length());
31   DCHECK(static_cast<size_t>(n) <= strlen(s));
32   MemCopy(&buffer_[position_], s, n * kCharSize);
33   position_ += n;
34 }
35 
36 
AddPadding(char c,int count)37 void SimpleStringBuilder::AddPadding(char c, int count) {
38   for (int i = 0; i < count; i++) {
39     AddCharacter(c);
40   }
41 }
42 
43 
AddDecimalInteger(int32_t value)44 void SimpleStringBuilder::AddDecimalInteger(int32_t value) {
45   uint32_t number = static_cast<uint32_t>(value);
46   if (value < 0) {
47     AddCharacter('-');
48     number = static_cast<uint32_t>(-value);
49   }
50   int digits = 1;
51   for (uint32_t factor = 10; digits < 10; digits++, factor *= 10) {
52     if (factor > number) break;
53   }
54   position_ += digits;
55   for (int i = 1; i <= digits; i++) {
56     buffer_[position_ - i] = '0' + static_cast<char>(number % 10);
57     number /= 10;
58   }
59 }
60 
61 
Finalize()62 char* SimpleStringBuilder::Finalize() {
63   DCHECK(!is_finalized() && position_ <= buffer_.length());
64   // If there is no space for null termination, overwrite last character.
65   if (position_ == buffer_.length()) {
66     position_--;
67     // Print ellipsis.
68     for (int i = 3; i > 0 && position_ > i; --i) buffer_[position_ - i] = '.';
69   }
70   buffer_[position_] = '\0';
71   // Make sure nobody managed to add a 0-character to the
72   // buffer while building the string.
73   DCHECK(strlen(buffer_.start()) == static_cast<size_t>(position_));
74   position_ = -1;
75   DCHECK(is_finalized());
76   return buffer_.start();
77 }
78 
79 
PrintF(const char * format,...)80 void PrintF(const char* format, ...) {
81   va_list arguments;
82   va_start(arguments, format);
83   base::OS::VPrint(format, arguments);
84   va_end(arguments);
85 }
86 
87 
PrintF(FILE * out,const char * format,...)88 void PrintF(FILE* out, const char* format, ...) {
89   va_list arguments;
90   va_start(arguments, format);
91   base::OS::VFPrint(out, format, arguments);
92   va_end(arguments);
93 }
94 
95 
PrintPID(const char * format,...)96 void PrintPID(const char* format, ...) {
97   base::OS::Print("[%d] ", base::OS::GetCurrentProcessId());
98   va_list arguments;
99   va_start(arguments, format);
100   base::OS::VPrint(format, arguments);
101   va_end(arguments);
102 }
103 
104 
SNPrintF(Vector<char> str,const char * format,...)105 int SNPrintF(Vector<char> str, const char* format, ...) {
106   va_list args;
107   va_start(args, format);
108   int result = VSNPrintF(str, format, args);
109   va_end(args);
110   return result;
111 }
112 
113 
VSNPrintF(Vector<char> str,const char * format,va_list args)114 int VSNPrintF(Vector<char> str, const char* format, va_list args) {
115   return base::OS::VSNPrintF(str.start(), str.length(), format, args);
116 }
117 
118 
StrNCpy(Vector<char> dest,const char * src,size_t n)119 void StrNCpy(Vector<char> dest, const char* src, size_t n) {
120   base::OS::StrNCpy(dest.start(), dest.length(), src, n);
121 }
122 
123 
Flush(FILE * out)124 void Flush(FILE* out) {
125   fflush(out);
126 }
127 
128 
ReadLine(const char * prompt)129 char* ReadLine(const char* prompt) {
130   char* result = NULL;
131   char line_buf[256];
132   int offset = 0;
133   bool keep_going = true;
134   fprintf(stdout, "%s", prompt);
135   fflush(stdout);
136   while (keep_going) {
137     if (fgets(line_buf, sizeof(line_buf), stdin) == NULL) {
138       // fgets got an error. Just give up.
139       if (result != NULL) {
140         DeleteArray(result);
141       }
142       return NULL;
143     }
144     int len = StrLength(line_buf);
145     if (len > 1 &&
146         line_buf[len - 2] == '\\' &&
147         line_buf[len - 1] == '\n') {
148       // When we read a line that ends with a "\" we remove the escape and
149       // append the remainder.
150       line_buf[len - 2] = '\n';
151       line_buf[len - 1] = 0;
152       len -= 1;
153     } else if ((len > 0) && (line_buf[len - 1] == '\n')) {
154       // Since we read a new line we are done reading the line. This
155       // will exit the loop after copying this buffer into the result.
156       keep_going = false;
157     }
158     if (result == NULL) {
159       // Allocate the initial result and make room for the terminating '\0'
160       result = NewArray<char>(len + 1);
161     } else {
162       // Allocate a new result with enough room for the new addition.
163       int new_len = offset + len + 1;
164       char* new_result = NewArray<char>(new_len);
165       // Copy the existing input into the new array and set the new
166       // array as the result.
167       MemCopy(new_result, result, offset * kCharSize);
168       DeleteArray(result);
169       result = new_result;
170     }
171     // Copy the newly read line into the result.
172     MemCopy(result + offset, line_buf, len * kCharSize);
173     offset += len;
174   }
175   DCHECK(result != NULL);
176   result[offset] = '\0';
177   return result;
178 }
179 
180 
ReadCharsFromFile(FILE * file,int * size,int extra_space,bool verbose,const char * filename)181 char* ReadCharsFromFile(FILE* file,
182                         int* size,
183                         int extra_space,
184                         bool verbose,
185                         const char* filename) {
186   if (file == NULL || fseek(file, 0, SEEK_END) != 0) {
187     if (verbose) {
188       base::OS::PrintError("Cannot read from file %s.\n", filename);
189     }
190     return NULL;
191   }
192 
193   // Get the size of the file and rewind it.
194   *size = ftell(file);
195   rewind(file);
196 
197   char* result = NewArray<char>(*size + extra_space);
198   for (int i = 0; i < *size && feof(file) == 0;) {
199     int read = static_cast<int>(fread(&result[i], 1, *size - i, file));
200     if (read != (*size - i) && ferror(file) != 0) {
201       fclose(file);
202       DeleteArray(result);
203       return NULL;
204     }
205     i += read;
206   }
207   return result;
208 }
209 
210 
ReadCharsFromFile(const char * filename,int * size,int extra_space,bool verbose)211 char* ReadCharsFromFile(const char* filename,
212                         int* size,
213                         int extra_space,
214                         bool verbose) {
215   FILE* file = base::OS::FOpen(filename, "rb");
216   char* result = ReadCharsFromFile(file, size, extra_space, verbose, filename);
217   if (file != NULL) fclose(file);
218   return result;
219 }
220 
221 
ReadBytes(const char * filename,int * size,bool verbose)222 byte* ReadBytes(const char* filename, int* size, bool verbose) {
223   char* chars = ReadCharsFromFile(filename, size, 0, verbose);
224   return reinterpret_cast<byte*>(chars);
225 }
226 
227 
SetVectorContents(char * chars,int size,bool * exists)228 static Vector<const char> SetVectorContents(char* chars,
229                                             int size,
230                                             bool* exists) {
231   if (!chars) {
232     *exists = false;
233     return Vector<const char>::empty();
234   }
235   chars[size] = '\0';
236   *exists = true;
237   return Vector<const char>(chars, size);
238 }
239 
240 
ReadFile(const char * filename,bool * exists,bool verbose)241 Vector<const char> ReadFile(const char* filename,
242                             bool* exists,
243                             bool verbose) {
244   int size;
245   char* result = ReadCharsFromFile(filename, &size, 1, verbose);
246   return SetVectorContents(result, size, exists);
247 }
248 
249 
ReadFile(FILE * file,bool * exists,bool verbose)250 Vector<const char> ReadFile(FILE* file,
251                             bool* exists,
252                             bool verbose) {
253   int size;
254   char* result = ReadCharsFromFile(file, &size, 1, verbose, "");
255   return SetVectorContents(result, size, exists);
256 }
257 
258 
WriteCharsToFile(const char * str,int size,FILE * f)259 int WriteCharsToFile(const char* str, int size, FILE* f) {
260   int total = 0;
261   while (total < size) {
262     int write = static_cast<int>(fwrite(str, 1, size - total, f));
263     if (write == 0) {
264       return total;
265     }
266     total += write;
267     str += write;
268   }
269   return total;
270 }
271 
272 
AppendChars(const char * filename,const char * str,int size,bool verbose)273 int AppendChars(const char* filename,
274                 const char* str,
275                 int size,
276                 bool verbose) {
277   FILE* f = base::OS::FOpen(filename, "ab");
278   if (f == NULL) {
279     if (verbose) {
280       base::OS::PrintError("Cannot open file %s for writing.\n", filename);
281     }
282     return 0;
283   }
284   int written = WriteCharsToFile(str, size, f);
285   fclose(f);
286   return written;
287 }
288 
289 
WriteChars(const char * filename,const char * str,int size,bool verbose)290 int WriteChars(const char* filename,
291                const char* str,
292                int size,
293                bool verbose) {
294   FILE* f = base::OS::FOpen(filename, "wb");
295   if (f == NULL) {
296     if (verbose) {
297       base::OS::PrintError("Cannot open file %s for writing.\n", filename);
298     }
299     return 0;
300   }
301   int written = WriteCharsToFile(str, size, f);
302   fclose(f);
303   return written;
304 }
305 
306 
WriteBytes(const char * filename,const byte * bytes,int size,bool verbose)307 int WriteBytes(const char* filename,
308                const byte* bytes,
309                int size,
310                bool verbose) {
311   const char* str = reinterpret_cast<const char*>(bytes);
312   return WriteChars(filename, str, size, verbose);
313 }
314 
315 
316 
AddFormatted(const char * format,...)317 void StringBuilder::AddFormatted(const char* format, ...) {
318   va_list arguments;
319   va_start(arguments, format);
320   AddFormattedList(format, arguments);
321   va_end(arguments);
322 }
323 
324 
AddFormattedList(const char * format,va_list list)325 void StringBuilder::AddFormattedList(const char* format, va_list list) {
326   DCHECK(!is_finalized() && position_ <= buffer_.length());
327   int n = VSNPrintF(buffer_ + position_, format, list);
328   if (n < 0 || n >= (buffer_.length() - position_)) {
329     position_ = buffer_.length();
330   } else {
331     position_ += n;
332   }
333 }
334 
335 
336 #if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
MemMoveWrapper(void * dest,const void * src,size_t size)337 static void MemMoveWrapper(void* dest, const void* src, size_t size) {
338   memmove(dest, src, size);
339 }
340 
341 
342 // Initialize to library version so we can call this at any time during startup.
343 static MemMoveFunction memmove_function = &MemMoveWrapper;
344 
345 // Defined in codegen-ia32.cc.
346 MemMoveFunction CreateMemMoveFunction();
347 
348 // Copy memory area to disjoint memory area.
MemMove(void * dest,const void * src,size_t size)349 void MemMove(void* dest, const void* src, size_t size) {
350   if (size == 0) return;
351   // Note: here we rely on dependent reads being ordered. This is true
352   // on all architectures we currently support.
353   (*memmove_function)(dest, src, size);
354 }
355 
356 #elif V8_OS_POSIX && V8_HOST_ARCH_ARM
MemCopyUint16Uint8Wrapper(uint16_t * dest,const uint8_t * src,size_t chars)357 void MemCopyUint16Uint8Wrapper(uint16_t* dest, const uint8_t* src,
358                                size_t chars) {
359   uint16_t* limit = dest + chars;
360   while (dest < limit) {
361     *dest++ = static_cast<uint16_t>(*src++);
362   }
363 }
364 
365 
366 MemCopyUint8Function memcopy_uint8_function = &MemCopyUint8Wrapper;
367 MemCopyUint16Uint8Function memcopy_uint16_uint8_function =
368     &MemCopyUint16Uint8Wrapper;
369 // Defined in codegen-arm.cc.
370 MemCopyUint8Function CreateMemCopyUint8Function(MemCopyUint8Function stub);
371 MemCopyUint16Uint8Function CreateMemCopyUint16Uint8Function(
372     MemCopyUint16Uint8Function stub);
373 
374 #elif V8_OS_POSIX && V8_HOST_ARCH_MIPS
375 MemCopyUint8Function memcopy_uint8_function = &MemCopyUint8Wrapper;
376 // Defined in codegen-mips.cc.
377 MemCopyUint8Function CreateMemCopyUint8Function(MemCopyUint8Function stub);
378 #endif
379 
380 
init_memcopy_functions()381 void init_memcopy_functions() {
382 #if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
383   MemMoveFunction generated_memmove = CreateMemMoveFunction();
384   if (generated_memmove != NULL) {
385     memmove_function = generated_memmove;
386   }
387 #elif V8_OS_POSIX && V8_HOST_ARCH_ARM
388   memcopy_uint8_function = CreateMemCopyUint8Function(&MemCopyUint8Wrapper);
389   memcopy_uint16_uint8_function =
390       CreateMemCopyUint16Uint8Function(&MemCopyUint16Uint8Wrapper);
391 #elif V8_OS_POSIX && V8_HOST_ARCH_MIPS
392   memcopy_uint8_function = CreateMemCopyUint8Function(&MemCopyUint8Wrapper);
393 #endif
394 }
395 
396 
DoubleToBoolean(double d)397 bool DoubleToBoolean(double d) {
398   // NaN, +0, and -0 should return the false object
399 #if __BYTE_ORDER == __LITTLE_ENDIAN
400   union IeeeDoubleLittleEndianArchType u;
401 #elif __BYTE_ORDER == __BIG_ENDIAN
402   union IeeeDoubleBigEndianArchType u;
403 #endif
404   u.d = d;
405   if (u.bits.exp == 2047) {
406     // Detect NaN for IEEE double precision floating point.
407     if ((u.bits.man_low | u.bits.man_high) != 0) return false;
408   }
409   if (u.bits.exp == 0) {
410     // Detect +0, and -0 for IEEE double precision floating point.
411     if ((u.bits.man_low | u.bits.man_high) == 0) return false;
412   }
413   return true;
414 }
415 
416 
417 } }  // namespace v8::internal
418