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() { ...@@ -1767,7 +1767,12 @@ void MaglevGraphBuilder::VisitTestIn() {
AddNewNode<HasProperty>({context, object, name}, feedback_source)); 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) { void MaglevGraphBuilder::BuildToNumberOrToNumeric(Object::Conversion mode) {
ValueNode* value = GetAccumulatorTagged(); ValueNode* value = GetAccumulatorTagged();
...@@ -1797,8 +1802,19 @@ void MaglevGraphBuilder::VisitToNumeric() { ...@@ -1797,8 +1802,19 @@ void MaglevGraphBuilder::VisitToNumeric() {
BuildToNumberOrToNumeric(Object::Conversion::kToNumeric); BuildToNumberOrToNumeric(Object::Conversion::kToNumeric);
} }
MAGLEV_UNIMPLEMENTED_BYTECODE(ToObject) void MaglevGraphBuilder::VisitToObject() {
MAGLEV_UNIMPLEMENTED_BYTECODE(ToString) // 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() { void MaglevGraphBuilder::VisitCreateRegExpLiteral() {
// CreateRegExpLiteral <pattern_idx> <literal_idx> <flags> // CreateRegExpLiteral <pattern_idx> <literal_idx> <flags>
......
...@@ -155,8 +155,11 @@ class MaglevGraphVerifier { ...@@ -155,8 +155,11 @@ class MaglevGraphVerifier {
// TODO(victorgomes): Can we check that second input is a Smi? // TODO(victorgomes): Can we check that second input is a Smi?
case Opcode::kStoreTaggedFieldWithWriteBarrier: case Opcode::kStoreTaggedFieldWithWriteBarrier:
case Opcode::kLoadNamedGeneric: case Opcode::kLoadNamedGeneric:
case Opcode::kToNumberOrNumeric:
case Opcode::kThrowIfNotSuperConstructor: case Opcode::kThrowIfNotSuperConstructor:
case Opcode::kToName:
case Opcode::kToNumberOrNumeric:
case Opcode::kToObject:
case Opcode::kToString:
DCHECK_EQ(node->input_count(), 2); DCHECK_EQ(node->input_count(), 2);
CheckValueInputIs(node, 0, ValueRepresentation::kTagged); CheckValueInputIs(node, 0, ValueRepresentation::kTagged);
CheckValueInputIs(node, 1, ValueRepresentation::kTagged); CheckValueInputIs(node, 1, ValueRepresentation::kTagged);
......
...@@ -31,7 +31,7 @@ namespace v8 { ...@@ -31,7 +31,7 @@ namespace v8 {
namespace internal { namespace internal {
namespace maglev { namespace maglev {
const char* ToString(Opcode opcode) { const char* OpcodeToString(Opcode opcode) {
#define DEF_NAME(Name) #Name, #define DEF_NAME(Name) #Name,
static constexpr const char* const names[] = {NODE_BASE_LIST(DEF_NAME)}; static constexpr const char* const names[] = {NODE_BASE_LIST(DEF_NAME)};
#undef DEF_NAME #undef DEF_NAME
...@@ -2293,6 +2293,23 @@ void TestTypeOf::GenerateCode(MaglevCodeGenState* code_gen_state, ...@@ -2293,6 +2293,23 @@ void TestTypeOf::GenerateCode(MaglevCodeGenState* code_gen_state,
__ bind(&done); __ 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) { void ToNumberOrNumeric::AllocateVreg(MaglevVregAllocationState* vreg_state) {
using D = TypeConversionDescriptor; using D = TypeConversionDescriptor;
UseFixed(context(), kContextRegister); UseFixed(context(), kContextRegister);
...@@ -2312,6 +2329,60 @@ void ToNumberOrNumeric::GenerateCode(MaglevCodeGenState* code_gen_state, ...@@ -2312,6 +2329,60 @@ void ToNumberOrNumeric::GenerateCode(MaglevCodeGenState* code_gen_state,
code_gen_state->DefineLazyDeoptPoint(lazy_deopt_info()); 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) { void ChangeInt32ToFloat64::AllocateVreg(MaglevVregAllocationState* vreg_state) {
UseRegister(input()); UseRegister(input());
DefineAsRegister(vreg_state, this); DefineAsRegister(vreg_state, this);
......
...@@ -156,7 +156,10 @@ class CompactInterpreterFrameState; ...@@ -156,7 +156,10 @@ class CompactInterpreterFrameState;
V(TestInstanceOf) \ V(TestInstanceOf) \
V(TestUndetectable) \ V(TestUndetectable) \
V(TestTypeOf) \ V(TestTypeOf) \
V(ToName) \
V(ToNumberOrNumeric) \ V(ToNumberOrNumeric) \
V(ToObject) \
V(ToString) \
CONSTANT_VALUE_NODE_LIST(V) \ CONSTANT_VALUE_NODE_LIST(V) \
INT32_OPERATIONS_NODE_LIST(V) \ INT32_OPERATIONS_NODE_LIST(V) \
FLOAT64_OPERATIONS_NODE_LIST(V) \ FLOAT64_OPERATIONS_NODE_LIST(V) \
...@@ -218,9 +221,9 @@ static constexpr Opcode kFirstOpcode = static_cast<Opcode>(0); ...@@ -218,9 +221,9 @@ static constexpr Opcode kFirstOpcode = static_cast<Opcode>(0);
static constexpr Opcode kLastOpcode = static_cast<Opcode>(kOpcodeCount - 1); static constexpr Opcode kLastOpcode = static_cast<Opcode>(kOpcodeCount - 1);
#undef PLUS_ONE #undef PLUS_ONE
const char* ToString(Opcode opcode); const char* OpcodeToString(Opcode opcode);
inline std::ostream& operator<<(std::ostream& os, 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, #define V(Name) Opcode::k##Name,
...@@ -1658,6 +1661,23 @@ class TestTypeOf : public FixedInputValueNodeT<1, TestTypeOf> { ...@@ -1658,6 +1661,23 @@ class TestTypeOf : public FixedInputValueNodeT<1, TestTypeOf> {
interpreter::TestTypeOfFlags::LiteralFlag literal_; 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> { class ToNumberOrNumeric : public FixedInputValueNodeT<2, ToNumberOrNumeric> {
using Base = FixedInputValueNodeT<2, ToNumberOrNumeric>; using Base = FixedInputValueNodeT<2, ToNumberOrNumeric>;
...@@ -1705,6 +1725,39 @@ class HasProperty : public FixedInputValueNodeT<3, HasProperty> { ...@@ -1705,6 +1725,39 @@ class HasProperty : public FixedInputValueNodeT<3, HasProperty> {
const compiler::FeedbackSource feedback_; 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> { class InitialValue : public FixedInputValueNodeT<0, InitialValue> {
using Base = 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