Index: src/x64/codegen-x64.cc |
diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc |
index 50e5aa110e7e82ecea528ff8330f2df786ca272c..bf2aa876700d204517c663adc0cda55d8bf1c042 100644 |
--- a/src/x64/codegen-x64.cc |
+++ b/src/x64/codegen-x64.cc |
@@ -7018,7 +7018,43 @@ Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr, |
left->reg(), |
rcx, |
overwrite_mode); |
- __ JumpIfNotBothSmi(left->reg(), rcx, deferred->entry_label()); |
+ |
+ Label do_op; |
+ if (right_type_info.IsSmi()) { |
+ if (FLAG_debug_code) { |
+ __ AbortIfNotSmi(right->reg()); |
+ } |
+ __ movq(answer.reg(), left->reg()); |
+ // If left is not known to be a smi, check if it is. |
+ // If left is not known to be a number, and it isn't a smi, check if |
+ // it is a HeapNumber. |
+ if (!left_type_info.IsSmi()) { |
+ __ JumpIfSmi(answer.reg(), &do_op); |
+ if (!left_type_info.IsNumber()) { |
+ // Branch if not a heapnumber. |
+ __ Cmp(FieldOperand(answer.reg(), HeapObject::kMapOffset), |
+ Factory::heap_number_map()); |
+ deferred->Branch(not_equal); |
+ } |
+ // Load integer value into answer register using truncation. |
William Hesse
2010/05/21 09:05:27
This is the case we also hope to avoid by using th
|
+ __ cvttsd2si(answer.reg(), |
+ FieldOperand(answer.reg(), HeapNumber::kValueOffset)); |
+ // Branch if we might have overflowed. |
+ // (False negative for Smi::kMinValue) |
+ __ cmpq(answer.reg(), Immediate(0x80000000)); |
+ deferred->Branch(equal); |
+ // TODO(lrn): Inline shifts on int32 here instead of first smi-tagging. |
+ __ Integer32ToSmi(answer.reg(), answer.reg()); |
+ } else { |
+ // Fast case - both are actually smis. |
+ if (FLAG_debug_code) { |
+ __ AbortIfNotSmi(left->reg()); |
+ } |
+ } |
+ } else { |
+ __ JumpIfNotBothSmi(left->reg(), rcx, deferred->entry_label()); |
+ } |
+ __ bind(&do_op); |
// Perform the operation. |
switch (op) { |