| Index: src/codegen-ia32.cc
|
| ===================================================================
|
| --- src/codegen-ia32.cc (revision 1676)
|
| +++ src/codegen-ia32.cc (working copy)
|
| @@ -4724,11 +4724,11 @@
|
| DeferredCountOperation(CodeGenerator* generator,
|
| bool is_postfix,
|
| bool is_increment,
|
| - int result_offset)
|
| + int target_size)
|
| : DeferredCode(generator),
|
| is_postfix_(is_postfix),
|
| is_increment_(is_increment),
|
| - result_offset_(result_offset) {
|
| + target_size_(target_size) {
|
| set_comment("[ DeferredCountOperation");
|
| }
|
|
|
| @@ -4737,75 +4737,38 @@
|
| private:
|
| bool is_postfix_;
|
| bool is_increment_;
|
| - int result_offset_;
|
| + int target_size_;
|
| };
|
|
|
|
|
| -class RevertToNumberStub: public CodeStub {
|
| - public:
|
| - explicit RevertToNumberStub(bool is_increment)
|
| - : is_increment_(is_increment) { }
|
| -
|
| - private:
|
| - bool is_increment_;
|
| -
|
| - Major MajorKey() { return RevertToNumber; }
|
| - int MinorKey() { return is_increment_ ? 1 : 0; }
|
| - void Generate(MacroAssembler* masm);
|
| -
|
| -#ifdef DEBUG
|
| - void Print() {
|
| - PrintF("RevertToNumberStub (is_increment %s)\n",
|
| - is_increment_ ? "true" : "false");
|
| - }
|
| -#endif
|
| -};
|
| -
|
| -
|
| -class CounterOpStub: public CodeStub {
|
| - public:
|
| - CounterOpStub(int result_offset, bool is_postfix, bool is_increment)
|
| - : result_offset_(result_offset),
|
| - is_postfix_(is_postfix),
|
| - is_increment_(is_increment) { }
|
| -
|
| - private:
|
| - int result_offset_;
|
| - bool is_postfix_;
|
| - bool is_increment_;
|
| -
|
| - Major MajorKey() { return CounterOp; }
|
| - int MinorKey() {
|
| - return ((result_offset_ << 2) |
|
| - (is_postfix_ ? 2 : 0) |
|
| - (is_increment_ ? 1 : 0));
|
| - }
|
| - void Generate(MacroAssembler* masm);
|
| -
|
| -#ifdef DEBUG
|
| - void Print() {
|
| - PrintF("CounterOpStub (result_offset %d), (is_postfix %s),"
|
| - " (is_increment %s)\n",
|
| - result_offset_,
|
| - is_postfix_ ? "true" : "false",
|
| - is_increment_ ? "true" : "false");
|
| - }
|
| -#endif
|
| -};
|
| -
|
| -
|
| void DeferredCountOperation::Generate() {
|
| CodeGenerator* cgen = generator();
|
| -
|
| Result value(cgen);
|
| enter()->Bind(&value);
|
| - if (is_postfix_) {
|
| - RevertToNumberStub to_number_stub(is_increment_);
|
| - value = generator()->frame()->CallStub(&to_number_stub, &value);
|
| + VirtualFrame* frame = cgen->frame();
|
| + // Undo the optimistic smi operation.
|
| + value.ToRegister();
|
| + frame->Spill(value.reg());
|
| + if (is_increment_) {
|
| + __ sub(Operand(value.reg()), Immediate(Smi::FromInt(1)));
|
| + } else {
|
| + __ add(Operand(value.reg()), Immediate(Smi::FromInt(1)));
|
| }
|
| -
|
| - CounterOpStub stub(result_offset_, is_postfix_, is_increment_);
|
| - value = generator()->frame()->CallStub(&stub, &value);
|
| + frame->Push(&value);
|
| + value = frame->InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION, 1);
|
| + frame->Push(&value);
|
| + if (is_postfix_) { // Fix up copy of old value with ToNumber(value).
|
| + // This is only safe because VisitCountOperation makes this frame slot
|
| + // beneath the reference a register, which is spilled at the above call.
|
| + // We cannot safely write to constants or copies below the water line.
|
| + frame->StoreToElementAt(target_size_ + 1);
|
| + }
|
| + frame->Push(Smi::FromInt(1));
|
| + if (is_increment_) {
|
| + value = frame->CallRuntime(Runtime::kNumberAdd, 2);
|
| + } else {
|
| + value = frame->CallRuntime(Runtime::kNumberSub, 2);
|
| + }
|
| exit_.Jump(&value);
|
| }
|
|
|
| @@ -4819,7 +4782,8 @@
|
| Variable* var = node->expression()->AsVariableProxy()->AsVariable();
|
| bool is_const = (var != NULL && var->mode() == Variable::CONST);
|
|
|
| - // Postfix: Make room for the result.
|
| + // Postfix operators need a stack slot under the reference to hold
|
| + // the old value while the new one is being stored.
|
| if (is_postfix) {
|
| frame_->Push(Smi::FromInt(0));
|
| }
|
| @@ -4836,16 +4800,21 @@
|
| target.TakeValue(NOT_INSIDE_TYPEOF);
|
|
|
| DeferredCountOperation* deferred =
|
| - new DeferredCountOperation(this, is_postfix, is_increment,
|
| - target.size() * kPointerSize);
|
| + new DeferredCountOperation(this, is_postfix,
|
| + is_increment, target.size());
|
|
|
| Result value = frame_->Pop();
|
| value.ToRegister();
|
| - ASSERT(value.is_valid());
|
|
|
| // Postfix: Store the old value as the result.
|
| if (is_postfix) {
|
| - Result old_value = value;
|
| + // Explicitly back the slot for the old value with a new register.
|
| + // This improves performance in some cases.
|
| + Result old_value = allocator_->Allocate();
|
| + ASSERT(old_value.is_valid());
|
| + __ mov(old_value.reg(), value.reg());
|
| + // SetElement must not create a constant element or a copy in this slot,
|
| + // since we will write to it, below the waterline, in deferred code.
|
| frame_->SetElementAt(target.size(), &old_value);
|
| }
|
|
|
| @@ -4885,7 +4854,7 @@
|
| tmp.Unuse();
|
| __ test(value.reg(), Immediate(kSmiTagMask));
|
| deferred->enter()->Branch(not_zero, &value, not_taken);
|
| - } else {
|
| + } else { // Otherwise we test separately for overflow and smi check.
|
| deferred->enter()->Branch(overflow, &value, not_taken);
|
| __ test(value.reg(), Immediate(kSmiTagMask));
|
| deferred->enter()->Branch(not_zero, &value, not_taken);
|
| @@ -6777,50 +6746,7 @@
|
| }
|
|
|
|
|
| -void RevertToNumberStub::Generate(MacroAssembler* masm) {
|
| - // Revert optimistic increment/decrement.
|
| - if (is_increment_) {
|
| - __ sub(Operand(eax), Immediate(Smi::FromInt(1)));
|
| - } else {
|
| - __ add(Operand(eax), Immediate(Smi::FromInt(1)));
|
| - }
|
|
|
| - __ pop(ecx);
|
| - __ push(eax);
|
| - __ push(ecx);
|
| - __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION);
|
| - // Code never returns due to JUMP_FUNCTION.
|
| -}
|
| -
|
| -
|
| -void CounterOpStub::Generate(MacroAssembler* masm) {
|
| - // Store to the result on the stack (skip return address) before
|
| - // performing the count operation.
|
| - if (is_postfix_) {
|
| - __ mov(Operand(esp, result_offset_ + kPointerSize), eax);
|
| - }
|
| -
|
| - // Revert optimistic increment/decrement but only for prefix
|
| - // counts. For postfix counts it has already been reverted before
|
| - // the conversion to numbers.
|
| - if (!is_postfix_) {
|
| - if (is_increment_) {
|
| - __ sub(Operand(eax), Immediate(Smi::FromInt(1)));
|
| - } else {
|
| - __ add(Operand(eax), Immediate(Smi::FromInt(1)));
|
| - }
|
| - }
|
| -
|
| - // Compute the new value by calling the right JavaScript native.
|
| - __ pop(ecx);
|
| - __ push(eax);
|
| - __ push(ecx);
|
| - Builtins::JavaScript builtin = is_increment_ ? Builtins::INC : Builtins::DEC;
|
| - __ InvokeBuiltin(builtin, JUMP_FUNCTION);
|
| - // Code never returns due to JUMP_FUNCTION.
|
| -}
|
| -
|
| -
|
| void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
|
| ASSERT(StackHandlerConstants::kSize == 6 * kPointerSize); // adjust this code
|
| ExternalReference handler_address(Top::k_handler_address);
|
|
|