Commit 55b4df73 authored by bmeurer's avatar bmeurer Committed by Commit bot

[runtime] Unify comparison operator runtime entries.

Only use one set of %StrictEquals/%StrictNotEquals and
%Equals/%NotEquals runtime entries for both the interpreter
and the old-style CompareICStub. The long-term plan is to
update the CompareICStub to also return boolean values, and
even allow some more code sharing with the interpreter there.

R=mstarzinger@chromium.org

Review URL: https://codereview.chromium.org/1738883002

Cr-Commit-Position: refs/heads/master@{#34303}
parent 01b8fc89
......@@ -671,11 +671,19 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
__ bind(&slow);
__ Push(lhs, rhs);
// Figure out which native to call and setup the arguments.
if (cc == eq) {
__ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals);
{
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
__ Push(lhs, rhs);
__ CallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals);
}
// Turn true into 0 and false into some non-zero value.
STATIC_ASSERT(EQUAL == 0);
__ LoadRoot(r1, Heap::kTrueValueRootIndex);
__ sub(r0, r0, r1);
__ Ret();
} else {
__ Push(lhs, rhs);
int ncr; // NaN compare result
if (cc == lt || cc == le) {
ncr = GREATER;
......
......@@ -628,11 +628,19 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
__ Bind(&slow);
__ Push(lhs, rhs);
// Figure out which native to call and setup the arguments.
if (cond == eq) {
__ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals);
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(lhs, rhs);
__ CallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals);
}
// Turn true into 0 and false into some non-zero value.
STATIC_ASSERT(EQUAL == 0);
__ LoadRoot(x1, Heap::kTrueValueRootIndex);
__ Sub(x0, x0, x1);
__ Ret();
} else {
__ Push(lhs, rhs);
int ncr; // NaN compare result
if ((cond == lt) || (cond == le)) {
ncr = GREATER;
......
......@@ -1442,21 +1442,24 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
}
__ bind(&runtime_call);
// Push arguments below the return address.
__ pop(ecx);
__ push(edx);
__ push(eax);
// Figure out which native to call and setup the arguments.
if (cc == equal) {
__ push(ecx);
__ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals);
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(edx);
__ Push(eax);
__ CallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals);
}
// Turn true into 0 and false into some non-zero value.
STATIC_ASSERT(EQUAL == 0);
__ sub(eax, Immediate(isolate()->factory()->true_value()));
__ Ret();
} else {
// Push arguments below the return address.
__ pop(ecx);
__ push(edx);
__ push(eax);
__ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc))));
// Restore return address on the stack.
__ push(ecx);
// Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
// tagged as a small integer.
__ TailCallRuntime(Runtime::kCompare);
......
......@@ -1144,7 +1144,7 @@ void Interpreter::DoNewWide(InterpreterAssembler* assembler) {
//
// Test if the value in the <src> register equals the accumulator.
void Interpreter::DoTestEqual(InterpreterAssembler* assembler) {
DoBinaryOp(Runtime::kInterpreterEquals, assembler);
DoBinaryOp(Runtime::kEquals, assembler);
}
......@@ -1152,7 +1152,7 @@ void Interpreter::DoTestEqual(InterpreterAssembler* assembler) {
//
// Test if the value in the <src> register is not equal to the accumulator.
void Interpreter::DoTestNotEqual(InterpreterAssembler* assembler) {
DoBinaryOp(Runtime::kInterpreterNotEquals, assembler);
DoBinaryOp(Runtime::kNotEquals, assembler);
}
......@@ -1160,7 +1160,7 @@ void Interpreter::DoTestNotEqual(InterpreterAssembler* assembler) {
//
// Test if the value in the <src> register is strictly equal to the accumulator.
void Interpreter::DoTestEqualStrict(InterpreterAssembler* assembler) {
DoBinaryOp(Runtime::kInterpreterStrictEquals, assembler);
DoBinaryOp(Runtime::kStrictEquals, assembler);
}
......@@ -1169,7 +1169,7 @@ void Interpreter::DoTestEqualStrict(InterpreterAssembler* assembler) {
// Test if the value in the <src> register is not strictly equal to the
// accumulator.
void Interpreter::DoTestNotEqualStrict(InterpreterAssembler* assembler) {
DoBinaryOp(Runtime::kInterpreterStrictNotEquals, assembler);
DoBinaryOp(Runtime::kStrictNotEquals, assembler);
}
......
......@@ -718,13 +718,21 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
// Never falls through to here.
__ bind(&slow);
// Prepare for call to builtin. Push object pointers, a0 (lhs) first,
// a1 (rhs) second.
__ Push(lhs, rhs);
// Figure out which native to call and setup the arguments.
if (cc == eq) {
__ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals);
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(lhs, rhs);
__ CallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals);
}
// Turn true into 0 and false into some non-zero value.
STATIC_ASSERT(EQUAL == 0);
__ LoadRoot(a0, Heap::kTrueValueRootIndex);
__ Ret(USE_DELAY_SLOT);
__ subu(v0, v0, a0); // In delay slot.
} else {
// Prepare for call to builtin. Push object pointers, a0 (lhs) first,
// a1 (rhs) second.
__ Push(lhs, rhs);
int ncr; // NaN compare result.
if (cc == lt || cc == le) {
ncr = GREATER;
......
......@@ -715,13 +715,21 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
// Never falls through to here.
__ bind(&slow);
// Prepare for call to builtin. Push object pointers, a0 (lhs) first,
// a1 (rhs) second.
__ Push(lhs, rhs);
// Figure out which native to call and setup the arguments.
if (cc == eq) {
__ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals);
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(lhs, rhs);
__ CallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals);
}
// Turn true into 0 and false into some non-zero value.
STATIC_ASSERT(EQUAL == 0);
__ LoadRoot(a0, Heap::kTrueValueRootIndex);
__ Ret(USE_DELAY_SLOT);
__ subu(v0, v0, a0); // In delay slot.
} else {
// Prepare for call to builtin. Push object pointers, a0 (lhs) first,
// a1 (rhs) second.
__ Push(lhs, rhs);
int ncr; // NaN compare result.
if (cc == lt || cc == le) {
ncr = GREATER;
......
......@@ -16,35 +16,6 @@
namespace v8 {
namespace internal {
RUNTIME_FUNCTION(Runtime_InterpreterEquals) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
Maybe<bool> result = Object::Equals(x, y);
if (result.IsJust()) {
return isolate->heap()->ToBoolean(result.FromJust());
} else {
return isolate->heap()->exception();
}
}
RUNTIME_FUNCTION(Runtime_InterpreterNotEquals) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
Maybe<bool> result = Object::Equals(x, y);
if (result.IsJust()) {
return isolate->heap()->ToBoolean(!result.FromJust());
} else {
return isolate->heap()->exception();
}
}
RUNTIME_FUNCTION(Runtime_InterpreterLessThan) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
......@@ -101,24 +72,6 @@ RUNTIME_FUNCTION(Runtime_InterpreterGreaterThanOrEqual) {
}
RUNTIME_FUNCTION(Runtime_InterpreterStrictEquals) {
SealHandleScope shs(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_CHECKED(Object, x, 0);
CONVERT_ARG_CHECKED(Object, y, 1);
return isolate->heap()->ToBoolean(x->StrictEquals(y));
}
RUNTIME_FUNCTION(Runtime_InterpreterStrictNotEquals) {
SealHandleScope shs(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_CHECKED(Object, x, 0);
CONVERT_ARG_CHECKED(Object, y, 1);
return isolate->heap()->ToBoolean(!x->StrictEquals(y));
}
RUNTIME_FUNCTION(Runtime_InterpreterToBoolean) {
SealHandleScope shs(isolate);
DCHECK_EQ(1, args.length());
......
......@@ -1073,28 +1073,6 @@ RUNTIME_FUNCTION(Runtime_ToName) {
}
RUNTIME_FUNCTION(Runtime_Equals) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
Maybe<bool> result = Object::Equals(x, y);
if (!result.IsJust()) return isolate->heap()->exception();
// TODO(bmeurer): Change this at some point to return true/false instead.
return Smi::FromInt(result.FromJust() ? EQUAL : NOT_EQUAL);
}
RUNTIME_FUNCTION(Runtime_StrictEquals) {
SealHandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_CHECKED(Object, x, 0);
CONVERT_ARG_CHECKED(Object, y, 1);
// TODO(bmeurer): Change this at some point to return true/false instead.
return Smi::FromInt(x->StrictEquals(y) ? EQUAL : NOT_EQUAL);
}
RUNTIME_FUNCTION(Runtime_SameValue) {
SealHandleScope scope(isolate);
DCHECK_EQ(2, args.length());
......
......@@ -140,5 +140,41 @@ RUNTIME_FUNCTION(Runtime_BitwiseXor) {
return *result;
}
RUNTIME_FUNCTION(Runtime_Equals) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
Maybe<bool> result = Object::Equals(x, y);
if (!result.IsJust()) return isolate->heap()->exception();
return isolate->heap()->ToBoolean(result.FromJust());
}
RUNTIME_FUNCTION(Runtime_NotEquals) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
Maybe<bool> result = Object::Equals(x, y);
if (!result.IsJust()) return isolate->heap()->exception();
return isolate->heap()->ToBoolean(!result.FromJust());
}
RUNTIME_FUNCTION(Runtime_StrictEquals) {
SealHandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_CHECKED(Object, x, 0);
CONVERT_ARG_CHECKED(Object, y, 1);
return isolate->heap()->ToBoolean(x->StrictEquals(y));
}
RUNTIME_FUNCTION(Runtime_StrictNotEquals) {
SealHandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_CHECKED(Object, x, 0);
CONVERT_ARG_CHECKED(Object, y, 1);
return isolate->heap()->ToBoolean(!x->StrictEquals(y));
}
} // namespace internal
} // namespace v8
......@@ -206,10 +206,6 @@ namespace internal {
F(ForInStep, 1, 1)
#define FOR_EACH_INTRINSIC_INTERPRETER(F) \
F(InterpreterEquals, 2, 1) \
F(InterpreterNotEquals, 2, 1) \
F(InterpreterStrictEquals, 2, 1) \
F(InterpreterStrictNotEquals, 2, 1) \
F(InterpreterLessThan, 2, 1) \
F(InterpreterGreaterThan, 2, 1) \
F(InterpreterLessThanOrEqual, 2, 1) \
......@@ -455,8 +451,6 @@ namespace internal {
F(ToLength, 1, 1) \
F(ToString, 1, 1) \
F(ToName, 1, 1) \
F(Equals, 2, 1) \
F(StrictEquals, 2, 1) \
F(SameValue, 2, 1) \
F(SameValueZero, 2, 1) \
F(Compare, 3, 1) \
......@@ -491,7 +485,11 @@ namespace internal {
F(ShiftRightLogical, 2, 1) \
F(BitwiseAnd, 2, 1) \
F(BitwiseOr, 2, 1) \
F(BitwiseXor, 2, 1)
F(BitwiseXor, 2, 1) \
F(Equals, 2, 1) \
F(NotEquals, 2, 1) \
F(StrictEquals, 2, 1) \
F(StrictNotEquals, 2, 1)
#define FOR_EACH_INTRINSIC_PROXY(F) \
F(IsJSProxy, 1, 1) \
......
......@@ -1320,16 +1320,23 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
}
__ bind(&runtime_call);
// Push arguments below the return address to prepare jump to builtin.
__ PopReturnAddressTo(rcx);
__ Push(rdx);
__ Push(rax);
// Figure out which native to call and setup the arguments.
if (cc == equal) {
__ PushReturnAddressFrom(rcx);
__ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals);
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(rdx);
__ Push(rax);
__ CallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals);
}
// Turn true into 0 and false into some non-zero value.
STATIC_ASSERT(EQUAL == 0);
__ LoadRoot(rdx, Heap::kTrueValueRootIndex);
__ subp(rax, rdx);
__ Ret();
} else {
// Push arguments below the return address to prepare jump to builtin.
__ PopReturnAddressTo(rcx);
__ Push(rdx);
__ Push(rax);
__ Push(Smi::FromInt(NegativeComparisonResult(cc)));
__ PushReturnAddressFrom(rcx);
__ TailCallRuntime(Runtime::kCompare);
......
......@@ -77,10 +77,6 @@ TEST_F(RuntimeInterpreterTest, TestOperatorsWithIntegers) {
TRACED_FOREACH(int, rhs, inputs) {
#define INTEGER_OPERATOR_CHECK(r, op, x, y) \
CHECK(TestOperator(Runtime_Interpreter##r, x, y, x op y))
INTEGER_OPERATOR_CHECK(Equals, ==, lhs, rhs);
INTEGER_OPERATOR_CHECK(NotEquals, !=, lhs, rhs);
INTEGER_OPERATOR_CHECK(StrictEquals, ==, lhs, rhs);
INTEGER_OPERATOR_CHECK(StrictNotEquals, !=, lhs, rhs);
INTEGER_OPERATOR_CHECK(LessThan, <, lhs, rhs);
INTEGER_OPERATOR_CHECK(GreaterThan, >, lhs, rhs);
INTEGER_OPERATOR_CHECK(LessThanOrEqual, <=, lhs, rhs);
......@@ -102,10 +98,6 @@ TEST_F(RuntimeInterpreterTest, TestOperatorsWithDoubles) {
TRACED_FOREACH(double, rhs, inputs) {
#define DOUBLE_OPERATOR_CHECK(r, op, x, y) \
CHECK(TestOperator(Runtime_Interpreter##r, x, y, x op y))
DOUBLE_OPERATOR_CHECK(Equals, ==, lhs, rhs);
DOUBLE_OPERATOR_CHECK(NotEquals, !=, lhs, rhs);
DOUBLE_OPERATOR_CHECK(StrictEquals, ==, lhs, rhs);
DOUBLE_OPERATOR_CHECK(StrictNotEquals, !=, lhs, rhs);
DOUBLE_OPERATOR_CHECK(LessThan, <, lhs, rhs);
DOUBLE_OPERATOR_CHECK(GreaterThan, >, lhs, rhs);
DOUBLE_OPERATOR_CHECK(LessThanOrEqual, <=, lhs, rhs);
......@@ -123,10 +115,6 @@ TEST_F(RuntimeInterpreterTest, TestOperatorsWithString) {
#define STRING_OPERATOR_CHECK(r, op, x, y) \
CHECK(TestOperator(Runtime_Interpreter##r, x, y, \
std::string(x) op std::string(y)))
STRING_OPERATOR_CHECK(Equals, ==, lhs, rhs);
STRING_OPERATOR_CHECK(NotEquals, !=, lhs, rhs);
STRING_OPERATOR_CHECK(StrictEquals, ==, lhs, rhs);
STRING_OPERATOR_CHECK(StrictNotEquals, !=, lhs, rhs);
STRING_OPERATOR_CHECK(LessThan, <, lhs, rhs);
STRING_OPERATOR_CHECK(GreaterThan, >, lhs, rhs);
STRING_OPERATOR_CHECK(LessThanOrEqual, <=, lhs, rhs);
......
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