Commit 72de9278 authored by erik.corry@gmail.com's avatar erik.corry@gmail.com

ARM: Defer the prefix/postfix code generation. This is a fixed

version of http://codereview.chromium.org/3666001/ by ZhangK with
an added call to ForgetTypeInfo to fix a debug mode assert.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5884 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 0c064efd
......@@ -6024,6 +6024,68 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
}
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);
}
__ 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();
......@@ -6083,9 +6145,7 @@ void CodeGenerator::VisitCountOperation(CountOperation* node) {
// the target. It also pushes the current value of the target.
target.GetValue();
JumpTarget slow;
JumpTarget exit;
bool value_is_known_smi = frame_->KnownSmiAt(0);
Register value = frame_->PopToRegister();
// Postfix: Store the old value as the result.
......@@ -6097,9 +6157,27 @@ void CodeGenerator::VisitCountOperation(CountOperation* node) {
value = VirtualFrame::scratch0();
}
// Check for smi operand.
__ tst(value, Operand(kSmiTagMask));
slow.Branch(ne);
// We can't use any type information here since the virtual frame from the
// deferred code may have lost information and we can't merge a virtual
// frame with less specific type knowledge to a virtual frame with more
// specific knowledge that has already used that specific knowledge to
// generate code.
frame_->ForgetTypeInfo();
// The constructor here will capture the current virtual frame and use it to
// merge to after the deferred code has run. No virtual frame changes are
// allowed from here until the 'BindExit' below.
DeferredCode* deferred =
new DeferredCountOperation(value,
is_increment,
is_postfix,
target.size());
if (!value_is_known_smi) {
// Check for smi operand.
__ tst(value, Operand(kSmiTagMask));
deferred->Branch(ne);
}
// Perform optimistic increment/decrement.
if (is_increment) {
......@@ -6108,46 +6186,13 @@ void CodeGenerator::VisitCountOperation(CountOperation* node) {
__ sub(value, value, Operand(Smi::FromInt(1)), SetCC);
}
// If the increment/decrement didn't overflow, we're done.
exit.Branch(vc);
// Revert optimistic increment/decrement.
if (is_increment) {
__ sub(value, value, Operand(Smi::FromInt(1)));
} else {
__ add(value, value, Operand(Smi::FromInt(1)));
}
// If increment/decrement overflows, go to deferred code.
deferred->Branch(vs);
// 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);
}
}
deferred->BindExit();
__ 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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment