}
+void CompareICStub::GenerateBooleans(MacroAssembler* masm) {
+ DCHECK_EQ(CompareICState::BOOLEAN, state());
+ Label miss;
+
+ __ CheckMap(r1, r2, Heap::kBooleanMapRootIndex, &miss, DO_SMI_CHECK);
+ __ CheckMap(r0, r3, Heap::kBooleanMapRootIndex, &miss, DO_SMI_CHECK);
+ if (op() != Token::EQ_STRICT && is_strong(strength())) {
+ __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion, 0, 1);
+ } else {
+ if (!Token::IsEqualityOp(op())) {
+ __ ldr(r1, FieldMemOperand(r1, Oddball::kToNumberOffset));
+ __ AssertSmi(r1);
+ __ ldr(r0, FieldMemOperand(r0, Oddball::kToNumberOffset));
+ __ AssertSmi(r0);
+ }
+ __ sub(r0, r1, r0);
+ __ Ret();
+ }
+
+ __ bind(&miss);
+ GenerateMiss(masm);
+}
+
+
void CompareICStub::GenerateSmis(MacroAssembler* masm) {
DCHECK(state() == CompareICState::SMI);
Label miss;
}
+void CompareICStub::GenerateBooleans(MacroAssembler* masm) {
+ // Inputs are in x0 (lhs) and x1 (rhs).
+ DCHECK_EQ(CompareICState::BOOLEAN, state());
+ ASM_LOCATION("CompareICStub[Booleans]");
+ Label miss;
+
+ __ CheckMap(x1, x2, Heap::kBooleanMapRootIndex, &miss, DO_SMI_CHECK);
+ __ CheckMap(x0, x3, Heap::kBooleanMapRootIndex, &miss, DO_SMI_CHECK);
+ if (op() != Token::EQ_STRICT && is_strong(strength())) {
+ __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion, 0, 1);
+ } else {
+ if (!Token::IsEqualityOp(op())) {
+ __ Ldr(x1, FieldMemOperand(x1, Oddball::kToNumberOffset));
+ __ AssertSmi(x1);
+ __ Ldr(x0, FieldMemOperand(x0, Oddball::kToNumberOffset));
+ __ AssertSmi(x0);
+ }
+ __ Sub(x0, x1, x0);
+ __ Ret();
+ }
+
+ __ Bind(&miss);
+ GenerateMiss(masm);
+}
+
+
void CompareICStub::GenerateSmis(MacroAssembler* masm) {
// Inputs are in x0 (lhs) and x1 (rhs).
DCHECK(state() == CompareICState::SMI);
switch (state) {
case CompareICState::UNINITIALIZED:
return ::v8::internal::UNINITIALIZED;
+ case CompareICState::BOOLEAN:
case CompareICState::SMI:
case CompareICState::NUMBER:
case CompareICState::INTERNALIZED_STRING:
case CompareICState::UNINITIALIZED:
GenerateMiss(masm);
break;
+ case CompareICState::BOOLEAN:
+ GenerateBooleans(masm);
+ break;
case CompareICState::SMI:
GenerateSmis(masm);
break;
private:
Code::Kind GetCodeKind() const override { return Code::COMPARE_IC; }
+ void GenerateBooleans(MacroAssembler* masm);
void GenerateSmis(MacroAssembler* masm);
void GenerateNumbers(MacroAssembler* masm);
void GenerateInternalizedStrings(MacroAssembler* masm);
Representation::Integer32());
}
+ static HObjectAccess ForOddballToNumber(
+ Representation representation = Representation::Tagged()) {
+ return HObjectAccess(kInobject, Oddball::kToNumberOffset, representation);
+ }
+
static HObjectAccess ForOddballTypeOf() {
return HObjectAccess(kInobject, Oddball::kTypeOfOffset,
Representation::HeapObject());
HStringCompareAndBranch* result =
New<HStringCompareAndBranch>(left, right, op);
return result;
+ } else if (combined_type->Is(Type::Boolean())) {
+ AddCheckMap(left, isolate()->factory()->boolean_map());
+ AddCheckMap(right, isolate()->factory()->boolean_map());
+ if (Token::IsEqualityOp(op)) {
+ HCompareObjectEqAndBranch* result =
+ New<HCompareObjectEqAndBranch>(left, right);
+ return result;
+ }
+ left = Add<HLoadNamedField>(
+ left, nullptr,
+ HObjectAccess::ForOddballToNumber(Representation::Smi()));
+ right = Add<HLoadNamedField>(
+ right, nullptr,
+ HObjectAccess::ForOddballToNumber(Representation::Smi()));
+ HCompareNumericAndBranch* result =
+ New<HCompareNumericAndBranch>(left, right, op);
+ return result;
} else {
if (combined_rep.IsTagged() || combined_rep.IsNone()) {
HCompareGeneric* result = Add<HCompareGeneric>(
}
+void CompareICStub::GenerateBooleans(MacroAssembler* masm) {
+ DCHECK_EQ(CompareICState::BOOLEAN, state());
+ Label miss;
+ Label::Distance const miss_distance =
+ masm->emit_debug_code() ? Label::kFar : Label::kNear;
+
+ __ JumpIfSmi(edx, &miss, miss_distance);
+ __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
+ __ JumpIfSmi(eax, &miss, miss_distance);
+ __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
+ __ JumpIfNotRoot(ecx, Heap::kBooleanMapRootIndex, &miss, miss_distance);
+ __ JumpIfNotRoot(ebx, Heap::kBooleanMapRootIndex, &miss, miss_distance);
+ if (op() != Token::EQ_STRICT && is_strong(strength())) {
+ __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion, 0, 1);
+ } else {
+ if (!Token::IsEqualityOp(op())) {
+ __ mov(eax, FieldOperand(eax, Oddball::kToNumberOffset));
+ __ AssertSmi(eax);
+ __ mov(edx, FieldOperand(edx, Oddball::kToNumberOffset));
+ __ AssertSmi(edx);
+ __ xchg(eax, edx);
+ }
+ __ sub(eax, edx);
+ __ Ret();
+ }
+
+ __ bind(&miss);
+ GenerateMiss(masm);
+}
+
+
void CompareICStub::GenerateSmis(MacroAssembler* masm) {
DCHECK(state() == CompareICState::SMI);
Label miss;
switch (state) {
case UNINITIALIZED:
return "UNINITIALIZED";
+ case BOOLEAN:
+ return "BOOLEAN";
case SMI:
return "SMI";
case NUMBER:
switch (state) {
case UNINITIALIZED:
return Type::None(zone);
+ case BOOLEAN:
+ return Type::Boolean(zone);
case SMI:
return Type::SignedSmall(zone);
case NUMBER:
Handle<Object> value) {
switch (old_state) {
case UNINITIALIZED:
+ if (value->IsBoolean()) return BOOLEAN;
if (value->IsSmi()) return SMI;
if (value->IsHeapNumber()) return NUMBER;
if (value->IsInternalizedString()) return INTERNALIZED_STRING;
if (value->IsSymbol()) return UNIQUE_NAME;
if (value->IsJSObject()) return OBJECT;
break;
+ case BOOLEAN:
+ if (value->IsBoolean()) return BOOLEAN;
+ break;
case SMI:
if (value->IsSmi()) return SMI;
if (value->IsHeapNumber()) return NUMBER;
bool has_inlined_smi_code, Handle<Object> x, Handle<Object> y) {
switch (old_state) {
case UNINITIALIZED:
+ if (x->IsBoolean() && y->IsBoolean()) return BOOLEAN;
if (x->IsSmi() && y->IsSmi()) return SMI;
if (x->IsNumber() && y->IsNumber()) return NUMBER;
if (Token::IsOrderedRelationalCompareOp(op)) {
return Token::IsEqualityOp(op) ? OBJECT : GENERIC;
}
return GENERIC;
+ case BOOLEAN:
case STRING:
case UNIQUE_NAME:
case OBJECT:
UNREACHABLE();
return GENERIC; // Make the compiler happy.
}
+
} // namespace internal
} // namespace v8
// ... < GENERIC
// SMI < NUMBER
// INTERNALIZED_STRING < STRING
+ // INTERNALIZED_STRING < UNIQUE_NAME
// KNOWN_OBJECT < OBJECT
enum State {
UNINITIALIZED,
+ BOOLEAN,
SMI,
NUMBER,
STRING,
}
+void CompareICStub::GenerateBooleans(MacroAssembler* masm) {
+ DCHECK_EQ(CompareICState::BOOLEAN, state());
+ Label miss;
+
+ __ CheckMap(a1, a2, Heap::kBooleanMapRootIndex, &miss, DO_SMI_CHECK);
+ __ CheckMap(a0, a3, Heap::kBooleanMapRootIndex, &miss, DO_SMI_CHECK);
+ if (op() != Token::EQ_STRICT && is_strong(strength())) {
+ __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion, 0, 1);
+ } else {
+ if (!Token::IsEqualityOp(op())) {
+ __ lw(a1, FieldMemOperand(a1, Oddball::kToNumberOffset));
+ __ AssertSmi(a1);
+ __ lw(a0, FieldMemOperand(a0, Oddball::kToNumberOffset));
+ __ AssertSmi(a0);
+ }
+ __ Ret(USE_DELAY_SLOT);
+ __ Subu(v0, a1, a0);
+ }
+
+ __ bind(&miss);
+ GenerateMiss(masm);
+}
+
+
void CompareICStub::GenerateSmis(MacroAssembler* masm) {
DCHECK(state() == CompareICState::SMI);
Label miss;
}
+void CompareICStub::GenerateBooleans(MacroAssembler* masm) {
+ DCHECK_EQ(CompareICState::BOOLEAN, state());
+ Label miss;
+
+ __ CheckMap(a1, a2, Heap::kBooleanMapRootIndex, &miss, DO_SMI_CHECK);
+ __ CheckMap(a0, a3, Heap::kBooleanMapRootIndex, &miss, DO_SMI_CHECK);
+ if (op() != Token::EQ_STRICT && is_strong(strength())) {
+ __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion, 0, 1);
+ } else {
+ if (!Token::IsEqualityOp(op())) {
+ __ ld(a1, FieldMemOperand(a1, Oddball::kToNumberOffset));
+ __ AssertSmi(a1);
+ __ ld(a0, FieldMemOperand(a0, Oddball::kToNumberOffset));
+ __ AssertSmi(a0);
+ }
+ __ Ret(USE_DELAY_SLOT);
+ __ Dsubu(v0, a1, a0);
+ }
+
+ __ bind(&miss);
+ GenerateMiss(masm);
+}
+
+
void CompareICStub::GenerateSmis(MacroAssembler* masm) {
DCHECK(state() == CompareICState::SMI);
Label miss;
}
+void CompareICStub::GenerateBooleans(MacroAssembler* masm) {
+ DCHECK_EQ(CompareICState::BOOLEAN, state());
+ Label miss;
+ Label::Distance const miss_distance =
+ masm->emit_debug_code() ? Label::kFar : Label::kNear;
+
+ __ JumpIfSmi(rdx, &miss, miss_distance);
+ __ movp(rcx, FieldOperand(rdx, HeapObject::kMapOffset));
+ __ JumpIfSmi(rax, &miss, miss_distance);
+ __ movp(rbx, FieldOperand(rax, HeapObject::kMapOffset));
+ __ JumpIfNotRoot(rcx, Heap::kBooleanMapRootIndex, &miss, miss_distance);
+ __ JumpIfNotRoot(rbx, Heap::kBooleanMapRootIndex, &miss, miss_distance);
+ if (op() != Token::EQ_STRICT && is_strong(strength())) {
+ __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion, 0, 1);
+ } else {
+ if (!Token::IsEqualityOp(op())) {
+ __ movp(rax, FieldOperand(rax, Oddball::kToNumberOffset));
+ __ AssertSmi(rax);
+ __ movp(rdx, FieldOperand(rdx, Oddball::kToNumberOffset));
+ __ AssertSmi(rdx);
+ __ xchgp(rax, rdx);
+ }
+ __ subp(rax, rdx);
+ __ Ret();
+ }
+
+ __ bind(&miss);
+ GenerateMiss(masm);
+}
+
+
void CompareICStub::GenerateSmis(MacroAssembler* masm) {
DCHECK(state() == CompareICState::SMI);
Label miss;