Add inline floating point comparisons for comparison operators to x64 platform.
Review URL: http://codereview.chromium.org/1703019 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4545 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
a0c1310479
commit
3e689b5283
@ -5708,7 +5708,7 @@ void CodeGenerator::Comparison(AstNode* node,
|
|||||||
CompareStub stub(cc, strict, kCantBothBeNaN);
|
CompareStub stub(cc, strict, kCantBothBeNaN);
|
||||||
Result result = frame_->CallStub(&stub, &left_side, &right_side);
|
Result result = frame_->CallStub(&stub, &left_side, &right_side);
|
||||||
result.ToRegister();
|
result.ToRegister();
|
||||||
__ SmiCompare(result.reg(), Smi::FromInt(0));
|
__ testq(result.reg(), result.reg());
|
||||||
result.Unuse();
|
result.Unuse();
|
||||||
dest->true_target()->Branch(cc);
|
dest->true_target()->Branch(cc);
|
||||||
dest->false_target()->Jump();
|
dest->false_target()->Jump();
|
||||||
@ -5805,13 +5805,9 @@ void CodeGenerator::Comparison(AstNode* node,
|
|||||||
GenerateInlineNumberComparison(&left_side, &right_side, cc, dest);
|
GenerateInlineNumberComparison(&left_side, &right_side, cc, dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call the compare stub.
|
CompareStub stub(cc, strict, nan_info, !inline_number_compare);
|
||||||
// TODO(whesse@chromium.org): Enable the inlining flag once
|
|
||||||
// GenerateInlineNumberComparison is implemented.
|
|
||||||
CompareStub stub(cc, strict, nan_info, true || !inline_number_compare);
|
|
||||||
Result answer = frame_->CallStub(&stub, &left_side, &right_side);
|
Result answer = frame_->CallStub(&stub, &left_side, &right_side);
|
||||||
// The result is a Smi, which is negative, zero, or positive.
|
__ testq(answer.reg(), answer.reg()); // Sets both zero and sign flag.
|
||||||
__ SmiTest(answer.reg()); // Sets both zero and sign flag.
|
|
||||||
answer.Unuse();
|
answer.Unuse();
|
||||||
dest->Split(cc);
|
dest->Split(cc);
|
||||||
} else {
|
} else {
|
||||||
@ -5839,12 +5835,9 @@ void CodeGenerator::Comparison(AstNode* node,
|
|||||||
GenerateInlineNumberComparison(&left_side, &right_side, cc, dest);
|
GenerateInlineNumberComparison(&left_side, &right_side, cc, dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call the compare stub.
|
CompareStub stub(cc, strict, nan_info, !inline_number_compare);
|
||||||
// TODO(whesse@chromium.org): Enable the inlining flag once
|
|
||||||
// GenerateInlineNumberComparison is implemented.
|
|
||||||
CompareStub stub(cc, strict, nan_info, true || !inline_number_compare);
|
|
||||||
Result answer = frame_->CallStub(&stub, &left_side, &right_side);
|
Result answer = frame_->CallStub(&stub, &left_side, &right_side);
|
||||||
__ SmiTest(answer.reg()); // Sets both zero and sign flags.
|
__ testq(answer.reg(), answer.reg()); // Sets both zero and sign flags.
|
||||||
answer.Unuse();
|
answer.Unuse();
|
||||||
dest->true_target()->Branch(cc);
|
dest->true_target()->Branch(cc);
|
||||||
dest->false_target()->Jump();
|
dest->false_target()->Jump();
|
||||||
@ -5861,14 +5854,70 @@ void CodeGenerator::Comparison(AstNode* node,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Load a comparison operand into into a XMM register. Jump to not_numbers jump
|
||||||
|
// target passing the left and right result if the operand is not a number.
|
||||||
|
static void LoadComparisonOperand(MacroAssembler* masm_,
|
||||||
|
Result* operand,
|
||||||
|
XMMRegister xmm_reg,
|
||||||
|
Result* left_side,
|
||||||
|
Result* right_side,
|
||||||
|
JumpTarget* not_numbers) {
|
||||||
|
Label done;
|
||||||
|
if (operand->type_info().IsDouble()) {
|
||||||
|
// Operand is known to be a heap number, just load it.
|
||||||
|
__ movsd(xmm_reg, FieldOperand(operand->reg(), HeapNumber::kValueOffset));
|
||||||
|
} else if (operand->type_info().IsSmi()) {
|
||||||
|
// Operand is known to be a smi. Convert it to double and keep the original
|
||||||
|
// smi.
|
||||||
|
__ SmiToInteger32(kScratchRegister, operand->reg());
|
||||||
|
__ cvtlsi2sd(xmm_reg, kScratchRegister);
|
||||||
|
} else {
|
||||||
|
// Operand type not known, check for smi or heap number.
|
||||||
|
Label smi;
|
||||||
|
__ JumpIfSmi(operand->reg(), &smi);
|
||||||
|
if (!operand->type_info().IsNumber()) {
|
||||||
|
__ LoadRoot(kScratchRegister, Heap::kHeapNumberMapRootIndex);
|
||||||
|
__ cmpq(FieldOperand(operand->reg(), HeapObject::kMapOffset),
|
||||||
|
kScratchRegister);
|
||||||
|
not_numbers->Branch(not_equal, left_side, right_side, taken);
|
||||||
|
}
|
||||||
|
__ movsd(xmm_reg, FieldOperand(operand->reg(), HeapNumber::kValueOffset));
|
||||||
|
__ jmp(&done);
|
||||||
|
|
||||||
|
__ bind(&smi);
|
||||||
|
// Comvert smi to float and keep the original smi.
|
||||||
|
__ SmiToInteger32(kScratchRegister, operand->reg());
|
||||||
|
__ cvtlsi2sd(xmm_reg, kScratchRegister);
|
||||||
|
__ jmp(&done);
|
||||||
|
}
|
||||||
|
__ bind(&done);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void CodeGenerator::GenerateInlineNumberComparison(Result* left_side,
|
void CodeGenerator::GenerateInlineNumberComparison(Result* left_side,
|
||||||
Result* right_side,
|
Result* right_side,
|
||||||
Condition cc,
|
Condition cc,
|
||||||
ControlDestination* dest) {
|
ControlDestination* dest) {
|
||||||
ASSERT(left_side->is_register());
|
ASSERT(left_side->is_register());
|
||||||
ASSERT(right_side->is_register());
|
ASSERT(right_side->is_register());
|
||||||
// TODO(whesse@chromium.org): Implement this function, and enable the
|
|
||||||
// corresponding flags in the CompareStub.
|
JumpTarget not_numbers;
|
||||||
|
// Load left and right operand into registers xmm0 and xmm1 and compare.
|
||||||
|
LoadComparisonOperand(masm_, left_side, xmm0, left_side, right_side,
|
||||||
|
¬_numbers);
|
||||||
|
LoadComparisonOperand(masm_, right_side, xmm1, left_side, right_side,
|
||||||
|
¬_numbers);
|
||||||
|
__ comisd(xmm0, xmm1);
|
||||||
|
// Bail out if a NaN is involved.
|
||||||
|
not_numbers.Branch(parity_even, left_side, right_side);
|
||||||
|
|
||||||
|
// Split to destination targets based on comparison.
|
||||||
|
left_side->Unuse();
|
||||||
|
right_side->Unuse();
|
||||||
|
dest->true_target()->Branch(DoubleCondition(cc));
|
||||||
|
dest->false_target()->Jump();
|
||||||
|
|
||||||
|
not_numbers.Bind(left_side, right_side);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -7991,12 +8040,12 @@ static int NegativeComparisonResult(Condition cc) {
|
|||||||
|
|
||||||
void CompareStub::Generate(MacroAssembler* masm) {
|
void CompareStub::Generate(MacroAssembler* masm) {
|
||||||
Label call_builtin, done;
|
Label call_builtin, done;
|
||||||
|
// The compare stub returns a positive, negative, or zero 64-bit integer
|
||||||
|
// value in rax, corresponding to result of comparing the two inputs.
|
||||||
// NOTICE! This code is only reached after a smi-fast-case check, so
|
// NOTICE! This code is only reached after a smi-fast-case check, so
|
||||||
// it is certain that at least one operand isn't a smi.
|
// it is certain that at least one operand isn't a smi.
|
||||||
|
|
||||||
// Identical objects can be compared fast, but there are some tricky cases
|
// Two identical objects are equal unless they are both NaN or undefined.
|
||||||
// for NaN and undefined.
|
|
||||||
{
|
{
|
||||||
Label not_identical;
|
Label not_identical;
|
||||||
__ cmpq(rax, rdx);
|
__ cmpq(rax, rdx);
|
||||||
|
Loading…
Reference in New Issue
Block a user