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