Commit ca6d0b1e authored by bmeurer's avatar bmeurer Committed by Commit bot

[compiler] Introduce proper StrictNotEqualStub.

Generalize the code that we have for StrictEqualStub to also general a
StrictNotEqualStub and hook that up with TurboFan and Ignition. It's
still falling back to the runtime for every String (in)equality check.

R=yangguo@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#34426}
parent 94f0abf9
......@@ -200,6 +200,12 @@ Callable CodeFactory::StrictEqual(Isolate* isolate) {
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
}
// static
Callable CodeFactory::StrictNotEqual(Isolate* isolate) {
StrictNotEqualStub stub(isolate);
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
}
// static
Callable CodeFactory::StringAdd(Isolate* isolate, StringAddFlags flags,
PretenureFlag pretenure_flag) {
......
......@@ -76,6 +76,7 @@ class CodeFactory final {
static Callable RegExpExec(Isolate* isolate);
static Callable StrictEqual(Isolate* isolate);
static Callable StrictNotEqual(Isolate* isolate);
static Callable StringAdd(Isolate* isolate, StringAddFlags flags,
PretenureFlag pretenure_flag);
......
......@@ -498,9 +498,14 @@ void StringLengthStub::GenerateAssembly(
assembler->Return(result);
}
void StrictEqualStub::GenerateAssembly(
compiler::CodeStubAssembler* assembler) const {
// Here's pseudo-code for the algorithm below:
namespace {
enum StrictEqualMode { kStrictEqual, kStrictNotEqual };
void GenerateStrictEqual(compiler::CodeStubAssembler* assembler,
StrictEqualMode mode) {
// Here's pseudo-code for the algorithm below in case of kStrictEqual mode;
// for kStrictNotEqual mode we properly negate the result.
//
// if (lhs == rhs) {
// if (lhs->IsHeapNumber()) return HeapNumber::cast(lhs)->value() != NaN;
......@@ -554,7 +559,7 @@ void StrictEqualStub::GenerateAssembly(
Node* rhs = assembler->Parameter(1);
Node* context = assembler->Parameter(2);
Label if_true(assembler), if_false(assembler);
Label if_equal(assembler), if_notequal(assembler);
// Check if {lhs} and {rhs} refer to the same object.
Label if_same(assembler), if_notsame(assembler);
......@@ -588,15 +593,15 @@ void StrictEqualStub::GenerateAssembly(
Node* lhs_value = assembler->LoadHeapNumberValue(lhs);
// Check if the HeapNumber value is a NaN.
assembler->BranchIfFloat64IsNaN(lhs_value, &if_false, &if_true);
assembler->BranchIfFloat64IsNaN(lhs_value, &if_notequal, &if_equal);
}
assembler->Bind(&if_lhsisnotnumber);
assembler->Goto(&if_true);
assembler->Goto(&if_equal);
}
assembler->Bind(&if_lhsissmi);
assembler->Goto(&if_true);
assembler->Goto(&if_equal);
}
assembler->Bind(&if_notsame);
......@@ -633,8 +638,8 @@ void StrictEqualStub::GenerateAssembly(
Node* rhs_value = assembler->SmiToFloat64(rhs);
// Perform a floating point comparison of {lhs} and {rhs}.
assembler->BranchIfFloat64Equal(lhs_value, rhs_value, &if_true,
&if_false);
assembler->BranchIfFloat64Equal(lhs_value, rhs_value, &if_equal,
&if_notequal);
}
assembler->Bind(&if_rhsisnotsmi);
......@@ -655,12 +660,12 @@ void StrictEqualStub::GenerateAssembly(
Node* rhs_value = assembler->LoadHeapNumberValue(rhs);
// Perform a floating point comparison of {lhs} and {rhs}.
assembler->BranchIfFloat64Equal(lhs_value, rhs_value, &if_true,
&if_false);
assembler->BranchIfFloat64Equal(lhs_value, rhs_value, &if_equal,
&if_notequal);
}
assembler->Bind(&if_rhsisnotnumber);
assembler->Goto(&if_false);
assembler->Goto(&if_notequal);
}
}
......@@ -672,7 +677,7 @@ void StrictEqualStub::GenerateAssembly(
&if_rhsisnotsmi);
assembler->Bind(&if_rhsissmi);
assembler->Goto(&if_false);
assembler->Goto(&if_notequal);
assembler->Bind(&if_rhsisnotsmi);
{
......@@ -702,12 +707,14 @@ void StrictEqualStub::GenerateAssembly(
{
// TODO(bmeurer): Optimize this further once the StringEqual
// functionality is available in TurboFan land.
assembler->TailCallRuntime(Runtime::kStringEqual, context, lhs,
rhs);
Runtime::FunctionId function_id = (mode == kStrictEqual)
? Runtime::kStringEqual
: Runtime::kStringNotEqual;
assembler->TailCallRuntime(function_id, context, lhs, rhs);
}
assembler->Bind(&if_rhsisnotstring);
assembler->Goto(&if_false);
assembler->Goto(&if_notequal);
}
assembler->Bind(&if_lhsisnotstring);
......@@ -723,12 +730,14 @@ void StrictEqualStub::GenerateAssembly(
assembler->Bind(&if_lhsissimd128value);
{
// TODO(bmeurer): Inline the Simd128Value equality check.
assembler->TailCallRuntime(Runtime::kStrictEqual, context, lhs,
rhs);
Runtime::FunctionId function_id = (mode == kStrictEqual)
? Runtime::kStrictEqual
: Runtime::kStrictNotEqual;
assembler->TailCallRuntime(function_id, context, lhs, rhs);
}
assembler->Bind(&if_lhsisnotsimd128value);
assembler->Goto(&if_false);
assembler->Goto(&if_notequal);
}
}
}
......@@ -746,7 +755,7 @@ void StrictEqualStub::GenerateAssembly(
&if_rhsisnotsmi);
assembler->Bind(&if_rhsissmi);
assembler->Goto(&if_false);
assembler->Goto(&if_notequal);
assembler->Bind(&if_rhsisnotsmi);
{
......@@ -765,21 +774,33 @@ void StrictEqualStub::GenerateAssembly(
Node* rhs_value = assembler->LoadHeapNumberValue(rhs);
// Perform a floating point comparison of {lhs} and {rhs}.
assembler->BranchIfFloat64Equal(lhs_value, rhs_value, &if_true,
&if_false);
assembler->BranchIfFloat64Equal(lhs_value, rhs_value, &if_equal,
&if_notequal);
}
assembler->Bind(&if_rhsisnotnumber);
assembler->Goto(&if_false);
assembler->Goto(&if_notequal);
}
}
}
assembler->Bind(&if_true);
assembler->Return(assembler->BooleanConstant(true));
assembler->Bind(&if_equal);
assembler->Return(assembler->BooleanConstant(mode == kStrictEqual));
assembler->Bind(&if_notequal);
assembler->Return(assembler->BooleanConstant(mode == kStrictNotEqual));
}
} // namespace
void StrictEqualStub::GenerateAssembly(
compiler::CodeStubAssembler* assembler) const {
GenerateStrictEqual(assembler, kStrictEqual);
}
assembler->Bind(&if_false);
assembler->Return(assembler->BooleanConstant(false));
void StrictNotEqualStub::GenerateAssembly(
compiler::CodeStubAssembler* assembler) const {
GenerateStrictEqual(assembler, kStrictNotEqual);
}
void ToBooleanStub::GenerateAssembly(
......
......@@ -102,6 +102,7 @@ namespace internal {
V(AllocateMutableHeapNumber) \
V(StringLength) \
V(StrictEqual) \
V(StrictNotEqual) \
V(ToBoolean) \
/* IC Handler stubs */ \
V(ArrayBufferViewLoadField) \
......@@ -642,6 +643,16 @@ class StrictEqualStub final : public TurboFanCodeStub {
DEFINE_CODE_STUB(StrictEqual, TurboFanCodeStub);
};
class StrictNotEqualStub final : public TurboFanCodeStub {
public:
explicit StrictNotEqualStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
void GenerateAssembly(compiler::CodeStubAssembler* assembler) const final;
DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
DEFINE_CODE_STUB(StrictNotEqual, TurboFanCodeStub);
};
class ToBooleanStub final : public TurboFanCodeStub {
public:
explicit ToBooleanStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
......
......@@ -89,7 +89,6 @@ REPLACE_BINARY_OP_IC_CALL(JSModulus, Token::MOD)
}
REPLACE_RUNTIME_CALL(JSEqual, Runtime::kEqual)
REPLACE_RUNTIME_CALL(JSNotEqual, Runtime::kNotEqual)
REPLACE_RUNTIME_CALL(JSStrictNotEqual, Runtime::kStrictNotEqual)
REPLACE_RUNTIME_CALL(JSLessThan, Runtime::kLessThan)
REPLACE_RUNTIME_CALL(JSGreaterThan, Runtime::kGreaterThan)
REPLACE_RUNTIME_CALL(JSLessThanOrEqual, Runtime::kLessThanOrEqual)
......@@ -99,13 +98,14 @@ REPLACE_RUNTIME_CALL(JSCreateModuleContext, Runtime::kPushModuleContext)
REPLACE_RUNTIME_CALL(JSConvertReceiver, Runtime::kConvertReceiver)
#undef REPLACE_RUNTIME_CALL
#define REPLACE_STUB_CALL(Op, Stub) \
void JSGenericLowering::Lower##Op(Node* node) { \
#define REPLACE_STUB_CALL(Name) \
void JSGenericLowering::LowerJS##Name(Node* node) { \
CallDescriptor::Flags flags = AdjustFrameStatesForCall(node); \
Callable callable = CodeFactory::Stub(isolate()); \
Callable callable = CodeFactory::Name(isolate()); \
ReplaceWithStubCall(node, callable, flags); \
}
REPLACE_STUB_CALL(JSStrictEqual, StrictEqual)
REPLACE_STUB_CALL(StrictEqual)
REPLACE_STUB_CALL(StrictNotEqual)
#undef REPLACE_STUB_CALL
void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable,
......
......@@ -1197,7 +1197,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::kStrictNotEqual, assembler);
DoBinaryOp(CodeFactory::StrictNotEqual(isolate_), assembler);
}
......
......@@ -1153,6 +1153,13 @@ RUNTIME_FUNCTION(Runtime_StringEqual) {
return isolate->heap()->ToBoolean(String::Equals(x, y));
}
RUNTIME_FUNCTION(Runtime_StringNotEqual) {
HandleScope handle_scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(String, x, 0);
CONVERT_ARG_HANDLE_CHECKED(String, y, 1);
return isolate->heap()->ToBoolean(!String::Equals(x, y));
}
RUNTIME_FUNCTION(Runtime_FlattenString) {
HandleScope scope(isolate);
......
......@@ -863,6 +863,7 @@ namespace internal {
F(TruncateString, 2, 1) \
F(NewString, 2, 1) \
F(StringEqual, 2, 1) \
F(StringNotEqual, 2, 1) \
F(FlattenString, 1, 1) \
F(StringCharFromCode, 1, 1) \
F(StringCharAt, 2, 1) \
......
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