1 // Copyright 2020 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_OBJECTS_CODE_KIND_H_
6 #define V8_OBJECTS_CODE_KIND_H_
7 
8 #include "src/base/bounds.h"
9 #include "src/base/flags.h"
10 #include "src/flags/flags.h"
11 
12 namespace v8 {
13 namespace internal {
14 
15 // The order of INTERPRETED_FUNCTION to TURBOFAN is important. We use it to
16 // check the relative ordering of the tiers when fetching / installing optimized
17 // code.
18 #define CODE_KIND_LIST(V)       \
19   V(BYTECODE_HANDLER)           \
20   V(FOR_TESTING)                \
21   V(BUILTIN)                    \
22   V(REGEXP)                     \
23   V(WASM_FUNCTION)              \
24   V(WASM_TO_CAPI_FUNCTION)      \
25   V(WASM_TO_JS_FUNCTION)        \
26   V(JS_TO_WASM_FUNCTION)        \
27   V(JS_TO_JS_FUNCTION)          \
28   V(C_WASM_ENTRY)               \
29   V(INTERPRETED_FUNCTION)       \
30   V(BASELINE)                   \
31   V(TURBOPROP)                  \
32   V(TURBOFAN)
33 
34 enum class CodeKind {
35 #define DEFINE_CODE_KIND_ENUM(name) name,
36   CODE_KIND_LIST(DEFINE_CODE_KIND_ENUM)
37 #undef DEFINE_CODE_KIND_ENUM
38 };
39 STATIC_ASSERT(CodeKind::INTERPRETED_FUNCTION < CodeKind::TURBOPROP &&
40               CodeKind::INTERPRETED_FUNCTION < CodeKind::BASELINE);
41 STATIC_ASSERT(CodeKind::BASELINE < CodeKind::TURBOPROP);
42 STATIC_ASSERT(CodeKind::BASELINE < CodeKind::TURBOFAN &&
43               CodeKind::TURBOPROP < CodeKind::TURBOFAN);
44 
45 #define V(...) +1
46 static constexpr int kCodeKindCount = CODE_KIND_LIST(V);
47 #undef V
48 
49 const char* CodeKindToString(CodeKind kind);
50 
51 const char* CodeKindToMarker(CodeKind kind);
52 
CodeKindIsInterpretedJSFunction(CodeKind kind)53 inline constexpr bool CodeKindIsInterpretedJSFunction(CodeKind kind) {
54   return kind == CodeKind::INTERPRETED_FUNCTION;
55 }
56 
CodeKindIsBaselinedJSFunction(CodeKind kind)57 inline constexpr bool CodeKindIsBaselinedJSFunction(CodeKind kind) {
58   return kind == CodeKind::BASELINE;
59 }
60 
CodeKindIsUnoptimizedJSFunction(CodeKind kind)61 inline constexpr bool CodeKindIsUnoptimizedJSFunction(CodeKind kind) {
62   STATIC_ASSERT(static_cast<int>(CodeKind::INTERPRETED_FUNCTION) + 1 ==
63                 static_cast<int>(CodeKind::BASELINE));
64   return base::IsInRange(kind, CodeKind::INTERPRETED_FUNCTION,
65                          CodeKind::BASELINE);
66 }
67 
CodeKindIsOptimizedJSFunction(CodeKind kind)68 inline constexpr bool CodeKindIsOptimizedJSFunction(CodeKind kind) {
69   STATIC_ASSERT(static_cast<int>(CodeKind::TURBOPROP) + 1 ==
70                 static_cast<int>(CodeKind::TURBOFAN));
71   return base::IsInRange(kind, CodeKind::TURBOPROP, CodeKind::TURBOFAN);
72 }
73 
CodeKindIsJSFunction(CodeKind kind)74 inline constexpr bool CodeKindIsJSFunction(CodeKind kind) {
75   return CodeKindIsUnoptimizedJSFunction(kind) ||
76          CodeKindIsOptimizedJSFunction(kind);
77 }
78 
CodeKindIsBuiltinOrJSFunction(CodeKind kind)79 inline constexpr bool CodeKindIsBuiltinOrJSFunction(CodeKind kind) {
80   return kind == CodeKind::BUILTIN || CodeKindIsJSFunction(kind);
81 }
82 
CodeKindCanDeoptimize(CodeKind kind)83 inline constexpr bool CodeKindCanDeoptimize(CodeKind kind) {
84   return CodeKindIsOptimizedJSFunction(kind);
85 }
86 
CodeKindCanOSR(CodeKind kind)87 inline constexpr bool CodeKindCanOSR(CodeKind kind) {
88   return kind == CodeKind::TURBOFAN || kind == CodeKind::TURBOPROP;
89 }
90 
CodeKindIsOptimizedAndCanTierUp(CodeKind kind)91 inline bool CodeKindIsOptimizedAndCanTierUp(CodeKind kind) {
92   return !FLAG_turboprop_as_toptier && kind == CodeKind::TURBOPROP;
93 }
94 
CodeKindCanTierUp(CodeKind kind)95 inline constexpr bool CodeKindCanTierUp(CodeKind kind) {
96   return CodeKindIsUnoptimizedJSFunction(kind) ||
97          CodeKindIsOptimizedAndCanTierUp(kind);
98 }
99 
100 // The optimization marker field on the feedback vector has a dual purpose of
101 // controlling the tier-up workflow, and caching the produced code object for
102 // access from multiple closures.
CodeKindIsStoredInOptimizedCodeCache(CodeKind kind)103 inline constexpr bool CodeKindIsStoredInOptimizedCodeCache(CodeKind kind) {
104   return kind == CodeKind::TURBOFAN || kind == CodeKind::TURBOPROP;
105 }
106 
GetTierForCodeKind(CodeKind kind)107 inline OptimizationTier GetTierForCodeKind(CodeKind kind) {
108   if (kind == CodeKind::TURBOFAN) return OptimizationTier::kTopTier;
109   if (kind == CodeKind::TURBOPROP) {
110     return FLAG_turboprop_as_toptier ? OptimizationTier::kTopTier
111                                      : OptimizationTier::kMidTier;
112   }
113   return OptimizationTier::kNone;
114 }
115 
CodeKindForTopTier()116 inline CodeKind CodeKindForTopTier() {
117   if (V8_UNLIKELY(FLAG_turboprop_as_toptier)) {
118     return CodeKind::TURBOPROP;
119   }
120   return CodeKind::TURBOFAN;
121 }
122 
CodeKindForOSR()123 inline CodeKind CodeKindForOSR() {
124   if (V8_UNLIKELY(FLAG_turboprop)) {
125     return CodeKind::TURBOPROP;
126   }
127   return CodeKind::TURBOFAN;
128 }
129 
130 // The dedicated CodeKindFlag enum represents all code kinds in a format
131 // suitable for bit sets.
132 enum class CodeKindFlag {
133 #define V(name) name = 1 << static_cast<int>(CodeKind::name),
134   CODE_KIND_LIST(V)
135 #undef V
136 };
137 STATIC_ASSERT(kCodeKindCount <= kInt32Size * kBitsPerByte);
138 
CodeKindToCodeKindFlag(CodeKind kind)139 inline constexpr CodeKindFlag CodeKindToCodeKindFlag(CodeKind kind) {
140 #define V(name) kind == CodeKind::name ? CodeKindFlag::name:
141   return CODE_KIND_LIST(V) CodeKindFlag::INTERPRETED_FUNCTION;
142 #undef V
143 }
144 
145 // CodeKinds represents a set of CodeKind.
146 using CodeKinds = base::Flags<CodeKindFlag>;
DEFINE_OPERATORS_FOR_FLAGS(CodeKinds)147 DEFINE_OPERATORS_FOR_FLAGS(CodeKinds)
148 
149 static constexpr CodeKinds kJSFunctionCodeKindsMask{
150     CodeKindFlag::INTERPRETED_FUNCTION | CodeKindFlag::TURBOFAN |
151     CodeKindFlag::TURBOPROP | CodeKindFlag::BASELINE};
152 static constexpr CodeKinds kOptimizedJSFunctionCodeKindsMask{
153     CodeKindFlag::TURBOFAN | CodeKindFlag::TURBOPROP};
154 
155 }  // namespace internal
156 }  // namespace v8
157 
158 #endif  // V8_OBJECTS_CODE_KIND_H_
159