V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
utils.cc
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 
15 namespace v8 {
16 namespace internal {
17 
18 SimpleStringBuilder::SimpleStringBuilder(int size) {
19  buffer_ = Vector<char>::New(size);
20  position_ = 0;
21 }
22 
23 
24 void SimpleStringBuilder::AddString(const char* s) {
25  AddSubstring(s, StrLength(s));
26 }
27 
28 
29 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  MemCopy(&buffer_[position_], s, n * kCharSize);
33  position_ += n;
34 }
35 
36 
37 void SimpleStringBuilder::AddPadding(char c, int count) {
38  for (int i = 0; i < count; i++) {
39  AddCharacter(c);
40  }
41 }
42 
43 
44 void SimpleStringBuilder::AddDecimalInteger(int32_t value) {
45  uint32_t number = static_cast<uint32_t>(value);
46  if (value < 0) {
47  AddCharacter('-');
48  number = static_cast<uint32_t>(-value);
49  }
50  int digits = 1;
51  for (uint32_t factor = 10; digits < 10; digits++, factor *= 10) {
52  if (factor > number) break;
53  }
54  position_ += digits;
55  for (int i = 1; i <= digits; i++) {
56  buffer_[position_ - i] = '0' + static_cast<char>(number % 10);
57  number /= 10;
58  }
59 }
60 
61 
62 char* SimpleStringBuilder::Finalize() {
63  DCHECK(!is_finalized() && position_ <= buffer_.length());
64  // If there is no space for null termination, overwrite last character.
65  if (position_ == buffer_.length()) {
66  position_--;
67  // Print ellipsis.
68  for (int i = 3; i > 0 && position_ > i; --i) buffer_[position_ - i] = '.';
69  }
70  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  position_ = -1;
75  DCHECK(is_finalized());
76  return buffer_.start();
77 }
78 
79 std::ostream& operator<<(std::ostream& os, FeedbackSlot slot) {
80  return os << "#" << slot.id_;
81 }
82 
83 
84 size_t hash_value(BailoutId id) {
85  base::hash<int> h;
86  return h(id.id_);
87 }
88 
89 
90 std::ostream& operator<<(std::ostream& os, BailoutId id) {
91  return os << id.id_;
92 }
93 
94 
95 void PrintF(const char* format, ...) {
96  va_list arguments;
97  va_start(arguments, format);
98  base::OS::VPrint(format, arguments);
99  va_end(arguments);
100 }
101 
102 
103 void PrintF(FILE* out, const char* format, ...) {
104  va_list arguments;
105  va_start(arguments, format);
106  base::OS::VFPrint(out, format, arguments);
107  va_end(arguments);
108 }
109 
110 
111 void PrintPID(const char* format, ...) {
112  base::OS::Print("[%d] ", base::OS::GetCurrentProcessId());
113  va_list arguments;
114  va_start(arguments, format);
115  base::OS::VPrint(format, arguments);
116  va_end(arguments);
117 }
118 
119 
120 void PrintIsolate(void* isolate, const char* format, ...) {
121  base::OS::Print("[%d:%p] ", base::OS::GetCurrentProcessId(), isolate);
122  va_list arguments;
123  va_start(arguments, format);
124  base::OS::VPrint(format, arguments);
125  va_end(arguments);
126 }
127 
128 
129 int SNPrintF(Vector<char> str, const char* format, ...) {
130  va_list args;
131  va_start(args, format);
132  int result = VSNPrintF(str, format, args);
133  va_end(args);
134  return result;
135 }
136 
137 
138 int VSNPrintF(Vector<char> str, const char* format, va_list args) {
139  return base::OS::VSNPrintF(str.start(), str.length(), format, args);
140 }
141 
142 
143 void StrNCpy(Vector<char> dest, const char* src, size_t n) {
144  base::OS::StrNCpy(dest.start(), dest.length(), src, n);
145 }
146 
147 
148 void Flush(FILE* out) {
149  fflush(out);
150 }
151 
152 
153 char* ReadLine(const char* prompt) {
154  char* result = nullptr;
155  char line_buf[256];
156  int offset = 0;
157  bool keep_going = true;
158  fprintf(stdout, "%s", prompt);
159  fflush(stdout);
160  while (keep_going) {
161  if (fgets(line_buf, sizeof(line_buf), stdin) == nullptr) {
162  // fgets got an error. Just give up.
163  if (result != nullptr) {
164  DeleteArray(result);
165  }
166  return nullptr;
167  }
168  int len = StrLength(line_buf);
169  if (len > 1 &&
170  line_buf[len - 2] == '\\' &&
171  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  line_buf[len - 2] = '\n';
175  line_buf[len - 1] = 0;
176  len -= 1;
177  } 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  if (result == nullptr) {
183  // Allocate the initial result and make room for the terminating '\0'
184  result = NewArray<char>(len + 1);
185  } else {
186  // Allocate a new result with enough room for the new addition.
187  int new_len = offset + len + 1;
188  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  MemCopy(new_result, result, offset * kCharSize);
192  DeleteArray(result);
193  result = new_result;
194  }
195  // Copy the newly read line into the result.
196  MemCopy(result + offset, line_buf, len * kCharSize);
197  offset += len;
198  }
199  DCHECK_NOT_NULL(result);
200  result[offset] = '\0';
201  return result;
202 }
203 
204 namespace {
205 
206 std::vector<char> ReadCharsFromFile(FILE* file, bool* exists, bool verbose,
207  const char* filename) {
208  if (file == nullptr || fseek(file, 0, SEEK_END) != 0) {
209  if (verbose) {
210  base::OS::PrintError("Cannot read from file %s.\n", filename);
211  }
212  *exists = false;
213  return std::vector<char>();
214  }
215 
216  // Get the size of the file and rewind it.
217  ptrdiff_t size = ftell(file);
218  rewind(file);
219 
220  std::vector<char> result(size);
221  for (ptrdiff_t i = 0; i < size && feof(file) == 0;) {
222  ptrdiff_t read = fread(result.data() + i, 1, size - i, file);
223  if (read != (size - i) && ferror(file) != 0) {
224  fclose(file);
225  *exists = false;
226  return std::vector<char>();
227  }
228  i += read;
229  }
230  *exists = true;
231  return result;
232 }
233 
234 std::vector<char> ReadCharsFromFile(const char* filename, bool* exists,
235  bool verbose) {
236  FILE* file = base::OS::FOpen(filename, "rb");
237  std::vector<char> result = ReadCharsFromFile(file, exists, verbose, filename);
238  if (file != nullptr) fclose(file);
239  return result;
240 }
241 
242 std::string VectorToString(const std::vector<char>& chars) {
243  if (chars.size() == 0) {
244  return std::string();
245  }
246  return std::string(chars.begin(), chars.end());
247 }
248 
249 } // namespace
250 
251 std::string ReadFile(const char* filename, bool* exists, bool verbose) {
252  std::vector<char> result = ReadCharsFromFile(filename, exists, verbose);
253  return VectorToString(result);
254 }
255 
256 std::string ReadFile(FILE* file, bool* exists, bool verbose) {
257  std::vector<char> result = ReadCharsFromFile(file, exists, verbose, "");
258  return VectorToString(result);
259 }
260 
261 
262 int WriteCharsToFile(const char* str, int size, FILE* f) {
263  int total = 0;
264  while (total < size) {
265  int write = static_cast<int>(fwrite(str, 1, size - total, f));
266  if (write == 0) {
267  return total;
268  }
269  total += write;
270  str += write;
271  }
272  return total;
273 }
274 
275 
276 int AppendChars(const char* filename,
277  const char* str,
278  int size,
279  bool verbose) {
280  FILE* f = base::OS::FOpen(filename, "ab");
281  if (f == nullptr) {
282  if (verbose) {
283  base::OS::PrintError("Cannot open file %s for writing.\n", filename);
284  }
285  return 0;
286  }
287  int written = WriteCharsToFile(str, size, f);
288  fclose(f);
289  return written;
290 }
291 
292 
293 int WriteChars(const char* filename,
294  const char* str,
295  int size,
296  bool verbose) {
297  FILE* f = base::OS::FOpen(filename, "wb");
298  if (f == nullptr) {
299  if (verbose) {
300  base::OS::PrintError("Cannot open file %s for writing.\n", filename);
301  }
302  return 0;
303  }
304  int written = WriteCharsToFile(str, size, f);
305  fclose(f);
306  return written;
307 }
308 
309 
310 int WriteBytes(const char* filename,
311  const byte* bytes,
312  int size,
313  bool verbose) {
314  const char* str = reinterpret_cast<const char*>(bytes);
315  return WriteChars(filename, str, size, verbose);
316 }
317 
318 
319 
320 void StringBuilder::AddFormatted(const char* format, ...) {
321  va_list arguments;
322  va_start(arguments, format);
323  AddFormattedList(format, arguments);
324  va_end(arguments);
325 }
326 
327 
328 void StringBuilder::AddFormattedList(const char* format, va_list list) {
329  DCHECK(!is_finalized() && position_ <= buffer_.length());
330  int n = VSNPrintF(buffer_ + position_, format, list);
331  if (n < 0 || n >= (buffer_.length() - position_)) {
332  position_ = buffer_.length();
333  } else {
334  position_ += n;
335  }
336 }
337 
338 #if V8_TARGET_ARCH_IA32
339 static void MemMoveWrapper(void* dest, const void* src, size_t size) {
340  memmove(dest, src, size);
341 }
342 
343 
344 // Initialize to library version so we can call this at any time during startup.
345 static MemMoveFunction memmove_function = &MemMoveWrapper;
346 
347 // Defined in codegen-ia32.cc.
348 MemMoveFunction CreateMemMoveFunction();
349 
350 // Copy memory area to disjoint memory area.
351 void MemMove(void* dest, const void* src, size_t size) {
352  if (size == 0) return;
353  // Note: here we rely on dependent reads being ordered. This is true
354  // on all architectures we currently support.
355  (*memmove_function)(dest, src, size);
356 }
357 
358 #elif V8_OS_POSIX && V8_HOST_ARCH_ARM
359 void MemCopyUint16Uint8Wrapper(uint16_t* dest, const uint8_t* src,
360  size_t chars) {
361  uint16_t* limit = dest + chars;
362  while (dest < limit) {
363  *dest++ = static_cast<uint16_t>(*src++);
364  }
365 }
366 
367 V8_EXPORT_PRIVATE MemCopyUint8Function memcopy_uint8_function =
368  &MemCopyUint8Wrapper;
369 MemCopyUint16Uint8Function memcopy_uint16_uint8_function =
370  &MemCopyUint16Uint8Wrapper;
371 // Defined in codegen-arm.cc.
372 MemCopyUint8Function CreateMemCopyUint8Function(MemCopyUint8Function stub);
373 MemCopyUint16Uint8Function CreateMemCopyUint16Uint8Function(
374  MemCopyUint16Uint8Function stub);
375 
376 #elif V8_OS_POSIX && V8_HOST_ARCH_MIPS
377 V8_EXPORT_PRIVATE MemCopyUint8Function memcopy_uint8_function =
378  &MemCopyUint8Wrapper;
379 // Defined in codegen-mips.cc.
380 MemCopyUint8Function CreateMemCopyUint8Function(MemCopyUint8Function stub);
381 #endif
382 
383 
384 static bool g_memcopy_functions_initialized = false;
385 
386 void init_memcopy_functions() {
387  if (g_memcopy_functions_initialized) return;
388  g_memcopy_functions_initialized = true;
389 #if V8_TARGET_ARCH_IA32
390  MemMoveFunction generated_memmove = CreateMemMoveFunction();
391  if (generated_memmove != nullptr) {
392  memmove_function = generated_memmove;
393  }
394 #elif V8_OS_POSIX && V8_HOST_ARCH_ARM
395  memcopy_uint8_function = CreateMemCopyUint8Function(&MemCopyUint8Wrapper);
396  memcopy_uint16_uint8_function =
397  CreateMemCopyUint16Uint8Function(&MemCopyUint16Uint8Wrapper);
398 #elif V8_OS_POSIX && V8_HOST_ARCH_MIPS
399  memcopy_uint8_function = CreateMemCopyUint8Function(&MemCopyUint8Wrapper);
400 #endif
401 }
402 
403 // Returns false iff d is NaN, +0, or -0.
404 bool DoubleToBoolean(double d) {
405  IeeeDoubleArchType u;
406  u.d = d;
407  if (u.bits.exp == 2047) {
408  // Detect NaN for IEEE double precision floating point.
409  if ((u.bits.man_low | u.bits.man_high) != 0) return false;
410  }
411  if (u.bits.exp == 0) {
412  // Detect +0, and -0 for IEEE double precision floating point.
413  if ((u.bits.man_low | u.bits.man_high) == 0) return false;
414  }
415  return true;
416 }
417 
418 uintptr_t GetCurrentStackPosition() {
419 #if V8_CC_MSVC
420  return reinterpret_cast<uintptr_t>(_AddressOfReturnAddress());
421 #else
422  return reinterpret_cast<uintptr_t>(__builtin_frame_address(0));
423 #endif
424 }
425 
426 // The filter is a pattern that matches function names in this way:
427 // "*" all; the default
428 // "-" all but the top-level function
429 // "-name" all but the function "name"
430 // "" only the top-level function
431 // "name" only the function "name"
432 // "name*" only functions starting with "name"
433 // "~" none; the tilde is not an identifier
434 bool PassesFilter(Vector<const char> name, Vector<const char> filter) {
435  if (filter.size() == 0) return name.size() == 0;
436  auto filter_it = filter.begin();
437  bool positive_filter = true;
438  if (*filter_it == '-') {
439  ++filter_it;
440  positive_filter = false;
441  }
442  if (filter_it == filter.end()) return name.size() != 0;
443  if (*filter_it == '*') return positive_filter;
444  if (*filter_it == '~') return !positive_filter;
445 
446  bool prefix_match = filter[filter.size() - 1] == '*';
447  size_t min_match_length = filter.size();
448  if (!positive_filter) min_match_length--; // Subtract 1 for leading '-'.
449  if (prefix_match) min_match_length--; // Subtract 1 for trailing '*'.
450 
451  if (name.size() < min_match_length) return !positive_filter;
452 
453  // TODO(sigurds): Use the new version of std::mismatch here, once we
454  // can assume C++14.
455  auto res = std::mismatch(filter_it, filter.end(), name.begin());
456  if (res.first == filter.end()) {
457  if (res.second == name.end()) {
458  // The strings match, so {name} passes if we have a {positive_filter}.
459  return positive_filter;
460  }
461  // {name} is longer than the filter, so {name} passes if we don't have a
462  // {positive_filter}.
463  return !positive_filter;
464  }
465  if (*res.first == '*') {
466  // We matched up to the wildcard, so {name} passes if we have a
467  // {positive_filter}.
468  return positive_filter;
469  }
470  // We don't match, so {name} passes if we don't have a {positive_filter}.
471  return !positive_filter;
472 }
473 
474 } // namespace internal
475 } // namespace v8
Definition: libplatform.h:13