Commit 5f405c7d authored by Victor Gomes's avatar Victor Gomes Committed by V8 LUCI CQ

[maglev] Support ToName, ToObject and ToString

Bug: v8:7700
Change-Id: I72b85094b22c2fb5a94c42d5920f750aee2fd167
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3803025
Auto-Submit: Victor Gomes <victorgomes@chromium.org>
Commit-Queue: Victor Gomes <victorgomes@chromium.org>
Reviewed-by: 's avatarJakob Linke <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/main@{#82114}
parent 45a1d0da
......@@ -1767,7 +1767,12 @@ void MaglevGraphBuilder::VisitTestIn() {
AddNewNode<HasProperty>({context, object, name}, feedback_source));
}
MAGLEV_UNIMPLEMENTED_BYTECODE(ToName)
void MaglevGraphBuilder::VisitToName() {
// ToObject <dst>
ValueNode* value = GetAccumulatorTagged();
interpreter::Register destination = iterator_.GetRegisterOperand(0);
StoreRegister(destination, AddNewNode<ToName>({GetContext(), value}));
}
void MaglevGraphBuilder::BuildToNumberOrToNumeric(Object::Conversion mode) {
ValueNode* value = GetAccumulatorTagged();
......@@ -1797,8 +1802,19 @@ void MaglevGraphBuilder::VisitToNumeric() {
BuildToNumberOrToNumeric(Object::Conversion::kToNumeric);
}
MAGLEV_UNIMPLEMENTED_BYTECODE(ToObject)
MAGLEV_UNIMPLEMENTED_BYTECODE(ToString)
void MaglevGraphBuilder::VisitToObject() {
// ToObject <dst>
ValueNode* value = GetAccumulatorTagged();
interpreter::Register destination = iterator_.GetRegisterOperand(0);
StoreRegister(destination, AddNewNode<ToObject>({GetContext(), value}));
}
void MaglevGraphBuilder::VisitToString() {
// ToString
ValueNode* value = GetAccumulatorTagged();
// TODO(victorgomes): Add fast path for constant nodes.
SetAccumulator(AddNewNode<ToString>({GetContext(), value}));
}
void MaglevGraphBuilder::VisitCreateRegExpLiteral() {
// CreateRegExpLiteral <pattern_idx> <literal_idx> <flags>
......
......@@ -155,8 +155,11 @@ class MaglevGraphVerifier {
// TODO(victorgomes): Can we check that second input is a Smi?
case Opcode::kStoreTaggedFieldWithWriteBarrier:
case Opcode::kLoadNamedGeneric:
case Opcode::kToNumberOrNumeric:
case Opcode::kThrowIfNotSuperConstructor:
case Opcode::kToName:
case Opcode::kToNumberOrNumeric:
case Opcode::kToObject:
case Opcode::kToString:
DCHECK_EQ(node->input_count(), 2);
CheckValueInputIs(node, 0, ValueRepresentation::kTagged);
CheckValueInputIs(node, 1, ValueRepresentation::kTagged);
......
......@@ -31,7 +31,7 @@ namespace v8 {
namespace internal {
namespace maglev {
const char* ToString(Opcode opcode) {
const char* OpcodeToString(Opcode opcode) {
#define DEF_NAME(Name) #Name,
static constexpr const char* const names[] = {NODE_BASE_LIST(DEF_NAME)};
#undef DEF_NAME
......@@ -2293,6 +2293,23 @@ void TestTypeOf::GenerateCode(MaglevCodeGenState* code_gen_state,
__ bind(&done);
}
void ToName::AllocateVreg(MaglevVregAllocationState* vreg_state) {
using D = CallInterfaceDescriptorFor<Builtin::kToName>::type;
UseFixed(context(), kContextRegister);
UseFixed(value_input(), D::GetRegisterParameter(D::kInput));
DefineAsFixed(vreg_state, this, kReturnRegister0);
}
void ToName::GenerateCode(MaglevCodeGenState* code_gen_state,
const ProcessingState& state) {
#ifdef DEBUG
using D = CallInterfaceDescriptorFor<Builtin::kToName>::type;
DCHECK_EQ(ToRegister(context()), kContextRegister);
DCHECK_EQ(ToRegister(value_input()), D::GetRegisterParameter(D::kInput));
#endif // DEBUG
__ CallBuiltin(Builtin::kToName);
code_gen_state->DefineLazyDeoptPoint(lazy_deopt_info());
}
void ToNumberOrNumeric::AllocateVreg(MaglevVregAllocationState* vreg_state) {
using D = TypeConversionDescriptor;
UseFixed(context(), kContextRegister);
......@@ -2312,6 +2329,60 @@ void ToNumberOrNumeric::GenerateCode(MaglevCodeGenState* code_gen_state,
code_gen_state->DefineLazyDeoptPoint(lazy_deopt_info());
}
void ToObject::AllocateVreg(MaglevVregAllocationState* vreg_state) {
using D = CallInterfaceDescriptorFor<Builtin::kToObject>::type;
UseFixed(context(), kContextRegister);
UseFixed(value_input(), D::GetRegisterParameter(D::kInput));
DefineAsFixed(vreg_state, this, kReturnRegister0);
}
void ToObject::GenerateCode(MaglevCodeGenState* code_gen_state,
const ProcessingState& state) {
#ifdef DEBUG
using D = CallInterfaceDescriptorFor<Builtin::kToObject>::type;
DCHECK_EQ(ToRegister(context()), kContextRegister);
DCHECK_EQ(ToRegister(value_input()), D::GetRegisterParameter(D::kInput));
#endif // DEBUG
Register value = ToRegister(value_input());
Label call_builtin, done;
// Avoid the builtin call if {value} is a JSReceiver.
__ JumpIfSmi(value, &call_builtin);
__ LoadMap(kScratchRegister, value);
__ cmpw(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset),
Immediate(FIRST_JS_RECEIVER_TYPE));
__ j(greater_equal, &done);
__ bind(&call_builtin);
__ CallBuiltin(Builtin::kToObject);
code_gen_state->DefineLazyDeoptPoint(lazy_deopt_info());
__ bind(&done);
}
void ToString::AllocateVreg(MaglevVregAllocationState* vreg_state) {
using D = CallInterfaceDescriptorFor<Builtin::kToString>::type;
UseFixed(context(), kContextRegister);
UseFixed(value_input(), D::GetRegisterParameter(D::kO));
DefineAsFixed(vreg_state, this, kReturnRegister0);
}
void ToString::GenerateCode(MaglevCodeGenState* code_gen_state,
const ProcessingState& state) {
#ifdef DEBUG
using D = CallInterfaceDescriptorFor<Builtin::kToString>::type;
DCHECK_EQ(ToRegister(context()), kContextRegister);
DCHECK_EQ(ToRegister(value_input()), D::GetRegisterParameter(D::kO));
#endif // DEBUG
Register value = ToRegister(value_input());
Label call_builtin, done;
// Avoid the builtin call if {value} is a string.
__ JumpIfSmi(value, &call_builtin);
__ LoadMap(kScratchRegister, value);
__ cmpw(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset),
Immediate(FIRST_NONSTRING_TYPE));
__ j(less, &done);
__ bind(&call_builtin);
__ CallBuiltin(Builtin::kToString);
code_gen_state->DefineLazyDeoptPoint(lazy_deopt_info());
__ bind(&done);
}
void ChangeInt32ToFloat64::AllocateVreg(MaglevVregAllocationState* vreg_state) {
UseRegister(input());
DefineAsRegister(vreg_state, this);
......
......@@ -156,7 +156,10 @@ class CompactInterpreterFrameState;
V(TestInstanceOf) \
V(TestUndetectable) \
V(TestTypeOf) \
V(ToName) \
V(ToNumberOrNumeric) \
V(ToObject) \
V(ToString) \
CONSTANT_VALUE_NODE_LIST(V) \
INT32_OPERATIONS_NODE_LIST(V) \
FLOAT64_OPERATIONS_NODE_LIST(V) \
......@@ -218,9 +221,9 @@ static constexpr Opcode kFirstOpcode = static_cast<Opcode>(0);
static constexpr Opcode kLastOpcode = static_cast<Opcode>(kOpcodeCount - 1);
#undef PLUS_ONE
const char* ToString(Opcode opcode);
const char* OpcodeToString(Opcode opcode);
inline std::ostream& operator<<(std::ostream& os, Opcode opcode) {
return os << ToString(opcode);
return os << OpcodeToString(opcode);
}
#define V(Name) Opcode::k##Name,
......@@ -1658,6 +1661,23 @@ class TestTypeOf : public FixedInputValueNodeT<1, TestTypeOf> {
interpreter::TestTypeOfFlags::LiteralFlag literal_;
};
class ToName : public FixedInputValueNodeT<2, ToName> {
using Base = FixedInputValueNodeT<2, ToName>;
public:
explicit ToName(uint64_t bitfield) : Base(bitfield) {}
// The implementation currently calls runtime.
static constexpr OpProperties kProperties = OpProperties::JSCall();
Input& context() { return Node::input(0); }
Input& value_input() { return Node::input(1); }
void AllocateVreg(MaglevVregAllocationState*);
void GenerateCode(MaglevCodeGenState*, const ProcessingState&);
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {}
};
class ToNumberOrNumeric : public FixedInputValueNodeT<2, ToNumberOrNumeric> {
using Base = FixedInputValueNodeT<2, ToNumberOrNumeric>;
......@@ -1705,6 +1725,39 @@ class HasProperty : public FixedInputValueNodeT<3, HasProperty> {
const compiler::FeedbackSource feedback_;
};
class ToObject : public FixedInputValueNodeT<2, ToObject> {
using Base = FixedInputValueNodeT<2, ToObject>;
public:
explicit ToObject(uint64_t bitfield) : Base(bitfield) {}
// The implementation currently calls runtime.
static constexpr OpProperties kProperties = OpProperties::JSCall();
Input& context() { return Node::input(0); }
Input& value_input() { return Node::input(1); }
void AllocateVreg(MaglevVregAllocationState*);
void GenerateCode(MaglevCodeGenState*, const ProcessingState&);
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {}
};
class ToString : public FixedInputValueNodeT<2, ToString> {
using Base = FixedInputValueNodeT<2, ToString>;
public:
explicit ToString(uint64_t bitfield) : Base(bitfield) {}
// The implementation currently calls runtime.
static constexpr OpProperties kProperties = OpProperties::JSCall();
Input& context() { return Node::input(0); }
Input& value_input() { return Node::input(1); }
void AllocateVreg(MaglevVregAllocationState*);
void GenerateCode(MaglevCodeGenState*, const ProcessingState&);
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {}
};
class InitialValue : public FixedInputValueNodeT<0, InitialValue> {
using Base = FixedInputValueNodeT<0, InitialValue>;
......
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