Commit 8c12c24d authored by Leszek Swirski's avatar Leszek Swirski Committed by V8 LUCI CQ

[maglev] Add fast-path trampolines for dynamic lookup

Dynamic maybe-context/maybe-global lookup can fast-path in the case
where there are no context extensions in the parent contexts. Add a
trampoline builtin for maglev which performs this fast path.

This is similar to Sparkplug, which calls a similar builtin (except one
which loads context and FBV from Sparkplug frame slots), and unlike
TurboFan, which creates local control flow to inline this operation
fully. Maglev avoids creating local control flow, so the builtin
approach seems more fitting.

Bug: v8:7700
Change-Id: I2f63694d9c1f907f91b8b7b8982adc9f9ba106ca
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3871210Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/main@{#82985}
parent 9a2912d2
......@@ -655,7 +655,9 @@ namespace internal {
TFH(DefineKeyedOwnICBaseline, StoreBaseline) \
TFH(StoreInArrayLiteralIC, StoreWithVector) \
TFH(StoreInArrayLiteralICBaseline, StoreBaseline) \
TFH(LookupContextTrampoline, LookupTrampoline) \
TFH(LookupContextBaseline, LookupBaseline) \
TFH(LookupContextInsideTypeofTrampoline, LookupTrampoline) \
TFH(LookupContextInsideTypeofBaseline, LookupBaseline) \
TFH(LoadGlobalIC, LoadGlobalWithVector) \
TFH(LoadGlobalICInsideTypeof, LoadGlobalWithVector) \
......@@ -663,7 +665,9 @@ namespace internal {
TFH(LoadGlobalICBaseline, LoadGlobalBaseline) \
TFH(LoadGlobalICInsideTypeofTrampoline, LoadGlobal) \
TFH(LoadGlobalICInsideTypeofBaseline, LoadGlobalBaseline) \
TFH(LookupGlobalICTrampoline, LookupTrampoline) \
TFH(LookupGlobalICBaseline, LookupBaseline) \
TFH(LookupGlobalICInsideTypeofTrampoline, LookupTrampoline) \
TFH(LookupGlobalICInsideTypeofBaseline, LookupBaseline) \
TFH(CloneObjectIC, CloneObjectWithVector) \
TFH(CloneObjectICBaseline, CloneObjectBaseline) \
......
......@@ -230,24 +230,48 @@ void Builtins::Generate_LoadGlobalICInsideTypeofBaseline(
assembler.GenerateLoadGlobalICBaseline(TypeofMode::kInside);
}
void Builtins::Generate_LookupGlobalICTrampoline(
compiler::CodeAssemblerState* state) {
AccessorAssembler assembler(state);
assembler.GenerateLookupGlobalICTrampoline(TypeofMode::kNotInside);
}
void Builtins::Generate_LookupGlobalICBaseline(
compiler::CodeAssemblerState* state) {
AccessorAssembler assembler(state);
assembler.GenerateLookupGlobalICBaseline(TypeofMode::kNotInside);
}
void Builtins::Generate_LookupGlobalICInsideTypeofTrampoline(
compiler::CodeAssemblerState* state) {
AccessorAssembler assembler(state);
assembler.GenerateLookupGlobalICTrampoline(TypeofMode::kInside);
}
void Builtins::Generate_LookupGlobalICInsideTypeofBaseline(
compiler::CodeAssemblerState* state) {
AccessorAssembler assembler(state);
assembler.GenerateLookupGlobalICBaseline(TypeofMode::kInside);
}
void Builtins::Generate_LookupContextTrampoline(
compiler::CodeAssemblerState* state) {
AccessorAssembler assembler(state);
assembler.GenerateLookupContextTrampoline(TypeofMode::kNotInside);
}
void Builtins::Generate_LookupContextBaseline(
compiler::CodeAssemblerState* state) {
AccessorAssembler assembler(state);
assembler.GenerateLookupContextBaseline(TypeofMode::kNotInside);
}
void Builtins::Generate_LookupContextInsideTypeofTrampoline(
compiler::CodeAssemblerState* state) {
AccessorAssembler assembler(state);
assembler.GenerateLookupContextTrampoline(TypeofMode::kInside);
}
void Builtins::Generate_LookupContextInsideTypeofBaseline(
compiler::CodeAssemblerState* state) {
AccessorAssembler assembler(state);
......
......@@ -99,6 +99,7 @@ namespace internal {
V(LoadWithReceiverAndVector) \
V(LoadWithReceiverBaseline) \
V(LoadWithVector) \
V(LookupTrampoline) \
V(LookupBaseline) \
V(NewHeapNumber) \
V(NoContext) \
......@@ -844,6 +845,16 @@ class LoadGlobalBaselineDescriptor
static constexpr auto registers();
};
class LookupTrampolineDescriptor
: public StaticCallInterfaceDescriptor<LookupTrampolineDescriptor> {
public:
DEFINE_PARAMETERS(kName, kDepth, kSlot)
DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kName
MachineType::AnyTagged(), // kDepth
MachineType::AnyTagged()) // kSlot
DECLARE_DESCRIPTOR(LookupTrampolineDescriptor)
};
class LookupBaselineDescriptor
: public StaticCallInterfaceDescriptor<LookupBaselineDescriptor> {
public:
......
......@@ -4377,11 +4377,11 @@ void AccessorAssembler::GenerateLoadGlobalICBaseline(TypeofMode typeof_mode) {
TailCallStub(callable, context, name, slot, vector);
}
void AccessorAssembler::GenerateLookupContextBaseline(TypeofMode typeof_mode) {
using Descriptor = LookupBaselineDescriptor;
auto depth = Parameter<TaggedIndex>(Descriptor::kDepth);
TNode<Context> context = LoadContextFromBaseline();
void AccessorAssembler::LookupContext(LazyNode<Object> lazy_name,
TNode<TaggedIndex> depth,
LazyNode<TaggedIndex> lazy_slot,
TNode<Context> context,
TypeofMode typeof_mode) {
Label slowpath(this, Label::kDeferred);
// Check for context extensions to allow the fast path.
......@@ -4391,14 +4391,14 @@ void AccessorAssembler::GenerateLookupContextBaseline(TypeofMode typeof_mode) {
// Fast path does a normal load context.
{
auto slot = Parameter<TaggedIndex>(Descriptor::kSlot);
auto slot = lazy_slot();
Return(LoadContextElement(slot_context, TaggedIndexToIntPtr(slot)));
}
// Slow path when we have to call out to the runtime.
BIND(&slowpath);
{
auto name = Parameter<Object>(Descriptor::kName);
auto name = lazy_name();
Runtime::FunctionId function_id = typeof_mode == TypeofMode::kInside
? Runtime::kLoadLookupSlotInsideTypeof
: Runtime::kLoadLookupSlot;
......@@ -4406,14 +4406,27 @@ void AccessorAssembler::GenerateLookupContextBaseline(TypeofMode typeof_mode) {
}
}
void AccessorAssembler::GenerateLookupGlobalICBaseline(TypeofMode typeof_mode) {
using Descriptor = LookupBaselineDescriptor;
void AccessorAssembler::GenerateLookupContextTrampoline(
TypeofMode typeof_mode) {
using Descriptor = LookupTrampolineDescriptor;
LookupContext([&] { return Parameter<Object>(Descriptor::kName); },
Parameter<TaggedIndex>(Descriptor::kDepth),
[&] { return Parameter<TaggedIndex>(Descriptor::kSlot); },
Parameter<Context>(Descriptor::kContext), typeof_mode);
}
auto name = Parameter<Object>(Descriptor::kName);
auto depth = Parameter<TaggedIndex>(Descriptor::kDepth);
auto slot = Parameter<TaggedIndex>(Descriptor::kSlot);
TNode<Context> context = LoadContextFromBaseline();
void AccessorAssembler::GenerateLookupContextBaseline(TypeofMode typeof_mode) {
using Descriptor = LookupBaselineDescriptor;
LookupContext([&] { return Parameter<Object>(Descriptor::kName); },
Parameter<TaggedIndex>(Descriptor::kDepth),
[&] { return Parameter<TaggedIndex>(Descriptor::kSlot); },
LoadContextFromBaseline(), typeof_mode);
}
void AccessorAssembler::LookupGlobalIC(
LazyNode<Object> lazy_name, TNode<TaggedIndex> depth,
LazyNode<TaggedIndex> lazy_slot, TNode<Context> context,
LazyNode<FeedbackVector> lazy_feedback_vector, TypeofMode typeof_mode) {
Label slowpath(this, Label::kDeferred);
// Check for context extensions to allow the fast path
......@@ -4425,8 +4438,8 @@ void AccessorAssembler::GenerateLookupGlobalICBaseline(TypeofMode typeof_mode) {
{
Callable callable =
CodeFactory::LoadGlobalICInOptimizedCode(isolate(), typeof_mode);
TNode<FeedbackVector> vector = LoadFeedbackVectorFromBaseline();
TailCallStub(callable, context, name, slot, vector);
TailCallStub(callable, context, lazy_name(), lazy_slot(),
lazy_feedback_vector());
}
// Slow path when we have to call out to the runtime
......@@ -4434,7 +4447,26 @@ void AccessorAssembler::GenerateLookupGlobalICBaseline(TypeofMode typeof_mode) {
Runtime::FunctionId function_id = typeof_mode == TypeofMode::kInside
? Runtime::kLoadLookupSlotInsideTypeof
: Runtime::kLoadLookupSlot;
TailCallRuntime(function_id, context, name);
TailCallRuntime(function_id, context, lazy_name());
}
void AccessorAssembler::GenerateLookupGlobalICTrampoline(
TypeofMode typeof_mode) {
using Descriptor = LookupTrampolineDescriptor;
LookupGlobalIC([&] { return Parameter<Object>(Descriptor::kName); },
Parameter<TaggedIndex>(Descriptor::kDepth),
[&] { return Parameter<TaggedIndex>(Descriptor::kSlot); },
Parameter<Context>(Descriptor::kContext),
[&] { return LoadFeedbackVectorForStub(); }, typeof_mode);
}
void AccessorAssembler::GenerateLookupGlobalICBaseline(TypeofMode typeof_mode) {
using Descriptor = LookupBaselineDescriptor;
LookupGlobalIC([&] { return Parameter<Object>(Descriptor::kName); },
Parameter<TaggedIndex>(Descriptor::kDepth),
[&] { return Parameter<TaggedIndex>(Descriptor::kSlot); },
LoadContextFromBaseline(),
[&] { return LoadFeedbackVectorFromBaseline(); }, typeof_mode);
}
void AccessorAssembler::GenerateKeyedLoadIC() {
......
......@@ -59,7 +59,9 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler {
void GenerateLoadGlobalIC(TypeofMode typeof_mode);
void GenerateLoadGlobalICTrampoline(TypeofMode typeof_mode);
void GenerateLoadGlobalICBaseline(TypeofMode typeof_mode);
void GenerateLookupGlobalICTrampoline(TypeofMode typeof_mode);
void GenerateLookupGlobalICBaseline(TypeofMode typeof_mode);
void GenerateLookupContextTrampoline(TypeofMode typeof_mode);
void GenerateLookupContextBaseline(TypeofMode typeof_mode);
void GenerateKeyedStoreIC();
......@@ -333,6 +335,14 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler {
void DefineKeyedOwnIC(const StoreICParameters* p);
void StoreInArrayLiteralIC(const StoreICParameters* p);
void LookupGlobalIC(LazyNode<Object> lazy_name, TNode<TaggedIndex> depth,
LazyNode<TaggedIndex> lazy_slot, TNode<Context> context,
LazyNode<FeedbackVector> lazy_feedback_vector,
TypeofMode typeof_mode);
void LookupContext(LazyNode<Object> lazy_name, TNode<TaggedIndex> depth,
LazyNode<TaggedIndex> lazy_slot, TNode<Context> context,
TypeofMode typeof_mode);
// IC dispatcher behavior.
// Checks monomorphic case. Returns {feedback} entry of the vector.
......
......@@ -838,18 +838,20 @@ void MaglevGraphBuilder::VisitLdaLookupSlot() {
void MaglevGraphBuilder::VisitLdaLookupContextSlot() {
// LdaLookupContextSlot <name_index> <feedback_slot> <depth>
// TODO(v8:7700): Add a simple load context fast path when there are no
// contexts with extension between the current one and the context at <depth>.
ValueNode* name = GetConstant(GetRefOperand<Name>(0));
SetAccumulator(BuildCallRuntime(Runtime::kLoadLookupSlot, {name}));
ValueNode* slot = GetSmiConstant(iterator_.GetIndexOperand(1));
ValueNode* depth = GetSmiConstant(iterator_.GetUnsignedImmediateOperand(2));
SetAccumulator(
BuildCallBuiltin<Builtin::kLookupContextTrampoline>({name, depth, slot}));
}
void MaglevGraphBuilder::VisitLdaLookupGlobalSlot() {
// LdaLookupGlobalSlot <name_index> <feedback_slot> <depth>
// TODO(v8:7700): Add a simple load context fast path when there are no
// contexts with extension between the current one and the context at <depth>.
ValueNode* name = GetConstant(GetRefOperand<Name>(0));
SetAccumulator(BuildCallRuntime(Runtime::kLoadLookupSlot, {name}));
ValueNode* slot = GetSmiConstant(iterator_.GetIndexOperand(1));
ValueNode* depth = GetSmiConstant(iterator_.GetUnsignedImmediateOperand(2));
SetAccumulator(BuildCallBuiltin<Builtin::kLookupGlobalICTrampoline>(
{name, depth, slot}));
}
void MaglevGraphBuilder::VisitLdaLookupSlotInsideTypeof() {
......@@ -860,21 +862,23 @@ void MaglevGraphBuilder::VisitLdaLookupSlotInsideTypeof() {
}
void MaglevGraphBuilder::VisitLdaLookupContextSlotInsideTypeof() {
// LdaLookupContextSlotInsideTypeof <name_index>
// TODO(v8:7700): Add a simple load context fast path when there are no
// contexts with extension between the current one and the context at <depth>.
// LdaLookupContextSlotInsideTypeof <name_index> <context_slot> <depth>
ValueNode* name = GetConstant(GetRefOperand<Name>(0));
ValueNode* slot = GetSmiConstant(iterator_.GetIndexOperand(1));
ValueNode* depth = GetSmiConstant(iterator_.GetUnsignedImmediateOperand(2));
SetAccumulator(
BuildCallRuntime(Runtime::kLoadLookupSlotInsideTypeof, {name}));
BuildCallBuiltin<Builtin::kLookupContextInsideTypeofTrampoline>(
{name, depth, slot}));
}
void MaglevGraphBuilder::VisitLdaLookupGlobalSlotInsideTypeof() {
// LdaLookupGlobalSlotInsideTypeof <name_index> <feedback_slot> <depth>
// TODO(v8:7700): Add a simple load context fast path when there are no
// contexts with extension between the current one and the context at <depth>.
// LdaLookupGlobalSlotInsideTypeof <name_index> <context_slot> <depth>
ValueNode* name = GetConstant(GetRefOperand<Name>(0));
ValueNode* slot = GetSmiConstant(iterator_.GetIndexOperand(1));
ValueNode* depth = GetSmiConstant(iterator_.GetUnsignedImmediateOperand(2));
SetAccumulator(
BuildCallRuntime(Runtime::kLoadLookupSlotInsideTypeof, {name}));
BuildCallBuiltin<Builtin::kLookupGlobalICInsideTypeofTrampoline>(
{name, depth, slot}));
}
namespace {
......
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