• 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 "src/utils.h"
6 
7 #include <stdarg.h>
8 #include <sys/stat.h>
9 
10 #include "src/base/functional.h"
11 #include "src/base/logging.h"
12 #include "src/base/platform/platform.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 
operator <<(std::ostream & os,FeedbackSlot slot)79 std::ostream& operator<<(std::ostream& os, FeedbackSlot slot) {
80   return os << "#" << slot.id_;
81 }
82 
83 
hash_value(BailoutId id)84 size_t hash_value(BailoutId id) {
85   base::hash<int> h;
86   return h(id.id_);
87 }
88 
89 
operator <<(std::ostream & os,BailoutId id)90 std::ostream& operator<<(std::ostream& os, BailoutId id) {
91   return os << id.id_;
92 }
93 
94 
PrintF(const char * format,...)95 void PrintF(const char* format, ...) {
96   va_list arguments;
97   va_start(arguments, format);
98   base::OS::VPrint(format, arguments);
99   va_end(arguments);
100 }
101 
102 
PrintF(FILE * out,const char * format,...)103 void PrintF(FILE* out, const char* format, ...) {
104   va_list arguments;
105   va_start(arguments, format);
106   base::OS::VFPrint(out, format, arguments);
107   va_end(arguments);
108 }
109 
110 
PrintPID(const char * format,...)111 void PrintPID(const char* format, ...) {
112   base::OS::Print("[%d] ", base::OS::GetCurrentProcessId());
113   va_list arguments;
114   va_start(arguments, format);
115   base::OS::VPrint(format, arguments);
116   va_end(arguments);
117 }
118 
119 
PrintIsolate(void * isolate,const char * format,...)120 void PrintIsolate(void* isolate, const char* format, ...) {
121   base::OS::Print("[%d:%p] ", base::OS::GetCurrentProcessId(), isolate);
122   va_list arguments;
123   va_start(arguments, format);
124   base::OS::VPrint(format, arguments);
125   va_end(arguments);
126 }
127 
128 
SNPrintF(Vector<char> str,const char * format,...)129 int SNPrintF(Vector<char> str, const char* format, ...) {
130   va_list args;
131   va_start(args, format);
132   int result = VSNPrintF(str, format, args);
133   va_end(args);
134   return result;
135 }
136 
137 
VSNPrintF(Vector<char> str,const char * format,va_list args)138 int VSNPrintF(Vector<char> str, const char* format, va_list args) {
139   return base::OS::VSNPrintF(str.start(), str.length(), format, args);
140 }
141 
142 
StrNCpy(Vector<char> dest,const char * src,size_t n)143 void StrNCpy(Vector<char> dest, const char* src, size_t n) {
144   base::OS::StrNCpy(dest.start(), dest.length(), src, n);
145 }
146 
147 
Flush(FILE * out)148 void Flush(FILE* out) {
149   fflush(out);
150 }
151 
152 
ReadLine(const char * prompt)153 char* ReadLine(const char* prompt) {
154   char* result = NULL;
155   char line_buf[256];
156   int offset = 0;
157   bool keep_going = true;
158   fprintf(stdout, "%s", prompt);
159   fflush(stdout);
160   while (keep_going) {
161     if (fgets(line_buf, sizeof(line_buf), stdin) == NULL) {
162       // fgets got an error. Just give up.
163       if (result != NULL) {
164         DeleteArray(result);
165       }
166       return NULL;
167     }
168     int len = StrLength(line_buf);
169     if (len > 1 &&
170         line_buf[len - 2] == '\\' &&
171         line_buf[len - 1] == '\n') {
172       // When we read a line that ends with a "\" we remove the escape and
173       // append the remainder.
174       line_buf[len - 2] = '\n';
175       line_buf[len - 1] = 0;
176       len -= 1;
177     } else if ((len > 0) && (line_buf[len - 1] == '\n')) {
178       // Since we read a new line we are done reading the line. This
179       // will exit the loop after copying this buffer into the result.
180       keep_going = false;
181     }
182     if (result == NULL) {
183       // Allocate the initial result and make room for the terminating '\0'
184       result = NewArray<char>(len + 1);
185     } else {
186       // Allocate a new result with enough room for the new addition.
187       int new_len = offset + len + 1;
188       char* new_result = NewArray<char>(new_len);
189       // Copy the existing input into the new array and set the new
190       // array as the result.
191       MemCopy(new_result, result, offset * kCharSize);
192       DeleteArray(result);
193       result = new_result;
194     }
195     // Copy the newly read line into the result.
196     MemCopy(result + offset, line_buf, len * kCharSize);
197     offset += len;
198   }
199   DCHECK(result != NULL);
200   result[offset] = '\0';
201   return result;
202 }
203 
204 
ReadCharsFromFile(FILE * file,int * size,int extra_space,bool verbose,const char * filename)205 char* ReadCharsFromFile(FILE* file,
206                         int* size,
207                         int extra_space,
208                         bool verbose,
209                         const char* filename) {
210   if (file == NULL || fseek(file, 0, SEEK_END) != 0) {
211     if (verbose) {
212       base::OS::PrintError("Cannot read from file %s.\n", filename);
213     }
214     return NULL;
215   }
216 
217   // Get the size of the file and rewind it.
218   *size = static_cast<int>(ftell(file));
219   rewind(file);
220 
221   char* result = NewArray<char>(*size + extra_space);
222   for (int i = 0; i < *size && feof(file) == 0;) {
223     int read = static_cast<int>(fread(&result[i], 1, *size - i, file));
224     if (read != (*size - i) && ferror(file) != 0) {
225       fclose(file);
226       DeleteArray(result);
227       return NULL;
228     }
229     i += read;
230   }
231   return result;
232 }
233 
234 
ReadCharsFromFile(const char * filename,int * size,int extra_space,bool verbose)235 char* ReadCharsFromFile(const char* filename,
236                         int* size,
237                         int extra_space,
238                         bool verbose) {
239   FILE* file = base::OS::FOpen(filename, "rb");
240   char* result = ReadCharsFromFile(file, size, extra_space, verbose, filename);
241   if (file != NULL) fclose(file);
242   return result;
243 }
244 
245 
ReadBytes(const char * filename,int * size,bool verbose)246 byte* ReadBytes(const char* filename, int* size, bool verbose) {
247   char* chars = ReadCharsFromFile(filename, size, 0, verbose);
248   return reinterpret_cast<byte*>(chars);
249 }
250 
251 
SetVectorContents(char * chars,int size,bool * exists)252 static Vector<const char> SetVectorContents(char* chars,
253                                             int size,
254                                             bool* exists) {
255   if (!chars) {
256     *exists = false;
257     return Vector<const char>::empty();
258   }
259   chars[size] = '\0';
260   *exists = true;
261   return Vector<const char>(chars, size);
262 }
263 
264 
ReadFile(const char * filename,bool * exists,bool verbose)265 Vector<const char> ReadFile(const char* filename,
266                             bool* exists,
267                             bool verbose) {
268   int size;
269   char* result = ReadCharsFromFile(filename, &size, 1, verbose);
270   return SetVectorContents(result, size, exists);
271 }
272 
273 
ReadFile(FILE * file,bool * exists,bool verbose)274 Vector<const char> ReadFile(FILE* file,
275                             bool* exists,
276                             bool verbose) {
277   int size;
278   char* result = ReadCharsFromFile(file, &size, 1, verbose, "");
279   return SetVectorContents(result, size, exists);
280 }
281 
282 
WriteCharsToFile(const char * str,int size,FILE * f)283 int WriteCharsToFile(const char* str, int size, FILE* f) {
284   int total = 0;
285   while (total < size) {
286     int write = static_cast<int>(fwrite(str, 1, size - total, f));
287     if (write == 0) {
288       return total;
289     }
290     total += write;
291     str += write;
292   }
293   return total;
294 }
295 
296 
AppendChars(const char * filename,const char * str,int size,bool verbose)297 int AppendChars(const char* filename,
298                 const char* str,
299                 int size,
300                 bool verbose) {
301   FILE* f = base::OS::FOpen(filename, "ab");
302   if (f == NULL) {
303     if (verbose) {
304       base::OS::PrintError("Cannot open file %s for writing.\n", filename);
305     }
306     return 0;
307   }
308   int written = WriteCharsToFile(str, size, f);
309   fclose(f);
310   return written;
311 }
312 
313 
WriteChars(const char * filename,const char * str,int size,bool verbose)314 int WriteChars(const char* filename,
315                const char* str,
316                int size,
317                bool verbose) {
318   FILE* f = base::OS::FOpen(filename, "wb");
319   if (f == NULL) {
320     if (verbose) {
321       base::OS::PrintError("Cannot open file %s for writing.\n", filename);
322     }
323     return 0;
324   }
325   int written = WriteCharsToFile(str, size, f);
326   fclose(f);
327   return written;
328 }
329 
330 
WriteBytes(const char * filename,const byte * bytes,int size,bool verbose)331 int WriteBytes(const char* filename,
332                const byte* bytes,
333                int size,
334                bool verbose) {
335   const char* str = reinterpret_cast<const char*>(bytes);
336   return WriteChars(filename, str, size, verbose);
337 }
338 
339 
340 
AddFormatted(const char * format,...)341 void StringBuilder::AddFormatted(const char* format, ...) {
342   va_list arguments;
343   va_start(arguments, format);
344   AddFormattedList(format, arguments);
345   va_end(arguments);
346 }
347 
348 
AddFormattedList(const char * format,va_list list)349 void StringBuilder::AddFormattedList(const char* format, va_list list) {
350   DCHECK(!is_finalized() && position_ <= buffer_.length());
351   int n = VSNPrintF(buffer_ + position_, format, list);
352   if (n < 0 || n >= (buffer_.length() - position_)) {
353     position_ = buffer_.length();
354   } else {
355     position_ += n;
356   }
357 }
358 
359 
360 #if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
MemMoveWrapper(void * dest,const void * src,size_t size)361 static void MemMoveWrapper(void* dest, const void* src, size_t size) {
362   memmove(dest, src, size);
363 }
364 
365 
366 // Initialize to library version so we can call this at any time during startup.
367 static MemMoveFunction memmove_function = &MemMoveWrapper;
368 
369 // Defined in codegen-ia32.cc.
370 MemMoveFunction CreateMemMoveFunction(Isolate* isolate);
371 
372 // Copy memory area to disjoint memory area.
MemMove(void * dest,const void * src,size_t size)373 void MemMove(void* dest, const void* src, size_t size) {
374   if (size == 0) return;
375   // Note: here we rely on dependent reads being ordered. This is true
376   // on all architectures we currently support.
377   (*memmove_function)(dest, src, size);
378 }
379 
380 #elif V8_OS_POSIX && V8_HOST_ARCH_ARM
MemCopyUint16Uint8Wrapper(uint16_t * dest,const uint8_t * src,size_t chars)381 void MemCopyUint16Uint8Wrapper(uint16_t* dest, const uint8_t* src,
382                                size_t chars) {
383   uint16_t* limit = dest + chars;
384   while (dest < limit) {
385     *dest++ = static_cast<uint16_t>(*src++);
386   }
387 }
388 
389 V8_EXPORT_PRIVATE MemCopyUint8Function memcopy_uint8_function =
390     &MemCopyUint8Wrapper;
391 MemCopyUint16Uint8Function memcopy_uint16_uint8_function =
392     &MemCopyUint16Uint8Wrapper;
393 // Defined in codegen-arm.cc.
394 MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate,
395                                                 MemCopyUint8Function stub);
396 MemCopyUint16Uint8Function CreateMemCopyUint16Uint8Function(
397     Isolate* isolate, MemCopyUint16Uint8Function stub);
398 
399 #elif V8_OS_POSIX && V8_HOST_ARCH_MIPS
400 V8_EXPORT_PRIVATE MemCopyUint8Function memcopy_uint8_function =
401     &MemCopyUint8Wrapper;
402 // Defined in codegen-mips.cc.
403 MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate,
404                                                 MemCopyUint8Function stub);
405 #endif
406 
407 
408 static bool g_memcopy_functions_initialized = false;
409 
410 
init_memcopy_functions(Isolate * isolate)411 void init_memcopy_functions(Isolate* isolate) {
412   if (g_memcopy_functions_initialized) return;
413   g_memcopy_functions_initialized = true;
414 #if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
415   MemMoveFunction generated_memmove = CreateMemMoveFunction(isolate);
416   if (generated_memmove != NULL) {
417     memmove_function = generated_memmove;
418   }
419 #elif V8_OS_POSIX && V8_HOST_ARCH_ARM
420   memcopy_uint8_function =
421       CreateMemCopyUint8Function(isolate, &MemCopyUint8Wrapper);
422   memcopy_uint16_uint8_function =
423       CreateMemCopyUint16Uint8Function(isolate, &MemCopyUint16Uint8Wrapper);
424 #elif V8_OS_POSIX && V8_HOST_ARCH_MIPS
425   memcopy_uint8_function =
426       CreateMemCopyUint8Function(isolate, &MemCopyUint8Wrapper);
427 #endif
428 }
429 
430 
DoubleToBoolean(double d)431 bool DoubleToBoolean(double d) {
432   // NaN, +0, and -0 should return the false object
433   IeeeDoubleArchType u;
434 
435   u.d = d;
436   if (u.bits.exp == 2047) {
437     // Detect NaN for IEEE double precision floating point.
438     if ((u.bits.man_low | u.bits.man_high) != 0) return false;
439   }
440   if (u.bits.exp == 0) {
441     // Detect +0, and -0 for IEEE double precision floating point.
442     if ((u.bits.man_low | u.bits.man_high) == 0) return false;
443   }
444   return true;
445 }
446 
447 
448 }  // namespace internal
449 }  // namespace v8
450