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(MAGLEV) \
32 V(TURBOFAN)
33
34 enum class CodeKind : uint8_t {
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::BASELINE);
40 STATIC_ASSERT(CodeKind::BASELINE < CodeKind::TURBOFAN);
41
42 #define V(...) +1
43 static constexpr int kCodeKindCount = CODE_KIND_LIST(V);
44 #undef V
45 // Unlikely, but just to be safe:
46 STATIC_ASSERT(kCodeKindCount <= std::numeric_limits<uint8_t>::max());
47
48 const char* CodeKindToString(CodeKind kind);
49
50 const char* CodeKindToMarker(CodeKind kind);
51
CodeKindIsInterpretedJSFunction(CodeKind kind)52 inline constexpr bool CodeKindIsInterpretedJSFunction(CodeKind kind) {
53 return kind == CodeKind::INTERPRETED_FUNCTION;
54 }
55
CodeKindIsBaselinedJSFunction(CodeKind kind)56 inline constexpr bool CodeKindIsBaselinedJSFunction(CodeKind kind) {
57 return kind == CodeKind::BASELINE;
58 }
59
CodeKindIsUnoptimizedJSFunction(CodeKind kind)60 inline constexpr bool CodeKindIsUnoptimizedJSFunction(CodeKind kind) {
61 STATIC_ASSERT(static_cast<int>(CodeKind::INTERPRETED_FUNCTION) + 1 ==
62 static_cast<int>(CodeKind::BASELINE));
63 return base::IsInRange(kind, CodeKind::INTERPRETED_FUNCTION,
64 CodeKind::BASELINE);
65 }
66
CodeKindIsOptimizedJSFunction(CodeKind kind)67 inline constexpr bool CodeKindIsOptimizedJSFunction(CodeKind kind) {
68 STATIC_ASSERT(static_cast<int>(CodeKind::MAGLEV) + 1 ==
69 static_cast<int>(CodeKind::TURBOFAN));
70 return base::IsInRange(kind, CodeKind::MAGLEV, CodeKind::TURBOFAN);
71 }
72
CodeKindIsJSFunction(CodeKind kind)73 inline constexpr bool CodeKindIsJSFunction(CodeKind kind) {
74 STATIC_ASSERT(static_cast<int>(CodeKind::BASELINE) + 1 ==
75 static_cast<int>(CodeKind::MAGLEV));
76 return base::IsInRange(kind, CodeKind::INTERPRETED_FUNCTION,
77 CodeKind::TURBOFAN);
78 }
79
CodeKindIsBuiltinOrJSFunction(CodeKind kind)80 inline constexpr bool CodeKindIsBuiltinOrJSFunction(CodeKind kind) {
81 return kind == CodeKind::BUILTIN || CodeKindIsJSFunction(kind);
82 }
83
CodeKindCanDeoptimize(CodeKind kind)84 inline constexpr bool CodeKindCanDeoptimize(CodeKind kind) {
85 return CodeKindIsOptimizedJSFunction(kind);
86 }
87
CodeKindCanOSR(CodeKind kind)88 inline constexpr bool CodeKindCanOSR(CodeKind kind) {
89 return kind == CodeKind::TURBOFAN;
90 }
91
CodeKindCanTierUp(CodeKind kind)92 inline constexpr bool CodeKindCanTierUp(CodeKind kind) {
93 return CodeKindIsUnoptimizedJSFunction(kind);
94 }
95
96 // TODO(jgruber): Rename or remove this predicate. Currently it means 'is this
97 // kind stored either in the FeedbackVector cache, or in the OSR cache?'.
CodeKindIsStoredInOptimizedCodeCache(CodeKind kind)98 inline constexpr bool CodeKindIsStoredInOptimizedCodeCache(CodeKind kind) {
99 return kind == CodeKind::TURBOFAN;
100 }
101
CodeKindForTopTier()102 inline CodeKind CodeKindForTopTier() { return CodeKind::TURBOFAN; }
103
104 // The dedicated CodeKindFlag enum represents all code kinds in a format
105 // suitable for bit sets.
106 enum class CodeKindFlag {
107 #define V(name) name = 1 << static_cast<int>(CodeKind::name),
108 CODE_KIND_LIST(V)
109 #undef V
110 };
111 STATIC_ASSERT(kCodeKindCount <= kInt32Size * kBitsPerByte);
112
CodeKindToCodeKindFlag(CodeKind kind)113 inline constexpr CodeKindFlag CodeKindToCodeKindFlag(CodeKind kind) {
114 #define V(name) kind == CodeKind::name ? CodeKindFlag::name:
115 return CODE_KIND_LIST(V) CodeKindFlag::INTERPRETED_FUNCTION;
116 #undef V
117 }
118
119 // CodeKinds represents a set of CodeKind.
120 using CodeKinds = base::Flags<CodeKindFlag>;
DEFINE_OPERATORS_FOR_FLAGS(CodeKinds)121 DEFINE_OPERATORS_FOR_FLAGS(CodeKinds)
122
123 static constexpr CodeKinds kJSFunctionCodeKindsMask{
124 CodeKindFlag::INTERPRETED_FUNCTION | CodeKindFlag::BASELINE |
125 CodeKindFlag::MAGLEV | CodeKindFlag::TURBOFAN};
126 static constexpr CodeKinds kOptimizedJSFunctionCodeKindsMask{
127 CodeKindFlag::MAGLEV | CodeKindFlag::TURBOFAN};
128
129 } // namespace internal
130 } // namespace v8
131
132 #endif // V8_OBJECTS_CODE_KIND_H_
133