Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1361)

Side by Side Diff: src/codegen-ia32.cc

Issue 56151: Rewrite of VisitCountOperation that should speed it up (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/codegen-arm.cc ('k') | src/runtime.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 4706 matching lines...) Expand 10 before | Expand all | Expand 10 after
4717 } 4717 }
4718 } 4718 }
4719 } 4719 }
4720 4720
4721 4721
4722 class DeferredCountOperation: public DeferredCode { 4722 class DeferredCountOperation: public DeferredCode {
4723 public: 4723 public:
4724 DeferredCountOperation(CodeGenerator* generator, 4724 DeferredCountOperation(CodeGenerator* generator,
4725 bool is_postfix, 4725 bool is_postfix,
4726 bool is_increment, 4726 bool is_increment,
4727 int result_offset) 4727 int target_size)
4728 : DeferredCode(generator), 4728 : DeferredCode(generator),
4729 is_postfix_(is_postfix), 4729 is_postfix_(is_postfix),
4730 is_increment_(is_increment), 4730 is_increment_(is_increment),
4731 result_offset_(result_offset) { 4731 target_size_(target_size) {
4732 set_comment("[ DeferredCountOperation"); 4732 set_comment("[ DeferredCountOperation");
4733 } 4733 }
4734 4734
4735 virtual void Generate(); 4735 virtual void Generate();
4736 4736
4737 private: 4737 private:
4738 bool is_postfix_; 4738 bool is_postfix_;
4739 bool is_increment_; 4739 bool is_increment_;
4740 int result_offset_; 4740 int target_size_;
4741 };
4742
4743
4744 class RevertToNumberStub: public CodeStub {
4745 public:
4746 explicit RevertToNumberStub(bool is_increment)
4747 : is_increment_(is_increment) { }
4748
4749 private:
4750 bool is_increment_;
4751
4752 Major MajorKey() { return RevertToNumber; }
4753 int MinorKey() { return is_increment_ ? 1 : 0; }
4754 void Generate(MacroAssembler* masm);
4755
4756 #ifdef DEBUG
4757 void Print() {
4758 PrintF("RevertToNumberStub (is_increment %s)\n",
4759 is_increment_ ? "true" : "false");
4760 }
4761 #endif
4762 };
4763
4764
4765 class CounterOpStub: public CodeStub {
4766 public:
4767 CounterOpStub(int result_offset, bool is_postfix, bool is_increment)
4768 : result_offset_(result_offset),
4769 is_postfix_(is_postfix),
4770 is_increment_(is_increment) { }
4771
4772 private:
4773 int result_offset_;
4774 bool is_postfix_;
4775 bool is_increment_;
4776
4777 Major MajorKey() { return CounterOp; }
4778 int MinorKey() {
4779 return ((result_offset_ << 2) |
4780 (is_postfix_ ? 2 : 0) |
4781 (is_increment_ ? 1 : 0));
4782 }
4783 void Generate(MacroAssembler* masm);
4784
4785 #ifdef DEBUG
4786 void Print() {
4787 PrintF("CounterOpStub (result_offset %d), (is_postfix %s),"
4788 " (is_increment %s)\n",
4789 result_offset_,
4790 is_postfix_ ? "true" : "false",
4791 is_increment_ ? "true" : "false");
4792 }
4793 #endif
4794 }; 4741 };
4795 4742
4796 4743
4797 void DeferredCountOperation::Generate() { 4744 void DeferredCountOperation::Generate() {
4798 CodeGenerator* cgen = generator(); 4745 CodeGenerator* cgen = generator();
4799
4800 Result value(cgen); 4746 Result value(cgen);
4801 enter()->Bind(&value); 4747 enter()->Bind(&value);
4802 if (is_postfix_) { 4748 VirtualFrame* frame = cgen->frame();
4803 RevertToNumberStub to_number_stub(is_increment_); 4749 // Undo the optimistic smi operation.
4804 value = generator()->frame()->CallStub(&to_number_stub, &value); 4750 value.ToRegister();
4751 frame->Spill(value.reg());
4752 if (is_increment_) {
4753 __ sub(Operand(value.reg()), Immediate(Smi::FromInt(1)));
4754 } else {
4755 __ add(Operand(value.reg()), Immediate(Smi::FromInt(1)));
4805 } 4756 }
4806 4757 frame->Push(&value);
4807 CounterOpStub stub(result_offset_, is_postfix_, is_increment_); 4758 value = frame->InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION, 1);
4808 value = generator()->frame()->CallStub(&stub, &value); 4759 frame->Push(&value);
4760 if (is_postfix_) { // Fix up copy of old value with ToNumber(value).
4761 // This is only safe because VisitCountOperation makes this frame slot
4762 // beneath the reference a register, which is spilled at the above call.
4763 // We cannot safely write to constants or copies below the water line.
4764 frame->StoreToElementAt(target_size_ + 1);
4765 }
4766 frame->Push(Smi::FromInt(1));
4767 if (is_increment_) {
4768 value = frame->CallRuntime(Runtime::kNumberAdd, 2);
4769 } else {
4770 value = frame->CallRuntime(Runtime::kNumberSub, 2);
4771 }
4809 exit_.Jump(&value); 4772 exit_.Jump(&value);
4810 } 4773 }
4811 4774
4812 4775
4813 void CodeGenerator::VisitCountOperation(CountOperation* node) { 4776 void CodeGenerator::VisitCountOperation(CountOperation* node) {
4814 Comment cmnt(masm_, "[ CountOperation"); 4777 Comment cmnt(masm_, "[ CountOperation");
4815 4778
4816 bool is_postfix = node->is_postfix(); 4779 bool is_postfix = node->is_postfix();
4817 bool is_increment = node->op() == Token::INC; 4780 bool is_increment = node->op() == Token::INC;
4818 4781
4819 Variable* var = node->expression()->AsVariableProxy()->AsVariable(); 4782 Variable* var = node->expression()->AsVariableProxy()->AsVariable();
4820 bool is_const = (var != NULL && var->mode() == Variable::CONST); 4783 bool is_const = (var != NULL && var->mode() == Variable::CONST);
4821 4784
4822 // Postfix: Make room for the result. 4785 // Postfix operators need a stack slot under the reference to hold
4786 // the old value while the new one is being stored.
4823 if (is_postfix) { 4787 if (is_postfix) {
4824 frame_->Push(Smi::FromInt(0)); 4788 frame_->Push(Smi::FromInt(0));
4825 } 4789 }
4826 4790
4827 { Reference target(this, node->expression()); 4791 { Reference target(this, node->expression());
4828 if (target.is_illegal()) { 4792 if (target.is_illegal()) {
4829 // Spoof the virtual frame to have the expected height (one higher 4793 // Spoof the virtual frame to have the expected height (one higher
4830 // than on entry). 4794 // than on entry).
4831 if (!is_postfix) { 4795 if (!is_postfix) {
4832 frame_->Push(Smi::FromInt(0)); 4796 frame_->Push(Smi::FromInt(0));
4833 } 4797 }
4834 return; 4798 return;
4835 } 4799 }
4836 target.TakeValue(NOT_INSIDE_TYPEOF); 4800 target.TakeValue(NOT_INSIDE_TYPEOF);
4837 4801
4838 DeferredCountOperation* deferred = 4802 DeferredCountOperation* deferred =
4839 new DeferredCountOperation(this, is_postfix, is_increment, 4803 new DeferredCountOperation(this, is_postfix,
4840 target.size() * kPointerSize); 4804 is_increment, target.size());
4841 4805
4842 Result value = frame_->Pop(); 4806 Result value = frame_->Pop();
4843 value.ToRegister(); 4807 value.ToRegister();
4844 ASSERT(value.is_valid());
4845 4808
4846 // Postfix: Store the old value as the result. 4809 // Postfix: Store the old value as the result.
4847 if (is_postfix) { 4810 if (is_postfix) {
4848 Result old_value = value; 4811 // Explicitly back the slot for the old value with a new register.
4812 // This improves performance in some cases.
4813 Result old_value = allocator_->Allocate();
4814 ASSERT(old_value.is_valid());
4815 __ mov(old_value.reg(), value.reg());
4816 // SetElement must not create a constant element or a copy in this slot,
4817 // since we will write to it, below the waterline, in deferred code.
4849 frame_->SetElementAt(target.size(), &old_value); 4818 frame_->SetElementAt(target.size(), &old_value);
4850 } 4819 }
4851 4820
4852 // Perform optimistic increment/decrement. Ensure the value is 4821 // Perform optimistic increment/decrement. Ensure the value is
4853 // writable. 4822 // writable.
4854 frame_->Spill(value.reg()); 4823 frame_->Spill(value.reg());
4855 ASSERT(allocator_->count(value.reg()) == 1); 4824 ASSERT(allocator_->count(value.reg()) == 1);
4856 4825
4857 // In order to combine the overflow and the smi check, we need to 4826 // In order to combine the overflow and the smi check, we need to
4858 // be able to allocate a byte register. We attempt to do so 4827 // be able to allocate a byte register. We attempt to do so
(...skipping 19 matching lines...) Expand all
4878 // slow-case code. 4847 // slow-case code.
4879 // 4848 //
4880 // We combine the overflow and the smi check if we could 4849 // We combine the overflow and the smi check if we could
4881 // successfully allocate a temporary byte register. 4850 // successfully allocate a temporary byte register.
4882 if (tmp.is_valid()) { 4851 if (tmp.is_valid()) {
4883 __ setcc(overflow, tmp.reg()); 4852 __ setcc(overflow, tmp.reg());
4884 __ or_(Operand(value.reg()), tmp.reg()); 4853 __ or_(Operand(value.reg()), tmp.reg());
4885 tmp.Unuse(); 4854 tmp.Unuse();
4886 __ test(value.reg(), Immediate(kSmiTagMask)); 4855 __ test(value.reg(), Immediate(kSmiTagMask));
4887 deferred->enter()->Branch(not_zero, &value, not_taken); 4856 deferred->enter()->Branch(not_zero, &value, not_taken);
4888 } else { 4857 } else { // Otherwise we test separately for overflow and smi check.
4889 deferred->enter()->Branch(overflow, &value, not_taken); 4858 deferred->enter()->Branch(overflow, &value, not_taken);
4890 __ test(value.reg(), Immediate(kSmiTagMask)); 4859 __ test(value.reg(), Immediate(kSmiTagMask));
4891 deferred->enter()->Branch(not_zero, &value, not_taken); 4860 deferred->enter()->Branch(not_zero, &value, not_taken);
4892 } 4861 }
4893 4862
4894 // Store the new value in the target if not const. 4863 // Store the new value in the target if not const.
4895 deferred->BindExit(&value); 4864 deferred->BindExit(&value);
4896 frame_->Push(&value); 4865 frame_->Push(&value);
4897 if (!is_const) { 4866 if (!is_const) {
4898 target.SetValue(NOT_CONST_INIT); 4867 target.SetValue(NOT_CONST_INIT);
(...skipping 1871 matching lines...) Expand 10 before | Expand all | Expand 10 after
6770 // Slow-case: Non-function called. 6739 // Slow-case: Non-function called.
6771 __ bind(&slow); 6740 __ bind(&slow);
6772 __ Set(eax, Immediate(argc_)); 6741 __ Set(eax, Immediate(argc_));
6773 __ Set(ebx, Immediate(0)); 6742 __ Set(ebx, Immediate(0));
6774 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); 6743 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);
6775 Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)); 6744 Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline));
6776 __ jmp(adaptor, RelocInfo::CODE_TARGET); 6745 __ jmp(adaptor, RelocInfo::CODE_TARGET);
6777 } 6746 }
6778 6747
6779 6748
6780 void RevertToNumberStub::Generate(MacroAssembler* masm) {
6781 // Revert optimistic increment/decrement.
6782 if (is_increment_) {
6783 __ sub(Operand(eax), Immediate(Smi::FromInt(1)));
6784 } else {
6785 __ add(Operand(eax), Immediate(Smi::FromInt(1)));
6786 }
6787
6788 __ pop(ecx);
6789 __ push(eax);
6790 __ push(ecx);
6791 __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION);
6792 // Code never returns due to JUMP_FUNCTION.
6793 }
6794
6795
6796 void CounterOpStub::Generate(MacroAssembler* masm) {
6797 // Store to the result on the stack (skip return address) before
6798 // performing the count operation.
6799 if (is_postfix_) {
6800 __ mov(Operand(esp, result_offset_ + kPointerSize), eax);
6801 }
6802
6803 // Revert optimistic increment/decrement but only for prefix
6804 // counts. For postfix counts it has already been reverted before
6805 // the conversion to numbers.
6806 if (!is_postfix_) {
6807 if (is_increment_) {
6808 __ sub(Operand(eax), Immediate(Smi::FromInt(1)));
6809 } else {
6810 __ add(Operand(eax), Immediate(Smi::FromInt(1)));
6811 }
6812 }
6813
6814 // Compute the new value by calling the right JavaScript native.
6815 __ pop(ecx);
6816 __ push(eax);
6817 __ push(ecx);
6818 Builtins::JavaScript builtin = is_increment_ ? Builtins::INC : Builtins::DEC;
6819 __ InvokeBuiltin(builtin, JUMP_FUNCTION);
6820 // Code never returns due to JUMP_FUNCTION.
6821 }
6822
6823 6749
6824 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { 6750 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
6825 ASSERT(StackHandlerConstants::kSize == 6 * kPointerSize); // adjust this code 6751 ASSERT(StackHandlerConstants::kSize == 6 * kPointerSize); // adjust this code
6826 ExternalReference handler_address(Top::k_handler_address); 6752 ExternalReference handler_address(Top::k_handler_address);
6827 __ mov(edx, Operand::StaticVariable(handler_address)); 6753 __ mov(edx, Operand::StaticVariable(handler_address));
6828 __ mov(ecx, Operand(edx, -1 * kPointerSize)); // get next in chain 6754 __ mov(ecx, Operand(edx, -1 * kPointerSize)); // get next in chain
6829 __ mov(Operand::StaticVariable(handler_address), ecx); 6755 __ mov(Operand::StaticVariable(handler_address), ecx);
6830 __ mov(esp, Operand(edx)); 6756 __ mov(esp, Operand(edx));
6831 __ pop(edi); 6757 __ pop(edi);
6832 __ pop(ebp); 6758 __ pop(ebp);
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after
7175 7101
7176 // Slow-case: Go through the JavaScript implementation. 7102 // Slow-case: Go through the JavaScript implementation.
7177 __ bind(&slow); 7103 __ bind(&slow);
7178 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 7104 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
7179 } 7105 }
7180 7106
7181 7107
7182 #undef __ 7108 #undef __
7183 7109
7184 } } // namespace v8::internal 7110 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/codegen-arm.cc ('k') | src/runtime.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698