Home | History | Annotate | Download | only in src
      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 
     18 SimpleStringBuilder::SimpleStringBuilder(int size) {
     19   buffer_ = Vector<char>::New(size);
     20   position_ = 0;
     21 }
     22 
     23 
     24 void SimpleStringBuilder::AddString(const char* s) {
     25   AddSubstring(s, StrLength(s));
     26 }
     27 
     28 
     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 
     37 void SimpleStringBuilder::AddPadding(char c, int count) {
     38   for (int i = 0; i < count; i++) {
     39     AddCharacter(c);
     40   }
     41 }
     42 
     43 
     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 
     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 std::ostream& operator<<(std::ostream& os, FeedbackSlot slot) {
     80   return os << "#" << slot.id_;
     81 }
     82 
     83 
     84 size_t hash_value(BailoutId id) {
     85   base::hash<int> h;
     86   return h(id.id_);
     87 }
     88 
     89 
     90 std::ostream& operator<<(std::ostream& os, BailoutId id) {
     91   return os << id.id_;
     92 }
     93 
     94 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    148 void Flush(FILE* out) {
    149   fflush(out);
    150 }
    151 
    152 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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
    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.
    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
    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 
    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 
    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