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

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

Issue 2033004: Implement fast load and call of arguments in the presence of eval.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 7 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/arm/codegen-arm.cc ('k') | src/x64/codegen-x64.cc » ('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 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 4713 matching lines...) Expand 10 before | Expand all | Expand 10 after
4724 JumpTarget slow; 4724 JumpTarget slow;
4725 JumpTarget done; 4725 JumpTarget done;
4726 4726
4727 // Generate fast-case code for variables that might be shadowed by 4727 // Generate fast-case code for variables that might be shadowed by
4728 // eval-introduced variables. Eval is used a lot without 4728 // eval-introduced variables. Eval is used a lot without
4729 // introducing variables. In those cases, we do not want to 4729 // introducing variables. In those cases, we do not want to
4730 // perform a runtime call for all variables in the scope 4730 // perform a runtime call for all variables in the scope
4731 // containing the eval. 4731 // containing the eval.
4732 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { 4732 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
4733 result = LoadFromGlobalSlotCheckExtensions(slot, typeof_state, &slow); 4733 result = LoadFromGlobalSlotCheckExtensions(slot, typeof_state, &slow);
4734 // If there was no control flow to slow, we can exit early.
4735 if (!slow.is_linked()) return result;
4736 done.Jump(&result); 4734 done.Jump(&result);
4737 4735
4738 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { 4736 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
4739 Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot(); 4737 Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot();
4740 // Only generate the fast case for locals that rewrite to slots. 4738 Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite();
4741 // This rules out argument loads because eval forces arguments
4742 // access to be through the arguments object.
4743 if (potential_slot != NULL) { 4739 if (potential_slot != NULL) {
4740 // Generate fast case for locals that rewrite to slots.
4744 // Allocate a fresh register to use as a temp in 4741 // Allocate a fresh register to use as a temp in
4745 // ContextSlotOperandCheckExtensions and to hold the result 4742 // ContextSlotOperandCheckExtensions and to hold the result
4746 // value. 4743 // value.
4747 result = allocator()->Allocate(); 4744 result = allocator()->Allocate();
4748 ASSERT(result.is_valid()); 4745 ASSERT(result.is_valid());
4749 __ mov(result.reg(), 4746 __ mov(result.reg(),
4750 ContextSlotOperandCheckExtensions(potential_slot, 4747 ContextSlotOperandCheckExtensions(potential_slot,
4751 result, 4748 result,
4752 &slow)); 4749 &slow));
4753 if (potential_slot->var()->mode() == Variable::CONST) { 4750 if (potential_slot->var()->mode() == Variable::CONST) {
4754 __ cmp(result.reg(), Factory::the_hole_value()); 4751 __ cmp(result.reg(), Factory::the_hole_value());
4755 done.Branch(not_equal, &result); 4752 done.Branch(not_equal, &result);
4756 __ mov(result.reg(), Factory::undefined_value()); 4753 __ mov(result.reg(), Factory::undefined_value());
4757 } 4754 }
4758 // There is always control flow to slow from
4759 // ContextSlotOperandCheckExtensions so we have to jump around
4760 // it.
4761 done.Jump(&result); 4755 done.Jump(&result);
4756 } else if (rewrite != NULL) {
4757 // Generate fast case for argument loads.
4758 Property* property = rewrite->AsProperty();
4759 if (property != NULL) {
4760 VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
4761 Literal* key_literal = property->key()->AsLiteral();
4762 if (obj_proxy != NULL &&
4763 key_literal != NULL &&
4764 obj_proxy->IsArguments() &&
4765 key_literal->handle()->IsSmi()) {
4766 // Load arguments object if there are no eval-introduced
4767 // variables. Then load the argument from the arguments
4768 // object using keyed load.
4769 Result arguments = allocator()->Allocate();
4770 ASSERT(arguments.is_valid());
4771 __ mov(arguments.reg(),
4772 ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(),
4773 arguments,
4774 &slow));
4775 frame_->Push(&arguments);
4776 frame_->Push(key_literal->handle());
4777 result = EmitKeyedLoad();
4778 done.Jump(&result);
4779 }
4780 }
4762 } 4781 }
4763 } 4782 }
4764 4783
4765 slow.Bind(); 4784 slow.Bind();
4766 // A runtime call is inevitable. We eagerly sync frame elements 4785 // A runtime call is inevitable. We eagerly sync frame elements
4767 // to memory so that we can push the arguments directly into place 4786 // to memory so that we can push the arguments directly into place
4768 // on top of the frame. 4787 // on top of the frame.
4769 frame()->SyncRange(0, frame()->element_count() - 1); 4788 frame()->SyncRange(0, frame()->element_count() - 1);
4770 frame()->EmitPush(esi); 4789 frame()->EmitPush(esi);
4771 frame()->EmitPush(Immediate(slot->var()->name())); 4790 frame()->EmitPush(Immediate(slot->var()->name()));
(...skipping 986 matching lines...) Expand 10 before | Expand all | Expand 10 after
5758 arg_count, 5777 arg_count,
5759 loop_nesting()); 5778 loop_nesting());
5760 frame_->RestoreContextRegister(); 5779 frame_->RestoreContextRegister();
5761 frame_->Push(&result); 5780 frame_->Push(&result);
5762 5781
5763 } else if (var != NULL && var->slot() != NULL && 5782 } else if (var != NULL && var->slot() != NULL &&
5764 var->slot()->type() == Slot::LOOKUP) { 5783 var->slot()->type() == Slot::LOOKUP) {
5765 // ---------------------------------- 5784 // ----------------------------------
5766 // JavaScript examples: 5785 // JavaScript examples:
5767 // 5786 //
5768 // with (obj) foo(1, 2, 3) // foo is in obj 5787 // with (obj) foo(1, 2, 3) // foo may be in obj.
5769 // 5788 //
5770 // function f() {}; 5789 // function f() {};
5771 // function g() { 5790 // function g() {
5772 // eval(...); 5791 // eval(...);
5773 // f(); // f could be in extension object 5792 // f(); // f could be in extension object.
5774 // } 5793 // }
5775 // ---------------------------------- 5794 // ----------------------------------
5776 5795
5777 JumpTarget slow; 5796 JumpTarget slow;
5778 JumpTarget done; 5797 JumpTarget done;
5779 5798
5780 // Generate fast-case code for variables that might be shadowed by 5799 // Generate fast-case code for variables that might be shadowed by
5781 // eval-introduced variables. Eval is used a lot without 5800 // eval-introduced variables. Eval is used a lot without
5782 // introducing variables. In those cases, we do not want to 5801 // introducing variables. In those cases, we do not want to
5783 // perform a runtime call for all variables in the scope 5802 // perform a runtime call for all variables in the scope
5784 // containing the eval. 5803 // containing the eval.
5785 Result function;
5786 if (var->mode() == Variable::DYNAMIC_GLOBAL) { 5804 if (var->mode() == Variable::DYNAMIC_GLOBAL) {
5787 function = LoadFromGlobalSlotCheckExtensions(var->slot(), 5805 Result function = LoadFromGlobalSlotCheckExtensions(var->slot(),
5788 NOT_INSIDE_TYPEOF, 5806 NOT_INSIDE_TYPEOF,
5789 &slow); 5807 &slow);
5790 frame_->Push(&function); 5808 frame_->Push(&function);
5791 LoadGlobalReceiver(); 5809 LoadGlobalReceiver();
5792 done.Jump(); 5810 done.Jump();
5793 5811
5794 } else if (var->mode() == Variable::DYNAMIC_LOCAL) { 5812 } else if (var->mode() == Variable::DYNAMIC_LOCAL) {
5795 Slot* potential_slot = var->local_if_not_shadowed()->slot(); 5813 Slot* potential_slot = var->local_if_not_shadowed()->slot();
5796 // Only generate the fast case for locals that rewrite to slots. 5814 Expression* rewrite = var->local_if_not_shadowed()->rewrite();
5797 // This rules out argument loads because eval forces arguments
5798 // access to be through the arguments object.
5799 if (potential_slot != NULL) { 5815 if (potential_slot != NULL) {
5816 // Generate fast case for locals that rewrite to slots.
5800 // Allocate a fresh register to use as a temp in 5817 // Allocate a fresh register to use as a temp in
5801 // ContextSlotOperandCheckExtensions and to hold the result 5818 // ContextSlotOperandCheckExtensions and to hold the result
5802 // value. 5819 // value.
5803 function = allocator()->Allocate(); 5820 Result function = allocator()->Allocate();
5804 ASSERT(function.is_valid()); 5821 ASSERT(function.is_valid());
5805 __ mov(function.reg(), 5822 __ mov(function.reg(),
5806 ContextSlotOperandCheckExtensions(potential_slot, 5823 ContextSlotOperandCheckExtensions(potential_slot,
5807 function, 5824 function,
5808 &slow)); 5825 &slow));
5809 JumpTarget push_function_and_receiver; 5826 JumpTarget push_function_and_receiver;
5810 if (potential_slot->var()->mode() == Variable::CONST) { 5827 if (potential_slot->var()->mode() == Variable::CONST) {
5811 __ cmp(function.reg(), Factory::the_hole_value()); 5828 __ cmp(function.reg(), Factory::the_hole_value());
5812 push_function_and_receiver.Branch(not_equal, &function); 5829 push_function_and_receiver.Branch(not_equal, &function);
5813 __ mov(function.reg(), Factory::undefined_value()); 5830 __ mov(function.reg(), Factory::undefined_value());
5814 } 5831 }
5815 push_function_and_receiver.Bind(&function); 5832 push_function_and_receiver.Bind(&function);
5816 frame_->Push(&function); 5833 frame_->Push(&function);
5817 LoadGlobalReceiver(); 5834 LoadGlobalReceiver();
5818 done.Jump(); 5835 done.Jump();
5836 } else if (rewrite != NULL) {
5837 // Generate fast case for calls of an argument function.
5838 Property* property = rewrite->AsProperty();
5839 if (property != NULL) {
5840 VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
5841 Literal* key_literal = property->key()->AsLiteral();
5842 if (obj_proxy != NULL &&
5843 key_literal != NULL &&
5844 obj_proxy->IsArguments() &&
5845 key_literal->handle()->IsSmi()) {
5846 // Load arguments object if there are no eval-introduced
5847 // variables. Then load the argument from the arguments
5848 // object using keyed load.
5849 Result arguments = allocator()->Allocate();
5850 ASSERT(arguments.is_valid());
5851 __ mov(arguments.reg(),
5852 ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(),
5853 arguments,
5854 &slow));
5855 frame_->Push(&arguments);
5856 frame_->Push(key_literal->handle());
5857 Result value = EmitKeyedLoad();
5858 frame_->Push(&value);
5859 LoadGlobalReceiver();
5860 done.Jump();
5861 }
5862 }
5819 } 5863 }
5820 } 5864 }
5821 5865
5822 slow.Bind(); 5866 slow.Bind();
5823 // Enter the runtime system to load the function from the context. 5867 // Enter the runtime system to load the function from the context.
5824 // Sync the frame so we can push the arguments directly into 5868 // Sync the frame so we can push the arguments directly into
5825 // place. 5869 // place.
5826 frame_->SyncRange(0, frame_->element_count() - 1); 5870 frame_->SyncRange(0, frame_->element_count() - 1);
5827 frame_->EmitPush(esi); 5871 frame_->EmitPush(esi);
5828 frame_->EmitPush(Immediate(var->name())); 5872 frame_->EmitPush(Immediate(var->name()));
(...skipping 7465 matching lines...) Expand 10 before | Expand all | Expand 10 after
13294 13338
13295 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 13339 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
13296 // tagged as a small integer. 13340 // tagged as a small integer.
13297 __ bind(&runtime); 13341 __ bind(&runtime);
13298 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 13342 __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
13299 } 13343 }
13300 13344
13301 #undef __ 13345 #undef __
13302 13346
13303 } } // namespace v8::internal 13347 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm/codegen-arm.cc ('k') | src/x64/codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698