Commit 1d00f787 authored by Ross McIlroy's avatar Ross McIlroy Committed by V8 LUCI CQ

[Turboprop] Enabling inlining for Turboprop

Adds support for Turboprop, limiting the amount of bytecode that
can be inlined into a function compared with TurboFan using a
scaling factor, currently set to 1/4.

To enable inlining, we make sure to only emit the tierup check
for the main (non-inlined) function and skip it for any inlined
functions.

BUG=v8:9684

Change-Id: I1399e2b275f797a5d3fd49c89f23296f75439eee
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2982337Reviewed-by: 's avatarSantiago Aboy Solanes <solanes@chromium.org>
Commit-Queue: Ross McIlroy <rmcilroy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#75352}
parent 7d3c3cfb
......@@ -470,7 +470,12 @@ class BytecodeGraphBuilder {
void set_currently_peeled_loop_offset(int offset) {
currently_peeled_loop_offset_ = offset;
}
bool skip_first_stack_check() const { return skip_first_stack_check_; }
bool skip_first_stack_check() const {
return skip_first_stack_and_tierup_check_;
}
bool skip_tierup_check() const {
return skip_first_stack_and_tierup_check_ || osr_;
}
int current_exception_handler() const { return current_exception_handler_; }
void set_current_exception_handler(int index) {
current_exception_handler_ = index;
......@@ -508,7 +513,7 @@ class BytecodeGraphBuilder {
int currently_peeled_loop_offset_;
bool is_osr_entry_stack_check_pending_;
const bool skip_first_stack_check_;
const bool skip_first_stack_and_tierup_check_;
// Merge environments are snapshots of the environment at points where the
// control flow merges. This models a forward data flow propagation of all
......@@ -1103,8 +1108,8 @@ BytecodeGraphBuilder::BytecodeGraphBuilder(
osr_(!osr_offset.IsNone()),
currently_peeled_loop_offset_(-1),
is_osr_entry_stack_check_pending_(osr_),
skip_first_stack_check_(flags &
BytecodeGraphBuilderFlag::kSkipFirstStackCheck),
skip_first_stack_and_tierup_check_(
flags & BytecodeGraphBuilderFlag::kSkipFirstStackAndTierupCheck),
merge_environments_(local_zone),
generator_merge_environments_(local_zone),
cached_parameters_(local_zone),
......@@ -1225,7 +1230,7 @@ void BytecodeGraphBuilder::MaybeBuildTierUpCheck() {
// For OSR we don't tier up, so we don't need to build this check. Also
// tiering up currently tail calls to IET which tail calls aren't supported
// with OSR. See AdjustStackPointerForTailCall.
if (!CodeKindCanTierUp(code_kind()) || osr_) return;
if (!CodeKindCanTierUp(code_kind()) || skip_tierup_check()) return;
int parameter_count = bytecode_array().parameter_count();
Node* target = GetFunctionClosure();
......
......@@ -30,7 +30,7 @@ class NodeObserver;
class SourcePositionTable;
enum class BytecodeGraphBuilderFlag : uint8_t {
kSkipFirstStackCheck = 1 << 0,
kSkipFirstStackAndTierupCheck = 1 << 0,
// TODO(neis): Remove liveness flag here when concurrent inlining is always
// on, because then the serializer will be the only place where we perform
// bytecode analysis.
......
......@@ -2076,7 +2076,8 @@ SharedFunctionInfoData::SharedFunctionInfoData(
BROKER_SFI_FIELDS(INIT_MEMBER)
#undef INIT_MEMBER
,
inlineability_(object->GetInlineability(broker->isolate())),
inlineability_(
object->GetInlineability(broker->isolate(), broker->is_turboprop())),
function_template_info_(nullptr),
template_objects_(broker->zone()),
scope_info_(nullptr) {
......@@ -3599,9 +3600,11 @@ SharedFunctionInfo::Inlineability SharedFunctionInfoRef::GetInlineability()
const {
if (data_->should_access_heap()) {
if (!broker()->IsMainThread()) {
return object()->GetInlineability(broker()->local_isolate());
return object()->GetInlineability(broker()->local_isolate(),
broker()->is_turboprop());
} else {
return object()->GetInlineability(broker()->isolate());
return object()->GetInlineability(broker()->isolate(),
broker()->is_turboprop());
}
}
return ObjectRef ::data()->AsSharedFunctionInfo()->GetInlineability();
......
......@@ -150,7 +150,7 @@ Reduction JSInliningHeuristic::Reduce(Node* node) {
DCHECK_EQ(mode(), kJSOnly);
if (!IrOpcode::IsInlineeOpcode(node->opcode())) return NoChange();
if (total_inlined_bytecode_size_ >= FLAG_max_inlined_bytecode_size_absolute) {
if (total_inlined_bytecode_size_ >= max_inlined_bytecode_size_absolute_) {
return NoChange();
}
......@@ -277,7 +277,7 @@ void JSInliningHeuristic::Finalize() {
candidate.total_size * FLAG_reserve_inline_budget_scale_factor;
int total_size =
total_inlined_bytecode_size_ + static_cast<int>(size_of_candidate);
if (total_size > FLAG_max_inlined_bytecode_size_cumulative) {
if (total_size > max_inlined_bytecode_size_cumulative_) {
// Try if any smaller functions are available to inline.
continue;
}
......@@ -746,11 +746,11 @@ Reduction JSInliningHeuristic::InlineCandidate(Candidate const& candidate,
// Inline the individual, cloned call sites.
for (int i = 0; i < num_calls && total_inlined_bytecode_size_ <
FLAG_max_inlined_bytecode_size_absolute;
max_inlined_bytecode_size_absolute_;
++i) {
if (candidate.can_inline_function[i] &&
(small_function || total_inlined_bytecode_size_ <
FLAG_max_inlined_bytecode_size_cumulative)) {
max_inlined_bytecode_size_cumulative_)) {
Node* node = calls[i];
Reduction const reduction = inliner_.ReduceJSCall(node);
if (reduction.Changed()) {
......@@ -827,6 +827,13 @@ SimplifiedOperatorBuilder* JSInliningHeuristic::simplified() const {
return jsgraph()->simplified();
}
int JSInliningHeuristic::ScaleInliningSize(int value, JSHeapBroker* broker) {
if (broker->is_turboprop()) {
value = value / FLAG_turboprop_inline_scaling_factor;
}
return value;
}
#undef TRACE
} // namespace compiler
......
......@@ -26,7 +26,13 @@ class JSInliningHeuristic final : public AdvancedReducer {
source_positions_(source_positions),
jsgraph_(jsgraph),
broker_(broker),
mode_(mode) {}
mode_(mode),
max_inlined_bytecode_size_(
ScaleInliningSize(FLAG_max_inlined_bytecode_size, broker)),
max_inlined_bytecode_size_cumulative_(ScaleInliningSize(
FLAG_max_inlined_bytecode_size_cumulative, broker)),
max_inlined_bytecode_size_absolute_(ScaleInliningSize(
FLAG_max_inlined_bytecode_size_absolute, broker)) {}
const char* reducer_name() const override { return "JSInliningHeuristic"; }
......@@ -72,6 +78,8 @@ class JSInliningHeuristic final : public AdvancedReducer {
// Candidates are kept in a sorted set of unique candidates.
using Candidates = ZoneSet<Candidate, CandidateCompare>;
static int ScaleInliningSize(int value, JSHeapBroker* broker);
// Dumps candidates to console.
void PrintCandidates();
Reduction InlineCandidate(Candidate const& candidate, bool small_function);
......@@ -104,6 +112,9 @@ class JSInliningHeuristic final : public AdvancedReducer {
JSHeapBroker* const broker_;
int total_inlined_bytecode_size_ = 0;
const Mode mode_;
const int max_inlined_bytecode_size_;
const int max_inlined_bytecode_size_cumulative_;
const int max_inlined_bytecode_size_absolute_;
};
} // namespace compiler
......
......@@ -557,7 +557,7 @@ Reduction JSInliner::ReduceJSCall(Node* node) {
// Run the BytecodeGraphBuilder to create the subgraph.
Graph::SubgraphScope scope(graph());
BytecodeGraphBuilderFlags flags(
BytecodeGraphBuilderFlag::kSkipFirstStackCheck);
BytecodeGraphBuilderFlag::kSkipFirstStackAndTierupCheck);
if (info_->analyze_environment_liveness()) {
flags |= BytecodeGraphBuilderFlag::kAnalyzeEnvironmentLiveness;
}
......
......@@ -1167,7 +1167,7 @@ PipelineCompilationJob::Status PipelineCompilationJob::PrepareJobImpl(
if (FLAG_turbo_loop_peeling) {
compilation_info()->set_loop_peeling();
}
if (FLAG_turbo_inlining && !compilation_info()->IsTurboprop()) {
if (FLAG_turbo_inlining) {
compilation_info()->set_inlining();
}
......
......@@ -2025,16 +2025,19 @@ void SerializerForBackgroundCompilation::ProcessCalleeForCallOrConstruct(
Handle<SharedFunctionInfo> shared = callee.shared(broker()->isolate());
if (shared->IsApiFunction()) {
ProcessApiCall(shared, arguments);
DCHECK_NE(shared->GetInlineability(broker()->isolate()),
SharedFunctionInfo::kIsInlineable);
DCHECK_NE(
shared->GetInlineability(broker()->isolate(), broker()->is_turboprop()),
SharedFunctionInfo::kIsInlineable);
} else if (shared->HasBuiltinId()) {
ProcessBuiltinCall(shared, new_target, arguments, speculation_mode, padding,
result_hints);
DCHECK_NE(shared->GetInlineability(broker()->isolate()),
SharedFunctionInfo::kIsInlineable);
DCHECK_NE(
shared->GetInlineability(broker()->isolate(), broker()->is_turboprop()),
SharedFunctionInfo::kIsInlineable);
} else if ((flags() &
SerializerForBackgroundCompilationFlag::kEnableTurboInlining) &&
shared->GetInlineability(broker()->isolate()) ==
shared->GetInlineability(broker()->isolate(),
broker()->is_turboprop()) ==
SharedFunctionInfo::kIsInlineable &&
callee.HasFeedbackVector()) {
CompilationSubject subject =
......
......@@ -643,6 +643,9 @@ DEFINE_BOOL(
DEFINE_IMPLICATION(turboprop_as_toptier, turboprop)
DEFINE_UINT_READONLY(max_minimorphic_map_checks, 4,
"max number of map checks to perform in minimorphic state")
DEFINE_INT(turboprop_inline_scaling_factor, 4,
"scale factor for reduction in bytecode that can be inline for "
"TurboProp compared to TurboFan")
// The scale factor determines the interrupt budget when tiering up from
// Turboprop to TurboFan.
DEFINE_INT(interrupt_budget_scale_factor_for_top_tier, 5,
......
......@@ -206,7 +206,7 @@ bool SharedFunctionInfo::AreSourcePositionsAvailable(IsolateT* isolate) const {
template <typename IsolateT>
SharedFunctionInfo::Inlineability SharedFunctionInfo::GetInlineability(
IsolateT* isolate) const {
IsolateT* isolate, bool is_turboprop) const {
if (!script().IsScript()) return kHasNoScript;
if (GetIsolate()->is_precise_binary_code_coverage() &&
......@@ -227,7 +227,11 @@ SharedFunctionInfo::Inlineability SharedFunctionInfo::GetInlineability(
// inline.
if (!HasBytecodeArray()) return kHasNoBytecode;
if (GetBytecodeArray(isolate).length() > FLAG_max_inlined_bytecode_size) {
int max_inlined_size = FLAG_max_inlined_bytecode_size;
if (is_turboprop) {
max_inlined_size = max_inlined_size / FLAG_turboprop_inline_scaling_factor;
}
if (GetBytecodeArray(isolate).length() > max_inlined_size) {
return kExceedsBytecodeLimit;
}
......
......@@ -549,7 +549,7 @@ class SharedFunctionInfo
kMayContainBreakPoints,
};
template <typename IsolateT>
Inlineability GetInlineability(IsolateT* isolate) const;
Inlineability GetInlineability(IsolateT* isolate, bool is_turboprop) const;
// Source size of this function.
int SourceSize();
......
......@@ -178,6 +178,7 @@
# Re-enable again with dynamic map checks. (https://crbug.com/v8/9684)
'const-field-tracking-2': [SKIP],
'regress/regress-1141502': [SKIP],
# Tests that need to run sequentially (e.g. due to memory consumption).
'compiler/array-subclass': [PASS, HEAVY],
......@@ -1315,6 +1316,14 @@
'compiler/abstract-equal-receiver': [FAIL],
'compiler/constant-fold-cow-array': [FAIL],
'compiler/promise-resolve-stable-maps': [FAIL],
# Tests failing due to reduced constant propagation in Turboprop.
'compiler/js-create-arguments': [FAIL],
'compiler/catch-block-load': [FAIL],
'compiler/construct-bound-function': [FAIL],
'compiler/construct-object': [FAIL],
'compiler/construct-receiver': [FAIL],
'compiler/js-create': [FAIL],
}], # variant == turboprop or variant = turboprop_as_toptier
##############################################################################
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment