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