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

Side by Side Diff: src/arm/codegen-arm.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 | « no previous file | src/ia32/codegen-ia32.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 2758 matching lines...) Expand 10 before | Expand all | Expand 10 after
2769 JumpTarget slow; 2769 JumpTarget slow;
2770 JumpTarget done; 2770 JumpTarget done;
2771 2771
2772 // Generate fast-case code for variables that might be shadowed by 2772 // Generate fast-case code for variables that might be shadowed by
2773 // eval-introduced variables. Eval is used a lot without 2773 // eval-introduced variables. Eval is used a lot without
2774 // introducing variables. In those cases, we do not want to 2774 // introducing variables. In those cases, we do not want to
2775 // perform a runtime call for all variables in the scope 2775 // perform a runtime call for all variables in the scope
2776 // containing the eval. 2776 // containing the eval.
2777 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { 2777 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
2778 LoadFromGlobalSlotCheckExtensions(slot, typeof_state, &slow); 2778 LoadFromGlobalSlotCheckExtensions(slot, typeof_state, &slow);
2779 // If there was no control flow to slow, we can exit early.
2780 if (!slow.is_linked()) {
2781 frame_->EmitPush(r0);
2782 return;
2783 }
2784 frame_->SpillAll(); 2779 frame_->SpillAll();
2785
2786 done.Jump(); 2780 done.Jump();
2787 2781
2788 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { 2782 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
2789 frame_->SpillAll(); 2783 frame_->SpillAll();
2790 Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot(); 2784 Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot();
2791 // Only generate the fast case for locals that rewrite to slots. 2785 Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite();
2792 // This rules out argument loads because eval forces arguments
2793 // access to be through the arguments object.
2794 if (potential_slot != NULL) { 2786 if (potential_slot != NULL) {
2787 // Generate fast case for locals that rewrite to slots.
2795 __ ldr(r0, 2788 __ ldr(r0,
2796 ContextSlotOperandCheckExtensions(potential_slot, 2789 ContextSlotOperandCheckExtensions(potential_slot,
2797 r1, 2790 r1,
2798 r2, 2791 r2,
2799 &slow)); 2792 &slow));
2800 if (potential_slot->var()->mode() == Variable::CONST) { 2793 if (potential_slot->var()->mode() == Variable::CONST) {
2801 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 2794 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
2802 __ cmp(r0, ip); 2795 __ cmp(r0, ip);
2803 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); 2796 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
2804 } 2797 }
2805 // There is always control flow to slow from
2806 // ContextSlotOperandCheckExtensions so we have to jump around
2807 // it.
2808 done.Jump(); 2798 done.Jump();
2799 } else if (rewrite != NULL) {
2800 // Generate fast case for argument loads.
2801 Property* property = rewrite->AsProperty();
2802 if (property != NULL) {
2803 VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
2804 Literal* key_literal = property->key()->AsLiteral();
2805 if (obj_proxy != NULL &&
2806 key_literal != NULL &&
2807 obj_proxy->IsArguments() &&
2808 key_literal->handle()->IsSmi()) {
2809 // Load arguments object if there are no eval-introduced
2810 // variables. Then load the argument from the arguments
2811 // object using keyed load.
2812 __ ldr(r0,
2813 ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(),
2814 r1,
2815 r2,
2816 &slow));
2817 frame_->EmitPush(r0);
2818 __ mov(r1, Operand(key_literal->handle()));
2819 frame_->EmitPush(r1);
2820 EmitKeyedLoad();
2821 done.Jump();
2822 }
2823 }
2809 } 2824 }
2810 } 2825 }
2811 2826
2812 slow.Bind(); 2827 slow.Bind();
2813 VirtualFrame::SpilledScope spilled_scope(frame_); 2828 VirtualFrame::SpilledScope spilled_scope(frame_);
2814 frame_->EmitPush(cp); 2829 frame_->EmitPush(cp);
2815 __ mov(r0, Operand(slot->var()->name())); 2830 __ mov(r0, Operand(slot->var()->name()));
2816 frame_->EmitPush(r0); 2831 frame_->EmitPush(r0);
2817 2832
2818 if (typeof_state == INSIDE_TYPEOF) { 2833 if (typeof_state == INSIDE_TYPEOF) {
(...skipping 882 matching lines...) Expand 10 before | Expand all | Expand 10 after
3701 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT, 3716 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT,
3702 arg_count + 1); 3717 arg_count + 1);
3703 __ ldr(cp, frame_->Context()); 3718 __ ldr(cp, frame_->Context());
3704 frame_->EmitPush(r0); 3719 frame_->EmitPush(r0);
3705 3720
3706 } else if (var != NULL && var->slot() != NULL && 3721 } else if (var != NULL && var->slot() != NULL &&
3707 var->slot()->type() == Slot::LOOKUP) { 3722 var->slot()->type() == Slot::LOOKUP) {
3708 // ---------------------------------- 3723 // ----------------------------------
3709 // JavaScript examples: 3724 // JavaScript examples:
3710 // 3725 //
3711 // with (obj) foo(1, 2, 3) // foo is in obj 3726 // with (obj) foo(1, 2, 3) // foo may be in obj.
3712 // 3727 //
3713 // function f() {}; 3728 // function f() {};
3714 // function g() { 3729 // function g() {
3715 // eval(...); 3730 // eval(...);
3716 // f(); // f could be in extension object 3731 // f(); // f could be in extension object.
3717 // } 3732 // }
3718 // ---------------------------------- 3733 // ----------------------------------
3719 3734
3720 // JumpTargets do not yet support merging frames so the frame must be 3735 // JumpTargets do not yet support merging frames so the frame must be
3721 // spilled when jumping to these targets. 3736 // spilled when jumping to these targets.
3722 JumpTarget slow; 3737 JumpTarget slow;
3723 JumpTarget done; 3738 JumpTarget done;
3724 3739
3725 // Generate fast-case code for variables that might be shadowed by 3740 // Generate fast-case code for variables that might be shadowed by
3726 // eval-introduced variables. Eval is used a lot without 3741 // eval-introduced variables. Eval is used a lot without
3727 // introducing variables. In those cases, we do not want to 3742 // introducing variables. In those cases, we do not want to
3728 // perform a runtime call for all variables in the scope 3743 // perform a runtime call for all variables in the scope
3729 // containing the eval. 3744 // containing the eval.
3730 if (var->mode() == Variable::DYNAMIC_GLOBAL) { 3745 if (var->mode() == Variable::DYNAMIC_GLOBAL) {
3731 LoadFromGlobalSlotCheckExtensions(var->slot(), NOT_INSIDE_TYPEOF, &slow); 3746 LoadFromGlobalSlotCheckExtensions(var->slot(), NOT_INSIDE_TYPEOF, &slow);
3732 frame_->EmitPush(r0); 3747 frame_->EmitPush(r0);
3733 LoadGlobalReceiver(r1); 3748 LoadGlobalReceiver(r1);
3734 done.Jump(); 3749 done.Jump();
3735 3750
3736 } else if (var->mode() == Variable::DYNAMIC_LOCAL) { 3751 } else if (var->mode() == Variable::DYNAMIC_LOCAL) {
3737 Slot* potential_slot = var->local_if_not_shadowed()->slot(); 3752 Slot* potential_slot = var->local_if_not_shadowed()->slot();
3738 // Only generate the fast case for locals that rewrite to slots. 3753 Expression* rewrite = var->local_if_not_shadowed()->rewrite();
3739 // This rules out argument loads because eval forces arguments
3740 // access to be through the arguments object.
3741 if (potential_slot != NULL) { 3754 if (potential_slot != NULL) {
3755 // Generate fast case for locals that rewrite to slots.
3742 __ ldr(r0, 3756 __ ldr(r0,
3743 ContextSlotOperandCheckExtensions(potential_slot, 3757 ContextSlotOperandCheckExtensions(potential_slot,
3744 r1, 3758 r1,
3745 r2, 3759 r2,
3746 &slow)); 3760 &slow));
3747 if (potential_slot->var()->mode() == Variable::CONST) { 3761 if (potential_slot->var()->mode() == Variable::CONST) {
3748 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 3762 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
3749 __ cmp(r0, ip); 3763 __ cmp(r0, ip);
3750 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); 3764 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
3751 } 3765 }
3752 frame_->EmitPush(r0); 3766 frame_->EmitPush(r0);
3753 LoadGlobalReceiver(r1); 3767 LoadGlobalReceiver(r1);
3754 done.Jump(); 3768 done.Jump();
3769 } else if (rewrite != NULL) {
3770 // Generate fast case for calls of an argument function.
3771 Property* property = rewrite->AsProperty();
3772 if (property != NULL) {
3773 VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
3774 Literal* key_literal = property->key()->AsLiteral();
3775 if (obj_proxy != NULL &&
3776 key_literal != NULL &&
3777 obj_proxy->IsArguments() &&
3778 key_literal->handle()->IsSmi()) {
3779 // Load arguments object if there are no eval-introduced
3780 // variables. Then load the argument from the arguments
3781 // object using keyed load.
3782 __ ldr(r0,
3783 ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(),
3784 r1,
3785 r2,
3786 &slow));
3787 frame_->EmitPush(r0);
3788 __ mov(r1, Operand(key_literal->handle()));
3789 frame_->EmitPush(r1);
3790 EmitKeyedLoad();
3791 frame_->EmitPush(r0);
3792 LoadGlobalReceiver(r1);
3793 done.Jump();
3794 }
3795 }
3755 } 3796 }
3756 } 3797 }
3757 3798
3758 slow.Bind(); 3799 slow.Bind();
3759 // Load the function 3800 // Load the function
3760 frame_->EmitPush(cp); 3801 frame_->EmitPush(cp);
3761 __ mov(r0, Operand(var->name())); 3802 __ mov(r0, Operand(var->name()));
3762 frame_->EmitPush(r0); 3803 frame_->EmitPush(r0);
3763 frame_->CallRuntime(Runtime::kLoadContextSlot, 2); 3804 frame_->CallRuntime(Runtime::kLoadContextSlot, 2);
3764 // r0: slot value; r1: receiver 3805 // r0: slot value; r1: receiver
(...skipping 6195 matching lines...) Expand 10 before | Expand all | Expand 10 after
9960 10001
9961 // Just jump to runtime to add the two strings. 10002 // Just jump to runtime to add the two strings.
9962 __ bind(&string_add_runtime); 10003 __ bind(&string_add_runtime);
9963 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); 10004 __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
9964 } 10005 }
9965 10006
9966 10007
9967 #undef __ 10008 #undef __
9968 10009
9969 } } // namespace v8::internal 10010 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/ia32/codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698