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

[maglev] Add CreateFunctionContext support

Add a CreateFunctionContext implementation (which calls the same builtin
used by Sparkplug), and fix our deopt checkpoints to include the context
as a pseudo-register, so that Push/PopContext work with deopts.

Bug: v8:7700
Change-Id: Ia3efd105683f6922181b9f4c7db0bac6a3a5fcec
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3757683Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81664}
parent ff27a796
...@@ -585,8 +585,8 @@ class MaglevCodeGeneratorImpl final { ...@@ -585,8 +585,8 @@ class MaglevCodeGeneratorImpl final {
} }
// TODO(leszeks): The input locations array happens to be in the same order // TODO(leszeks): The input locations array happens to be in the same order
// as parameters+locals+accumulator are accessed here. We should make this // as parameters+context+locals+accumulator are accessed here. We should
// clearer and guard against this invariant failing. // make this clearer and guard against this invariant failing.
const InputLocation* input_location = input_locations; const InputLocation* input_location = input_locations;
// Parameters // Parameters
...@@ -607,9 +607,9 @@ class MaglevCodeGeneratorImpl final { ...@@ -607,9 +607,9 @@ class MaglevCodeGeneratorImpl final {
} }
// Context // Context
int context_index = ValueNode* value = checkpoint_state->context(compilation_unit);
DeoptStackSlotIndexFromFPOffset(StandardFrameConstants::kContextOffset); EmitDeoptFrameSingleValue(value, *input_location);
translation_array_builder_.StoreStackSlot(context_index); input_location++;
// Locals // Locals
{ {
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "src/ic/handler-configuration-inl.h" #include "src/ic/handler-configuration-inl.h"
#include "src/interpreter/bytecode-flags.h" #include "src/interpreter/bytecode-flags.h"
#include "src/interpreter/bytecodes.h" #include "src/interpreter/bytecodes.h"
#include "src/maglev/maglev-compilation-info.h"
#include "src/maglev/maglev-compilation-unit.h" #include "src/maglev/maglev-compilation-unit.h"
#include "src/maglev/maglev-interpreter-frame-state.h" #include "src/maglev/maglev-interpreter-frame-state.h"
#include "src/maglev/maglev-ir.h" #include "src/maglev/maglev-ir.h"
...@@ -1423,7 +1424,14 @@ MAGLEV_UNIMPLEMENTED_BYTECODE(GetTemplateObject) ...@@ -1423,7 +1424,14 @@ MAGLEV_UNIMPLEMENTED_BYTECODE(GetTemplateObject)
MAGLEV_UNIMPLEMENTED_BYTECODE(CreateClosure) MAGLEV_UNIMPLEMENTED_BYTECODE(CreateClosure)
MAGLEV_UNIMPLEMENTED_BYTECODE(CreateBlockContext) MAGLEV_UNIMPLEMENTED_BYTECODE(CreateBlockContext)
MAGLEV_UNIMPLEMENTED_BYTECODE(CreateCatchContext) MAGLEV_UNIMPLEMENTED_BYTECODE(CreateCatchContext)
MAGLEV_UNIMPLEMENTED_BYTECODE(CreateFunctionContext)
void MaglevGraphBuilder::VisitCreateFunctionContext() {
compiler::ScopeInfoRef info = GetRefOperand<ScopeInfo>(0);
uint32_t slot_count = iterator_.GetUnsignedImmediateOperand(1);
SetAccumulator(
AddNewNode<CreateFunctionContext>({GetContext()}, info, slot_count));
}
MAGLEV_UNIMPLEMENTED_BYTECODE(CreateEvalContext) MAGLEV_UNIMPLEMENTED_BYTECODE(CreateEvalContext)
MAGLEV_UNIMPLEMENTED_BYTECODE(CreateWithContext) MAGLEV_UNIMPLEMENTED_BYTECODE(CreateWithContext)
MAGLEV_UNIMPLEMENTED_BYTECODE(CreateMappedArguments) MAGLEV_UNIMPLEMENTED_BYTECODE(CreateMappedArguments)
......
...@@ -99,6 +99,7 @@ class MaglevGraphVerifier { ...@@ -99,6 +99,7 @@ class MaglevGraphVerifier {
case Opcode::kCheckedFloat64Unbox: case Opcode::kCheckedFloat64Unbox:
case Opcode::kCreateObjectLiteral: case Opcode::kCreateObjectLiteral:
case Opcode::kCreateShallowObjectLiteral: case Opcode::kCreateShallowObjectLiteral:
case Opcode::kCreateFunctionContext:
case Opcode::kReturn: case Opcode::kReturn:
DCHECK_EQ(node->input_count(), 1); DCHECK_EQ(node->input_count(), 1);
CheckValueInputIs(node, 0, ValueRepresentation::kTagged); CheckValueInputIs(node, 0, ValueRepresentation::kTagged);
......
...@@ -117,7 +117,8 @@ class CompactInterpreterFrameState { ...@@ -117,7 +117,8 @@ class CompactInterpreterFrameState {
int live_reg = 0; int live_reg = 0;
for (int register_index : *liveness_) { for (int register_index : *liveness_) {
interpreter::Register reg = interpreter::Register(register_index); interpreter::Register reg = interpreter::Register(register_index);
f(live_registers_and_accumulator_[info.parameter_count() + live_reg++], f(live_registers_and_accumulator_[info.parameter_count() +
context_register_count_ + live_reg++],
reg); reg);
} }
} }
...@@ -127,7 +128,8 @@ class CompactInterpreterFrameState { ...@@ -127,7 +128,8 @@ class CompactInterpreterFrameState {
int live_reg = 0; int live_reg = 0;
for (int register_index : *liveness_) { for (int register_index : *liveness_) {
interpreter::Register reg = interpreter::Register(register_index); interpreter::Register reg = interpreter::Register(register_index);
f(live_registers_and_accumulator_[info.parameter_count() + live_reg++], f(live_registers_and_accumulator_[info.parameter_count() +
context_register_count_ + live_reg++],
reg); reg);
} }
} }
...@@ -135,12 +137,14 @@ class CompactInterpreterFrameState { ...@@ -135,12 +137,14 @@ class CompactInterpreterFrameState {
template <typename Function> template <typename Function>
void ForEachRegister(const MaglevCompilationUnit& info, Function&& f) { void ForEachRegister(const MaglevCompilationUnit& info, Function&& f) {
ForEachParameter(info, f); ForEachParameter(info, f);
f(context(info), interpreter::Register::current_context());
ForEachLocal(info, f); ForEachLocal(info, f);
} }
template <typename Function> template <typename Function>
void ForEachRegister(const MaglevCompilationUnit& info, Function&& f) const { void ForEachRegister(const MaglevCompilationUnit& info, Function&& f) const {
ForEachParameter(info, f); ForEachParameter(info, f);
f(context(info), interpreter::Register::current_context());
ForEachLocal(info, f); ForEachLocal(info, f);
} }
...@@ -169,6 +173,13 @@ class CompactInterpreterFrameState { ...@@ -169,6 +173,13 @@ class CompactInterpreterFrameState {
return live_registers_and_accumulator_[size(info) - 1]; return live_registers_and_accumulator_[size(info) - 1];
} }
ValueNode*& context(const MaglevCompilationUnit& info) {
return live_registers_and_accumulator_[info.parameter_count()];
}
ValueNode* context(const MaglevCompilationUnit& info) const {
return live_registers_and_accumulator_[info.parameter_count()];
}
size_t size(const MaglevCompilationUnit& info) const { size_t size(const MaglevCompilationUnit& info) const {
return SizeFor(info, liveness_); return SizeFor(info, liveness_);
} }
...@@ -176,9 +187,13 @@ class CompactInterpreterFrameState { ...@@ -176,9 +187,13 @@ class CompactInterpreterFrameState {
private: private:
static size_t SizeFor(const MaglevCompilationUnit& info, static size_t SizeFor(const MaglevCompilationUnit& info,
const compiler::BytecodeLivenessState* liveness) { const compiler::BytecodeLivenessState* liveness) {
return info.parameter_count() + liveness->live_value_count(); return info.parameter_count() + context_register_count_ +
liveness->live_value_count();
} }
// TODO(leszeks): Only include the context register if there are any
// Push/PopContext calls.
static const int context_register_count_ = 1;
ValueNode** const live_registers_and_accumulator_; ValueNode** const live_registers_and_accumulator_;
const compiler::BytecodeLivenessState* const liveness_; const compiler::BytecodeLivenessState* const liveness_;
}; };
...@@ -220,6 +235,7 @@ class MergePointInterpreterFrameState { ...@@ -220,6 +235,7 @@ class MergePointInterpreterFrameState {
if (!analysis.IsLoopHeader(merge_offset)) return; if (!analysis.IsLoopHeader(merge_offset)) return;
auto& assignments = analysis.GetLoopInfoFor(merge_offset).assignments(); auto& assignments = analysis.GetLoopInfoFor(merge_offset).assignments();
if (reg.is_parameter()) { if (reg.is_parameter()) {
if (reg.is_current_context()) return;
if (!assignments.ContainsParameter(reg.ToParameterIndex())) return; if (!assignments.ContainsParameter(reg.ToParameterIndex())) return;
} else { } else {
DCHECK( DCHECK(
...@@ -257,6 +273,7 @@ class MergePointInterpreterFrameState { ...@@ -257,6 +273,7 @@ class MergePointInterpreterFrameState {
entry = NewLoopPhi(info.zone(), reg, merge_offset); entry = NewLoopPhi(info.zone(), reg, merge_offset);
} }
}); });
frame_state_.context(info) = nullptr;
frame_state_.ForEachLocal( frame_state_.ForEachLocal(
info, [&](ValueNode*& entry, interpreter::Register reg) { info, [&](ValueNode*& entry, interpreter::Register reg) {
entry = nullptr; entry = nullptr;
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "src/base/bits.h" #include "src/base/bits.h"
#include "src/base/logging.h" #include "src/base/logging.h"
#include "src/builtins/builtins-constructor.h"
#include "src/codegen/interface-descriptors-inl.h" #include "src/codegen/interface-descriptors-inl.h"
#include "src/codegen/interface-descriptors.h" #include "src/codegen/interface-descriptors.h"
#include "src/codegen/macro-assembler-inl.h" #include "src/codegen/macro-assembler-inl.h"
...@@ -634,6 +635,34 @@ void CreateShallowObjectLiteral::GenerateCode( ...@@ -634,6 +635,34 @@ void CreateShallowObjectLiteral::GenerateCode(
__ CallBuiltin(Builtin::kCreateShallowObjectLiteral); __ CallBuiltin(Builtin::kCreateShallowObjectLiteral);
} }
void CreateFunctionContext::AllocateVreg(
MaglevVregAllocationState* vreg_state) {
using D = CallInterfaceDescriptorFor<
Builtin::kFastNewFunctionContextFunction>::type;
static_assert(D::HasContextParameter());
UseFixed(context(), D::ContextRegister());
DefineAsFixed(vreg_state, this, kReturnRegister0);
}
void CreateFunctionContext::GenerateCode(MaglevCodeGenState* code_gen_state,
const ProcessingState& state) {
using D = CallInterfaceDescriptorFor<
Builtin::kFastNewFunctionContextFunction>::type;
DCHECK_LE(slot_count(), ConstructorBuiltins::MaximumFunctionContextSlots());
DCHECK_EQ(scope_info().object()->scope_type(), ScopeType::FUNCTION_SCOPE);
DCHECK_EQ(ToRegister(context()), D::ContextRegister());
__ Move(D::GetRegisterParameter(D::kScopeInfo), scope_info().object());
__ Move(D::GetRegisterParameter(D::kSlots), Immediate(slot_count()));
// TODO(leszeks): Consider inlining this allocation.
__ CallBuiltin(Builtin::kFastNewFunctionContextFunction);
code_gen_state->safepoint_table_builder()->DefineSafepoint(
code_gen_state->masm());
}
void CreateFunctionContext::PrintParams(
std::ostream& os, MaglevGraphLabeller* graph_labeller) const {
os << "(" << *scope_info().object() << ", " << slot_count() << ")";
}
void CheckMaps::AllocateVreg(MaglevVregAllocationState* vreg_state) { void CheckMaps::AllocateVreg(MaglevVregAllocationState* vreg_state) {
UseRegister(receiver_input()); UseRegister(receiver_input());
set_temporaries_needed(1); set_temporaries_needed(1);
......
...@@ -120,6 +120,7 @@ class CompactInterpreterFrameState; ...@@ -120,6 +120,7 @@ class CompactInterpreterFrameState;
V(CreateEmptyArrayLiteral) \ V(CreateEmptyArrayLiteral) \
V(CreateObjectLiteral) \ V(CreateObjectLiteral) \
V(CreateShallowObjectLiteral) \ V(CreateShallowObjectLiteral) \
V(CreateFunctionContext) \
V(InitialValue) \ V(InitialValue) \
V(LoadTaggedField) \ V(LoadTaggedField) \
V(LoadDoubleField) \ V(LoadDoubleField) \
...@@ -1709,6 +1710,33 @@ class CreateShallowObjectLiteral ...@@ -1709,6 +1710,33 @@ class CreateShallowObjectLiteral
const compiler::FeedbackSource feedback_; const compiler::FeedbackSource feedback_;
}; };
class CreateFunctionContext
: public FixedInputValueNodeT<1, CreateFunctionContext> {
using Base = FixedInputValueNodeT<1, CreateFunctionContext>;
public:
explicit CreateFunctionContext(uint64_t bitfield,
compiler::ScopeInfoRef scope_info,
uint32_t slot_count)
: Base(bitfield), scope_info_(scope_info), slot_count_(slot_count) {}
compiler::ScopeInfoRef scope_info() const { return scope_info_; }
uint32_t slot_count() const { return slot_count_; }
Input& context() { return input(0); }
// The implementation currently calls runtime.
static constexpr OpProperties kProperties = OpProperties::Call();
void AllocateVreg(MaglevVregAllocationState*);
void GenerateCode(MaglevCodeGenState*, const ProcessingState&);
void PrintParams(std::ostream&, MaglevGraphLabeller*) const;
private:
const compiler::ScopeInfoRef scope_info_;
const uint32_t slot_count_;
};
class CheckMaps : public FixedInputNodeT<1, CheckMaps> { class CheckMaps : public FixedInputNodeT<1, CheckMaps> {
using Base = FixedInputNodeT<1, CheckMaps>; using Base = FixedInputNodeT<1, CheckMaps>;
......
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