v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
utils.cc
Go to the documentation of this file.
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/utils.h"
6
7#include <stdarg.h>
8#include <sys/stat.h>
9
10#include <cstring>
11#include <vector>
12
13#include "src/base/hashing.h"
14#include "src/base/logging.h"
18
19#ifdef V8_CC_MSVC
20#include <intrin.h> // _AddressOfReturnAddress()
21#endif
22
23namespace v8 {
24namespace internal {
25
26std::ostream& operator<<(std::ostream& os, FeedbackSlot slot) {
27 return os << "#" << slot.id_;
28}
29
32 return h(id.id_);
33}
34
35std::ostream& operator<<(std::ostream& os, BytecodeOffset id) {
36 return os << id.id_;
37}
38
39void PrintF(const char* format, ...) {
40 va_list arguments;
41 va_start(arguments, format);
42 base::OS::VPrint(format, arguments);
43 va_end(arguments);
44}
45
46void PrintF(FILE* out, const char* format, ...) {
47 va_list arguments;
48 va_start(arguments, format);
49 base::OS::VFPrint(out, format, arguments);
50 va_end(arguments);
51}
52
53void PrintPID(const char* format, ...) {
54 base::OS::Print("[%d] ", base::OS::GetCurrentProcessId());
55 va_list arguments;
56 va_start(arguments, format);
57 base::OS::VPrint(format, arguments);
58 va_end(arguments);
59}
60
61void PrintIsolate(void* isolate, const char* format, ...) {
62 base::OS::Print("[%d:%p] ", base::OS::GetCurrentProcessId(), isolate);
63 va_list arguments;
64 va_start(arguments, format);
65 base::OS::VPrint(format, arguments);
66 va_end(arguments);
67}
68
69char* ReadLine(const char* prompt) {
70 char* result = nullptr;
71 char line_buf[256];
72 size_t offset = 0;
73 bool keep_going = true;
74 fprintf(stdout, "%s", prompt);
75 fflush(stdout);
76 while (keep_going) {
77 if (fgets(line_buf, sizeof(line_buf), stdin) == nullptr) {
78 // fgets got an error. Just give up.
79 if (result != nullptr) {
81 }
82 return nullptr;
83 }
84 size_t len = strlen(line_buf);
85 if (len > 1 && line_buf[len - 2] == '\\' && line_buf[len - 1] == '\n') {
86 // When we read a line that ends with a "\" we remove the escape and
87 // append the remainder.
88 line_buf[len - 2] = '\n';
89 line_buf[len - 1] = 0;
90 len -= 1;
91 } else if ((len > 0) && (line_buf[len - 1] == '\n')) {
92 // Since we read a new line we are done reading the line. This
93 // will exit the loop after copying this buffer into the result.
94 keep_going = false;
95 }
96 if (result == nullptr) {
97 // Allocate the initial result and make room for the terminating '\0'
98 result = NewArray<char>(len + 1);
99 } else {
100 // Allocate a new result with enough room for the new addition.
101 size_t new_len = offset + len + 1;
102 char* new_result = NewArray<char>(new_len);
103 // Copy the existing input into the new array and set the new
104 // array as the result.
105 std::memcpy(new_result, result, offset * kCharSize);
107 result = new_result;
108 }
109 // Copy the newly read line into the result.
110 std::memcpy(result + offset, line_buf, len * kCharSize);
111 offset += len;
112 }
114 result[offset] = '\0';
115 return result;
116}
117
118namespace {
119
120std::vector<char> ReadCharsFromFile(FILE* file, bool* exists, bool verbose,
121 const char* filename) {
122 if (file == nullptr || fseek(file, 0, SEEK_END) != 0) {
123 if (verbose) {
124 base::OS::PrintError("Cannot read from file %s.\n", filename);
125 }
126 *exists = false;
127 return std::vector<char>();
128 }
129
130 // Get the size of the file and rewind it.
131 ptrdiff_t size = ftell(file);
132 rewind(file);
133
134 std::vector<char> result(size);
135 for (ptrdiff_t i = 0; i < size && feof(file) == 0;) {
136 ptrdiff_t read = fread(result.data() + i, 1, size - i, file);
137 if (read != (size - i) && ferror(file) != 0) {
138 base::Fclose(file);
139 *exists = false;
140 return std::vector<char>();
141 }
142 i += read;
143 }
144 *exists = true;
145 return result;
146}
147
148std::vector<char> ReadCharsFromFile(const char* filename, bool* exists,
149 bool verbose) {
150 FILE* file = base::OS::FOpen(filename, "rb");
151 std::vector<char> result = ReadCharsFromFile(file, exists, verbose, filename);
152 if (file != nullptr) base::Fclose(file);
153 return result;
154}
155
156std::string VectorToString(const std::vector<char>& chars) {
157 if (chars.empty()) {
158 return std::string();
159 }
160 return std::string(chars.begin(), chars.end());
161}
162
163int WriteCharsToFile(const char* str, int size, FILE* f) {
164 int total = 0;
165 while (total < size) {
166 int write = static_cast<int>(fwrite(str, 1, size - total, f));
167 if (write == 0) {
168 return total;
169 }
170 total += write;
171 str += write;
172 }
173 return total;
174}
175
176} // namespace
177
178std::string ReadFile(const char* filename, bool* exists, bool verbose) {
179 std::vector<char> result = ReadCharsFromFile(filename, exists, verbose);
180 return VectorToString(result);
181}
182
183std::string ReadFile(FILE* file, bool* exists, bool verbose) {
184 std::vector<char> result = ReadCharsFromFile(file, exists, verbose, "");
185 return VectorToString(result);
186}
187
188int WriteChars(const char* filename, const char* str, int size, bool verbose) {
189 FILE* f = base::OS::FOpen(filename, "wb");
190 if (f == nullptr) {
191 if (verbose) {
192 base::OS::PrintError("Cannot open file %s for writing.\n", filename);
193 }
194 return 0;
195 }
196 int written = WriteCharsToFile(str, size, f);
197 base::Fclose(f);
198 return written;
199}
200
201int WriteBytes(const char* filename, const uint8_t* bytes, int size,
202 bool verbose) {
203 const char* str = reinterpret_cast<const char*>(bytes);
204 return WriteChars(filename, str, size, verbose);
205}
206
207// Returns false iff d is NaN, +0, or -0.
208bool DoubleToBoolean(double d) {
210 u.d = d;
211 if (u.bits.exp == 2047) {
212 // Detect NaN for IEEE double precision floating point.
213 if ((u.bits.man_low | u.bits.man_high) != 0) return false;
214 }
215 if (u.bits.exp == 0) {
216 // Detect +0, and -0 for IEEE double precision floating point.
217 if ((u.bits.man_low | u.bits.man_high) == 0) return false;
218 }
219 return true;
220}
221
223#if V8_CC_MSVC
224 return reinterpret_cast<uintptr_t>(_AddressOfReturnAddress());
225#else
226 return reinterpret_cast<uintptr_t>(__builtin_frame_address(0));
227#endif
228}
229
230// The filter is a pattern that matches function names in this way:
231// "*" all; the default
232// "-" all but the top-level function
233// "-name" all but the function "name"
234// "" only the top-level function
235// "name" only the function "name"
236// "name*" only functions starting with "name"
237// "~" none; the tilde is not an identifier
240 if (filter.empty()) return name.empty();
241 auto filter_it = filter.begin();
242 bool positive_filter = true;
243 if (*filter_it == '-') {
244 ++filter_it;
245 positive_filter = false;
246 }
247 if (filter_it == filter.end()) return !name.empty();
248 if (*filter_it == '*') return positive_filter;
249 if (*filter_it == '~') return !positive_filter;
250
251 bool prefix_match = filter[filter.size() - 1] == '*';
252 size_t min_match_length = filter.size();
253 if (!positive_filter) min_match_length--; // Subtract 1 for leading '-'.
254 if (prefix_match) min_match_length--; // Subtract 1 for trailing '*'.
255
256 if (name.size() < min_match_length) return !positive_filter;
257
258 // TODO(sigurds): Use the new version of std::mismatch here, once we
259 // can assume C++14.
260 auto res = std::mismatch(filter_it, filter.end(), name.begin());
261 if (res.first == filter.end()) {
262 if (res.second == name.end()) {
263 // The strings match, so {name} passes if we have a {positive_filter}.
264 return positive_filter;
265 }
266 // {name} is longer than the filter, so {name} passes if we don't have a
267 // {positive_filter}.
268 return !positive_filter;
269 }
270 if (*res.first == '*') {
271 // We matched up to the wildcard, so {name} passes if we have a
272 // {positive_filter}.
273 return positive_filter;
274 }
275 // We don't match, so {name} passes if we don't have a {positive_filter}.
276 return !positive_filter;
277}
278
279} // namespace internal
280} // namespace v8
static FILE * FOpen(const char *path, const char *mode)
static int GetCurrentProcessId()
std::string filename
int32_t offset
ZoneVector< RpoNumber > & result
int Fclose(FILE *stream)
Definition wrappers.h:22
void DeleteArray(T *array)
Definition allocation.h:63
int WriteBytes(const char *filename, const uint8_t *bytes, int size, bool verbose)
Definition utils.cc:201
void PrintPID(const char *format,...)
Definition utils.cc:53
size_t hash_value(AtomicMemoryOrder order)
void PrintF(const char *format,...)
Definition utils.cc:39
char * ReadLine(const char *prompt)
Definition utils.cc:69
bool DoubleToBoolean(double d)
Definition utils.cc:208
constexpr int kCharSize
Definition globals.h:396
std::ostream & operator<<(std::ostream &os, AtomicMemoryOrder order)
int WriteChars(const char *filename, const char *str, int size, bool verbose)
Definition utils.cc:188
uintptr_t GetCurrentStackPosition()
Definition utils.cc:222
bool PassesFilter(base::Vector< const char > name, base::Vector< const char > filter)
Definition utils.cc:238
void PrintIsolate(void *isolate, const char *format,...)
Definition utils.cc:61
T * NewArray(size_t size)
Definition allocation.h:43
std::string ReadFile(const char *filename, bool *exists, bool verbose)
Definition utils.cc:178
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
struct v8::internal::IeeeDoubleBigEndianArchType::@33 bits