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