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