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