11cb0ef41Sopenharmony_ci// Copyright 2011 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/utils/utils.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include <stdarg.h> 81cb0ef41Sopenharmony_ci#include <sys/stat.h> 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ci#include <cstring> 111cb0ef41Sopenharmony_ci#include <vector> 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_ci#include "src/base/functional.h" 141cb0ef41Sopenharmony_ci#include "src/base/logging.h" 151cb0ef41Sopenharmony_ci#include "src/base/platform/platform.h" 161cb0ef41Sopenharmony_ci#include "src/base/platform/wrappers.h" 171cb0ef41Sopenharmony_ci#include "src/base/strings.h" 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_cinamespace v8 { 201cb0ef41Sopenharmony_cinamespace internal { 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, FeedbackSlot slot) { 231cb0ef41Sopenharmony_ci return os << "#" << slot.id_; 241cb0ef41Sopenharmony_ci} 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_cisize_t hash_value(BytecodeOffset id) { 271cb0ef41Sopenharmony_ci base::hash<int> h; 281cb0ef41Sopenharmony_ci return h(id.id_); 291cb0ef41Sopenharmony_ci} 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, BytecodeOffset id) { 321cb0ef41Sopenharmony_ci return os << id.id_; 331cb0ef41Sopenharmony_ci} 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_civoid PrintF(const char* format, ...) { 361cb0ef41Sopenharmony_ci va_list arguments; 371cb0ef41Sopenharmony_ci va_start(arguments, format); 381cb0ef41Sopenharmony_ci base::OS::VPrint(format, arguments); 391cb0ef41Sopenharmony_ci va_end(arguments); 401cb0ef41Sopenharmony_ci} 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_civoid PrintF(FILE* out, const char* format, ...) { 431cb0ef41Sopenharmony_ci va_list arguments; 441cb0ef41Sopenharmony_ci va_start(arguments, format); 451cb0ef41Sopenharmony_ci base::OS::VFPrint(out, format, arguments); 461cb0ef41Sopenharmony_ci va_end(arguments); 471cb0ef41Sopenharmony_ci} 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_civoid PrintPID(const char* format, ...) { 501cb0ef41Sopenharmony_ci base::OS::Print("[%d] ", base::OS::GetCurrentProcessId()); 511cb0ef41Sopenharmony_ci va_list arguments; 521cb0ef41Sopenharmony_ci va_start(arguments, format); 531cb0ef41Sopenharmony_ci base::OS::VPrint(format, arguments); 541cb0ef41Sopenharmony_ci va_end(arguments); 551cb0ef41Sopenharmony_ci} 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_civoid PrintIsolate(void* isolate, const char* format, ...) { 581cb0ef41Sopenharmony_ci base::OS::Print("[%d:%p] ", base::OS::GetCurrentProcessId(), isolate); 591cb0ef41Sopenharmony_ci va_list arguments; 601cb0ef41Sopenharmony_ci va_start(arguments, format); 611cb0ef41Sopenharmony_ci base::OS::VPrint(format, arguments); 621cb0ef41Sopenharmony_ci va_end(arguments); 631cb0ef41Sopenharmony_ci} 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_cichar* ReadLine(const char* prompt) { 661cb0ef41Sopenharmony_ci char* result = nullptr; 671cb0ef41Sopenharmony_ci char line_buf[256]; 681cb0ef41Sopenharmony_ci size_t offset = 0; 691cb0ef41Sopenharmony_ci bool keep_going = true; 701cb0ef41Sopenharmony_ci fprintf(stdout, "%s", prompt); 711cb0ef41Sopenharmony_ci fflush(stdout); 721cb0ef41Sopenharmony_ci while (keep_going) { 731cb0ef41Sopenharmony_ci if (fgets(line_buf, sizeof(line_buf), stdin) == nullptr) { 741cb0ef41Sopenharmony_ci // fgets got an error. Just give up. 751cb0ef41Sopenharmony_ci if (result != nullptr) { 761cb0ef41Sopenharmony_ci DeleteArray(result); 771cb0ef41Sopenharmony_ci } 781cb0ef41Sopenharmony_ci return nullptr; 791cb0ef41Sopenharmony_ci } 801cb0ef41Sopenharmony_ci size_t len = strlen(line_buf); 811cb0ef41Sopenharmony_ci if (len > 1 && line_buf[len - 2] == '\\' && line_buf[len - 1] == '\n') { 821cb0ef41Sopenharmony_ci // When we read a line that ends with a "\" we remove the escape and 831cb0ef41Sopenharmony_ci // append the remainder. 841cb0ef41Sopenharmony_ci line_buf[len - 2] = '\n'; 851cb0ef41Sopenharmony_ci line_buf[len - 1] = 0; 861cb0ef41Sopenharmony_ci len -= 1; 871cb0ef41Sopenharmony_ci } else if ((len > 0) && (line_buf[len - 1] == '\n')) { 881cb0ef41Sopenharmony_ci // Since we read a new line we are done reading the line. This 891cb0ef41Sopenharmony_ci // will exit the loop after copying this buffer into the result. 901cb0ef41Sopenharmony_ci keep_going = false; 911cb0ef41Sopenharmony_ci } 921cb0ef41Sopenharmony_ci if (result == nullptr) { 931cb0ef41Sopenharmony_ci // Allocate the initial result and make room for the terminating '\0' 941cb0ef41Sopenharmony_ci result = NewArray<char>(len + 1); 951cb0ef41Sopenharmony_ci } else { 961cb0ef41Sopenharmony_ci // Allocate a new result with enough room for the new addition. 971cb0ef41Sopenharmony_ci size_t new_len = offset + len + 1; 981cb0ef41Sopenharmony_ci char* new_result = NewArray<char>(new_len); 991cb0ef41Sopenharmony_ci // Copy the existing input into the new array and set the new 1001cb0ef41Sopenharmony_ci // array as the result. 1011cb0ef41Sopenharmony_ci std::memcpy(new_result, result, offset * kCharSize); 1021cb0ef41Sopenharmony_ci DeleteArray(result); 1031cb0ef41Sopenharmony_ci result = new_result; 1041cb0ef41Sopenharmony_ci } 1051cb0ef41Sopenharmony_ci // Copy the newly read line into the result. 1061cb0ef41Sopenharmony_ci std::memcpy(result + offset, line_buf, len * kCharSize); 1071cb0ef41Sopenharmony_ci offset += len; 1081cb0ef41Sopenharmony_ci } 1091cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(result); 1101cb0ef41Sopenharmony_ci result[offset] = '\0'; 1111cb0ef41Sopenharmony_ci return result; 1121cb0ef41Sopenharmony_ci} 1131cb0ef41Sopenharmony_ci 1141cb0ef41Sopenharmony_cinamespace { 1151cb0ef41Sopenharmony_ci 1161cb0ef41Sopenharmony_cistd::vector<char> ReadCharsFromFile(FILE* file, bool* exists, bool verbose, 1171cb0ef41Sopenharmony_ci const char* filename) { 1181cb0ef41Sopenharmony_ci if (file == nullptr || fseek(file, 0, SEEK_END) != 0) { 1191cb0ef41Sopenharmony_ci if (verbose) { 1201cb0ef41Sopenharmony_ci base::OS::PrintError("Cannot read from file %s.\n", filename); 1211cb0ef41Sopenharmony_ci } 1221cb0ef41Sopenharmony_ci *exists = false; 1231cb0ef41Sopenharmony_ci return std::vector<char>(); 1241cb0ef41Sopenharmony_ci } 1251cb0ef41Sopenharmony_ci 1261cb0ef41Sopenharmony_ci // Get the size of the file and rewind it. 1271cb0ef41Sopenharmony_ci ptrdiff_t size = ftell(file); 1281cb0ef41Sopenharmony_ci rewind(file); 1291cb0ef41Sopenharmony_ci 1301cb0ef41Sopenharmony_ci std::vector<char> result(size); 1311cb0ef41Sopenharmony_ci for (ptrdiff_t i = 0; i < size && feof(file) == 0;) { 1321cb0ef41Sopenharmony_ci ptrdiff_t read = fread(result.data() + i, 1, size - i, file); 1331cb0ef41Sopenharmony_ci if (read != (size - i) && ferror(file) != 0) { 1341cb0ef41Sopenharmony_ci base::Fclose(file); 1351cb0ef41Sopenharmony_ci *exists = false; 1361cb0ef41Sopenharmony_ci return std::vector<char>(); 1371cb0ef41Sopenharmony_ci } 1381cb0ef41Sopenharmony_ci i += read; 1391cb0ef41Sopenharmony_ci } 1401cb0ef41Sopenharmony_ci *exists = true; 1411cb0ef41Sopenharmony_ci return result; 1421cb0ef41Sopenharmony_ci} 1431cb0ef41Sopenharmony_ci 1441cb0ef41Sopenharmony_cistd::vector<char> ReadCharsFromFile(const char* filename, bool* exists, 1451cb0ef41Sopenharmony_ci bool verbose) { 1461cb0ef41Sopenharmony_ci FILE* file = base::OS::FOpen(filename, "rb"); 1471cb0ef41Sopenharmony_ci std::vector<char> result = ReadCharsFromFile(file, exists, verbose, filename); 1481cb0ef41Sopenharmony_ci if (file != nullptr) base::Fclose(file); 1491cb0ef41Sopenharmony_ci return result; 1501cb0ef41Sopenharmony_ci} 1511cb0ef41Sopenharmony_ci 1521cb0ef41Sopenharmony_cistd::string VectorToString(const std::vector<char>& chars) { 1531cb0ef41Sopenharmony_ci if (chars.empty()) { 1541cb0ef41Sopenharmony_ci return std::string(); 1551cb0ef41Sopenharmony_ci } 1561cb0ef41Sopenharmony_ci return std::string(chars.begin(), chars.end()); 1571cb0ef41Sopenharmony_ci} 1581cb0ef41Sopenharmony_ci 1591cb0ef41Sopenharmony_ciint WriteCharsToFile(const char* str, int size, FILE* f) { 1601cb0ef41Sopenharmony_ci int total = 0; 1611cb0ef41Sopenharmony_ci while (total < size) { 1621cb0ef41Sopenharmony_ci int write = static_cast<int>(fwrite(str, 1, size - total, f)); 1631cb0ef41Sopenharmony_ci if (write == 0) { 1641cb0ef41Sopenharmony_ci return total; 1651cb0ef41Sopenharmony_ci } 1661cb0ef41Sopenharmony_ci total += write; 1671cb0ef41Sopenharmony_ci str += write; 1681cb0ef41Sopenharmony_ci } 1691cb0ef41Sopenharmony_ci return total; 1701cb0ef41Sopenharmony_ci} 1711cb0ef41Sopenharmony_ci 1721cb0ef41Sopenharmony_ci} // namespace 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_cistd::string ReadFile(const char* filename, bool* exists, bool verbose) { 1751cb0ef41Sopenharmony_ci std::vector<char> result = ReadCharsFromFile(filename, exists, verbose); 1761cb0ef41Sopenharmony_ci return VectorToString(result); 1771cb0ef41Sopenharmony_ci} 1781cb0ef41Sopenharmony_ci 1791cb0ef41Sopenharmony_cistd::string ReadFile(FILE* file, bool* exists, bool verbose) { 1801cb0ef41Sopenharmony_ci std::vector<char> result = ReadCharsFromFile(file, exists, verbose, ""); 1811cb0ef41Sopenharmony_ci return VectorToString(result); 1821cb0ef41Sopenharmony_ci} 1831cb0ef41Sopenharmony_ci 1841cb0ef41Sopenharmony_ciint WriteChars(const char* filename, const char* str, int size, bool verbose) { 1851cb0ef41Sopenharmony_ci FILE* f = base::OS::FOpen(filename, "wb"); 1861cb0ef41Sopenharmony_ci if (f == nullptr) { 1871cb0ef41Sopenharmony_ci if (verbose) { 1881cb0ef41Sopenharmony_ci base::OS::PrintError("Cannot open file %s for writing.\n", filename); 1891cb0ef41Sopenharmony_ci } 1901cb0ef41Sopenharmony_ci return 0; 1911cb0ef41Sopenharmony_ci } 1921cb0ef41Sopenharmony_ci int written = WriteCharsToFile(str, size, f); 1931cb0ef41Sopenharmony_ci base::Fclose(f); 1941cb0ef41Sopenharmony_ci return written; 1951cb0ef41Sopenharmony_ci} 1961cb0ef41Sopenharmony_ci 1971cb0ef41Sopenharmony_ciint WriteBytes(const char* filename, const byte* bytes, int size, 1981cb0ef41Sopenharmony_ci bool verbose) { 1991cb0ef41Sopenharmony_ci const char* str = reinterpret_cast<const char*>(bytes); 2001cb0ef41Sopenharmony_ci return WriteChars(filename, str, size, verbose); 2011cb0ef41Sopenharmony_ci} 2021cb0ef41Sopenharmony_ci 2031cb0ef41Sopenharmony_ci// Returns false iff d is NaN, +0, or -0. 2041cb0ef41Sopenharmony_cibool DoubleToBoolean(double d) { 2051cb0ef41Sopenharmony_ci IeeeDoubleArchType u; 2061cb0ef41Sopenharmony_ci u.d = d; 2071cb0ef41Sopenharmony_ci if (u.bits.exp == 2047) { 2081cb0ef41Sopenharmony_ci // Detect NaN for IEEE double precision floating point. 2091cb0ef41Sopenharmony_ci if ((u.bits.man_low | u.bits.man_high) != 0) return false; 2101cb0ef41Sopenharmony_ci } 2111cb0ef41Sopenharmony_ci if (u.bits.exp == 0) { 2121cb0ef41Sopenharmony_ci // Detect +0, and -0 for IEEE double precision floating point. 2131cb0ef41Sopenharmony_ci if ((u.bits.man_low | u.bits.man_high) == 0) return false; 2141cb0ef41Sopenharmony_ci } 2151cb0ef41Sopenharmony_ci return true; 2161cb0ef41Sopenharmony_ci} 2171cb0ef41Sopenharmony_ci 2181cb0ef41Sopenharmony_ciuintptr_t GetCurrentStackPosition() { 2191cb0ef41Sopenharmony_ci#if V8_CC_MSVC 2201cb0ef41Sopenharmony_ci return reinterpret_cast<uintptr_t>(_AddressOfReturnAddress()); 2211cb0ef41Sopenharmony_ci#else 2221cb0ef41Sopenharmony_ci return reinterpret_cast<uintptr_t>(__builtin_frame_address(0)); 2231cb0ef41Sopenharmony_ci#endif 2241cb0ef41Sopenharmony_ci} 2251cb0ef41Sopenharmony_ci 2261cb0ef41Sopenharmony_ci// The filter is a pattern that matches function names in this way: 2271cb0ef41Sopenharmony_ci// "*" all; the default 2281cb0ef41Sopenharmony_ci// "-" all but the top-level function 2291cb0ef41Sopenharmony_ci// "-name" all but the function "name" 2301cb0ef41Sopenharmony_ci// "" only the top-level function 2311cb0ef41Sopenharmony_ci// "name" only the function "name" 2321cb0ef41Sopenharmony_ci// "name*" only functions starting with "name" 2331cb0ef41Sopenharmony_ci// "~" none; the tilde is not an identifier 2341cb0ef41Sopenharmony_cibool PassesFilter(base::Vector<const char> name, 2351cb0ef41Sopenharmony_ci base::Vector<const char> filter) { 2361cb0ef41Sopenharmony_ci if (filter.size() == 0) return name.size() == 0; 2371cb0ef41Sopenharmony_ci auto filter_it = filter.begin(); 2381cb0ef41Sopenharmony_ci bool positive_filter = true; 2391cb0ef41Sopenharmony_ci if (*filter_it == '-') { 2401cb0ef41Sopenharmony_ci ++filter_it; 2411cb0ef41Sopenharmony_ci positive_filter = false; 2421cb0ef41Sopenharmony_ci } 2431cb0ef41Sopenharmony_ci if (filter_it == filter.end()) return name.size() != 0; 2441cb0ef41Sopenharmony_ci if (*filter_it == '*') return positive_filter; 2451cb0ef41Sopenharmony_ci if (*filter_it == '~') return !positive_filter; 2461cb0ef41Sopenharmony_ci 2471cb0ef41Sopenharmony_ci bool prefix_match = filter[filter.size() - 1] == '*'; 2481cb0ef41Sopenharmony_ci size_t min_match_length = filter.size(); 2491cb0ef41Sopenharmony_ci if (!positive_filter) min_match_length--; // Subtract 1 for leading '-'. 2501cb0ef41Sopenharmony_ci if (prefix_match) min_match_length--; // Subtract 1 for trailing '*'. 2511cb0ef41Sopenharmony_ci 2521cb0ef41Sopenharmony_ci if (name.size() < min_match_length) return !positive_filter; 2531cb0ef41Sopenharmony_ci 2541cb0ef41Sopenharmony_ci // TODO(sigurds): Use the new version of std::mismatch here, once we 2551cb0ef41Sopenharmony_ci // can assume C++14. 2561cb0ef41Sopenharmony_ci auto res = std::mismatch(filter_it, filter.end(), name.begin()); 2571cb0ef41Sopenharmony_ci if (res.first == filter.end()) { 2581cb0ef41Sopenharmony_ci if (res.second == name.end()) { 2591cb0ef41Sopenharmony_ci // The strings match, so {name} passes if we have a {positive_filter}. 2601cb0ef41Sopenharmony_ci return positive_filter; 2611cb0ef41Sopenharmony_ci } 2621cb0ef41Sopenharmony_ci // {name} is longer than the filter, so {name} passes if we don't have a 2631cb0ef41Sopenharmony_ci // {positive_filter}. 2641cb0ef41Sopenharmony_ci return !positive_filter; 2651cb0ef41Sopenharmony_ci } 2661cb0ef41Sopenharmony_ci if (*res.first == '*') { 2671cb0ef41Sopenharmony_ci // We matched up to the wildcard, so {name} passes if we have a 2681cb0ef41Sopenharmony_ci // {positive_filter}. 2691cb0ef41Sopenharmony_ci return positive_filter; 2701cb0ef41Sopenharmony_ci } 2711cb0ef41Sopenharmony_ci // We don't match, so {name} passes if we don't have a {positive_filter}. 2721cb0ef41Sopenharmony_ci return !positive_filter; 2731cb0ef41Sopenharmony_ci} 2741cb0ef41Sopenharmony_ci 2751cb0ef41Sopenharmony_ci} // namespace internal 2761cb0ef41Sopenharmony_ci} // namespace v8 277