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 14namespace v8 { 15namespace internal { 16 17 18SimpleStringBuilder::SimpleStringBuilder(int size) { 19 buffer_ = Vector<char>::New(size); 20 position_ = 0; 21} 22 23 24void SimpleStringBuilder::AddString(const char* s) { 25 AddSubstring(s, StrLength(s)); 26} 27 28 29void 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 37void SimpleStringBuilder::AddPadding(char c, int count) { 38 for (int i = 0; i < count; i++) { 39 AddCharacter(c); 40 } 41} 42 43 44void 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 62char* 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 80std::ostream& operator<<(std::ostream& os, FeedbackVectorSlot slot) { 81 return os << "#" << slot.id_; 82} 83 84 85size_t hash_value(BailoutId id) { 86 base::hash<int> h; 87 return h(id.id_); 88} 89 90 91std::ostream& operator<<(std::ostream& os, BailoutId id) { 92 return os << id.id_; 93} 94 95 96void 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 104void 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 112void 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 121void 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 130int 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 139int VSNPrintF(Vector<char> str, const char* format, va_list args) { 140 return base::OS::VSNPrintF(str.start(), str.length(), format, args); 141} 142 143 144void StrNCpy(Vector<char> dest, const char* src, size_t n) { 145 base::OS::StrNCpy(dest.start(), dest.length(), src, n); 146} 147 148 149void Flush(FILE* out) { 150 fflush(out); 151} 152 153 154char* 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 206char* 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 236char* 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 247byte* 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 253static 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 266Vector<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 275Vector<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 284int 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 298int 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 315int 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 332int 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 342void 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 350void 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 362static 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. 368static MemMoveFunction memmove_function = &MemMoveWrapper; 369 370// Defined in codegen-ia32.cc. 371MemMoveFunction CreateMemMoveFunction(Isolate* isolate); 372 373// Copy memory area to disjoint memory area. 374void 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 382void 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 391MemCopyUint8Function memcopy_uint8_function = &MemCopyUint8Wrapper; 392MemCopyUint16Uint8Function memcopy_uint16_uint8_function = 393 &MemCopyUint16Uint8Wrapper; 394// Defined in codegen-arm.cc. 395MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate, 396 MemCopyUint8Function stub); 397MemCopyUint16Uint8Function CreateMemCopyUint16Uint8Function( 398 Isolate* isolate, MemCopyUint16Uint8Function stub); 399 400#elif V8_OS_POSIX && V8_HOST_ARCH_MIPS 401MemCopyUint8Function memcopy_uint8_function = &MemCopyUint8Wrapper; 402// Defined in codegen-mips.cc. 403MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate, 404 MemCopyUint8Function stub); 405#endif 406 407 408static bool g_memcopy_functions_initialized = false; 409 410 411void 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 431bool 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