Index: runtime/vm/intermediate_language_x64.cc |
=================================================================== |
--- runtime/vm/intermediate_language_x64.cc (revision 9640) |
+++ runtime/vm/intermediate_language_x64.cc (working copy) |
@@ -200,16 +200,18 @@ |
LocationSummary* EqualityCompareComp::MakeLocationSummary() const { |
const intptr_t kNumInputs = 2; |
- if (HasICData() && |
- (ic_data()->NumberOfChecks() == 1) && |
- (ic_data()->GetReceiverClassIdAt(0) == kSmi)) { |
- const intptr_t kNumTemps = 1; |
+ if (receiver_class_id() != kObject) { |
+ ASSERT((receiver_class_id() == kSmi) || (receiver_class_id() == kDouble)); |
+ // No temporary register needed for double comparison. |
+ const intptr_t kNumTemps = (receiver_class_id() == kSmi) ? 1 : 0; |
LocationSummary* locs = new LocationSummary(kNumInputs, |
kNumTemps, |
LocationSummary::kNoCall); |
locs->set_in(0, Location::RequiresRegister()); |
locs->set_in(1, Location::RequiresRegister()); |
- locs->set_temp(0, Location::RequiresRegister()); |
+ if (receiver_class_id() == kSmi) { |
+ locs->set_temp(0, Location::RequiresRegister()); |
+ } |
if (!is_fused_with_branch()) { |
locs->set_out(Location::RequiresRegister()); |
} |
@@ -241,6 +243,8 @@ |
} |
+// Optional integer arguments can often be null. Null is not collected |
+// by IC data. TODO(srdjan): Shall we collect null classes in ICData as well? |
static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler, |
EqualityCompareComp* comp) { |
Register left = comp->locs()->in(0).reg(); |
@@ -249,10 +253,9 @@ |
Label* deopt = compiler->AddDeoptStub(comp->cid(), |
comp->token_pos(), |
comp->try_index(), |
- kDeoptSmiCompareSmis, |
+ kDeoptSmiCompareSmi, |
left, |
right); |
- // TODO(srdjan): Should we always include NULL test (common case)? |
__ movq(temp, left); |
__ orq(temp, right); |
__ testq(temp, Immediate(kSmiTagMask)); |
@@ -273,6 +276,34 @@ |
} |
+// TODO(srdjan): Add support for mixed Smi/Double equality |
+// (see LoadDoubleOrSmiToXmm). |
+static void EmitDoubleEqualityCompare(FlowGraphCompiler* compiler, |
+ EqualityCompareComp* comp) { |
+ Register left = comp->locs()->in(0).reg(); |
+ Register right = comp->locs()->in(1).reg(); |
+ Label* deopt = compiler->AddDeoptStub(comp->cid(), |
+ comp->token_pos(), |
+ comp->try_index(), |
+ kDeoptDoubleCompareDouble, |
+ left, |
+ right); |
+ __ CompareClassId(left, kDouble); |
+ __ j(NOT_EQUAL, deopt); |
+ __ CompareClassId(right, kDouble); |
+ __ j(NOT_EQUAL, deopt); |
+ __ movsd(XMM0, FieldAddress(left, Double::value_offset())); |
+ __ movsd(XMM1, FieldAddress(right, Double::value_offset())); |
+ if (comp->is_fused_with_branch()) { |
+ compiler->EmitDoubleCompareBranch( |
+ EQUAL, XMM0, XMM1, comp->fused_with_branch()); |
+ } else { |
+ compiler->EmitDoubleCompareBool( |
+ EQUAL, XMM0, XMM1, comp->locs()->out().reg()); |
+ } |
+} |
+ |
+ |
static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, |
EqualityCompareComp* comp) { |
compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
@@ -305,7 +336,7 @@ |
Register left, |
Register right) { |
ASSERT(comp->HasICData()); |
- const ICData& ic_data = *comp->ic_data(); |
+ const ICData& ic_data = ICData::Handle(comp->ic_data()->AsUnaryClassChecks()); |
ASSERT(ic_data.NumberOfChecks() > 0); |
ASSERT(ic_data.num_args_tested() == 1); |
Label* deopt = compiler->AddDeoptStub(comp->cid(), |
@@ -415,12 +446,14 @@ |
void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
- if (HasICData() && |
- (ic_data()->NumberOfChecks() == 1) && |
- (ic_data()->GetReceiverClassIdAt(0) == kSmi)) { |
+ if (receiver_class_id() == kSmi) { |
EmitSmiEqualityCompare(compiler, this); |
return; |
} |
+ if (receiver_class_id() == kDouble) { |
+ EmitDoubleEqualityCompare(compiler, this); |
+ return; |
+ } |
EmitGenericEqualityCompare(compiler, this); |
} |
@@ -469,7 +502,7 @@ |
Label* deopt = compiler->AddDeoptStub(comp->cid(), |
comp->token_pos(), |
comp->try_index(), |
- kDeoptSmiCompareSmis, |
+ kDeoptSmiCompareSmi, |
left, |
right); |
__ movq(temp, left); |
@@ -525,25 +558,12 @@ |
compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); |
Condition true_condition = TokenKindToDoubleCondition(comp->kind()); |
- __ comisd(XMM0, XMM1); |
- |
if (comp->is_fused_with_branch()) { |
- BranchInstr* branch = comp->fused_with_branch(); |
- BlockEntryInstr* nan_result = branch->is_negated() ? |
- branch->true_successor() : branch->false_successor(); |
- __ j(PARITY_EVEN, compiler->GetBlockLabel(nan_result)); |
- branch->EmitBranchOnCondition(compiler, true_condition); |
+ compiler->EmitDoubleCompareBranch( |
+ true_condition, XMM0, XMM1, comp->fused_with_branch()); |
} else { |
- Register result = comp->locs()->out().reg(); |
- Label is_false, is_true, done; |
- __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false; |
- __ j(true_condition, &is_true, Assembler::kNearJump); |
- __ Bind(&is_false); |
- __ LoadObject(result, compiler->bool_false()); |
- __ jmp(&done); |
- __ Bind(&is_true); |
- __ LoadObject(result, compiler->bool_true()); |
- __ Bind(&done); |
+ compiler->EmitDoubleCompareBool( |
+ true_condition, XMM0, XMM1, comp->locs()->out().reg()); |
} |
} |