Line data Source code
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 : #include <vector>
10 :
11 : #include "src/base/functional.h"
12 : #include "src/base/logging.h"
13 : #include "src/base/platform/platform.h"
14 : #include "src/memcopy.h"
15 :
16 : namespace v8 {
17 : namespace internal {
18 :
19 12792 : SimpleStringBuilder::SimpleStringBuilder(int size) {
20 12792 : buffer_ = Vector<char>::New(size);
21 12792 : position_ = 0;
22 12792 : }
23 :
24 :
25 1156927 : void SimpleStringBuilder::AddString(const char* s) {
26 : AddSubstring(s, StrLength(s));
27 1156927 : }
28 :
29 :
30 705094 : void SimpleStringBuilder::AddSubstring(const char* s, int n) {
31 : DCHECK(!is_finalized() && position_ + n <= buffer_.length());
32 : DCHECK(static_cast<size_t>(n) <= strlen(s));
33 1862021 : MemCopy(&buffer_[position_], s, n * kCharSize);
34 1862021 : position_ += n;
35 705094 : }
36 :
37 :
38 159388 : void SimpleStringBuilder::AddPadding(char c, int count) {
39 443490 : for (int i = 0; i < count; i++) {
40 : AddCharacter(c);
41 : }
42 159388 : }
43 :
44 :
45 291225 : void SimpleStringBuilder::AddDecimalInteger(int32_t value) {
46 291225 : uint32_t number = static_cast<uint32_t>(value);
47 291225 : if (value < 0) {
48 : AddCharacter('-');
49 0 : number = static_cast<uint32_t>(-value);
50 : }
51 : int digits = 1;
52 1108643 : for (uint32_t factor = 10; digits < 10; digits++, factor *= 10) {
53 699934 : if (factor > number) break;
54 : }
55 291225 : position_ += digits;
56 1691093 : for (int i = 1; i <= digits; i++) {
57 1399868 : buffer_[position_ - i] = '0' + static_cast<char>(number % 10);
58 699934 : number /= 10;
59 : }
60 291225 : }
61 :
62 :
63 1142617 : char* SimpleStringBuilder::Finalize() {
64 : DCHECK(!is_finalized() && position_ <= buffer_.length());
65 : // If there is no space for null termination, overwrite last character.
66 2285234 : if (position_ == buffer_.length()) {
67 0 : position_--;
68 : // Print ellipsis.
69 0 : for (int i = 3; i > 0 && position_ > i; --i) buffer_[position_ - i] = '.';
70 : }
71 2285234 : buffer_[position_] = '\0';
72 : // Make sure nobody managed to add a 0-character to the
73 : // buffer while building the string.
74 : DCHECK(strlen(buffer_.start()) == static_cast<size_t>(position_));
75 1142617 : position_ = -1;
76 : DCHECK(is_finalized());
77 1142617 : return buffer_.start();
78 : }
79 :
80 272 : std::ostream& operator<<(std::ostream& os, FeedbackSlot slot) {
81 544 : return os << "#" << slot.id_;
82 : }
83 :
84 :
85 29729504 : size_t hash_value(BailoutId id) {
86 : base::hash<int> h;
87 59458882 : return h(id.id_);
88 : }
89 :
90 :
91 74 : std::ostream& operator<<(std::ostream& os, BailoutId id) {
92 74 : return os << id.id_;
93 : }
94 :
95 :
96 141751 : void PrintF(const char* format, ...) {
97 : va_list arguments;
98 141751 : va_start(arguments, format);
99 141751 : base::OS::VPrint(format, arguments);
100 141751 : va_end(arguments);
101 141751 : }
102 :
103 :
104 3490936 : void PrintF(FILE* out, const char* format, ...) {
105 : va_list arguments;
106 3490936 : va_start(arguments, format);
107 3490936 : base::OS::VFPrint(out, format, arguments);
108 3490936 : va_end(arguments);
109 3490936 : }
110 :
111 :
112 0 : void PrintPID(const char* format, ...) {
113 0 : base::OS::Print("[%d] ", base::OS::GetCurrentProcessId());
114 : va_list arguments;
115 0 : va_start(arguments, format);
116 0 : base::OS::VPrint(format, arguments);
117 0 : va_end(arguments);
118 0 : }
119 :
120 :
121 0 : void PrintIsolate(void* isolate, const char* format, ...) {
122 0 : base::OS::Print("[%d:%p] ", base::OS::GetCurrentProcessId(), isolate);
123 : va_list arguments;
124 0 : va_start(arguments, format);
125 0 : base::OS::VPrint(format, arguments);
126 0 : va_end(arguments);
127 0 : }
128 :
129 :
130 2068216 : int SNPrintF(Vector<char> str, const char* format, ...) {
131 : va_list args;
132 2068216 : va_start(args, format);
133 : int result = VSNPrintF(str, format, args);
134 2068937 : va_end(args);
135 2068937 : return result;
136 : }
137 :
138 :
139 4588734 : int VSNPrintF(Vector<char> str, const char* format, va_list args) {
140 6656950 : return base::OS::VSNPrintF(str.start(), str.length(), format, args);
141 : }
142 :
143 :
144 26090 : void StrNCpy(Vector<char> dest, const char* src, size_t n) {
145 26090 : base::OS::StrNCpy(dest.start(), dest.length(), src, n);
146 26090 : }
147 :
148 :
149 0 : void Flush(FILE* out) {
150 0 : fflush(out);
151 0 : }
152 :
153 :
154 0 : char* ReadLine(const char* prompt) {
155 : char* result = nullptr;
156 : char line_buf[256];
157 : int offset = 0;
158 : bool keep_going = true;
159 0 : fprintf(stdout, "%s", prompt);
160 0 : fflush(stdout);
161 0 : while (keep_going) {
162 0 : if (fgets(line_buf, sizeof(line_buf), stdin) == nullptr) {
163 : // fgets got an error. Just give up.
164 0 : if (result != nullptr) {
165 : DeleteArray(result);
166 : }
167 : return nullptr;
168 : }
169 : int len = StrLength(line_buf);
170 0 : if (len > 1 &&
171 0 : line_buf[len - 2] == '\\' &&
172 0 : 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 0 : line_buf[len - 2] = '\n';
176 0 : line_buf[len - 1] = 0;
177 0 : len -= 1;
178 0 : } 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 0 : if (result == nullptr) {
184 : // Allocate the initial result and make room for the terminating '\0'
185 0 : result = NewArray<char>(len + 1);
186 : } else {
187 : // Allocate a new result with enough room for the new addition.
188 0 : int new_len = offset + len + 1;
189 0 : 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 0 : MemCopy(new_result, result, offset * kCharSize);
193 : DeleteArray(result);
194 : result = new_result;
195 : }
196 : // Copy the newly read line into the result.
197 0 : MemCopy(result + offset, line_buf, len * kCharSize);
198 0 : offset += len;
199 : }
200 : DCHECK_NOT_NULL(result);
201 0 : result[offset] = '\0';
202 0 : return result;
203 : }
204 :
205 : namespace {
206 :
207 2369 : std::vector<char> ReadCharsFromFile(FILE* file, bool* exists, bool verbose,
208 : const char* filename) {
209 2369 : if (file == nullptr || fseek(file, 0, SEEK_END) != 0) {
210 0 : if (verbose) {
211 0 : base::OS::PrintError("Cannot read from file %s.\n", filename);
212 : }
213 0 : *exists = false;
214 : return std::vector<char>();
215 : }
216 :
217 : // Get the size of the file and rewind it.
218 2369 : ptrdiff_t size = ftell(file);
219 2369 : rewind(file);
220 :
221 2369 : std::vector<char> result(size);
222 7107 : for (ptrdiff_t i = 0; i < size && feof(file) == 0;) {
223 4738 : ptrdiff_t read = fread(result.data() + i, 1, size - i, file);
224 2369 : if (read != (size - i) && ferror(file) != 0) {
225 0 : fclose(file);
226 0 : *exists = false;
227 : return std::vector<char>();
228 : }
229 2369 : i += read;
230 : }
231 2369 : *exists = true;
232 : return result;
233 : }
234 :
235 2315 : std::vector<char> ReadCharsFromFile(const char* filename, bool* exists,
236 : bool verbose) {
237 2315 : FILE* file = base::OS::FOpen(filename, "rb");
238 2315 : std::vector<char> result = ReadCharsFromFile(file, exists, verbose, filename);
239 2315 : if (file != nullptr) fclose(file);
240 2315 : return result;
241 : }
242 :
243 : std::string VectorToString(const std::vector<char>& chars) {
244 2369 : if (chars.size() == 0) {
245 : return std::string();
246 : }
247 : return std::string(chars.begin(), chars.end());
248 : }
249 :
250 : } // namespace
251 :
252 2315 : std::string ReadFile(const char* filename, bool* exists, bool verbose) {
253 2315 : std::vector<char> result = ReadCharsFromFile(filename, exists, verbose);
254 2315 : return VectorToString(result);
255 : }
256 :
257 54 : std::string ReadFile(FILE* file, bool* exists, bool verbose) {
258 54 : std::vector<char> result = ReadCharsFromFile(file, exists, verbose, "");
259 54 : return VectorToString(result);
260 : }
261 :
262 :
263 0 : int WriteCharsToFile(const char* str, int size, FILE* f) {
264 : int total = 0;
265 0 : while (total < size) {
266 0 : int write = static_cast<int>(fwrite(str, 1, size - total, f));
267 0 : if (write == 0) {
268 : return total;
269 : }
270 0 : total += write;
271 0 : str += write;
272 : }
273 : return total;
274 : }
275 :
276 :
277 0 : int AppendChars(const char* filename,
278 : const char* str,
279 : int size,
280 : bool verbose) {
281 0 : FILE* f = base::OS::FOpen(filename, "ab");
282 0 : if (f == nullptr) {
283 0 : if (verbose) {
284 0 : base::OS::PrintError("Cannot open file %s for writing.\n", filename);
285 : }
286 : return 0;
287 : }
288 0 : int written = WriteCharsToFile(str, size, f);
289 0 : fclose(f);
290 0 : return written;
291 : }
292 :
293 :
294 0 : int WriteChars(const char* filename,
295 : const char* str,
296 : int size,
297 : bool verbose) {
298 0 : FILE* f = base::OS::FOpen(filename, "wb");
299 0 : if (f == nullptr) {
300 0 : if (verbose) {
301 0 : base::OS::PrintError("Cannot open file %s for writing.\n", filename);
302 : }
303 : return 0;
304 : }
305 0 : int written = WriteCharsToFile(str, size, f);
306 0 : fclose(f);
307 0 : return written;
308 : }
309 :
310 :
311 0 : int WriteBytes(const char* filename,
312 : const byte* bytes,
313 : int size,
314 : bool verbose) {
315 : const char* str = reinterpret_cast<const char*>(bytes);
316 0 : return WriteChars(filename, str, size, verbose);
317 : }
318 :
319 :
320 :
321 0 : void StringBuilder::AddFormatted(const char* format, ...) {
322 : va_list arguments;
323 0 : va_start(arguments, format);
324 0 : AddFormattedList(format, arguments);
325 0 : va_end(arguments);
326 0 : }
327 :
328 :
329 0 : void StringBuilder::AddFormattedList(const char* format, va_list list) {
330 : DCHECK(!is_finalized() && position_ <= buffer_.length());
331 0 : int n = VSNPrintF(buffer_ + position_, format, list);
332 0 : if (n < 0 || n >= (buffer_.length() - position_)) {
333 0 : position_ = buffer_.length();
334 : } else {
335 0 : position_ += n;
336 : }
337 0 : }
338 :
339 : // Returns false iff d is NaN, +0, or -0.
340 469851 : bool DoubleToBoolean(double d) {
341 : IeeeDoubleArchType u;
342 469851 : u.d = d;
343 469851 : if (u.bits.exp == 2047) {
344 : // Detect NaN for IEEE double precision floating point.
345 2862 : if ((u.bits.man_low | u.bits.man_high) != 0) return false;
346 : }
347 466995 : if (u.bits.exp == 0) {
348 : // Detect +0, and -0 for IEEE double precision floating point.
349 466713 : if ((u.bits.man_low | u.bits.man_high) == 0) return false;
350 : }
351 282 : return true;
352 : }
353 :
354 716542925 : uintptr_t GetCurrentStackPosition() {
355 : #if V8_CC_MSVC
356 : return reinterpret_cast<uintptr_t>(_AddressOfReturnAddress());
357 : #else
358 716542925 : return reinterpret_cast<uintptr_t>(__builtin_frame_address(0));
359 : #endif
360 : }
361 :
362 : // The filter is a pattern that matches function names in this way:
363 : // "*" all; the default
364 : // "-" all but the top-level function
365 : // "-name" all but the function "name"
366 : // "" only the top-level function
367 : // "name" only the function "name"
368 : // "name*" only functions starting with "name"
369 : // "~" none; the tilde is not an identifier
370 2946992 : bool PassesFilter(Vector<const char> name, Vector<const char> filter) {
371 2946992 : if (filter.size() == 0) return name.size() == 0;
372 : auto filter_it = filter.begin();
373 : bool positive_filter = true;
374 2946956 : if (*filter_it == '-') {
375 162 : ++filter_it;
376 : positive_filter = false;
377 : }
378 2946956 : if (filter_it == filter.end()) return name.size() != 0;
379 2946920 : if (*filter_it == '*') return positive_filter;
380 442 : if (*filter_it == '~') return !positive_filter;
381 :
382 812 : bool prefix_match = filter[filter.size() - 1] == '*';
383 : size_t min_match_length = filter.size();
384 406 : if (!positive_filter) min_match_length--; // Subtract 1 for leading '-'.
385 406 : if (prefix_match) min_match_length--; // Subtract 1 for trailing '*'.
386 :
387 406 : if (name.size() < min_match_length) return !positive_filter;
388 :
389 : // TODO(sigurds): Use the new version of std::mismatch here, once we
390 : // can assume C++14.
391 : auto res = std::mismatch(filter_it, filter.end(), name.begin());
392 274 : if (res.first == filter.end()) {
393 113 : if (res.second == name.end()) {
394 : // The strings match, so {name} passes if we have a {positive_filter}.
395 : return positive_filter;
396 : }
397 : // {name} is longer than the filter, so {name} passes if we don't have a
398 : // {positive_filter}.
399 0 : return !positive_filter;
400 : }
401 161 : if (*res.first == '*') {
402 : // We matched up to the wildcard, so {name} passes if we have a
403 : // {positive_filter}.
404 : return positive_filter;
405 : }
406 : // We don't match, so {name} passes if we don't have a {positive_filter}.
407 73 : return !positive_filter;
408 : }
409 :
410 : } // namespace internal
411 120216 : } // namespace v8
|