OLD | NEW |
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 4730 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4741 // containing the eval. | 4741 // containing the eval. |
4742 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { | 4742 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { |
4743 result = LoadFromGlobalSlotCheckExtensions(slot, typeof_state, &slow); | 4743 result = LoadFromGlobalSlotCheckExtensions(slot, typeof_state, &slow); |
4744 // If there was no control flow to slow, we can exit early. | 4744 // If there was no control flow to slow, we can exit early. |
4745 if (!slow.is_linked()) return result; | 4745 if (!slow.is_linked()) return result; |
4746 done.Jump(&result); | 4746 done.Jump(&result); |
4747 | 4747 |
4748 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { | 4748 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { |
4749 Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot(); | 4749 Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot(); |
4750 // Only generate the fast case for locals that rewrite to slots. | 4750 // Only generate the fast case for locals that rewrite to slots. |
4751 // This rules out argument loads. | 4751 // This rules out argument loads because eval forces arguments |
| 4752 // access to be through the arguments object. |
4752 if (potential_slot != NULL) { | 4753 if (potential_slot != NULL) { |
4753 // Allocate a fresh register to use as a temp in | 4754 // Allocate a fresh register to use as a temp in |
4754 // ContextSlotOperandCheckExtensions and to hold the result | 4755 // ContextSlotOperandCheckExtensions and to hold the result |
4755 // value. | 4756 // value. |
4756 result = allocator()->Allocate(); | 4757 result = allocator()->Allocate(); |
4757 ASSERT(result.is_valid()); | 4758 ASSERT(result.is_valid()); |
4758 __ mov(result.reg(), | 4759 __ mov(result.reg(), |
4759 ContextSlotOperandCheckExtensions(potential_slot, | 4760 ContextSlotOperandCheckExtensions(potential_slot, |
4760 result, | 4761 result, |
4761 &slow)); | 4762 &slow)); |
(...skipping 1003 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5765 CodeForSourcePosition(node->position()); | 5766 CodeForSourcePosition(node->position()); |
5766 Result result = frame_->CallCallIC(RelocInfo::CODE_TARGET_CONTEXT, | 5767 Result result = frame_->CallCallIC(RelocInfo::CODE_TARGET_CONTEXT, |
5767 arg_count, | 5768 arg_count, |
5768 loop_nesting()); | 5769 loop_nesting()); |
5769 frame_->RestoreContextRegister(); | 5770 frame_->RestoreContextRegister(); |
5770 frame_->Push(&result); | 5771 frame_->Push(&result); |
5771 | 5772 |
5772 } else if (var != NULL && var->slot() != NULL && | 5773 } else if (var != NULL && var->slot() != NULL && |
5773 var->slot()->type() == Slot::LOOKUP) { | 5774 var->slot()->type() == Slot::LOOKUP) { |
5774 // ---------------------------------- | 5775 // ---------------------------------- |
5775 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj | 5776 // JavaScript examples: |
| 5777 // |
| 5778 // with (obj) foo(1, 2, 3) // foo is in obj |
| 5779 // |
| 5780 // function f() {}; |
| 5781 // function g() { |
| 5782 // eval(...); |
| 5783 // f(); // f could be in extension object |
| 5784 // } |
5776 // ---------------------------------- | 5785 // ---------------------------------- |
5777 | 5786 |
5778 // Load the function from the context. Sync the frame so we can | 5787 JumpTarget slow; |
5779 // push the arguments directly into place. | 5788 JumpTarget done; |
| 5789 |
| 5790 // Generate fast-case code for variables that might be shadowed by |
| 5791 // eval-introduced variables. Eval is used a lot without |
| 5792 // introducing variables. In those cases, we do not want to |
| 5793 // perform a runtime call for all variables in the scope |
| 5794 // containing the eval. |
| 5795 Result function; |
| 5796 if (var->mode() == Variable::DYNAMIC_GLOBAL) { |
| 5797 function = LoadFromGlobalSlotCheckExtensions(var->slot(), |
| 5798 NOT_INSIDE_TYPEOF, |
| 5799 &slow); |
| 5800 frame_->Push(&function); |
| 5801 LoadGlobalReceiver(); |
| 5802 done.Jump(); |
| 5803 |
| 5804 } else if (var->mode() == Variable::DYNAMIC_LOCAL) { |
| 5805 Slot* potential_slot = var->local_if_not_shadowed()->slot(); |
| 5806 // Only generate the fast case for locals that rewrite to slots. |
| 5807 // This rules out argument loads because eval forces arguments |
| 5808 // access to be through the arguments object. |
| 5809 if (potential_slot != NULL) { |
| 5810 // Allocate a fresh register to use as a temp in |
| 5811 // ContextSlotOperandCheckExtensions and to hold the result |
| 5812 // value. |
| 5813 function = allocator()->Allocate(); |
| 5814 ASSERT(function.is_valid()); |
| 5815 __ mov(function.reg(), |
| 5816 ContextSlotOperandCheckExtensions(potential_slot, |
| 5817 function, |
| 5818 &slow)); |
| 5819 JumpTarget push_function_and_receiver; |
| 5820 if (potential_slot->var()->mode() == Variable::CONST) { |
| 5821 __ cmp(function.reg(), Factory::the_hole_value()); |
| 5822 push_function_and_receiver.Branch(not_equal, &function); |
| 5823 __ mov(function.reg(), Factory::undefined_value()); |
| 5824 } |
| 5825 push_function_and_receiver.Bind(&function); |
| 5826 frame_->Push(&function); |
| 5827 LoadGlobalReceiver(); |
| 5828 done.Jump(); |
| 5829 } |
| 5830 } |
| 5831 |
| 5832 slow.Bind(); |
| 5833 // Enter the runtime system to load the function from the context. |
| 5834 // Sync the frame so we can push the arguments directly into |
| 5835 // place. |
5780 frame_->SyncRange(0, frame_->element_count() - 1); | 5836 frame_->SyncRange(0, frame_->element_count() - 1); |
5781 frame_->EmitPush(esi); | 5837 frame_->EmitPush(esi); |
5782 frame_->EmitPush(Immediate(var->name())); | 5838 frame_->EmitPush(Immediate(var->name())); |
5783 frame_->CallRuntime(Runtime::kLoadContextSlot, 2); | 5839 frame_->CallRuntime(Runtime::kLoadContextSlot, 2); |
5784 // The runtime call returns a pair of values in eax and edx. The | 5840 // The runtime call returns a pair of values in eax and edx. The |
5785 // looked-up function is in eax and the receiver is in edx. These | 5841 // looked-up function is in eax and the receiver is in edx. These |
5786 // register references are not ref counted here. We spill them | 5842 // register references are not ref counted here. We spill them |
5787 // eagerly since they are arguments to an inevitable call (and are | 5843 // eagerly since they are arguments to an inevitable call (and are |
5788 // not sharable by the arguments). | 5844 // not sharable by the arguments). |
5789 ASSERT(!allocator()->is_used(eax)); | 5845 ASSERT(!allocator()->is_used(eax)); |
5790 frame_->EmitPush(eax); | 5846 frame_->EmitPush(eax); |
5791 | 5847 |
5792 // Load the receiver. | 5848 // Load the receiver. |
5793 ASSERT(!allocator()->is_used(edx)); | 5849 ASSERT(!allocator()->is_used(edx)); |
5794 frame_->EmitPush(edx); | 5850 frame_->EmitPush(edx); |
5795 | 5851 |
| 5852 done.Bind(); |
5796 // Call the function. | 5853 // Call the function. |
5797 CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position()); | 5854 CallWithArguments(args, NO_CALL_FUNCTION_FLAGS, node->position()); |
5798 | 5855 |
5799 } else if (property != NULL) { | 5856 } else if (property != NULL) { |
5800 // Check if the key is a literal string. | 5857 // Check if the key is a literal string. |
5801 Literal* literal = property->key()->AsLiteral(); | 5858 Literal* literal = property->key()->AsLiteral(); |
5802 | 5859 |
5803 if (literal != NULL && literal->handle()->IsSymbol()) { | 5860 if (literal != NULL && literal->handle()->IsSymbol()) { |
5804 // ------------------------------------------------------------------ | 5861 // ------------------------------------------------------------------ |
5805 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)' | 5862 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)' |
(...skipping 7337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13143 | 13200 |
13144 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 13201 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
13145 // tagged as a small integer. | 13202 // tagged as a small integer. |
13146 __ bind(&runtime); | 13203 __ bind(&runtime); |
13147 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 13204 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
13148 } | 13205 } |
13149 | 13206 |
13150 #undef __ | 13207 #undef __ |
13151 | 13208 |
13152 } } // namespace v8::internal | 13209 } } // namespace v8::internal |
OLD | NEW |