Commit 8a809501 authored by bmeurer's avatar bmeurer Committed by Commit bot

[compiler] Introduce code stubs for abstract equality.

Add EqualStub and NotEqualStub, based on the CodeStubAssembler, and hook
them up with TurboFan and Ignition. The stubs are a full implementation
of abstract equality for ES6 plus the current SIMD.js draft, unlike the
generic version of the CompareIC, which only implements a subset with
funky runtime fallbacks.

Drive-by-fix: Introduce some common helper methods.

R=epertoso@chromium.org
BUG=chromium:592690
LOG=n

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

Cr-Commit-Position: refs/heads/master@{#34806}
parent 2d9c29cc
...@@ -218,6 +218,18 @@ Callable CodeFactory::GreaterThanOrEqual(Isolate* isolate) { ...@@ -218,6 +218,18 @@ Callable CodeFactory::GreaterThanOrEqual(Isolate* isolate) {
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor()); return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
} }
// static
Callable CodeFactory::Equal(Isolate* isolate) {
EqualStub stub(isolate);
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
}
// static
Callable CodeFactory::NotEqual(Isolate* isolate) {
NotEqualStub stub(isolate);
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
}
// static // static
Callable CodeFactory::StrictEqual(Isolate* isolate) { Callable CodeFactory::StrictEqual(Isolate* isolate) {
StrictEqualStub stub(isolate); StrictEqualStub stub(isolate);
......
...@@ -79,6 +79,8 @@ class CodeFactory final { ...@@ -79,6 +79,8 @@ class CodeFactory final {
static Callable LessThanOrEqual(Isolate* isolate); static Callable LessThanOrEqual(Isolate* isolate);
static Callable GreaterThan(Isolate* isolate); static Callable GreaterThan(Isolate* isolate);
static Callable GreaterThanOrEqual(Isolate* isolate); static Callable GreaterThanOrEqual(Isolate* isolate);
static Callable Equal(Isolate* isolate);
static Callable NotEqual(Isolate* isolate);
static Callable StrictEqual(Isolate* isolate); static Callable StrictEqual(Isolate* isolate);
static Callable StrictNotEqual(Isolate* isolate); static Callable StrictNotEqual(Isolate* isolate);
......
This diff is collapsed.
...@@ -103,6 +103,8 @@ namespace internal { ...@@ -103,6 +103,8 @@ namespace internal {
V(LessThanOrEqual) \ V(LessThanOrEqual) \
V(GreaterThan) \ V(GreaterThan) \
V(GreaterThanOrEqual) \ V(GreaterThanOrEqual) \
V(Equal) \
V(NotEqual) \
V(StrictEqual) \ V(StrictEqual) \
V(StrictNotEqual) \ V(StrictNotEqual) \
V(StringEqual) \ V(StringEqual) \
...@@ -684,6 +686,22 @@ class GreaterThanOrEqualStub final : public TurboFanCodeStub { ...@@ -684,6 +686,22 @@ class GreaterThanOrEqualStub final : public TurboFanCodeStub {
DEFINE_TURBOFAN_CODE_STUB(GreaterThanOrEqual, TurboFanCodeStub); DEFINE_TURBOFAN_CODE_STUB(GreaterThanOrEqual, TurboFanCodeStub);
}; };
class EqualStub final : public TurboFanCodeStub {
public:
explicit EqualStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
DEFINE_TURBOFAN_CODE_STUB(Equal, TurboFanCodeStub);
};
class NotEqualStub final : public TurboFanCodeStub {
public:
explicit NotEqualStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
DEFINE_TURBOFAN_CODE_STUB(NotEqual, TurboFanCodeStub);
};
class StrictEqualStub final : public TurboFanCodeStub { class StrictEqualStub final : public TurboFanCodeStub {
public: public:
explicit StrictEqualStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} explicit StrictEqualStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
......
...@@ -105,6 +105,10 @@ Node* CodeStubAssembler::Float64Constant(double value) { ...@@ -105,6 +105,10 @@ Node* CodeStubAssembler::Float64Constant(double value) {
return raw_assembler_->Float64Constant(value); return raw_assembler_->Float64Constant(value);
} }
Node* CodeStubAssembler::BooleanMapConstant() {
return HeapConstant(isolate()->factory()->boolean_map());
}
Node* CodeStubAssembler::HeapNumberMapConstant() { Node* CodeStubAssembler::HeapNumberMapConstant() {
return HeapConstant(isolate()->factory()->heap_number_map()); return HeapConstant(isolate()->factory()->heap_number_map());
} }
...@@ -222,6 +226,11 @@ Node* CodeStubAssembler::LoadHeapNumberValue(Node* object) { ...@@ -222,6 +226,11 @@ Node* CodeStubAssembler::LoadHeapNumberValue(Node* object) {
IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag)); IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag));
} }
Node* CodeStubAssembler::LoadMapBitField(Node* map) {
return Load(MachineType::Uint8(), map,
IntPtrConstant(Map::kBitFieldOffset - kHeapObjectTag));
}
Node* CodeStubAssembler::LoadMapInstanceType(Node* map) { Node* CodeStubAssembler::LoadMapInstanceType(Node* map) {
return Load(MachineType::Uint8(), map, return Load(MachineType::Uint8(), map,
IntPtrConstant(Map::kInstanceTypeOffset - kHeapObjectTag)); IntPtrConstant(Map::kInstanceTypeOffset - kHeapObjectTag));
...@@ -429,8 +438,12 @@ Node* CodeStubAssembler::Projection(int index, Node* value) { ...@@ -429,8 +438,12 @@ Node* CodeStubAssembler::Projection(int index, Node* value) {
return raw_assembler_->Projection(index, value); return raw_assembler_->Projection(index, value);
} }
Node* CodeStubAssembler::LoadMap(Node* object) {
return LoadObjectField(object, HeapObject::kMapOffset);
}
Node* CodeStubAssembler::LoadInstanceType(Node* object) { Node* CodeStubAssembler::LoadInstanceType(Node* object) {
return LoadMapInstanceType(LoadObjectField(object, HeapObject::kMapOffset)); return LoadMapInstanceType(LoadMap(object));
} }
Node* CodeStubAssembler::BitFieldDecode(Node* word32, uint32_t shift, Node* CodeStubAssembler::BitFieldDecode(Node* word32, uint32_t shift,
...@@ -527,6 +540,16 @@ void CodeStubAssembler::BranchIfFloat64GreaterThanOrEqual(Node* a, Node* b, ...@@ -527,6 +540,16 @@ void CodeStubAssembler::BranchIfFloat64GreaterThanOrEqual(Node* a, Node* b,
Goto(if_false); Goto(if_false);
} }
void CodeStubAssembler::BranchIfWord32Equal(Node* a, Node* b, Label* if_true,
Label* if_false) {
Label if_equal(this), if_notequal(this);
Branch(Word32Equal(a, b), &if_equal, &if_notequal);
Bind(&if_equal);
Goto(if_true);
Bind(&if_notequal);
Goto(if_false);
}
Node* CodeStubAssembler::CallN(CallDescriptor* descriptor, Node* code_target, Node* CodeStubAssembler::CallN(CallDescriptor* descriptor, Node* code_target,
Node** args) { Node** args) {
CallPrologue(); CallPrologue();
......
...@@ -36,6 +36,11 @@ class RawMachineLabel; ...@@ -36,6 +36,11 @@ class RawMachineLabel;
class Schedule; class Schedule;
#define CODE_STUB_ASSEMBLER_BINARY_OP_LIST(V) \ #define CODE_STUB_ASSEMBLER_BINARY_OP_LIST(V) \
V(Float32Equal) \
V(Float32LessThan) \
V(Float32LessThanOrEqual) \
V(Float32GreaterThan) \
V(Float32GreaterThanOrEqual) \
V(Float64Equal) \ V(Float64Equal) \
V(Float64LessThan) \ V(Float64LessThan) \
V(Float64LessThanOrEqual) \ V(Float64LessThanOrEqual) \
...@@ -141,6 +146,7 @@ class CodeStubAssembler { ...@@ -141,6 +146,7 @@ class CodeStubAssembler {
Node* BooleanConstant(bool value); Node* BooleanConstant(bool value);
Node* ExternalConstant(ExternalReference address); Node* ExternalConstant(ExternalReference address);
Node* Float64Constant(double value); Node* Float64Constant(double value);
Node* BooleanMapConstant();
Node* HeapNumberMapConstant(); Node* HeapNumberMapConstant();
Node* Parameter(int value); Node* Parameter(int value);
...@@ -267,6 +273,8 @@ class CodeStubAssembler { ...@@ -267,6 +273,8 @@ class CodeStubAssembler {
Node* LoadObjectField(Node* object, int offset); Node* LoadObjectField(Node* object, int offset);
// Load the floating point value of a HeapNumber. // Load the floating point value of a HeapNumber.
Node* LoadHeapNumberValue(Node* object); Node* LoadHeapNumberValue(Node* object);
// Load the bit field of a Map.
Node* LoadMapBitField(Node* map);
// Load the instance type of a Map. // Load the instance type of a Map.
Node* LoadMapInstanceType(Node* map); Node* LoadMapInstanceType(Node* map);
...@@ -281,6 +289,9 @@ class CodeStubAssembler { ...@@ -281,6 +289,9 @@ class CodeStubAssembler {
// Store an array element to a FixedArray. // Store an array element to a FixedArray.
Node* StoreFixedArrayElementNoWriteBarrier(Node* object, Node* index, Node* StoreFixedArrayElementNoWriteBarrier(Node* object, Node* index,
Node* value); Node* value);
// Load the Map of an HeapObject.
Node* LoadMap(Node* object);
// Load the instance type of an HeapObject.
Node* LoadInstanceType(Node* object); Node* LoadInstanceType(Node* object);
// Returns a node that is true if the given bit is set in |word32|. // Returns a node that is true if the given bit is set in |word32|.
...@@ -309,6 +320,7 @@ class CodeStubAssembler { ...@@ -309,6 +320,7 @@ class CodeStubAssembler {
void BranchIfFloat64IsNaN(Node* value, Label* if_true, Label* if_false) { void BranchIfFloat64IsNaN(Node* value, Label* if_true, Label* if_false) {
BranchIfFloat64Equal(value, value, if_false, if_true); BranchIfFloat64Equal(value, value, if_false, if_true);
} }
void BranchIfWord32Equal(Node* a, Node* b, Label* if_true, Label* if_false);
// Helpers which delegate to RawMachineAssembler. // Helpers which delegate to RawMachineAssembler.
Factory* factory() const; Factory* factory() const;
......
...@@ -87,8 +87,6 @@ REPLACE_BINARY_OP_IC_CALL(JSModulus, Token::MOD) ...@@ -87,8 +87,6 @@ REPLACE_BINARY_OP_IC_CALL(JSModulus, Token::MOD)
void JSGenericLowering::Lower##op(Node* node) { \ void JSGenericLowering::Lower##op(Node* node) { \
ReplaceWithRuntimeCall(node, fun); \ ReplaceWithRuntimeCall(node, fun); \
} }
REPLACE_RUNTIME_CALL(JSEqual, Runtime::kEqual)
REPLACE_RUNTIME_CALL(JSNotEqual, Runtime::kNotEqual)
REPLACE_RUNTIME_CALL(JSCreateWithContext, Runtime::kPushWithContext) REPLACE_RUNTIME_CALL(JSCreateWithContext, Runtime::kPushWithContext)
REPLACE_RUNTIME_CALL(JSCreateModuleContext, Runtime::kPushModuleContext) REPLACE_RUNTIME_CALL(JSCreateModuleContext, Runtime::kPushModuleContext)
REPLACE_RUNTIME_CALL(JSConvertReceiver, Runtime::kConvertReceiver) REPLACE_RUNTIME_CALL(JSConvertReceiver, Runtime::kConvertReceiver)
...@@ -104,6 +102,8 @@ REPLACE_STUB_CALL(LessThan) ...@@ -104,6 +102,8 @@ REPLACE_STUB_CALL(LessThan)
REPLACE_STUB_CALL(LessThanOrEqual) REPLACE_STUB_CALL(LessThanOrEqual)
REPLACE_STUB_CALL(GreaterThan) REPLACE_STUB_CALL(GreaterThan)
REPLACE_STUB_CALL(GreaterThanOrEqual) REPLACE_STUB_CALL(GreaterThanOrEqual)
REPLACE_STUB_CALL(Equal)
REPLACE_STUB_CALL(NotEqual)
REPLACE_STUB_CALL(StrictEqual) REPLACE_STUB_CALL(StrictEqual)
REPLACE_STUB_CALL(StrictNotEqual) REPLACE_STUB_CALL(StrictNotEqual)
#undef REPLACE_STUB_CALL #undef REPLACE_STUB_CALL
......
...@@ -1176,7 +1176,7 @@ void Interpreter::DoNewWide(InterpreterAssembler* assembler) { ...@@ -1176,7 +1176,7 @@ void Interpreter::DoNewWide(InterpreterAssembler* assembler) {
// //
// Test if the value in the <src> register equals the accumulator. // Test if the value in the <src> register equals the accumulator.
void Interpreter::DoTestEqual(InterpreterAssembler* assembler) { void Interpreter::DoTestEqual(InterpreterAssembler* assembler) {
DoBinaryOp(Runtime::kEqual, assembler); DoBinaryOp(CodeFactory::Equal(isolate_), assembler);
} }
...@@ -1184,7 +1184,7 @@ void Interpreter::DoTestEqual(InterpreterAssembler* assembler) { ...@@ -1184,7 +1184,7 @@ void Interpreter::DoTestEqual(InterpreterAssembler* assembler) {
// //
// Test if the value in the <src> register is not equal to the accumulator. // Test if the value in the <src> register is not equal to the accumulator.
void Interpreter::DoTestNotEqual(InterpreterAssembler* assembler) { void Interpreter::DoTestNotEqual(InterpreterAssembler* assembler) {
DoBinaryOp(Runtime::kNotEqual, assembler); DoBinaryOp(CodeFactory::NotEqual(isolate_), assembler);
} }
......
...@@ -285,6 +285,10 @@ Maybe<ComparisonResult> Object::Compare(Handle<Object> x, Handle<Object> y) { ...@@ -285,6 +285,10 @@ Maybe<ComparisonResult> Object::Compare(Handle<Object> x, Handle<Object> y) {
// static // static
Maybe<bool> Object::Equals(Handle<Object> x, Handle<Object> y) { Maybe<bool> Object::Equals(Handle<Object> x, Handle<Object> y) {
// This is the generic version of Abstract Equality Comparison; a version in
// JavaScript land is available in the EqualStub and NotEqualStub. Whenever
// you change something functionality wise in here, remember to update the
// TurboFan code stubs as well.
while (true) { while (true) {
if (x->IsNumber()) { if (x->IsNumber()) {
if (y->IsNumber()) { if (y->IsNumber()) {
......
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