Index: src/ia32/codegen-ia32.cc |
=================================================================== |
--- src/ia32/codegen-ia32.cc (revision 4153) |
+++ src/ia32/codegen-ia32.cc (working copy) |
@@ -1578,6 +1578,7 @@ |
// if right is a smi we make a fast case if left is either a smi |
// or a heapnumber. |
if (CpuFeatures::IsSupported(SSE2) && right->number_info().IsSmi()) { |
+ CpuFeatures::Scope use_sse2(SSE2); |
__ mov(answer.reg(), left->reg()); |
// Fast case - both are actually smis. |
if (!left->number_info().IsSmi()) { |
@@ -1608,6 +1609,7 @@ |
__ SmiUntag(answer.reg()); |
} |
+ __ bind(&do_op); |
__ SmiUntag(ecx); |
// Perform the operation. |
switch (op) { |
@@ -6652,7 +6654,6 @@ |
break; |
} |
frame_->Push(&value); |
- |
} else { |
Load(node->expression()); |
bool overwrite = |
@@ -6663,38 +6664,58 @@ |
GenericUnaryOpStub stub(Token::SUB, overwrite); |
Result operand = frame_->Pop(); |
Result answer = frame_->CallStub(&stub, &operand); |
+ answer.set_number_info(NumberInfo::Number()); |
frame_->Push(&answer); |
break; |
} |
- |
case Token::BIT_NOT: { |
// Smi check. |
JumpTarget smi_label; |
JumpTarget continue_label; |
Result operand = frame_->Pop(); |
+ NumberInfo operand_info = operand.number_info(); |
operand.ToRegister(); |
- __ test(operand.reg(), Immediate(kSmiTagMask)); |
- smi_label.Branch(zero, &operand, taken); |
+ if (operand_info.IsSmi()) { |
+ if (FLAG_debug_code) { |
+ __ AbortIfNotSmi(operand.reg(), "Operand not a smi."); |
+ } |
+ frame_->Spill(operand.reg()); |
+ // Set smi tag bit. It will be reset by the not operation. |
+ __ lea(operand.reg(), Operand(operand.reg(), kSmiTagMask)); |
+ __ not_(operand.reg()); |
+ Result answer = operand; |
+ answer.set_number_info(NumberInfo::Smi()); |
+ frame_->Push(&answer); |
+ } else { |
+ __ test(operand.reg(), Immediate(kSmiTagMask)); |
+ smi_label.Branch(zero, &operand, taken); |
- GenericUnaryOpStub stub(Token::BIT_NOT, overwrite); |
- Result answer = frame_->CallStub(&stub, &operand); |
- continue_label.Jump(&answer); |
+ GenericUnaryOpStub stub(Token::BIT_NOT, overwrite); |
+ Result answer = frame_->CallStub(&stub, &operand); |
+ continue_label.Jump(&answer); |
- smi_label.Bind(&answer); |
- answer.ToRegister(); |
- frame_->Spill(answer.reg()); |
- __ not_(answer.reg()); |
- __ and_(answer.reg(), ~kSmiTagMask); // Remove inverted smi-tag. |
+ smi_label.Bind(&answer); |
+ answer.ToRegister(); |
+ frame_->Spill(answer.reg()); |
+ // Set smi tag bit. It will be reset by the not operation. |
+ __ lea(answer.reg(), Operand(answer.reg(), kSmiTagMask)); |
+ __ not_(answer.reg()); |
- continue_label.Bind(&answer); |
- frame_->Push(&answer); |
+ continue_label.Bind(&answer); |
+ if (operand_info.IsInteger32()) { |
+ answer.set_number_info(NumberInfo::Integer32()); |
+ } else { |
+ answer.set_number_info(NumberInfo::Number()); |
+ } |
+ frame_->Push(&answer); |
+ } |
break; |
} |
- |
case Token::ADD: { |
// Smi check. |
JumpTarget continue_label; |
Result operand = frame_->Pop(); |
+ NumberInfo operand_info = operand.number_info(); |
operand.ToRegister(); |
__ test(operand.reg(), Immediate(kSmiTagMask)); |
continue_label.Branch(zero, &operand, taken); |
@@ -6704,10 +6725,16 @@ |
CALL_FUNCTION, 1); |
continue_label.Bind(&answer); |
+ if (operand_info.IsSmi()) { |
+ answer.set_number_info(NumberInfo::Smi()); |
+ } else if (operand_info.IsInteger32()) { |
+ answer.set_number_info(NumberInfo::Integer32()); |
+ } else { |
+ answer.set_number_info(NumberInfo::Number()); |
+ } |
frame_->Push(&answer); |
break; |
} |
- |
default: |
// NOT, DELETE, TYPEOF, and VOID are handled outside the |
// switch. |