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 { ...@@ -655,7 +655,9 @@ namespace internal {
TFH(DefineKeyedOwnICBaseline, StoreBaseline) \ TFH(DefineKeyedOwnICBaseline, StoreBaseline) \
TFH(StoreInArrayLiteralIC, StoreWithVector) \ TFH(StoreInArrayLiteralIC, StoreWithVector) \
TFH(StoreInArrayLiteralICBaseline, StoreBaseline) \ TFH(StoreInArrayLiteralICBaseline, StoreBaseline) \
TFH(LookupContextTrampoline, LookupTrampoline) \
TFH(LookupContextBaseline, LookupBaseline) \ TFH(LookupContextBaseline, LookupBaseline) \
TFH(LookupContextInsideTypeofTrampoline, LookupTrampoline) \
TFH(LookupContextInsideTypeofBaseline, LookupBaseline) \ TFH(LookupContextInsideTypeofBaseline, LookupBaseline) \
TFH(LoadGlobalIC, LoadGlobalWithVector) \ TFH(LoadGlobalIC, LoadGlobalWithVector) \
TFH(LoadGlobalICInsideTypeof, LoadGlobalWithVector) \ TFH(LoadGlobalICInsideTypeof, LoadGlobalWithVector) \
...@@ -663,7 +665,9 @@ namespace internal { ...@@ -663,7 +665,9 @@ namespace internal {
TFH(LoadGlobalICBaseline, LoadGlobalBaseline) \ TFH(LoadGlobalICBaseline, LoadGlobalBaseline) \
TFH(LoadGlobalICInsideTypeofTrampoline, LoadGlobal) \ TFH(LoadGlobalICInsideTypeofTrampoline, LoadGlobal) \
TFH(LoadGlobalICInsideTypeofBaseline, LoadGlobalBaseline) \ TFH(LoadGlobalICInsideTypeofBaseline, LoadGlobalBaseline) \
TFH(LookupGlobalICTrampoline, LookupTrampoline) \
TFH(LookupGlobalICBaseline, LookupBaseline) \ TFH(LookupGlobalICBaseline, LookupBaseline) \
TFH(LookupGlobalICInsideTypeofTrampoline, LookupTrampoline) \
TFH(LookupGlobalICInsideTypeofBaseline, LookupBaseline) \ TFH(LookupGlobalICInsideTypeofBaseline, LookupBaseline) \
TFH(CloneObjectIC, CloneObjectWithVector) \ TFH(CloneObjectIC, CloneObjectWithVector) \
TFH(CloneObjectICBaseline, CloneObjectBaseline) \ TFH(CloneObjectICBaseline, CloneObjectBaseline) \
......
...@@ -230,24 +230,48 @@ void Builtins::Generate_LoadGlobalICInsideTypeofBaseline( ...@@ -230,24 +230,48 @@ void Builtins::Generate_LoadGlobalICInsideTypeofBaseline(
assembler.GenerateLoadGlobalICBaseline(TypeofMode::kInside); assembler.GenerateLoadGlobalICBaseline(TypeofMode::kInside);
} }
void Builtins::Generate_LookupGlobalICTrampoline(
compiler::CodeAssemblerState* state) {
AccessorAssembler assembler(state);
assembler.GenerateLookupGlobalICTrampoline(TypeofMode::kNotInside);
}
void Builtins::Generate_LookupGlobalICBaseline( void Builtins::Generate_LookupGlobalICBaseline(
compiler::CodeAssemblerState* state) { compiler::CodeAssemblerState* state) {
AccessorAssembler assembler(state); AccessorAssembler assembler(state);
assembler.GenerateLookupGlobalICBaseline(TypeofMode::kNotInside); assembler.GenerateLookupGlobalICBaseline(TypeofMode::kNotInside);
} }
void Builtins::Generate_LookupGlobalICInsideTypeofTrampoline(
compiler::CodeAssemblerState* state) {
AccessorAssembler assembler(state);
assembler.GenerateLookupGlobalICTrampoline(TypeofMode::kInside);
}
void Builtins::Generate_LookupGlobalICInsideTypeofBaseline( void Builtins::Generate_LookupGlobalICInsideTypeofBaseline(
compiler::CodeAssemblerState* state) { compiler::CodeAssemblerState* state) {
AccessorAssembler assembler(state); AccessorAssembler assembler(state);
assembler.GenerateLookupGlobalICBaseline(TypeofMode::kInside); assembler.GenerateLookupGlobalICBaseline(TypeofMode::kInside);
} }
void Builtins::Generate_LookupContextTrampoline(
compiler::CodeAssemblerState* state) {
AccessorAssembler assembler(state);
assembler.GenerateLookupContextTrampoline(TypeofMode::kNotInside);
}
void Builtins::Generate_LookupContextBaseline( void Builtins::Generate_LookupContextBaseline(
compiler::CodeAssemblerState* state) { compiler::CodeAssemblerState* state) {
AccessorAssembler assembler(state); AccessorAssembler assembler(state);
assembler.GenerateLookupContextBaseline(TypeofMode::kNotInside); assembler.GenerateLookupContextBaseline(TypeofMode::kNotInside);
} }
void Builtins::Generate_LookupContextInsideTypeofTrampoline(
compiler::CodeAssemblerState* state) {
AccessorAssembler assembler(state);
assembler.GenerateLookupContextTrampoline(TypeofMode::kInside);
}
void Builtins::Generate_LookupContextInsideTypeofBaseline( void Builtins::Generate_LookupContextInsideTypeofBaseline(
compiler::CodeAssemblerState* state) { compiler::CodeAssemblerState* state) {
AccessorAssembler assembler(state); AccessorAssembler assembler(state);
......
...@@ -99,6 +99,7 @@ namespace internal { ...@@ -99,6 +99,7 @@ namespace internal {
V(LoadWithReceiverAndVector) \ V(LoadWithReceiverAndVector) \
V(LoadWithReceiverBaseline) \ V(LoadWithReceiverBaseline) \
V(LoadWithVector) \ V(LoadWithVector) \
V(LookupTrampoline) \
V(LookupBaseline) \ V(LookupBaseline) \
V(NewHeapNumber) \ V(NewHeapNumber) \
V(NoContext) \ V(NoContext) \
...@@ -844,6 +845,16 @@ class LoadGlobalBaselineDescriptor ...@@ -844,6 +845,16 @@ class LoadGlobalBaselineDescriptor
static constexpr auto registers(); 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 class LookupBaselineDescriptor
: public StaticCallInterfaceDescriptor<LookupBaselineDescriptor> { : public StaticCallInterfaceDescriptor<LookupBaselineDescriptor> {
public: public:
......
...@@ -4377,11 +4377,11 @@ void AccessorAssembler::GenerateLoadGlobalICBaseline(TypeofMode typeof_mode) { ...@@ -4377,11 +4377,11 @@ void AccessorAssembler::GenerateLoadGlobalICBaseline(TypeofMode typeof_mode) {
TailCallStub(callable, context, name, slot, vector); TailCallStub(callable, context, name, slot, vector);
} }
void AccessorAssembler::GenerateLookupContextBaseline(TypeofMode typeof_mode) { void AccessorAssembler::LookupContext(LazyNode<Object> lazy_name,
using Descriptor = LookupBaselineDescriptor; TNode<TaggedIndex> depth,
auto depth = Parameter<TaggedIndex>(Descriptor::kDepth); LazyNode<TaggedIndex> lazy_slot,
TNode<Context> context = LoadContextFromBaseline(); TNode<Context> context,
TypeofMode typeof_mode) {
Label slowpath(this, Label::kDeferred); Label slowpath(this, Label::kDeferred);
// Check for context extensions to allow the fast path. // Check for context extensions to allow the fast path.
...@@ -4391,14 +4391,14 @@ void AccessorAssembler::GenerateLookupContextBaseline(TypeofMode typeof_mode) { ...@@ -4391,14 +4391,14 @@ void AccessorAssembler::GenerateLookupContextBaseline(TypeofMode typeof_mode) {
// Fast path does a normal load context. // Fast path does a normal load context.
{ {
auto slot = Parameter<TaggedIndex>(Descriptor::kSlot); auto slot = lazy_slot();
Return(LoadContextElement(slot_context, TaggedIndexToIntPtr(slot))); Return(LoadContextElement(slot_context, TaggedIndexToIntPtr(slot)));
} }
// Slow path when we have to call out to the runtime. // Slow path when we have to call out to the runtime.
BIND(&slowpath); BIND(&slowpath);
{ {
auto name = Parameter<Object>(Descriptor::kName); auto name = lazy_name();
Runtime::FunctionId function_id = typeof_mode == TypeofMode::kInside Runtime::FunctionId function_id = typeof_mode == TypeofMode::kInside
? Runtime::kLoadLookupSlotInsideTypeof ? Runtime::kLoadLookupSlotInsideTypeof
: Runtime::kLoadLookupSlot; : Runtime::kLoadLookupSlot;
...@@ -4406,14 +4406,27 @@ void AccessorAssembler::GenerateLookupContextBaseline(TypeofMode typeof_mode) { ...@@ -4406,14 +4406,27 @@ void AccessorAssembler::GenerateLookupContextBaseline(TypeofMode typeof_mode) {
} }
} }
void AccessorAssembler::GenerateLookupGlobalICBaseline(TypeofMode typeof_mode) { void AccessorAssembler::GenerateLookupContextTrampoline(
using Descriptor = LookupBaselineDescriptor; 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); void AccessorAssembler::GenerateLookupContextBaseline(TypeofMode typeof_mode) {
auto depth = Parameter<TaggedIndex>(Descriptor::kDepth); using Descriptor = LookupBaselineDescriptor;
auto slot = Parameter<TaggedIndex>(Descriptor::kSlot); LookupContext([&] { return Parameter<Object>(Descriptor::kName); },
TNode<Context> context = LoadContextFromBaseline(); 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); Label slowpath(this, Label::kDeferred);
// Check for context extensions to allow the fast path // Check for context extensions to allow the fast path
...@@ -4425,8 +4438,8 @@ void AccessorAssembler::GenerateLookupGlobalICBaseline(TypeofMode typeof_mode) { ...@@ -4425,8 +4438,8 @@ void AccessorAssembler::GenerateLookupGlobalICBaseline(TypeofMode typeof_mode) {
{ {
Callable callable = Callable callable =
CodeFactory::LoadGlobalICInOptimizedCode(isolate(), typeof_mode); CodeFactory::LoadGlobalICInOptimizedCode(isolate(), typeof_mode);
TNode<FeedbackVector> vector = LoadFeedbackVectorFromBaseline(); TailCallStub(callable, context, lazy_name(), lazy_slot(),
TailCallStub(callable, context, name, slot, vector); lazy_feedback_vector());
} }
// Slow path when we have to call out to the runtime // Slow path when we have to call out to the runtime
...@@ -4434,7 +4447,26 @@ void AccessorAssembler::GenerateLookupGlobalICBaseline(TypeofMode typeof_mode) { ...@@ -4434,7 +4447,26 @@ void AccessorAssembler::GenerateLookupGlobalICBaseline(TypeofMode typeof_mode) {
Runtime::FunctionId function_id = typeof_mode == TypeofMode::kInside Runtime::FunctionId function_id = typeof_mode == TypeofMode::kInside
? Runtime::kLoadLookupSlotInsideTypeof ? Runtime::kLoadLookupSlotInsideTypeof
: Runtime::kLoadLookupSlot; : 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() { void AccessorAssembler::GenerateKeyedLoadIC() {
......
...@@ -59,7 +59,9 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler { ...@@ -59,7 +59,9 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler {
void GenerateLoadGlobalIC(TypeofMode typeof_mode); void GenerateLoadGlobalIC(TypeofMode typeof_mode);
void GenerateLoadGlobalICTrampoline(TypeofMode typeof_mode); void GenerateLoadGlobalICTrampoline(TypeofMode typeof_mode);
void GenerateLoadGlobalICBaseline(TypeofMode typeof_mode); void GenerateLoadGlobalICBaseline(TypeofMode typeof_mode);
void GenerateLookupGlobalICTrampoline(TypeofMode typeof_mode);
void GenerateLookupGlobalICBaseline(TypeofMode typeof_mode); void GenerateLookupGlobalICBaseline(TypeofMode typeof_mode);
void GenerateLookupContextTrampoline(TypeofMode typeof_mode);
void GenerateLookupContextBaseline(TypeofMode typeof_mode); void GenerateLookupContextBaseline(TypeofMode typeof_mode);
void GenerateKeyedStoreIC(); void GenerateKeyedStoreIC();
...@@ -333,6 +335,14 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler { ...@@ -333,6 +335,14 @@ class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler {
void DefineKeyedOwnIC(const StoreICParameters* p); void DefineKeyedOwnIC(const StoreICParameters* p);
void StoreInArrayLiteralIC(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. // IC dispatcher behavior.
// Checks monomorphic case. Returns {feedback} entry of the vector. // Checks monomorphic case. Returns {feedback} entry of the vector.
......
...@@ -838,18 +838,20 @@ void MaglevGraphBuilder::VisitLdaLookupSlot() { ...@@ -838,18 +838,20 @@ void MaglevGraphBuilder::VisitLdaLookupSlot() {
void MaglevGraphBuilder::VisitLdaLookupContextSlot() { void MaglevGraphBuilder::VisitLdaLookupContextSlot() {
// LdaLookupContextSlot <name_index> <feedback_slot> <depth> // 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)); 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() { void MaglevGraphBuilder::VisitLdaLookupGlobalSlot() {
// LdaLookupGlobalSlot <name_index> <feedback_slot> <depth> // 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)); 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() { void MaglevGraphBuilder::VisitLdaLookupSlotInsideTypeof() {
...@@ -860,21 +862,23 @@ void MaglevGraphBuilder::VisitLdaLookupSlotInsideTypeof() { ...@@ -860,21 +862,23 @@ void MaglevGraphBuilder::VisitLdaLookupSlotInsideTypeof() {
} }
void MaglevGraphBuilder::VisitLdaLookupContextSlotInsideTypeof() { void MaglevGraphBuilder::VisitLdaLookupContextSlotInsideTypeof() {
// LdaLookupContextSlotInsideTypeof <name_index> // LdaLookupContextSlotInsideTypeof <name_index> <context_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)); ValueNode* name = GetConstant(GetRefOperand<Name>(0));
ValueNode* slot = GetSmiConstant(iterator_.GetIndexOperand(1));
ValueNode* depth = GetSmiConstant(iterator_.GetUnsignedImmediateOperand(2));
SetAccumulator( SetAccumulator(
BuildCallRuntime(Runtime::kLoadLookupSlotInsideTypeof, {name})); BuildCallBuiltin<Builtin::kLookupContextInsideTypeofTrampoline>(
{name, depth, slot}));
} }
void MaglevGraphBuilder::VisitLdaLookupGlobalSlotInsideTypeof() { void MaglevGraphBuilder::VisitLdaLookupGlobalSlotInsideTypeof() {
// LdaLookupGlobalSlotInsideTypeof <name_index> <feedback_slot> <depth> // LdaLookupGlobalSlotInsideTypeof <name_index> <context_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)); ValueNode* name = GetConstant(GetRefOperand<Name>(0));
ValueNode* slot = GetSmiConstant(iterator_.GetIndexOperand(1));
ValueNode* depth = GetSmiConstant(iterator_.GetUnsignedImmediateOperand(2));
SetAccumulator( SetAccumulator(
BuildCallRuntime(Runtime::kLoadLookupSlotInsideTypeof, {name})); BuildCallBuiltin<Builtin::kLookupGlobalICInsideTypeofTrampoline>(
{name, depth, slot}));
} }
namespace { 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