[maglev] Support CreateClosure

Bug: v8:7700
Change-Id: Iacdb0ecd04d7b50d7dd623feb8646c89cc4016ff
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3757884
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81683}
This commit is contained in:
Leszek Swirski 2022-07-12 15:56:58 +02:00 committed by V8 LUCI CQ
parent fb945c9185
commit c906eec72a
5 changed files with 153 additions and 1 deletions

View File

@ -6,6 +6,7 @@
#include "src/base/optional.h"
#include "src/base/v8-fallthrough.h"
#include "src/builtins/builtins-constructor.h"
#include "src/common/globals.h"
#include "src/compiler/compilation-dependencies.h"
#include "src/compiler/feedback-source.h"
@ -1489,7 +1490,25 @@ void MaglevGraphBuilder::VisitCreateObjectLiteral() {
MAGLEV_UNIMPLEMENTED_BYTECODE(CreateEmptyObjectLiteral)
MAGLEV_UNIMPLEMENTED_BYTECODE(CloneObject)
MAGLEV_UNIMPLEMENTED_BYTECODE(GetTemplateObject)
MAGLEV_UNIMPLEMENTED_BYTECODE(CreateClosure)
void MaglevGraphBuilder::VisitCreateClosure() {
compiler::SharedFunctionInfoRef shared_function_info =
GetRefOperand<SharedFunctionInfo>(0);
compiler::FeedbackCellRef feedback_cell =
feedback().GetClosureFeedbackCell(iterator_.GetIndexOperand(1));
uint32_t flags = GetFlagOperand(2);
if (interpreter::CreateClosureFlags::FastNewClosureBit::decode(flags)) {
SetAccumulator(AddNewNode<FastCreateClosure>(
{GetContext()}, shared_function_info, feedback_cell));
} else {
bool pretenured =
interpreter::CreateClosureFlags::PretenuredBit::decode(flags);
SetAccumulator(AddNewNode<CreateClosure>(
{GetContext()}, shared_function_info, feedback_cell, pretenured));
}
}
MAGLEV_UNIMPLEMENTED_BYTECODE(CreateBlockContext)
MAGLEV_UNIMPLEMENTED_BYTECODE(CreateCatchContext)

View File

@ -101,6 +101,8 @@ class MaglevGraphVerifier {
case Opcode::kCreateObjectLiteral:
case Opcode::kCreateShallowObjectLiteral:
case Opcode::kCreateFunctionContext:
case Opcode::kCreateClosure:
case Opcode::kFastCreateClosure:
case Opcode::kReturn:
DCHECK_EQ(node->input_count(), 1);
CheckValueInputIs(node, 0, ValueRepresentation::kTagged);

View File

@ -17,6 +17,7 @@
#include "src/common/globals.h"
#include "src/compiler/backend/instruction.h"
#include "src/ic/handler-configuration.h"
#include "src/interpreter/bytecode-flags.h"
#include "src/maglev/maglev-code-gen-state.h"
#include "src/maglev/maglev-compilation-unit.h"
#include "src/maglev/maglev-graph-labeller.h"
@ -663,6 +664,50 @@ void CreateFunctionContext::PrintParams(
os << "(" << *scope_info().object() << ", " << slot_count() << ")";
}
void FastCreateClosure::AllocateVreg(MaglevVregAllocationState* vreg_state) {
using D = CallInterfaceDescriptorFor<Builtin::kFastNewClosure>::type;
static_assert(D::HasContextParameter());
UseFixed(context(), D::ContextRegister());
DefineAsFixed(vreg_state, this, kReturnRegister0);
}
void FastCreateClosure::GenerateCode(MaglevCodeGenState* code_gen_state,
const ProcessingState& state) {
using D = CallInterfaceDescriptorFor<Builtin::kFastNewClosure>::type;
DCHECK_EQ(ToRegister(context()), D::ContextRegister());
__ Move(D::GetRegisterParameter(D::kSharedFunctionInfo),
shared_function_info().object());
__ Move(D::GetRegisterParameter(D::kFeedbackCell), feedback_cell().object());
__ CallBuiltin(Builtin::kFastNewClosure);
}
void FastCreateClosure::PrintParams(std::ostream& os,
MaglevGraphLabeller* graph_labeller) const {
os << "(" << *shared_function_info().object() << ", "
<< feedback_cell().object() << ")";
}
void CreateClosure::AllocateVreg(MaglevVregAllocationState* vreg_state) {
UseFixed(context(), kContextRegister);
DefineAsFixed(vreg_state, this, kReturnRegister0);
}
void CreateClosure::GenerateCode(MaglevCodeGenState* code_gen_state,
const ProcessingState& state) {
Runtime::FunctionId function_id =
pretenured() ? Runtime::kNewClosure_Tenured : Runtime::kNewClosure;
__ Push(shared_function_info().object());
__ Push(feedback_cell().object());
__ CallRuntime(function_id);
}
void CreateClosure::PrintParams(std::ostream& os,
MaglevGraphLabeller* graph_labeller) const {
os << "(" << *shared_function_info().object() << ", "
<< feedback_cell().object();
if (pretenured()) {
os << " [pretenured]";
}
os << ")";
}
void CheckMaps::AllocateVreg(MaglevVregAllocationState* vreg_state) {
UseRegister(receiver_input());
set_temporaries_needed(1);

View File

@ -121,6 +121,8 @@ class CompactInterpreterFrameState;
V(CreateObjectLiteral) \
V(CreateShallowObjectLiteral) \
V(CreateFunctionContext) \
V(CreateClosure) \
V(FastCreateClosure) \
V(InitialValue) \
V(LoadTaggedField) \
V(LoadDoubleField) \
@ -1741,6 +1743,70 @@ class CreateFunctionContext
const uint32_t slot_count_;
};
class FastCreateClosure : public FixedInputValueNodeT<1, FastCreateClosure> {
using Base = FixedInputValueNodeT<1, FastCreateClosure>;
public:
explicit FastCreateClosure(
uint64_t bitfield, compiler::SharedFunctionInfoRef shared_function_info,
compiler::FeedbackCellRef feedback_cell)
: Base(bitfield),
shared_function_info_(shared_function_info),
feedback_cell_(feedback_cell) {}
compiler::SharedFunctionInfoRef shared_function_info() const {
return shared_function_info_;
}
compiler::FeedbackCellRef feedback_cell() const { return feedback_cell_; }
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::SharedFunctionInfoRef shared_function_info_;
const compiler::FeedbackCellRef feedback_cell_;
};
class CreateClosure : public FixedInputValueNodeT<0, CreateClosure> {
using Base = FixedInputValueNodeT<0, CreateClosure>;
public:
explicit CreateClosure(uint64_t bitfield,
compiler::SharedFunctionInfoRef shared_function_info,
compiler::FeedbackCellRef feedback_cell,
bool pretenured)
: Base(bitfield),
shared_function_info_(shared_function_info),
feedback_cell_(feedback_cell),
pretenured_(pretenured) {}
compiler::SharedFunctionInfoRef shared_function_info() const {
return shared_function_info_;
}
compiler::FeedbackCellRef feedback_cell() const { return feedback_cell_; }
bool pretenured() const { return pretenured_; }
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::SharedFunctionInfoRef shared_function_info_;
const compiler::FeedbackCellRef feedback_cell_;
const bool pretenured_;
};
class CheckMaps : public FixedInputNodeT<1, CheckMaps> {
using Base = FixedInputNodeT<1, CheckMaps>;

View File

@ -0,0 +1,20 @@
// Copyright 2022 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --maglev --no-stress-opt
function foo(x) {
var inner = function() {
return x;
}
return inner();
}
%PrepareFunctionForOptimization(foo);
assertEquals(1, foo(1));
assertEquals(2, foo(2));
%OptimizeMaglevOnNextCall(foo);
assertEquals(1, foo(1));
assertEquals(2, foo(2));
assertTrue(isMaglevved(foo));