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 :
10 : #include "src/base/functional.h"
11 : #include "src/base/logging.h"
12 : #include "src/base/platform/platform.h"
13 :
14 : namespace v8 {
15 : namespace internal {
16 :
17 13593 : SimpleStringBuilder::SimpleStringBuilder(int size) {
18 13593 : buffer_ = Vector<char>::New(size);
19 13593 : position_ = 0;
20 13593 : }
21 :
22 :
23 2765553 : void SimpleStringBuilder::AddString(const char* s) {
24 : AddSubstring(s, StrLength(s));
25 2765553 : }
26 :
27 :
28 664213 : void SimpleStringBuilder::AddSubstring(const char* s, int n) {
29 : DCHECK(!is_finalized() && position_ + n <= buffer_.length());
30 : DCHECK(static_cast<size_t>(n) <= strlen(s));
31 3429766 : MemCopy(&buffer_[position_], s, n * kCharSize);
32 3429766 : position_ += n;
33 664213 : }
34 :
35 :
36 1790496 : void SimpleStringBuilder::AddPadding(char c, int count) {
37 2116305 : for (int i = 0; i < count; i++) {
38 : AddCharacter(c);
39 : }
40 1790496 : }
41 :
42 :
43 310894 : void SimpleStringBuilder::AddDecimalInteger(int32_t value) {
44 310894 : uint32_t number = static_cast<uint32_t>(value);
45 310894 : if (value < 0) {
46 : AddCharacter('-');
47 0 : number = static_cast<uint32_t>(-value);
48 : }
49 : int digits = 1;
50 752601 : for (uint32_t factor = 10; digits < 10; digits++, factor *= 10) {
51 752601 : if (factor > number) break;
52 : }
53 310894 : position_ += digits;
54 1063495 : for (int i = 1; i <= digits; i++) {
55 1505202 : buffer_[position_ - i] = '0' + static_cast<char>(number % 10);
56 752601 : number /= 10;
57 : }
58 310894 : }
59 :
60 :
61 2751738 : char* SimpleStringBuilder::Finalize() {
62 : DCHECK(!is_finalized() && position_ <= buffer_.length());
63 : // If there is no space for null termination, overwrite last character.
64 11006952 : if (position_ == buffer_.length()) {
65 0 : position_--;
66 : // Print ellipsis.
67 0 : for (int i = 3; i > 0 && position_ > i; --i) buffer_[position_ - i] = '.';
68 : }
69 5503476 : buffer_[position_] = '\0';
70 : // Make sure nobody managed to add a 0-character to the
71 : // buffer while building the string.
72 : DCHECK(strlen(buffer_.start()) == static_cast<size_t>(position_));
73 2751738 : position_ = -1;
74 : DCHECK(is_finalized());
75 2751738 : return buffer_.start();
76 : }
77 :
78 0 : std::ostream& operator<<(std::ostream& os, FeedbackSlot slot) {
79 0 : return os << "#" << slot.id_;
80 : }
81 :
82 :
83 24853790 : size_t hash_value(BailoutId id) {
84 : base::hash<int> h;
85 49707521 : return h(id.id_);
86 : }
87 :
88 :
89 0 : std::ostream& operator<<(std::ostream& os, BailoutId id) {
90 0 : return os << id.id_;
91 : }
92 :
93 :
94 9328 : void PrintF(const char* format, ...) {
95 : va_list arguments;
96 9328 : va_start(arguments, format);
97 9328 : base::OS::VPrint(format, arguments);
98 9328 : va_end(arguments);
99 9328 : }
100 :
101 :
102 3182225 : void PrintF(FILE* out, const char* format, ...) {
103 : va_list arguments;
104 3182225 : va_start(arguments, format);
105 3182225 : base::OS::VFPrint(out, format, arguments);
106 3182225 : va_end(arguments);
107 3182225 : }
108 :
109 :
110 0 : void PrintPID(const char* format, ...) {
111 0 : base::OS::Print("[%d] ", base::OS::GetCurrentProcessId());
112 : va_list arguments;
113 0 : va_start(arguments, format);
114 0 : base::OS::VPrint(format, arguments);
115 0 : va_end(arguments);
116 0 : }
117 :
118 :
119 0 : void PrintIsolate(void* isolate, const char* format, ...) {
120 0 : base::OS::Print("[%d:%p] ", base::OS::GetCurrentProcessId(), isolate);
121 : va_list arguments;
122 0 : va_start(arguments, format);
123 0 : base::OS::VPrint(format, arguments);
124 0 : va_end(arguments);
125 0 : }
126 :
127 :
128 850752 : int SNPrintF(Vector<char> str, const char* format, ...) {
129 : va_list args;
130 850752 : va_start(args, format);
131 : int result = VSNPrintF(str, format, args);
132 850753 : va_end(args);
133 850753 : return result;
134 : }
135 :
136 :
137 3117679 : int VSNPrintF(Vector<char> str, const char* format, va_list args) {
138 7086110 : return base::OS::VSNPrintF(str.start(), str.length(), format, args);
139 : }
140 :
141 :
142 7619 : void StrNCpy(Vector<char> dest, const char* src, size_t n) {
143 15238 : base::OS::StrNCpy(dest.start(), dest.length(), src, n);
144 7619 : }
145 :
146 :
147 0 : void Flush(FILE* out) {
148 0 : fflush(out);
149 0 : }
150 :
151 :
152 0 : char* ReadLine(const char* prompt) {
153 : char* result = nullptr;
154 : char line_buf[256];
155 : int offset = 0;
156 : bool keep_going = true;
157 0 : fprintf(stdout, "%s", prompt);
158 0 : fflush(stdout);
159 0 : while (keep_going) {
160 0 : if (fgets(line_buf, sizeof(line_buf), stdin) == nullptr) {
161 : // fgets got an error. Just give up.
162 0 : if (result != nullptr) {
163 : DeleteArray(result);
164 : }
165 : return nullptr;
166 : }
167 : int len = StrLength(line_buf);
168 0 : if (len > 1 &&
169 0 : line_buf[len - 2] == '\\' &&
170 0 : line_buf[len - 1] == '\n') {
171 : // When we read a line that ends with a "\" we remove the escape and
172 : // append the remainder.
173 0 : line_buf[len - 2] = '\n';
174 0 : line_buf[len - 1] = 0;
175 0 : len -= 1;
176 0 : } else if ((len > 0) && (line_buf[len - 1] == '\n')) {
177 : // Since we read a new line we are done reading the line. This
178 : // will exit the loop after copying this buffer into the result.
179 : keep_going = false;
180 : }
181 0 : if (result == nullptr) {
182 : // Allocate the initial result and make room for the terminating '\0'
183 0 : result = NewArray<char>(len + 1);
184 : } else {
185 : // Allocate a new result with enough room for the new addition.
186 0 : int new_len = offset + len + 1;
187 0 : char* new_result = NewArray<char>(new_len);
188 : // Copy the existing input into the new array and set the new
189 : // array as the result.
190 0 : MemCopy(new_result, result, offset * kCharSize);
191 : DeleteArray(result);
192 : result = new_result;
193 : }
194 : // Copy the newly read line into the result.
195 0 : MemCopy(result + offset, line_buf, len * kCharSize);
196 0 : offset += len;
197 : }
198 : DCHECK_NOT_NULL(result);
199 0 : result[offset] = '\0';
200 0 : return result;
201 : }
202 :
203 :
204 1747 : char* ReadCharsFromFile(FILE* file,
205 : int* size,
206 : int extra_space,
207 : bool verbose,
208 : const char* filename) {
209 1747 : 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 : return nullptr;
214 : }
215 :
216 : // Get the size of the file and rewind it.
217 1747 : *size = static_cast<int>(ftell(file));
218 1747 : rewind(file);
219 :
220 1747 : char* result = NewArray<char>(*size + extra_space);
221 5241 : for (int i = 0; i < *size && feof(file) == 0;) {
222 3494 : int read = static_cast<int>(fread(&result[i], 1, *size - i, file));
223 1747 : if (read != (*size - i) && ferror(file) != 0) {
224 0 : fclose(file);
225 : DeleteArray(result);
226 : return nullptr;
227 : }
228 1747 : i += read;
229 : }
230 : return result;
231 : }
232 :
233 :
234 1731 : char* ReadCharsFromFile(const char* filename,
235 : int* size,
236 : int extra_space,
237 : bool verbose) {
238 1731 : FILE* file = base::OS::FOpen(filename, "rb");
239 1731 : char* result = ReadCharsFromFile(file, size, extra_space, verbose, filename);
240 1731 : if (file != nullptr) fclose(file);
241 1731 : return result;
242 : }
243 :
244 :
245 0 : byte* ReadBytes(const char* filename, int* size, bool verbose) {
246 0 : char* chars = ReadCharsFromFile(filename, size, 0, verbose);
247 0 : return reinterpret_cast<byte*>(chars);
248 : }
249 :
250 :
251 : static Vector<const char> SetVectorContents(char* chars,
252 : int size,
253 : bool* exists) {
254 1747 : if (!chars) {
255 0 : *exists = false;
256 : return Vector<const char>::empty();
257 : }
258 1747 : chars[size] = '\0';
259 1747 : *exists = true;
260 : return Vector<const char>(chars, size);
261 : }
262 :
263 :
264 1731 : Vector<const char> ReadFile(const char* filename,
265 : bool* exists,
266 : bool verbose) {
267 : int size;
268 1731 : char* result = ReadCharsFromFile(filename, &size, 1, verbose);
269 3462 : return SetVectorContents(result, size, exists);
270 : }
271 :
272 :
273 16 : Vector<const char> ReadFile(FILE* file,
274 : bool* exists,
275 : bool verbose) {
276 : int size;
277 16 : char* result = ReadCharsFromFile(file, &size, 1, verbose, "");
278 32 : return SetVectorContents(result, size, exists);
279 : }
280 :
281 :
282 0 : int WriteCharsToFile(const char* str, int size, FILE* f) {
283 : int total = 0;
284 0 : while (total < size) {
285 0 : int write = static_cast<int>(fwrite(str, 1, size - total, f));
286 0 : if (write == 0) {
287 : return total;
288 : }
289 0 : total += write;
290 0 : str += write;
291 : }
292 : return total;
293 : }
294 :
295 :
296 0 : int AppendChars(const char* filename,
297 : const char* str,
298 : int size,
299 : bool verbose) {
300 0 : FILE* f = base::OS::FOpen(filename, "ab");
301 0 : if (f == nullptr) {
302 0 : if (verbose) {
303 0 : base::OS::PrintError("Cannot open file %s for writing.\n", filename);
304 : }
305 : return 0;
306 : }
307 0 : int written = WriteCharsToFile(str, size, f);
308 0 : fclose(f);
309 0 : return written;
310 : }
311 :
312 :
313 0 : int WriteChars(const char* filename,
314 : const char* str,
315 : int size,
316 : bool verbose) {
317 0 : FILE* f = base::OS::FOpen(filename, "wb");
318 0 : if (f == nullptr) {
319 0 : if (verbose) {
320 0 : base::OS::PrintError("Cannot open file %s for writing.\n", filename);
321 : }
322 : return 0;
323 : }
324 0 : int written = WriteCharsToFile(str, size, f);
325 0 : fclose(f);
326 0 : return written;
327 : }
328 :
329 :
330 0 : int WriteBytes(const char* filename,
331 : const byte* bytes,
332 : int size,
333 : bool verbose) {
334 : const char* str = reinterpret_cast<const char*>(bytes);
335 0 : return WriteChars(filename, str, size, verbose);
336 : }
337 :
338 :
339 :
340 0 : void StringBuilder::AddFormatted(const char* format, ...) {
341 : va_list arguments;
342 0 : va_start(arguments, format);
343 0 : AddFormattedList(format, arguments);
344 0 : va_end(arguments);
345 0 : }
346 :
347 :
348 0 : void StringBuilder::AddFormattedList(const char* format, va_list list) {
349 : DCHECK(!is_finalized() && position_ <= buffer_.length());
350 0 : int n = VSNPrintF(buffer_ + position_, format, list);
351 0 : if (n < 0 || n >= (buffer_.length() - position_)) {
352 0 : position_ = buffer_.length();
353 : } else {
354 0 : position_ += n;
355 : }
356 0 : }
357 :
358 : #if V8_TARGET_ARCH_IA32
359 : static void MemMoveWrapper(void* dest, const void* src, size_t size) {
360 : memmove(dest, src, size);
361 : }
362 :
363 :
364 : // Initialize to library version so we can call this at any time during startup.
365 : static MemMoveFunction memmove_function = &MemMoveWrapper;
366 :
367 : // Defined in codegen-ia32.cc.
368 : MemMoveFunction CreateMemMoveFunction(Isolate* isolate);
369 :
370 : // Copy memory area to disjoint memory area.
371 : void MemMove(void* dest, const void* src, size_t size) {
372 : if (size == 0) return;
373 : // Note: here we rely on dependent reads being ordered. This is true
374 : // on all architectures we currently support.
375 : (*memmove_function)(dest, src, size);
376 : }
377 :
378 : #elif V8_OS_POSIX && V8_HOST_ARCH_ARM
379 : void MemCopyUint16Uint8Wrapper(uint16_t* dest, const uint8_t* src,
380 : size_t chars) {
381 : uint16_t* limit = dest + chars;
382 : while (dest < limit) {
383 : *dest++ = static_cast<uint16_t>(*src++);
384 : }
385 : }
386 :
387 : V8_EXPORT_PRIVATE MemCopyUint8Function memcopy_uint8_function =
388 : &MemCopyUint8Wrapper;
389 : MemCopyUint16Uint8Function memcopy_uint16_uint8_function =
390 : &MemCopyUint16Uint8Wrapper;
391 : // Defined in codegen-arm.cc.
392 : MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate,
393 : MemCopyUint8Function stub);
394 : MemCopyUint16Uint8Function CreateMemCopyUint16Uint8Function(
395 : Isolate* isolate, MemCopyUint16Uint8Function stub);
396 :
397 : #elif V8_OS_POSIX && V8_HOST_ARCH_MIPS
398 : V8_EXPORT_PRIVATE MemCopyUint8Function memcopy_uint8_function =
399 : &MemCopyUint8Wrapper;
400 : // Defined in codegen-mips.cc.
401 : MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate,
402 : MemCopyUint8Function stub);
403 : #endif
404 :
405 :
406 : static bool g_memcopy_functions_initialized = false;
407 :
408 :
409 54999 : void init_memcopy_functions(Isolate* isolate) {
410 109998 : if (g_memcopy_functions_initialized) return;
411 52470 : g_memcopy_functions_initialized = true;
412 : #if V8_TARGET_ARCH_IA32
413 : MemMoveFunction generated_memmove = CreateMemMoveFunction(isolate);
414 : if (generated_memmove != nullptr) {
415 : memmove_function = generated_memmove;
416 : }
417 : #elif V8_OS_POSIX && V8_HOST_ARCH_ARM
418 : memcopy_uint8_function =
419 : CreateMemCopyUint8Function(isolate, &MemCopyUint8Wrapper);
420 : memcopy_uint16_uint8_function =
421 : CreateMemCopyUint16Uint8Function(isolate, &MemCopyUint16Uint8Wrapper);
422 : #elif V8_OS_POSIX && V8_HOST_ARCH_MIPS
423 : memcopy_uint8_function =
424 : CreateMemCopyUint8Function(isolate, &MemCopyUint8Wrapper);
425 : #endif
426 : }
427 :
428 :
429 5841 : bool DoubleToBoolean(double d) {
430 : // NaN, +0, and -0 should return the false object
431 : IeeeDoubleArchType u;
432 :
433 5841 : u.d = d;
434 5841 : if (u.bits.exp == 2047) {
435 : // Detect NaN for IEEE double precision floating point.
436 2862 : if ((u.bits.man_low | u.bits.man_high) != 0) return false;
437 : }
438 2985 : if (u.bits.exp == 0) {
439 : // Detect +0, and -0 for IEEE double precision floating point.
440 2835 : if ((u.bits.man_low | u.bits.man_high) == 0) return false;
441 : }
442 150 : return true;
443 : }
444 :
445 :
446 : } // namespace internal
447 : } // namespace v8
|