Allow equality operation on mixed double/smi arguments.

Fix a bug in relational operations in 64 bit mode: if ICData specifies double and Smi as possible arguments, we generate code for double and unbox or convert to double the inputs. These works only if smi can fit into the double. Current solution for 64-bit architecture is to disallow two smi-s as input to a polymorphic comparison instruction (equality, relational).

R=johnmccutchan@google.com

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

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@25522 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
srdjan@google.com 2013-07-26 16:48:46 +00:00
parent de49b902db
commit 3d6b2fc18e
8 changed files with 189 additions and 165 deletions

View file

@ -617,6 +617,16 @@ static bool HasTwoMintOrSmi(const ICData& ic_data) {
}
// Returns false if the ICData contains anything other than the 4 combinations
// of Double and Smi for the receiver and argument classes.
static bool HasTwoDoubleOrSmi(const ICData& ic_data) {
GrowableArray<intptr_t> class_ids(2);
class_ids.Add(kSmiCid);
class_ids.Add(kDoubleCid);
return ICDataHasOnlyReceiverArgumentClassIds(ic_data, class_ids, class_ids);
}
static bool HasOnlyOneDouble(const ICData& ic_data) {
return (ic_data.NumberOfChecks() == 1)
&& ic_data.HasReceiverClassId(kDoubleCid);
@ -2744,36 +2754,57 @@ bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr,
}
static bool SmiFitsInDouble() { return kSmiBits < 53; }
void FlowGraphOptimizer::HandleComparison(ComparisonInstr* comp,
const ICData& ic_data,
Instruction* current_instruction) {
ASSERT(ic_data.num_args_tested() == 2);
ASSERT(comp->operation_cid() == kIllegalCid);
Instruction* instr = current_iterator()->Current();
if (HasOnlyTwoSmis(ic_data)) {
InsertBefore(instr,
new CheckSmiInstr(comp->left()->Copy(), comp->deopt_id()),
instr->env(),
Definition::kEffect);
InsertBefore(instr,
new CheckSmiInstr(comp->right()->Copy(), comp->deopt_id()),
instr->env(),
Definition::kEffect);
comp->set_operation_cid(kSmiCid);
} else if (HasTwoMintOrSmi(ic_data) &&
FlowGraphCompiler::SupportsUnboxedMints()) {
comp->set_operation_cid(kMintCid);
} else if (HasTwoDoubleOrSmi(ic_data)) {
// Use double comparison.
if (SmiFitsInDouble()) {
comp->set_operation_cid(kDoubleCid);
} else {
if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) {
// We cannot use double comparison on two Smi-s.
ASSERT(comp->operation_cid() == kIllegalCid);
} else {
InsertBefore(instr,
new CheckEitherNonSmiInstr(comp->left()->Copy(),
comp->right()->Copy(),
comp->deopt_id()),
instr->env(),
Definition::kEffect);
comp->set_operation_cid(kDoubleCid);
}
}
} else {
ASSERT(comp->operation_cid() == kIllegalCid);
}
}
void FlowGraphOptimizer::HandleRelationalOp(RelationalOpInstr* comp) {
if (!comp->HasICData() || (comp->ic_data()->NumberOfChecks() == 0)) {
return;
}
const ICData& ic_data = *comp->ic_data();
Instruction* instr = current_iterator()->Current();
if (ic_data.NumberOfChecks() == 1) {
ASSERT(ic_data.HasOneTarget());
if (HasOnlyTwoSmis(ic_data)) {
InsertBefore(instr,
new CheckSmiInstr(comp->left()->Copy(), comp->deopt_id()),
instr->env(),
Definition::kEffect);
InsertBefore(instr,
new CheckSmiInstr(comp->right()->Copy(), comp->deopt_id()),
instr->env(),
Definition::kEffect);
comp->set_operands_class_id(kSmiCid);
} else if (ShouldSpecializeForDouble(ic_data)) {
comp->set_operands_class_id(kDoubleCid);
} else if (HasTwoMintOrSmi(*comp->ic_data()) &&
FlowGraphCompiler::SupportsUnboxedMints()) {
comp->set_operands_class_id(kMintCid);
} else {
ASSERT(comp->operands_class_id() == kIllegalCid);
}
} else if (HasTwoMintOrSmi(*comp->ic_data()) &&
FlowGraphCompiler::SupportsUnboxedMints()) {
comp->set_operands_class_id(kMintCid);
}
HandleComparison(comp, *comp->ic_data(), current_iterator()->Current());
}
@ -2857,37 +2888,10 @@ void FlowGraphOptimizer::HandleEqualityCompare(EqualityCompareInstr* comp,
return;
}
ASSERT(comp->ic_data()->num_args_tested() == 2);
if (comp->ic_data()->NumberOfChecks() == 1) {
GrowableArray<intptr_t> class_ids;
Function& target = Function::Handle();
comp->ic_data()->GetCheckAt(0, &class_ids, &target);
// TODO(srdjan): allow for mixed mode int/double comparison.
const ICData& ic_data = *comp->ic_data();
HandleComparison(comp, ic_data, current_instruction);
if ((class_ids[0] == kSmiCid) && (class_ids[1] == kSmiCid)) {
InsertBefore(current_instruction,
new CheckSmiInstr(comp->left()->Copy(), comp->deopt_id()),
current_instruction->env(),
Definition::kEffect);
InsertBefore(current_instruction,
new CheckSmiInstr(comp->right()->Copy(), comp->deopt_id()),
current_instruction->env(),
Definition::kEffect);
comp->set_receiver_class_id(kSmiCid);
} else if ((class_ids[0] == kDoubleCid) && (class_ids[1] == kDoubleCid)) {
comp->set_receiver_class_id(kDoubleCid);
} else if (HasTwoMintOrSmi(*comp->ic_data()) &&
FlowGraphCompiler::SupportsUnboxedMints()) {
comp->set_receiver_class_id(kMintCid);
} else {
ASSERT(comp->receiver_class_id() == kIllegalCid);
}
} else if (HasTwoMintOrSmi(*comp->ic_data()) &&
FlowGraphCompiler::SupportsUnboxedMints()) {
comp->set_receiver_class_id(kMintCid);
}
if (comp->receiver_class_id() != kIllegalCid) {
if (comp->operation_cid() != kIllegalCid) {
// Done.
return;
}
@ -2899,7 +2903,7 @@ void FlowGraphOptimizer::HandleEqualityCompare(EqualityCompareInstr* comp,
GrowableArray<intptr_t> smi_or_null(2);
smi_or_null.Add(kSmiCid);
smi_or_null.Add(kNullCid);
if (ICDataHasOnlyReceiverArgumentClassIds(*comp->ic_data(),
if (ICDataHasOnlyReceiverArgumentClassIds(ic_data,
smi_or_null,
smi_or_null)) {
const ICData& unary_checks_0 =
@ -2917,7 +2921,7 @@ void FlowGraphOptimizer::HandleEqualityCompare(EqualityCompareInstr* comp,
comp->deopt_id(),
current_instruction->env(),
current_instruction);
comp->set_receiver_class_id(kSmiCid);
comp->set_operation_cid(kSmiCid);
}
}
@ -3237,7 +3241,7 @@ ConstraintInstr* RangeAnalysis::InsertConstraintFor(Definition* defn,
void RangeAnalysis::ConstrainValueAfterBranch(Definition* defn, Value* use) {
BranchInstr* branch = use->instruction()->AsBranch();
RelationalOpInstr* rel_op = branch->comparison()->AsRelationalOp();
if ((rel_op != NULL) && (rel_op->operands_class_id() == kSmiCid)) {
if ((rel_op != NULL) && (rel_op->operation_cid() == kSmiCid)) {
// Found comparison of two smis. Constrain defn at true and false
// successors using the other operand as a boundary.
Definition* boundary;
@ -5880,7 +5884,7 @@ void ConstantPropagator::VisitEqualityCompare(EqualityCompareInstr* instr) {
// Fold x == x, and x != x to true/false for numbers and checked strict
// comparisons.
if (instr->IsCheckedStrictEqual() ||
RawObject::IsIntegerClassId(instr->receiver_class_id())) {
RawObject::IsIntegerClassId(instr->operation_cid())) {
return SetValue(instr,
(instr->kind() == Token::kEQ)
? Bool::True()

View file

@ -172,6 +172,10 @@ class FlowGraphOptimizer : public FlowGraphVisitor {
void ReplaceWithMathCFunction(InstanceCallInstr* call,
MethodRecognizer::Kind recognized_kind);
void HandleComparison(ComparisonInstr* comp,
const ICData& ic_data,
Instruction* current_instruction);
void HandleRelationalOp(RelationalOpInstr* comp);
// Visit an equality compare. The current instruction can be the

View file

@ -2697,15 +2697,6 @@ class PolymorphicInstanceCallInstr : public TemplateDefinition<0> {
class ComparisonInstr : public TemplateDefinition<2> {
public:
ComparisonInstr(intptr_t token_pos,
Token::Kind kind,
Value* left,
Value* right)
: token_pos_(token_pos), kind_(kind) {
SetInputAt(0, left);
SetInputAt(1, right);
}
Value* left() const { return inputs_[0]; }
Value* right() const { return inputs_[1]; }
@ -2721,9 +2712,27 @@ class ComparisonInstr : public TemplateDefinition<2> {
deopt_id_ = deopt_id;
}
// Operation class id is computed from collected ICData.
void set_operation_cid(intptr_t value) { operation_cid_ = value; }
intptr_t operation_cid() const { return operation_cid_; }
protected:
ComparisonInstr(intptr_t token_pos,
Token::Kind kind,
Value* left,
Value* right)
: token_pos_(token_pos), kind_(kind), operation_cid_(kIllegalCid) {
SetInputAt(0, left);
SetInputAt(1, right);
}
intptr_t token_pos_;
Token::Kind kind_;
private:
intptr_t operation_cid_; // Set by optimizer.
DISALLOW_COPY_AND_ASSIGN(ComparisonInstr);
};
@ -2840,8 +2849,7 @@ class EqualityCompareInstr : public ComparisonInstr {
const Array& ic_data_array)
: ComparisonInstr(token_pos, kind, left, right),
ic_data_(GetICData(ic_data_array)),
unary_ic_data_(NULL),
receiver_class_id_(kIllegalCid) {
unary_ic_data_(NULL) {
ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
if (HasICData()) {
unary_ic_data_ = &ICData::ZoneHandle(ic_data_->AsUnaryClassChecks());
@ -2863,14 +2871,10 @@ class EqualityCompareInstr : public ComparisonInstr {
}
}
// Receiver class id is computed from collected ICData.
void set_receiver_class_id(intptr_t value) { receiver_class_id_ = value; }
intptr_t receiver_class_id() const { return receiver_class_id_; }
bool IsInlinedNumericComparison() const {
return (receiver_class_id() == kDoubleCid)
|| (receiver_class_id() == kMintCid)
|| (receiver_class_id() == kSmiCid);
return (operation_cid() == kDoubleCid)
|| (operation_cid() == kMintCid)
|| (operation_cid() == kSmiCid);
}
bool IsCheckedStrictEqual() const;
@ -2890,8 +2894,8 @@ class EqualityCompareInstr : public ComparisonInstr {
virtual Representation RequiredInputRepresentation(intptr_t idx) const {
ASSERT((idx == 0) || (idx == 1));
if (receiver_class_id() == kDoubleCid) return kUnboxedDouble;
if (receiver_class_id() == kMintCid) return kUnboxedMint;
if (operation_cid() == kDoubleCid) return kUnboxedDouble;
if (operation_cid() == kMintCid) return kUnboxedMint;
return kTagged;
}
@ -2908,7 +2912,6 @@ class EqualityCompareInstr : public ComparisonInstr {
private:
const ICData* ic_data_;
ICData* unary_ic_data_;
intptr_t receiver_class_id_; // Set by optimizer.
DISALLOW_COPY_AND_ASSIGN(EqualityCompareInstr);
};
@ -2922,8 +2925,7 @@ class RelationalOpInstr : public ComparisonInstr {
Value* right,
const Array& ic_data_array)
: ComparisonInstr(token_pos, kind, left, right),
ic_data_(GetICData(ic_data_array)),
operands_class_id_(kIllegalCid) {
ic_data_(GetICData(ic_data_array)) {
ASSERT(Token::IsRelationalOperator(kind));
}
@ -2937,18 +2939,10 @@ class RelationalOpInstr : public ComparisonInstr {
}
void set_ic_data(const ICData* value) { ic_data_ = value; }
// TODO(srdjan): instead of class-id pass an enum that can differentiate
// between boxed and unboxed doubles and integers.
void set_operands_class_id(intptr_t value) {
operands_class_id_ = value;
}
intptr_t operands_class_id() const { return operands_class_id_; }
bool IsInlinedNumericComparison() const {
return (operands_class_id() == kDoubleCid)
|| (operands_class_id() == kMintCid)
|| (operands_class_id() == kSmiCid);
return (operation_cid() == kDoubleCid)
|| (operation_cid() == kMintCid)
|| (operation_cid() == kSmiCid);
}
virtual void PrintOperandsTo(BufferFormatter* f) const;
@ -2967,8 +2961,8 @@ class RelationalOpInstr : public ComparisonInstr {
virtual Representation RequiredInputRepresentation(intptr_t idx) const {
ASSERT((idx == 0) || (idx == 1));
if (operands_class_id() == kDoubleCid) return kUnboxedDouble;
if (operands_class_id() == kMintCid) return kUnboxedMint;
if (operation_cid() == kDoubleCid) return kUnboxedDouble;
if (operation_cid() == kMintCid) return kUnboxedMint;
return kTagged;
}
@ -2980,7 +2974,6 @@ class RelationalOpInstr : public ComparisonInstr {
private:
const ICData* ic_data_;
intptr_t operands_class_id_; // class id of both operands.
DISALLOW_COPY_AND_ASSIGN(RelationalOpInstr);
};

View file

@ -283,7 +283,7 @@ static Condition TokenKindToSmiCondition(Token::Kind kind) {
LocationSummary* EqualityCompareInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 2;
if (receiver_class_id() == kMintCid) {
if (operation_cid() == kMintCid) {
const intptr_t kNumTemps = 1;
LocationSummary* locs =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
@ -293,7 +293,7 @@ LocationSummary* EqualityCompareInstr::MakeLocationSummary() const {
locs->set_out(Location::RequiresRegister());
return locs;
}
if (receiver_class_id() == kDoubleCid) {
if (operation_cid() == kDoubleCid) {
const intptr_t kNumTemps = 0;
LocationSummary* locs =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
@ -302,7 +302,7 @@ LocationSummary* EqualityCompareInstr::MakeLocationSummary() const {
locs->set_out(Location::RequiresRegister());
return locs;
}
if (receiver_class_id() == kSmiCid) {
if (operation_cid() == kSmiCid) {
const intptr_t kNumTemps = 0;
LocationSummary* locs =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
@ -746,15 +746,15 @@ static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
BranchInstr* kNoBranch = NULL;
if (receiver_class_id() == kSmiCid) {
if (operation_cid() == kSmiCid) {
EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch);
return;
}
if (receiver_class_id() == kMintCid) {
if (operation_cid() == kMintCid) {
EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), kNoBranch);
return;
}
if (receiver_class_id() == kDoubleCid) {
if (operation_cid() == kDoubleCid) {
EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch);
return;
}
@ -786,16 +786,16 @@ void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
if (receiver_class_id() == kSmiCid) {
if (operation_cid() == kSmiCid) {
// Deoptimizes if both arguments not Smi.
EmitSmiComparisonOp(compiler, *locs(), kind(), branch);
return;
}
if (receiver_class_id() == kMintCid) {
if (operation_cid() == kMintCid) {
EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), branch);
return;
}
if (receiver_class_id() == kDoubleCid) {
if (operation_cid() == kDoubleCid) {
EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
return;
}
@ -832,7 +832,7 @@ void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
LocationSummary* RelationalOpInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 2;
const intptr_t kNumTemps = 0;
if (operands_class_id() == kMintCid) {
if (operation_cid() == kMintCid) {
const intptr_t kNumTemps = 2;
LocationSummary* locs =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
@ -843,14 +843,14 @@ LocationSummary* RelationalOpInstr::MakeLocationSummary() const {
locs->set_out(Location::RequiresRegister());
return locs;
}
if (operands_class_id() == kDoubleCid) {
if (operation_cid() == kDoubleCid) {
LocationSummary* summary =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
summary->set_in(0, Location::RequiresFpuRegister());
summary->set_in(1, Location::RequiresFpuRegister());
summary->set_out(Location::RequiresRegister());
return summary;
} else if (operands_class_id() == kSmiCid) {
} else if (operation_cid() == kSmiCid) {
LocationSummary* summary =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
summary->set_in(0, Location::RegisterOrConstant(left()));
@ -873,15 +873,15 @@ LocationSummary* RelationalOpInstr::MakeLocationSummary() const {
void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
if (operands_class_id() == kSmiCid) {
if (operation_cid() == kSmiCid) {
EmitSmiComparisonOp(compiler, *locs(), kind(), NULL);
return;
}
if (operands_class_id() == kMintCid) {
if (operation_cid() == kMintCid) {
EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), NULL);
return;
}
if (operands_class_id() == kDoubleCid) {
if (operation_cid() == kDoubleCid) {
EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL);
return;
}
@ -950,15 +950,15 @@ void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
if (operands_class_id() == kSmiCid) {
if (operation_cid() == kSmiCid) {
EmitSmiComparisonOp(compiler, *locs(), kind(), branch);
return;
}
if (operands_class_id() == kMintCid) {
if (operation_cid() == kMintCid) {
EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), branch);
return;
}
if (operands_class_id() == kDoubleCid) {
if (operation_cid() == kDoubleCid) {
EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
return;
}

View file

@ -230,7 +230,7 @@ static Condition TokenKindToSmiCondition(Token::Kind kind) {
LocationSummary* EqualityCompareInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 2;
if (receiver_class_id() == kMintCid) {
if (operation_cid() == kMintCid) {
const intptr_t kNumTemps = 1;
LocationSummary* locs =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
@ -240,7 +240,7 @@ LocationSummary* EqualityCompareInstr::MakeLocationSummary() const {
locs->set_out(Location::RequiresRegister());
return locs;
}
if (receiver_class_id() == kDoubleCid) {
if (operation_cid() == kDoubleCid) {
const intptr_t kNumTemps = 0;
LocationSummary* locs =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
@ -249,7 +249,7 @@ LocationSummary* EqualityCompareInstr::MakeLocationSummary() const {
locs->set_out(Location::RequiresRegister());
return locs;
}
if (receiver_class_id() == kSmiCid) {
if (operation_cid() == kSmiCid) {
const intptr_t kNumTemps = 0;
LocationSummary* locs =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
@ -794,15 +794,15 @@ static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
BranchInstr* kNoBranch = NULL;
if (receiver_class_id() == kSmiCid) {
if (operation_cid() == kSmiCid) {
EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch);
return;
}
if (receiver_class_id() == kMintCid) {
if (operation_cid() == kMintCid) {
EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), kNoBranch);
return;
}
if (receiver_class_id() == kDoubleCid) {
if (operation_cid() == kDoubleCid) {
EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch);
return;
}
@ -833,16 +833,16 @@ void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
if (receiver_class_id() == kSmiCid) {
if (operation_cid() == kSmiCid) {
// Deoptimizes if both arguments not Smi.
EmitSmiComparisonOp(compiler, *locs(), kind(), branch);
return;
}
if (receiver_class_id() == kMintCid) {
if (operation_cid() == kMintCid) {
EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), branch);
return;
}
if (receiver_class_id() == kDoubleCid) {
if (operation_cid() == kDoubleCid) {
EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
return;
}
@ -878,7 +878,7 @@ void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
LocationSummary* RelationalOpInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 2;
const intptr_t kNumTemps = 0;
if (operands_class_id() == kMintCid) {
if (operation_cid() == kMintCid) {
const intptr_t kNumTemps = 2;
LocationSummary* locs =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
@ -889,14 +889,14 @@ LocationSummary* RelationalOpInstr::MakeLocationSummary() const {
locs->set_out(Location::RequiresRegister());
return locs;
}
if (operands_class_id() == kDoubleCid) {
if (operation_cid() == kDoubleCid) {
LocationSummary* summary =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
summary->set_in(0, Location::RequiresFpuRegister());
summary->set_in(1, Location::RequiresFpuRegister());
summary->set_out(Location::RequiresRegister());
return summary;
} else if (operands_class_id() == kSmiCid) {
} else if (operation_cid() == kSmiCid) {
LocationSummary* summary =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
summary->set_in(0, Location::RegisterOrConstant(left()));
@ -919,15 +919,15 @@ LocationSummary* RelationalOpInstr::MakeLocationSummary() const {
void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
if (operands_class_id() == kSmiCid) {
if (operation_cid() == kSmiCid) {
EmitSmiComparisonOp(compiler, *locs(), kind(), NULL);
return;
}
if (operands_class_id() == kMintCid) {
if (operation_cid() == kMintCid) {
EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), NULL);
return;
}
if (operands_class_id() == kDoubleCid) {
if (operation_cid() == kDoubleCid) {
EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL);
return;
}
@ -996,15 +996,15 @@ void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
if (operands_class_id() == kSmiCid) {
if (operation_cid() == kSmiCid) {
EmitSmiComparisonOp(compiler, *locs(), kind(), branch);
return;
}
if (operands_class_id() == kMintCid) {
if (operation_cid() == kMintCid) {
EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), branch);
return;
}
if (operands_class_id() == kDoubleCid) {
if (operation_cid() == kDoubleCid) {
EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
return;
}
@ -4625,7 +4625,7 @@ bool IfThenElseInstr::Supports(ComparisonInstr* comparison,
if (!(comparison->IsStrictCompare() &&
!comparison->AsStrictCompare()->needs_number_check()) &&
!(comparison->IsEqualityCompare() &&
(comparison->AsEqualityCompare()->receiver_class_id() == kSmiCid))) {
(comparison->AsEqualityCompare()->operation_cid() == kSmiCid))) {
return false;
}

View file

@ -272,7 +272,7 @@ void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
LocationSummary* EqualityCompareInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 2;
if (receiver_class_id() == kMintCid) {
if (operation_cid() == kMintCid) {
const intptr_t kNumTemps = 1;
LocationSummary* locs =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
@ -282,7 +282,7 @@ LocationSummary* EqualityCompareInstr::MakeLocationSummary() const {
locs->set_out(Location::RequiresRegister());
return locs;
}
if (receiver_class_id() == kDoubleCid) {
if (operation_cid() == kDoubleCid) {
const intptr_t kNumTemps = 0;
LocationSummary* locs =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
@ -291,7 +291,7 @@ LocationSummary* EqualityCompareInstr::MakeLocationSummary() const {
locs->set_out(Location::RequiresRegister());
return locs;
}
if (receiver_class_id() == kSmiCid) {
if (operation_cid() == kSmiCid) {
const intptr_t kNumTemps = 0;
LocationSummary* locs =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
@ -794,15 +794,15 @@ void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
BranchInstr* kNoBranch = NULL;
__ Comment("EqualityCompareInstr");
if (receiver_class_id() == kSmiCid) {
if (operation_cid() == kSmiCid) {
EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch);
return;
}
if (receiver_class_id() == kMintCid) {
if (operation_cid() == kMintCid) {
EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), kNoBranch);
return;
}
if (receiver_class_id() == kDoubleCid) {
if (operation_cid() == kDoubleCid) {
EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch);
return;
}
@ -838,16 +838,16 @@ void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
__ TraceSimMsg("EqualityCompareInstr");
__ Comment("EqualityCompareInstr:BranchCode");
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
if (receiver_class_id() == kSmiCid) {
if (operation_cid() == kSmiCid) {
// Deoptimizes if both arguments not Smi.
EmitSmiComparisonOp(compiler, *locs(), kind(), branch);
return;
}
if (receiver_class_id() == kMintCid) {
if (operation_cid() == kMintCid) {
EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), branch);
return;
}
if (receiver_class_id() == kDoubleCid) {
if (operation_cid() == kDoubleCid) {
EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
return;
}
@ -886,7 +886,7 @@ void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
LocationSummary* RelationalOpInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 2;
const intptr_t kNumTemps = 0;
if (operands_class_id() == kMintCid) {
if (operation_cid() == kMintCid) {
const intptr_t kNumTemps = 2;
LocationSummary* locs =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
@ -897,14 +897,14 @@ LocationSummary* RelationalOpInstr::MakeLocationSummary() const {
locs->set_out(Location::RequiresRegister());
return locs;
}
if (operands_class_id() == kDoubleCid) {
if (operation_cid() == kDoubleCid) {
LocationSummary* summary =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
summary->set_in(0, Location::RequiresFpuRegister());
summary->set_in(1, Location::RequiresFpuRegister());
summary->set_out(Location::RequiresRegister());
return summary;
} else if (operands_class_id() == kSmiCid) {
} else if (operation_cid() == kSmiCid) {
LocationSummary* summary =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
summary->set_in(0, Location::RegisterOrConstant(left()));
@ -928,15 +928,15 @@ LocationSummary* RelationalOpInstr::MakeLocationSummary() const {
void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ TraceSimMsg("RelationalOpInstr");
if (operands_class_id() == kSmiCid) {
if (operation_cid() == kSmiCid) {
EmitSmiComparisonOp(compiler, *locs(), kind(), NULL);
return;
}
if (operands_class_id() == kMintCid) {
if (operation_cid() == kMintCid) {
EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), NULL);
return;
}
if (operands_class_id() == kDoubleCid) {
if (operation_cid() == kDoubleCid) {
EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL);
return;
}
@ -1005,15 +1005,15 @@ void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
__ TraceSimMsg("RelationalOpInstr");
if (operands_class_id() == kSmiCid) {
if (operation_cid() == kSmiCid) {
EmitSmiComparisonOp(compiler, *locs(), kind(), branch);
return;
}
if (operands_class_id() == kMintCid) {
if (operation_cid() == kMintCid) {
EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), branch);
return;
}
if (operands_class_id() == kDoubleCid) {
if (operation_cid() == kDoubleCid) {
EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
return;
}

View file

@ -169,7 +169,7 @@ bool IfThenElseInstr::Supports(ComparisonInstr* comparison,
if (!(comparison->IsStrictCompare() &&
!comparison->AsStrictCompare()->needs_number_check()) &&
!(comparison->IsEqualityCompare() &&
(comparison->AsEqualityCompare()->receiver_class_id() == kSmiCid))) {
(comparison->AsEqualityCompare()->operation_cid() == kSmiCid))) {
return false;
}
@ -396,7 +396,7 @@ static Condition TokenKindToSmiCondition(Token::Kind kind) {
LocationSummary* EqualityCompareInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 2;
if (receiver_class_id() == kDoubleCid) {
if (operation_cid() == kDoubleCid) {
const intptr_t kNumTemps = 0;
LocationSummary* locs =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
@ -405,7 +405,7 @@ LocationSummary* EqualityCompareInstr::MakeLocationSummary() const {
locs->set_out(Location::RequiresRegister());
return locs;
}
if (receiver_class_id() == kSmiCid) {
if (operation_cid() == kSmiCid) {
const intptr_t kNumTemps = 0;
LocationSummary* locs =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
@ -841,12 +841,12 @@ static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE));
BranchInstr* kNoBranch = NULL;
if (receiver_class_id() == kSmiCid) {
if (operation_cid() == kSmiCid) {
// Deoptimizes if both arguments not Smi.
EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch);
return;
}
if (receiver_class_id() == kDoubleCid) {
if (operation_cid() == kDoubleCid) {
// Deoptimizes if both arguments are Smi, or if none is Double or Smi.
EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch);
return;
@ -878,12 +878,12 @@ void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
if (receiver_class_id() == kSmiCid) {
if (operation_cid() == kSmiCid) {
// Deoptimizes if both arguments not Smi.
EmitSmiComparisonOp(compiler, *locs(), kind(), branch);
return;
}
if (receiver_class_id() == kDoubleCid) {
if (operation_cid() == kDoubleCid) {
// Deoptimizes if both arguments are Smi, or if none is Double or Smi.
EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
return;
@ -920,14 +920,14 @@ void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
LocationSummary* RelationalOpInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 2;
const intptr_t kNumTemps = 0;
if (operands_class_id() == kDoubleCid) {
if (operation_cid() == kDoubleCid) {
LocationSummary* summary =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
summary->set_in(0, Location::RequiresFpuRegister());
summary->set_in(1, Location::RequiresFpuRegister());
summary->set_out(Location::RequiresRegister());
return summary;
} else if (operands_class_id() == kSmiCid) {
} else if (operation_cid() == kSmiCid) {
LocationSummary* summary =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
summary->set_in(0, Location::RegisterOrConstant(left()));
@ -950,11 +950,11 @@ LocationSummary* RelationalOpInstr::MakeLocationSummary() const {
void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
if (operands_class_id() == kSmiCid) {
if (operation_cid() == kSmiCid) {
EmitSmiComparisonOp(compiler, *locs(), kind(), NULL);
return;
}
if (operands_class_id() == kDoubleCid) {
if (operation_cid() == kDoubleCid) {
EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL);
return;
}
@ -1024,11 +1024,11 @@ void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
if (operands_class_id() == kSmiCid) {
if (operation_cid() == kSmiCid) {
EmitSmiComparisonOp(compiler, *locs(), kind(), branch);
return;
}
if (operands_class_id() == kDoubleCid) {
if (operation_cid() == kDoubleCid) {
EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
return;
}

View file

@ -0,0 +1,23 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Test correct comparison (equality and relational) when mixing double and
// Smi arguments. We convert Smi to doubles and to the operation. This is
// not correct in 64-bit mode where not every Smi can be converted to a
// double without loss of precision.
// VMOptions=--optimization-counter-threshold=10 --no-use-osr
import "package:expect/expect.dart";
equalityFunc(a, b) => a == b;
lessThanFunc(a, b) => a < b;
main() {
for (int i = 0; i < 20; i++) {
Expect.isFalse(equalityFunc(1.0, 4));
Expect.isTrue(lessThanFunc(1.0, 4));
}
Expect.isFalse(equalityFunc(3459045988797251776, 3459045988797251777));
Expect.isTrue(lessThanFunc(3459045988797251776, 3459045988797251777));
}