xref: /third_party/node/deps/v8/src/utils/utils-inl.h (revision 1cb0ef41)
1// Copyright 2016 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#ifndef V8_UTILS_UTILS_INL_H_
6#define V8_UTILS_UTILS_INL_H_
7
8#include "src/utils/utils.h"
9
10#include "include/v8-platform.h"
11#include "src/base/platform/time.h"
12#include "src/init/v8.h"
13#include "src/strings/char-predicates-inl.h"
14
15namespace v8 {
16namespace internal {
17
18class V8_NODISCARD TimedScope {
19 public:
20  explicit TimedScope(double* result)
21      : start_(TimestampMs()), result_(result) {}
22
23  ~TimedScope() { *result_ = TimestampMs() - start_; }
24
25 private:
26  static inline double TimestampMs() {
27    return V8::GetCurrentPlatform()->MonotonicallyIncreasingTime() *
28           static_cast<double>(base::Time::kMillisecondsPerSecond);
29  }
30
31  double start_;
32  double* result_;
33};
34
35template <typename Char>
36bool TryAddArrayIndexChar(uint32_t* index, Char c) {
37  if (!IsDecimalDigit(c)) return false;
38  int d = c - '0';
39  // The maximum index is 4294967294; for the computation below to not
40  // exceed that, the previous index value must be <= 429496729 if d <= 4,
41  // or <= 429496728 if d >= 5. The (d+3)>>3 computation is a branch-free
42  // way to express that.
43  if (*index > 429496729U - ((d + 3) >> 3)) return false;
44  *index = (*index) * 10 + d;
45  return true;
46}
47
48template <typename Char>
49bool TryAddIntegerIndexChar(uint64_t* index, Char c) {
50  if (!IsDecimalDigit(c)) return false;
51  int d = c - '0';
52  *index = (*index) * 10 + d;
53  return (*index <= kMaxSafeIntegerUint64);
54}
55
56template <typename Stream, typename index_t, enum ToIndexMode mode>
57bool StringToIndex(Stream* stream, index_t* index) {
58  uint16_t ch = stream->GetNext();
59
60  // If the string begins with a '0' character, it must only consist
61  // of it to be a legal array index.
62  if (ch == '0') {
63    *index = 0;
64    return !stream->HasMore();
65  }
66
67  // Convert string to uint32 array index; character by character.
68  if (!IsDecimalDigit(ch)) return false;
69  int d = ch - '0';
70  index_t result = d;
71  while (stream->HasMore()) {
72    // Clang on Mac doesn't think that size_t and uint*_t should be
73    // implicitly convertible.
74    if (sizeof(result) == 8) {
75      DCHECK_EQ(kToIntegerIndex, mode);
76      if (!TryAddIntegerIndexChar(reinterpret_cast<uint64_t*>(&result),
77                                  stream->GetNext())) {
78        return false;
79      }
80    } else {
81      // Either mode is fine here.
82      if (!TryAddArrayIndexChar(reinterpret_cast<uint32_t*>(&result),
83                                stream->GetNext()))
84        return false;
85    }
86  }
87
88  *index = result;
89  return true;
90}
91
92}  // namespace internal
93}  // namespace v8
94
95#endif  // V8_UTILS_UTILS_INL_H_
96