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
15 namespace v8 {
16 namespace internal {
17
18 class V8_NODISCARD TimedScope {
19 public:
TimedScope(double * result)20 explicit TimedScope(double* result)
21 : start_(TimestampMs()), result_(result) {}
22
~TimedScope()23 ~TimedScope() { *result_ = TimestampMs() - start_; }
24
25 private:
TimestampMs()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
35 template <typename Char>
TryAddArrayIndexChar(uint32_t * index,Char c)36 bool 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
48 template <typename Char>
TryAddIntegerIndexChar(uint64_t * index,Char c)49 bool 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
56 template <typename Stream, typename index_t, enum ToIndexMode mode>
StringToIndex(Stream * stream,index_t * index)57 bool 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