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