blob: 6314005649d86c9797682de78224fadf27e28581 [file] [log] [blame]
// 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_