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 {
}
// TODO(leszeks): The input locations array happens to be in the same order
// as parameters+locals+accumulator are accessed here. We should make this
// clearer and guard against this invariant failing.
// as parameters+context+locals+accumulator are accessed here. We should
// make this clearer and guard against this invariant failing.
const InputLocation* input_location = input_locations;
// Parameters
......@@ -607,9 +607,9 @@ class MaglevCodeGeneratorImpl final {
}
// Context
int context_index =
DeoptStackSlotIndexFromFPOffset(StandardFrameConstants::kContextOffset);
translation_array_builder_.StoreStackSlot(context_index);
ValueNode* value = checkpoint_state->context(compilation_unit);
EmitDeoptFrameSingleValue(value, *input_location);
input_location++;
// Locals
{
......
......@@ -15,6 +15,7 @@
#include "src/ic/handler-configuration-inl.h"
#include "src/interpreter/bytecode-flags.h"
#include "src/interpreter/bytecodes.h"
#include "src/maglev/maglev-compilation-info.h"
#include "src/maglev/maglev-compilation-unit.h"
#include "src/maglev/maglev-interpreter-frame-state.h"
#include "src/maglev/maglev-ir.h"
......@@ -1423,7 +1424,14 @@ MAGLEV_UNIMPLEMENTED_BYTECODE(GetTemplateObject)
MAGLEV_UNIMPLEMENTED_BYTECODE(CreateClosure)
MAGLEV_UNIMPLEMENTED_BYTECODE(CreateBlockContext)
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(CreateWithContext)
MAGLEV_UNIMPLEMENTED_BYTECODE(CreateMappedArguments)
......
......@@ -99,6 +99,7 @@ class MaglevGraphVerifier {
case Opcode::kCheckedFloat64Unbox:
case Opcode::kCreateObjectLiteral:
case Opcode::kCreateShallowObjectLiteral:
case Opcode::kCreateFunctionContext:
case Opcode::kReturn:
DCHECK_EQ(node->input_count(), 1);
CheckValueInputIs(node, 0, ValueRepresentation::kTagged);
......
......@@ -117,7 +117,8 @@ class CompactInterpreterFrameState {
int live_reg = 0;
for (int register_index : *liveness_) {
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);
}
}
......@@ -127,7 +128,8 @@ class CompactInterpreterFrameState {
int live_reg = 0;
for (int register_index : *liveness_) {
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);
}
}
......@@ -135,12 +137,14 @@ class CompactInterpreterFrameState {
template <typename Function>
void ForEachRegister(const MaglevCompilationUnit& info, Function&& f) {
ForEachParameter(info, f);
f(context(info), interpreter::Register::current_context());
ForEachLocal(info, f);
}
template <typename Function>
void ForEachRegister(const MaglevCompilationUnit& info, Function&& f) const {
ForEachParameter(info, f);
f(context(info), interpreter::Register::current_context());
ForEachLocal(info, f);
}
......@@ -169,6 +173,13 @@ class CompactInterpreterFrameState {
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 {
return SizeFor(info, liveness_);
}
......@@ -176,9 +187,13 @@ class CompactInterpreterFrameState {
private:
static size_t SizeFor(const MaglevCompilationUnit& info,
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_;
const compiler::BytecodeLivenessState* const liveness_;
};
......@@ -220,6 +235,7 @@ class MergePointInterpreterFrameState {
if (!analysis.IsLoopHeader(merge_offset)) return;
auto& assignments = analysis.GetLoopInfoFor(merge_offset).assignments();
if (reg.is_parameter()) {
if (reg.is_current_context()) return;
if (!assignments.ContainsParameter(reg.ToParameterIndex())) return;
} else {
DCHECK(
......@@ -257,6 +273,7 @@ class MergePointInterpreterFrameState {
entry = NewLoopPhi(info.zone(), reg, merge_offset);
}
});
frame_state_.context(info) = nullptr;
frame_state_.ForEachLocal(
info, [&](ValueNode*& entry, interpreter::Register reg) {
entry = nullptr;
......
......@@ -6,6 +6,7 @@
#include "src/base/bits.h"
#include "src/base/logging.h"
#include "src/builtins/builtins-constructor.h"
#include "src/codegen/interface-descriptors-inl.h"
#include "src/codegen/interface-descriptors.h"
#include "src/codegen/macro-assembler-inl.h"
......@@ -634,6 +635,34 @@ void CreateShallowObjectLiteral::GenerateCode(
__ 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) {
UseRegister(receiver_input());
set_temporaries_needed(1);
......
......@@ -120,6 +120,7 @@ class CompactInterpreterFrameState;
V(CreateEmptyArrayLiteral) \
V(CreateObjectLiteral) \
V(CreateShallowObjectLiteral) \
V(CreateFunctionContext) \
V(InitialValue) \
V(LoadTaggedField) \
V(LoadDoubleField) \
......@@ -1709,6 +1710,33 @@ class CreateShallowObjectLiteral
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> {
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