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)53inline constexpr bool CodeKindIsInterpretedJSFunction(CodeKind kind) { 54 return kind == CodeKind::INTERPRETED_FUNCTION; 55 } 56 CodeKindIsBaselinedJSFunction(CodeKind kind)57inline constexpr bool CodeKindIsBaselinedJSFunction(CodeKind kind) { 58 return kind == CodeKind::BASELINE; 59 } 60 CodeKindIsUnoptimizedJSFunction(CodeKind kind)61inline 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)68inline 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)74inline constexpr bool CodeKindIsJSFunction(CodeKind kind) { 75 return CodeKindIsUnoptimizedJSFunction(kind) || 76 CodeKindIsOptimizedJSFunction(kind); 77 } 78 CodeKindIsBuiltinOrJSFunction(CodeKind kind)79inline constexpr bool CodeKindIsBuiltinOrJSFunction(CodeKind kind) { 80 return kind == CodeKind::BUILTIN || CodeKindIsJSFunction(kind); 81 } 82 CodeKindCanDeoptimize(CodeKind kind)83inline constexpr bool CodeKindCanDeoptimize(CodeKind kind) { 84 return CodeKindIsOptimizedJSFunction(kind); 85 } 86 CodeKindCanOSR(CodeKind kind)87inline constexpr bool CodeKindCanOSR(CodeKind kind) { 88 return kind == CodeKind::TURBOFAN || kind == CodeKind::TURBOPROP; 89 } 90 CodeKindIsOptimizedAndCanTierUp(CodeKind kind)91inline bool CodeKindIsOptimizedAndCanTierUp(CodeKind kind) { 92 return !FLAG_turboprop_as_toptier && kind == CodeKind::TURBOPROP; 93 } 94 CodeKindCanTierUp(CodeKind kind)95inline 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)103inline constexpr bool CodeKindIsStoredInOptimizedCodeCache(CodeKind kind) { 104 return kind == CodeKind::TURBOFAN || kind == CodeKind::TURBOPROP; 105 } 106 GetTierForCodeKind(CodeKind kind)107inline 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()116inline CodeKind CodeKindForTopTier() { 117 if (V8_UNLIKELY(FLAG_turboprop_as_toptier)) { 118 return CodeKind::TURBOPROP; 119 } 120 return CodeKind::TURBOFAN; 121 } 122 CodeKindForOSR()123inline 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)139inline 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)147DEFINE_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