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) {
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
Callable CodeFactory::StrictEqual(Isolate* isolate) {
StrictEqualStub stub(isolate);
......
......@@ -79,6 +79,8 @@ class CodeFactory final {
static Callable LessThanOrEqual(Isolate* isolate);
static Callable GreaterThan(Isolate* isolate);
static Callable GreaterThanOrEqual(Isolate* isolate);
static Callable Equal(Isolate* isolate);
static Callable NotEqual(Isolate* isolate);
static Callable StrictEqual(Isolate* isolate);
static Callable StrictNotEqual(Isolate* isolate);
......
This diff is collapsed.
......@@ -103,6 +103,8 @@ namespace internal {
V(LessThanOrEqual) \
V(GreaterThan) \
V(GreaterThanOrEqual) \
V(Equal) \
V(NotEqual) \
V(StrictEqual) \
V(StrictNotEqual) \
V(StringEqual) \
......@@ -684,6 +686,22 @@ class GreaterThanOrEqualStub final : public 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 {
public:
explicit StrictEqualStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
......
......@@ -105,6 +105,10 @@ Node* CodeStubAssembler::Float64Constant(double value) {
return raw_assembler_->Float64Constant(value);
}
Node* CodeStubAssembler::BooleanMapConstant() {
return HeapConstant(isolate()->factory()->boolean_map());
}
Node* CodeStubAssembler::HeapNumberMapConstant() {
return HeapConstant(isolate()->factory()->heap_number_map());
}
......@@ -222,6 +226,11 @@ Node* CodeStubAssembler::LoadHeapNumberValue(Node* object) {
IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag));
}
Node* CodeStubAssembler::LoadMapBitField(Node* map) {
return Load(MachineType::Uint8(), map,
IntPtrConstant(Map::kBitFieldOffset - kHeapObjectTag));
}
Node* CodeStubAssembler::LoadMapInstanceType(Node* map) {
return Load(MachineType::Uint8(), map,
IntPtrConstant(Map::kInstanceTypeOffset - kHeapObjectTag));
......@@ -429,8 +438,12 @@ Node* CodeStubAssembler::Projection(int index, Node* value) {
return raw_assembler_->Projection(index, value);
}
Node* CodeStubAssembler::LoadMap(Node* object) {
return LoadObjectField(object, HeapObject::kMapOffset);
}
Node* CodeStubAssembler::LoadInstanceType(Node* object) {
return LoadMapInstanceType(LoadObjectField(object, HeapObject::kMapOffset));
return LoadMapInstanceType(LoadMap(object));
}
Node* CodeStubAssembler::BitFieldDecode(Node* word32, uint32_t shift,
......@@ -527,6 +540,16 @@ void CodeStubAssembler::BranchIfFloat64GreaterThanOrEqual(Node* a, Node* b,
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** args) {
CallPrologue();
......
......@@ -36,6 +36,11 @@ class RawMachineLabel;
class Schedule;
#define CODE_STUB_ASSEMBLER_BINARY_OP_LIST(V) \
V(Float32Equal) \
V(Float32LessThan) \
V(Float32LessThanOrEqual) \
V(Float32GreaterThan) \
V(Float32GreaterThanOrEqual) \
V(Float64Equal) \
V(Float64LessThan) \
V(Float64LessThanOrEqual) \
......@@ -141,6 +146,7 @@ class CodeStubAssembler {
Node* BooleanConstant(bool value);
Node* ExternalConstant(ExternalReference address);
Node* Float64Constant(double value);
Node* BooleanMapConstant();
Node* HeapNumberMapConstant();
Node* Parameter(int value);
......@@ -267,6 +273,8 @@ class CodeStubAssembler {
Node* LoadObjectField(Node* object, int offset);
// Load the floating point value of a HeapNumber.
Node* LoadHeapNumberValue(Node* object);
// Load the bit field of a Map.
Node* LoadMapBitField(Node* map);
// Load the instance type of a Map.
Node* LoadMapInstanceType(Node* map);
......@@ -281,6 +289,9 @@ class CodeStubAssembler {
// Store an array element to a FixedArray.
Node* StoreFixedArrayElementNoWriteBarrier(Node* object, Node* index,
Node* value);
// Load the Map of an HeapObject.
Node* LoadMap(Node* object);
// Load the instance type of an HeapObject.
Node* LoadInstanceType(Node* object);
// Returns a node that is true if the given bit is set in |word32|.
......@@ -309,6 +320,7 @@ class CodeStubAssembler {
void BranchIfFloat64IsNaN(Node* value, Label* if_true, Label* if_false) {
BranchIfFloat64Equal(value, value, if_false, if_true);
}
void BranchIfWord32Equal(Node* a, Node* b, Label* if_true, Label* if_false);
// Helpers which delegate to RawMachineAssembler.
Factory* factory() const;
......
......@@ -87,8 +87,6 @@ REPLACE_BINARY_OP_IC_CALL(JSModulus, Token::MOD)
void JSGenericLowering::Lower##op(Node* node) { \
ReplaceWithRuntimeCall(node, fun); \
}
REPLACE_RUNTIME_CALL(JSEqual, Runtime::kEqual)
REPLACE_RUNTIME_CALL(JSNotEqual, Runtime::kNotEqual)
REPLACE_RUNTIME_CALL(JSCreateWithContext, Runtime::kPushWithContext)
REPLACE_RUNTIME_CALL(JSCreateModuleContext, Runtime::kPushModuleContext)
REPLACE_RUNTIME_CALL(JSConvertReceiver, Runtime::kConvertReceiver)
......@@ -104,6 +102,8 @@ REPLACE_STUB_CALL(LessThan)
REPLACE_STUB_CALL(LessThanOrEqual)
REPLACE_STUB_CALL(GreaterThan)
REPLACE_STUB_CALL(GreaterThanOrEqual)
REPLACE_STUB_CALL(Equal)
REPLACE_STUB_CALL(NotEqual)
REPLACE_STUB_CALL(StrictEqual)
REPLACE_STUB_CALL(StrictNotEqual)
#undef REPLACE_STUB_CALL
......
......@@ -1176,7 +1176,7 @@ void Interpreter::DoNewWide(InterpreterAssembler* assembler) {
//
// Test if the value in the <src> register equals the accumulator.
void Interpreter::DoTestEqual(InterpreterAssembler* assembler) {
DoBinaryOp(Runtime::kEqual, assembler);
DoBinaryOp(CodeFactory::Equal(isolate_), assembler);
}
......@@ -1184,7 +1184,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::kNotEqual, assembler);
DoBinaryOp(CodeFactory::NotEqual(isolate_), assembler);
}
......
......@@ -285,6 +285,10 @@ Maybe<ComparisonResult> Object::Compare(Handle<Object> x, Handle<Object> y) {
// static
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) {
if (x->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