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 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