| // Copyright 2020 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef V8_OBJECTS_CODE_KIND_H_ |
| #define V8_OBJECTS_CODE_KIND_H_ |
| |
| #include "src/base/flags.h" |
| #include "src/flags/flags.h" |
| |
| namespace v8 { |
| namespace internal { |
| |
| // The order of INTERPRETED_FUNCTION to TURBOFAN is important. We use it to |
| // check the relative ordering of the tiers when fetching / installing optimized |
| // code. |
| #define CODE_KIND_LIST(V) \ |
| V(BYTECODE_HANDLER) \ |
| V(FOR_TESTING) \ |
| V(BUILTIN) \ |
| V(REGEXP) \ |
| V(WASM_FUNCTION) \ |
| V(WASM_TO_CAPI_FUNCTION) \ |
| V(WASM_TO_JS_FUNCTION) \ |
| V(JS_TO_WASM_FUNCTION) \ |
| V(JS_TO_JS_FUNCTION) \ |
| V(C_WASM_ENTRY) \ |
| V(INTERPRETED_FUNCTION) \ |
| V(NATIVE_CONTEXT_INDEPENDENT) \ |
| V(TURBOPROP) \ |
| V(TURBOFAN) |
| |
| enum class CodeKind { |
| #define DEFINE_CODE_KIND_ENUM(name) name, |
| CODE_KIND_LIST(DEFINE_CODE_KIND_ENUM) |
| #undef DEFINE_CODE_KIND_ENUM |
| }; |
| STATIC_ASSERT(CodeKind::INTERPRETED_FUNCTION < CodeKind::TURBOPROP && |
| CodeKind::INTERPRETED_FUNCTION < |
| CodeKind::NATIVE_CONTEXT_INDEPENDENT); |
| STATIC_ASSERT(CodeKind::TURBOPROP < CodeKind::TURBOFAN && |
| CodeKind::NATIVE_CONTEXT_INDEPENDENT < CodeKind::TURBOFAN); |
| |
| #define V(...) +1 |
| static constexpr int kCodeKindCount = CODE_KIND_LIST(V); |
| #undef V |
| |
| const char* CodeKindToString(CodeKind kind); |
| |
| inline constexpr bool CodeKindIsInterpretedJSFunction(CodeKind kind) { |
| return kind == CodeKind::INTERPRETED_FUNCTION; |
| } |
| |
| inline constexpr bool CodeKindIsNativeContextIndependentJSFunction( |
| CodeKind kind) { |
| return kind == CodeKind::NATIVE_CONTEXT_INDEPENDENT; |
| } |
| |
| inline constexpr bool CodeKindIsOptimizedJSFunction(CodeKind kind) { |
| return kind == CodeKind::TURBOFAN || |
| kind == CodeKind::NATIVE_CONTEXT_INDEPENDENT || |
| kind == CodeKind::TURBOPROP; |
| } |
| |
| inline constexpr bool CodeKindIsJSFunction(CodeKind kind) { |
| return kind == CodeKind::INTERPRETED_FUNCTION || |
| CodeKindIsOptimizedJSFunction(kind); |
| } |
| |
| inline constexpr bool CodeKindIsBuiltinOrJSFunction(CodeKind kind) { |
| return kind == CodeKind::BUILTIN || CodeKindIsJSFunction(kind); |
| } |
| |
| inline constexpr bool CodeKindCanDeoptimize(CodeKind kind) { |
| // Even though NCI code does not deopt by itself at the time of writing, |
| // tests may trigger deopts manually and thus we cannot make a narrower |
| // distinction here. |
| return CodeKindIsOptimizedJSFunction(kind); |
| } |
| |
| inline constexpr bool CodeKindCanOSR(CodeKind kind) { |
| return kind == CodeKind::TURBOFAN || kind == CodeKind::TURBOPROP; |
| } |
| |
| inline constexpr bool CodeKindIsOptimizedAndCanTierUp(CodeKind kind) { |
| return kind == CodeKind::NATIVE_CONTEXT_INDEPENDENT || |
| (FLAG_turboprop_as_midtier && kind == CodeKind::TURBOPROP); |
| } |
| |
| inline constexpr bool CodeKindCanTierUp(CodeKind kind) { |
| return kind == CodeKind::INTERPRETED_FUNCTION || |
| CodeKindIsOptimizedAndCanTierUp(kind); |
| } |
| |
| // The optimization marker field on the feedback vector has a dual purpose of |
| // controlling the tier-up workflow, and caching the produced code object for |
| // access from multiple closures. The marker is not used for all code kinds |
| // though, in particular it is not used when generating NCI code. |
| inline constexpr bool CodeKindIsStoredInOptimizedCodeCache(CodeKind kind) { |
| return kind == CodeKind::TURBOFAN || kind == CodeKind::TURBOPROP; |
| } |
| |
| inline OptimizationTier GetTierForCodeKind(CodeKind kind) { |
| if (kind == CodeKind::TURBOFAN) return OptimizationTier::kTopTier; |
| if (kind == CodeKind::TURBOPROP) { |
| return FLAG_turboprop_as_midtier ? OptimizationTier::kMidTier |
| : OptimizationTier::kTopTier; |
| } |
| if (kind == CodeKind::NATIVE_CONTEXT_INDEPENDENT) { |
| return FLAG_turbo_nci_as_midtier ? OptimizationTier::kMidTier |
| : OptimizationTier::kTopTier; |
| } |
| return OptimizationTier::kNone; |
| } |
| |
| inline CodeKind CodeKindForTopTier() { |
| // TODO(turboprop, mythria): We should make FLAG_turboprop mean turboprop is |
| // mid-tier compiler and replace FLAG_turboprop_as_midtier with |
| // FLAG_turboprop_as_top_tier to tier up to only Turboprop once |
| // FLAG_turboprop_as_midtier is stable and major regressions are addressed. |
| if (V8_UNLIKELY(FLAG_turboprop)) { |
| return FLAG_turboprop_as_midtier ? CodeKind::TURBOFAN : CodeKind::TURBOPROP; |
| } |
| return CodeKind::TURBOFAN; |
| } |
| |
| // The dedicated CodeKindFlag enum represents all code kinds in a format |
| // suitable for bit sets. |
| enum class CodeKindFlag { |
| #define V(name) name = 1 << static_cast<int>(CodeKind::name), |
| CODE_KIND_LIST(V) |
| #undef V |
| }; |
| STATIC_ASSERT(kCodeKindCount <= kInt32Size * kBitsPerByte); |
| |
| inline constexpr CodeKindFlag CodeKindToCodeKindFlag(CodeKind kind) { |
| #define V(name) kind == CodeKind::name ? CodeKindFlag::name: |
| return CODE_KIND_LIST(V) CodeKindFlag::INTERPRETED_FUNCTION; |
| #undef V |
| } |
| |
| // CodeKinds represents a set of CodeKind. |
| using CodeKinds = base::Flags<CodeKindFlag>; |
| DEFINE_OPERATORS_FOR_FLAGS(CodeKinds) |
| |
| static constexpr CodeKinds kJSFunctionCodeKindsMask{ |
| CodeKindFlag::INTERPRETED_FUNCTION | CodeKindFlag::TURBOFAN | |
| CodeKindFlag::NATIVE_CONTEXT_INDEPENDENT | CodeKindFlag::TURBOPROP}; |
| static constexpr CodeKinds kOptimizedJSFunctionCodeKindsMask{ |
| CodeKindFlag::TURBOFAN | CodeKindFlag::NATIVE_CONTEXT_INDEPENDENT | |
| CodeKindFlag::TURBOPROP}; |
| |
| } // namespace internal |
| } // namespace v8 |
| |
| #endif // V8_OBJECTS_CODE_KIND_H_ |