Index: src/arm/codegen-arm.cc |
=================================================================== |
--- src/arm/codegen-arm.cc (revision 5606) |
+++ src/arm/codegen-arm.cc (working copy) |
@@ -6048,6 +6048,69 @@ |
} |
+class DeferredCountOperation: public DeferredCode { |
+ public: |
+ DeferredCountOperation(Register value, |
+ bool is_increment, |
+ bool is_postfix, |
+ int target_size) |
+ : value_(value), |
+ is_increment_(is_increment), |
+ is_postfix_(is_postfix), |
+ target_size_(target_size) {} |
+ |
+ virtual void Generate() { |
+ VirtualFrame copied_frame(*frame_state()->frame()); |
+ |
+ Label slow; |
+ // Check for smi operand. |
+ __ tst(value_, Operand(kSmiTagMask)); |
+ __ b(ne, &slow); |
+ |
+ // Revert optimistic increment/decrement. |
+ if (is_increment_) { |
+ __ sub(value_, value_, Operand(Smi::FromInt(1))); |
+ } else { |
+ __ add(value_, value_, Operand(Smi::FromInt(1))); |
+ } |
+ |
+ // Slow case: Convert to number. At this point the |
+ // value to be incremented is in the value register.. |
+ __ bind(&slow); |
+ |
+ // Convert the operand to a number. |
+ copied_frame.EmitPush(value_); |
+ |
+ copied_frame.InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, 1); |
+ |
+ if (is_postfix_) { |
+ // Postfix: store to result (on the stack). |
+ __ str(r0, MemOperand(sp, target_size_ * kPointerSize)); |
+ } |
+ |
+ copied_frame.EmitPush(r0); |
+ copied_frame.EmitPush(Operand(Smi::FromInt(1))); |
+ |
+ if (is_increment_) { |
+ copied_frame.CallRuntime(Runtime::kNumberAdd, 2); |
+ } else { |
+ copied_frame.CallRuntime(Runtime::kNumberSub, 2); |
+ } |
+ |
+ if (!value_.is(r0)) |
Erik Corry
2010/11/24 09:56:33
The 'if' is not needed. I corrected this.
|
+ __ Move(value_, r0); |
+ |
+ copied_frame.MergeTo(frame_state()->frame()); |
+ } |
+ |
+ private: |
+ Register value_; |
+ bool is_increment_; |
+ bool is_postfix_; |
+ int target_size_; |
+}; |
+ |
+ |
void CodeGenerator::VisitCountOperation(CountOperation* node) { |
#ifdef DEBUG |
int original_height = frame_->height(); |
@@ -6107,9 +6170,6 @@ |
// the target. It also pushes the current value of the target. |
target.GetValue(); |
- JumpTarget slow; |
- JumpTarget exit; |
- |
Register value = frame_->PopToRegister(); |
// Postfix: Store the old value as the result. |
@@ -6123,8 +6183,14 @@ |
// Check for smi operand. |
__ tst(value, Operand(kSmiTagMask)); |
- slow.Branch(ne); |
+ DeferredCode* deferred = |
+ new DeferredCountOperation(value, |
+ is_increment, |
+ is_postfix, |
+ target.size()); |
+ deferred->Branch(ne); |
+ |
// Perform optimistic increment/decrement. |
if (is_increment) { |
__ add(value, value, Operand(Smi::FromInt(1)), SetCC); |
@@ -6132,46 +6198,13 @@ |
__ sub(value, value, Operand(Smi::FromInt(1)), SetCC); |
} |
- // If the increment/decrement didn't overflow, we're done. |
- exit.Branch(vc); |
+ // If increment/decrement overflows, go to deferred code. |
+ deferred->Branch(vs); |
- // Revert optimistic increment/decrement. |
- if (is_increment) { |
- __ sub(value, value, Operand(Smi::FromInt(1))); |
- } else { |
- __ add(value, value, Operand(Smi::FromInt(1))); |
- } |
+ deferred->BindExit(); |
- // Slow case: Convert to number. At this point the |
- // value to be incremented is in the value register.. |
- slow.Bind(); |
- |
- // Convert the operand to a number. |
- frame_->EmitPush(value); |
- |
- { |
- VirtualFrame::SpilledScope spilled(frame_); |
- frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, 1); |
- |
- if (is_postfix) { |
- // Postfix: store to result (on the stack). |
- __ str(r0, frame_->ElementAt(target.size())); |
- } |
- |
- // Compute the new value. |
- frame_->EmitPush(r0); |
- frame_->EmitPush(Operand(Smi::FromInt(1))); |
- if (is_increment) { |
- frame_->CallRuntime(Runtime::kNumberAdd, 2); |
- } else { |
- frame_->CallRuntime(Runtime::kNumberSub, 2); |
- } |
- } |
- |
- __ Move(value, r0); |
// Store the new value in the target if not const. |
// At this point the answer is in the value register. |
- exit.Bind(); |
frame_->EmitPush(value); |
// Set the target with the result, leaving the result on |
// top of the stack. Removes the target from the stack if |