| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 3743 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3754 " (is_increment %s)\n", | 3754 " (is_increment %s)\n", |
| 3755 result_offset_, | 3755 result_offset_, |
| 3756 is_postfix_ ? "true" : "false", | 3756 is_postfix_ ? "true" : "false", |
| 3757 is_increment_ ? "true" : "false"); | 3757 is_increment_ ? "true" : "false"); |
| 3758 } | 3758 } |
| 3759 #endif | 3759 #endif |
| 3760 }; | 3760 }; |
| 3761 | 3761 |
| 3762 | 3762 |
| 3763 void DeferredCountOperation::Generate() { | 3763 void DeferredCountOperation::Generate() { |
| 3764 // The argument is actually passed in eax. | 3764 CodeGenerator* cgen = generator(); |
| 3765 enter()->Bind(); | 3765 |
| 3766 VirtualFrame::SpilledScope spilled_scope(generator()); | 3766 // The argument will be passed in a register and the result returned in |
| 3767 // the same register. |
| 3768 Result value(cgen); |
| 3769 enter()->Bind(&value); |
| 3770 ASSERT(value.is_register()); |
| 3771 Register target = value.reg(); |
| 3772 value.ToRegister(eax); // The stubs below expect their argument in eax. |
| 3773 |
| 3767 if (is_postfix_) { | 3774 if (is_postfix_) { |
| 3768 RevertToNumberStub to_number_stub(is_increment_); | 3775 RevertToNumberStub to_number_stub(is_increment_); |
| 3769 generator()->frame()->CallStub(&to_number_stub, 0); | 3776 value = generator()->frame()->CallStub(&to_number_stub, &value, 0); |
| 3770 } | 3777 } |
| 3778 |
| 3771 CounterOpStub stub(result_offset_, is_postfix_, is_increment_); | 3779 CounterOpStub stub(result_offset_, is_postfix_, is_increment_); |
| 3772 generator()->frame()->CallStub(&stub, 0); | 3780 value = generator()->frame()->CallStub(&stub, &value, 0); |
| 3773 // The result is actually returned in eax. | 3781 value.ToRegister(target); |
| 3774 exit()->Jump(); | 3782 exit()->Jump(&value); |
| 3775 } | 3783 } |
| 3776 | 3784 |
| 3777 | 3785 |
| 3778 void CodeGenerator::VisitCountOperation(CountOperation* node) { | 3786 void CodeGenerator::VisitCountOperation(CountOperation* node) { |
| 3779 VirtualFrame::SpilledScope spilled_scope(this); | |
| 3780 Comment cmnt(masm_, "[ CountOperation"); | 3787 Comment cmnt(masm_, "[ CountOperation"); |
| 3781 | 3788 |
| 3782 bool is_postfix = node->is_postfix(); | 3789 bool is_postfix = node->is_postfix(); |
| 3783 bool is_increment = node->op() == Token::INC; | 3790 bool is_increment = node->op() == Token::INC; |
| 3784 | 3791 |
| 3785 Variable* var = node->expression()->AsVariableProxy()->AsVariable(); | 3792 Variable* var = node->expression()->AsVariableProxy()->AsVariable(); |
| 3786 bool is_const = (var != NULL && var->mode() == Variable::CONST); | 3793 bool is_const = (var != NULL && var->mode() == Variable::CONST); |
| 3787 | 3794 |
| 3788 // Postfix: Make room for the result. | 3795 // Postfix: Make room for the result. |
| 3789 if (is_postfix) { | 3796 if (is_postfix) { |
| 3790 frame_->EmitPush(Immediate(0)); | 3797 frame_->Push(Handle<Object>(Smi::FromInt(0))); |
| 3791 } | 3798 } |
| 3792 | 3799 |
| 3793 { Reference target(this, node->expression()); | 3800 { Reference target(this, node->expression()); |
| 3794 if (target.is_illegal()) { | 3801 if (target.is_illegal()) { |
| 3795 // Spoof the virtual frame to have the expected height (one higher | 3802 // Spoof the virtual frame to have the expected height (one higher |
| 3796 // than on entry). | 3803 // than on entry). |
| 3797 if (!is_postfix) { | 3804 if (!is_postfix) { |
| 3798 frame_->EmitPush(Immediate(Smi::FromInt(0))); | 3805 frame_->Push(Handle<Object>(Smi::FromInt(0))); |
| 3799 } | 3806 } |
| 3800 return; | 3807 return; |
| 3801 } | 3808 } |
| 3802 target.GetValueAndSpill(NOT_INSIDE_TYPEOF); | 3809 target.TakeValue(NOT_INSIDE_TYPEOF); |
| 3803 | 3810 |
| 3804 DeferredCountOperation* deferred = | 3811 DeferredCountOperation* deferred = |
| 3805 new DeferredCountOperation(this, is_postfix, is_increment, | 3812 new DeferredCountOperation(this, is_postfix, is_increment, |
| 3806 target.size() * kPointerSize); | 3813 target.size() * kPointerSize); |
| 3807 | 3814 |
| 3808 frame_->EmitPop(eax); // Load TOS into eax for calculations below | 3815 Result value = frame_->Pop(); |
| 3816 value.ToRegister(); |
| 3817 ASSERT(value.is_valid()); |
| 3809 | 3818 |
| 3810 // Postfix: Store the old value as the result. | 3819 // Postfix: Store the old value as the result. |
| 3811 if (is_postfix) { | 3820 if (is_postfix) { |
| 3812 __ mov(frame_->ElementAt(target.size()), eax); | 3821 Result old_value = value; |
| 3822 frame_->SetElementAt(target.size(), &old_value); |
| 3813 } | 3823 } |
| 3814 | 3824 |
| 3815 // Perform optimistic increment/decrement. | 3825 // Perform optimistic increment/decrement. Ensure the value is |
| 3826 // writable. |
| 3827 frame_->Spill(value.reg()); |
| 3828 ASSERT(allocator_->count(value.reg()) == 1); |
| 3816 if (is_increment) { | 3829 if (is_increment) { |
| 3817 __ add(Operand(eax), Immediate(Smi::FromInt(1))); | 3830 __ add(Operand(value.reg()), Immediate(Smi::FromInt(1))); |
| 3818 } else { | 3831 } else { |
| 3819 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); | 3832 __ sub(Operand(value.reg()), Immediate(Smi::FromInt(1))); |
| 3820 } | 3833 } |
| 3821 | 3834 |
| 3822 // If the count operation didn't overflow and the result is a | 3835 // If the count operation didn't overflow and the result is a |
| 3823 // valid smi, we're done. Otherwise, we jump to the deferred | 3836 // valid smi, we're done. Otherwise, we jump to the deferred |
| 3824 // slow-case code. | 3837 // slow-case code. |
| 3825 deferred->enter()->Branch(overflow, not_taken); | 3838 deferred->enter()->Branch(overflow, &value, not_taken); |
| 3826 __ test(eax, Immediate(kSmiTagMask)); | 3839 __ test(value.reg(), Immediate(kSmiTagMask)); |
| 3827 deferred->enter()->Branch(not_zero, not_taken); | 3840 deferred->enter()->Branch(not_zero, &value, not_taken); |
| 3828 | 3841 |
| 3829 // Store the new value in the target if not const. | 3842 // Store the new value in the target if not const. |
| 3830 deferred->exit()->Bind(); | 3843 deferred->exit()->Bind(&value); |
| 3831 frame_->EmitPush(eax); // Push the new value to TOS | 3844 frame_->Push(&value); |
| 3832 if (!is_const) target.SetValue(NOT_CONST_INIT); | 3845 if (!is_const) { |
| 3846 target.SetValue(NOT_CONST_INIT); |
| 3847 } |
| 3833 } | 3848 } |
| 3834 | 3849 |
| 3835 // Postfix: Discard the new value and use the old. | 3850 // Postfix: Discard the new value and use the old. |
| 3836 if (is_postfix) { | 3851 if (is_postfix) { |
| 3837 frame_->Drop(); | 3852 frame_->Drop(); |
| 3838 } | 3853 } |
| 3839 } | 3854 } |
| 3840 | 3855 |
| 3841 | 3856 |
| 3842 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { | 3857 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { |
| (...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4296 frame->EmitPush(eax); // IC call leaves result in eax, push it out | 4311 frame->EmitPush(eax); // IC call leaves result in eax, push it out |
| 4297 break; | 4312 break; |
| 4298 } | 4313 } |
| 4299 | 4314 |
| 4300 default: | 4315 default: |
| 4301 UNREACHABLE(); | 4316 UNREACHABLE(); |
| 4302 } | 4317 } |
| 4303 } | 4318 } |
| 4304 | 4319 |
| 4305 | 4320 |
| 4321 void Reference::TakeValue(TypeofState typeof_state) { |
| 4322 // For non-constant frame-allocated slots, we invalidate the value in the |
| 4323 // slot. For all others, we fall back on GetValue. |
| 4324 ASSERT(!cgen_->in_spilled_code()); |
| 4325 ASSERT(!is_illegal()); |
| 4326 ASSERT(!cgen_->has_cc()); |
| 4327 if (type_ != SLOT) { |
| 4328 GetValue(typeof_state); |
| 4329 return; |
| 4330 } |
| 4331 |
| 4332 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); |
| 4333 ASSERT(slot != NULL); |
| 4334 if (slot->type() == Slot::LOOKUP || |
| 4335 slot->type() == Slot::CONTEXT || |
| 4336 slot->var()->mode() == Variable::CONST) { |
| 4337 GetValue(typeof_state); |
| 4338 return; |
| 4339 } |
| 4340 |
| 4341 // Only non-constant, frame-allocated parameters and locals can reach |
| 4342 // here. |
| 4343 if (slot->type() == Slot::PARAMETER) { |
| 4344 cgen_->frame()->TakeParameterAt(slot->index()); |
| 4345 } else { |
| 4346 ASSERT(slot->type() == Slot::LOCAL); |
| 4347 cgen_->frame()->TakeLocalAt(slot->index()); |
| 4348 } |
| 4349 } |
| 4350 |
| 4351 |
| 4306 void Reference::SetValue(InitState init_state) { | 4352 void Reference::SetValue(InitState init_state) { |
| 4307 ASSERT(!is_illegal()); | 4353 ASSERT(!is_illegal()); |
| 4308 ASSERT(!cgen_->has_cc()); | 4354 ASSERT(!cgen_->has_cc()); |
| 4309 MacroAssembler* masm = cgen_->masm(); | 4355 MacroAssembler* masm = cgen_->masm(); |
| 4310 VirtualFrame* frame = cgen_->frame(); | 4356 VirtualFrame* frame = cgen_->frame(); |
| 4311 switch (type_) { | 4357 switch (type_) { |
| 4312 case SLOT: { | 4358 case SLOT: { |
| 4313 Comment cmnt(masm, "[ Store to Slot"); | 4359 Comment cmnt(masm, "[ Store to Slot"); |
| 4314 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); | 4360 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); |
| 4315 ASSERT(slot != NULL); | 4361 ASSERT(slot != NULL); |
| (...skipping 1408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5724 | 5770 |
| 5725 // Slow-case: Go through the JavaScript implementation. | 5771 // Slow-case: Go through the JavaScript implementation. |
| 5726 __ bind(&slow); | 5772 __ bind(&slow); |
| 5727 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 5773 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
| 5728 } | 5774 } |
| 5729 | 5775 |
| 5730 | 5776 |
| 5731 #undef __ | 5777 #undef __ |
| 5732 | 5778 |
| 5733 } } // namespace v8::internal | 5779 } } // namespace v8::internal |
| OLD | NEW |