Commit e78f4c7e authored by Maya Lekova's avatar Maya Lekova Committed by Commit Bot

[turbofan] Optimize stack slot usage for fast API calls

With this CL, fast API calls reuse the same stack slot they are
using for the {fallback} parameter. This relies on the fact that
the fast calls are non-reentrant, due to their inability to call
into JavaScript.

Bug: chromium:1052746
Change-Id: I2c56fcbe425023244a566bb39439e8e04072f316
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2461729
Commit-Queue: Maya Lekova <mslekova@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#70409}
parent c4a7bd86
...@@ -47,7 +47,8 @@ class EffectControlLinearizer { ...@@ -47,7 +47,8 @@ class EffectControlLinearizer {
node_origins_(node_origins), node_origins_(node_origins),
graph_assembler_(js_graph, temp_zone, base::nullopt, graph_assembler_(js_graph, temp_zone, base::nullopt,
should_maintain_schedule() ? schedule : nullptr), should_maintain_schedule() ? schedule : nullptr),
frame_state_zapper_(nullptr) {} frame_state_zapper_(nullptr),
fast_api_call_stack_slot_(nullptr) {}
void Run(); void Run();
...@@ -315,6 +316,8 @@ class EffectControlLinearizer { ...@@ -315,6 +316,8 @@ class EffectControlLinearizer {
NodeOriginTable* node_origins_; NodeOriginTable* node_origins_;
JSGraphAssembler graph_assembler_; JSGraphAssembler graph_assembler_;
Node* frame_state_zapper_; // For tracking down compiler::Node::New crashes. Node* frame_state_zapper_; // For tracking down compiler::Node::New crashes.
Node* fast_api_call_stack_slot_; // For caching the stack slot allocated for
// fast API calls.
}; };
namespace { namespace {
...@@ -5170,18 +5173,15 @@ Node* EffectControlLinearizer::LowerFastApiCall(Node* node) { ...@@ -5170,18 +5173,15 @@ Node* EffectControlLinearizer::LowerFastApiCall(Node* node) {
CHECK_EQ(FastApiCallNode::ArityForArgc(c_arg_count, js_arg_count), CHECK_EQ(FastApiCallNode::ArityForArgc(c_arg_count, js_arg_count),
value_input_count); value_input_count);
// TODO(mslekova): There's an opportunity to optimize the allocation if (fast_api_call_stack_slot_ == nullptr) {
// of the stack slot for all fast calls by reusing the same slot. // Add the { fallback } output parameter.
// If this is implemented, please update the FastApiStackSlot in int kAlign = 4;
// cctest/test-api.cc, which will probably become meaningless, as it relies int kSize = 4;
// on two separate stack slots being allocated. fast_api_call_stack_slot_ = __ StackSlot(kSize, kAlign);
// Add the { has_error } output parameter. }
int kAlign = 4; // Generate the store to `fast_api_call_stack_slot_`.
int kSize = 4;
Node* has_error = __ StackSlot(kSize, kAlign);
// Generate the store to `has_error`.
__ Store(StoreRepresentation(MachineRepresentation::kWord32, kNoWriteBarrier), __ Store(StoreRepresentation(MachineRepresentation::kWord32, kNoWriteBarrier),
has_error, 0, jsgraph()->ZeroConstant()); fast_api_call_stack_slot_, 0, jsgraph()->ZeroConstant());
MachineSignature::Builder builder( MachineSignature::Builder builder(
graph()->zone(), 1, c_arg_count + FastApiCallNode::kHasErrorInputCount); graph()->zone(), 1, c_arg_count + FastApiCallNode::kHasErrorInputCount);
...@@ -5192,7 +5192,7 @@ Node* EffectControlLinearizer::LowerFastApiCall(Node* node) { ...@@ -5192,7 +5192,7 @@ Node* EffectControlLinearizer::LowerFastApiCall(Node* node) {
MachineTypeFor(c_signature->ArgumentInfo(i).GetType()); MachineTypeFor(c_signature->ArgumentInfo(i).GetType());
builder.AddParam(machine_type); builder.AddParam(machine_type);
} }
builder.AddParam(MachineType::Pointer()); // has_error builder.AddParam(MachineType::Pointer()); // fast_api_call_stack_slot_
CallDescriptor* call_descriptor = CallDescriptor* call_descriptor =
Linkage::GetSimplifiedCDescriptor(graph()->zone(), builder.Build()); Linkage::GetSimplifiedCDescriptor(graph()->zone(), builder.Build());
...@@ -5212,15 +5212,15 @@ Node* EffectControlLinearizer::LowerFastApiCall(Node* node) { ...@@ -5212,15 +5212,15 @@ Node* EffectControlLinearizer::LowerFastApiCall(Node* node) {
inputs[i] = NodeProperties::GetValueInput(node, i); inputs[i] = NodeProperties::GetValueInput(node, i);
} }
} }
inputs[c_arg_count + 1] = has_error; inputs[c_arg_count + 1] = fast_api_call_stack_slot_;
inputs[c_arg_count + 2] = __ effect(); inputs[c_arg_count + 2] = __ effect();
inputs[c_arg_count + 3] = __ control(); inputs[c_arg_count + 3] = __ control();
__ Call(call_descriptor, __ Call(call_descriptor,
c_arg_count + FastApiCallNode::kFastCallExtraInputCount, inputs); c_arg_count + FastApiCallNode::kFastCallExtraInputCount, inputs);
// Generate the load from `has_error`. // Generate the load from `fast_api_call_stack_slot_`.
Node* load = __ Load(MachineType::Int32(), has_error, 0); Node* load = __ Load(MachineType::Int32(), fast_api_call_stack_slot_, 0);
TNode<Boolean> cond = TNode<Boolean> cond =
TNode<Boolean>::UncheckedCast(__ Word32Equal(load, __ Int32Constant(0))); TNode<Boolean>::UncheckedCast(__ Word32Equal(load, __ Int32Constant(0)));
......
...@@ -27595,6 +27595,7 @@ struct ApiNumberChecker : BasicApiChecker<T, ApiNumberChecker<T>> { ...@@ -27595,6 +27595,7 @@ struct ApiNumberChecker : BasicApiChecker<T, ApiNumberChecker<T>> {
// the default behavior expected from the embedder. The value is checked // the default behavior expected from the embedder. The value is checked
// against after loading it from a stack slot, as defined in // against after loading it from a stack slot, as defined in
// EffectControlLinearizer::LowerFastApiCall. // EffectControlLinearizer::LowerFastApiCall.
CHECK_EQ(*fallback, 0);
*fallback = 1; *fallback = 1;
} }
} }
......
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