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 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
167 #endif | 167 #endif |
168 | 168 |
169 // Allocate space for locals and initialize them. | 169 // Allocate space for locals and initialize them. |
170 frame_->AllocateStackSlots(scope_->num_stack_slots()); | 170 frame_->AllocateStackSlots(scope_->num_stack_slots()); |
171 | 171 |
172 // Allocate the arguments object and copy the parameters into it. | 172 // Allocate the arguments object and copy the parameters into it. |
173 if (scope_->arguments() != NULL) { | 173 if (scope_->arguments() != NULL) { |
174 ASSERT(scope_->arguments_shadow() != NULL); | 174 ASSERT(scope_->arguments_shadow() != NULL); |
175 Comment cmnt(masm_, "[ Allocate arguments object"); | 175 Comment cmnt(masm_, "[ Allocate arguments object"); |
176 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); | 176 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); |
177 VirtualFrame::SpilledScope spilled_scope(this); | 177 frame_->PushFunction(); |
178 __ lea(eax, frame_->Receiver()); | 178 frame_->PushReceiverSlotAddress(); |
179 frame_->EmitPush(frame_->Function()); | 179 frame_->Push(Smi::FromInt(scope_->num_parameters())); |
180 frame_->EmitPush(eax); | |
181 frame_->EmitPush(Immediate(Smi::FromInt(scope_->num_parameters()))); | |
182 Result answer = frame_->CallStub(&stub, 3); | 180 Result answer = frame_->CallStub(&stub, 3); |
183 frame_->Push(&answer); | 181 frame_->Push(&answer); |
184 } | 182 } |
185 | 183 |
186 if (scope_->num_heap_slots() > 0) { | 184 if (scope_->num_heap_slots() > 0) { |
187 Comment cmnt(masm_, "[ allocate local context"); | 185 Comment cmnt(masm_, "[ allocate local context"); |
188 // Allocate local context. | 186 // Allocate local context. |
189 // Get outer context and create a new context based on it. | 187 // Get outer context and create a new context based on it. |
190 VirtualFrame::SpilledScope spilled_scope(this); | 188 frame_->PushFunction(); |
191 frame_->EmitPush(frame_->Function()); | 189 Result context = frame_->CallRuntime(Runtime::kNewContext, 1); |
192 frame_->CallRuntime(Runtime::kNewContext, 1); // eax holds the result | |
193 | 190 |
194 if (kDebug) { | 191 if (kDebug) { |
| 192 frame_->SpillAll(); // Needed for breakpoint below. |
195 JumpTarget verified_true(this); | 193 JumpTarget verified_true(this); |
196 // Verify eax and esi are the same in debug mode | 194 // Verify eax and esi are the same in debug mode |
197 __ cmp(eax, Operand(esi)); | 195 __ cmp(context.reg(), Operand(esi)); |
| 196 context.Unuse(); |
198 verified_true.Branch(equal); | 197 verified_true.Branch(equal); |
199 __ int3(); | 198 __ int3(); |
200 verified_true.Bind(); | 199 verified_true.Bind(); |
201 } | 200 } |
202 // Update context local. | 201 // Update context local. |
203 frame_->SaveContextRegister(); | 202 frame_->SaveContextRegister(); |
204 } | 203 } |
205 | 204 |
206 // TODO(1241774): Improve this code: | 205 // TODO(1241774): Improve this code: |
207 // 1) only needed if we have a context | 206 // 1) only needed if we have a context |
(...skipping 648 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
856 | 855 |
857 class DeferredInlinedSmiAdd: public DeferredCode { | 856 class DeferredInlinedSmiAdd: public DeferredCode { |
858 public: | 857 public: |
859 DeferredInlinedSmiAdd(CodeGenerator* generator, int value, | 858 DeferredInlinedSmiAdd(CodeGenerator* generator, int value, |
860 OverwriteMode overwrite_mode) : | 859 OverwriteMode overwrite_mode) : |
861 DeferredCode(generator), value_(value), overwrite_mode_(overwrite_mode) { | 860 DeferredCode(generator), value_(value), overwrite_mode_(overwrite_mode) { |
862 set_comment("[ DeferredInlinedSmiAdd"); | 861 set_comment("[ DeferredInlinedSmiAdd"); |
863 } | 862 } |
864 | 863 |
865 virtual void Generate() { | 864 virtual void Generate() { |
866 // The argument is actually passed in eax. | 865 Result arg(generator()); |
867 enter()->Bind(); | 866 enter()->Bind(&arg); |
868 VirtualFrame::SpilledScope spilled_scope(generator()); | 867 arg.ToRegister(); |
| 868 generator()->frame()->Spill(arg.reg()); |
869 // Undo the optimistic add operation and call the shared stub. | 869 // Undo the optimistic add operation and call the shared stub. |
870 Immediate immediate(Smi::FromInt(value_)); | 870 __ sub(Operand(arg.reg()), Immediate(Smi::FromInt(value_))); |
871 __ sub(Operand(eax), immediate); | 871 generator()->frame()->Push(&arg); |
872 generator()->frame()->EmitPush(eax); | 872 generator()->frame()->Push(Smi::FromInt(value_)); |
873 generator()->frame()->EmitPush(immediate); | |
874 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED); | 873 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED); |
875 generator()->frame()->CallStub(&igostub, 2); | 874 Result result = generator()->frame()->CallStub(&igostub, 2); |
876 // The result is actually returned in eax. | 875 exit()->Jump(&result); |
877 exit()->Jump(); | |
878 } | 876 } |
879 | 877 |
880 private: | 878 private: |
881 int value_; | 879 int value_; |
882 OverwriteMode overwrite_mode_; | 880 OverwriteMode overwrite_mode_; |
883 }; | 881 }; |
884 | 882 |
885 | 883 |
886 class DeferredInlinedSmiAddReversed: public DeferredCode { | 884 class DeferredInlinedSmiAddReversed: public DeferredCode { |
887 public: | 885 public: |
888 DeferredInlinedSmiAddReversed(CodeGenerator* generator, int value, | 886 DeferredInlinedSmiAddReversed(CodeGenerator* generator, int value, |
889 OverwriteMode overwrite_mode) : | 887 OverwriteMode overwrite_mode) : |
890 DeferredCode(generator), value_(value), overwrite_mode_(overwrite_mode) { | 888 DeferredCode(generator), value_(value), overwrite_mode_(overwrite_mode) { |
891 set_comment("[ DeferredInlinedSmiAddReversed"); | 889 set_comment("[ DeferredInlinedSmiAddReversed"); |
892 } | 890 } |
893 | 891 |
894 virtual void Generate() { | 892 virtual void Generate() { |
895 // The argument is actually passed in eax. | 893 Result arg(generator()); |
896 enter()->Bind(); | 894 enter()->Bind(&arg); |
897 VirtualFrame::SpilledScope spilled_scope(generator()); | 895 arg.ToRegister(); |
| 896 generator()->frame()->Spill(arg.reg()); // Should not be needed. |
898 // Undo the optimistic add operation and call the shared stub. | 897 // Undo the optimistic add operation and call the shared stub. |
899 Immediate immediate(Smi::FromInt(value_)); | 898 Immediate immediate(Smi::FromInt(value_)); |
900 __ sub(Operand(eax), immediate); | 899 __ sub(Operand(arg.reg()), immediate); |
901 generator()->frame()->EmitPush(immediate); | 900 generator()->frame()->Push(Smi::FromInt(value_)); |
902 generator()->frame()->EmitPush(eax); | 901 generator()->frame()->Push(&arg); |
903 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED); | 902 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED); |
904 generator()->frame()->CallStub(&igostub, 2); | 903 arg = generator()->frame()->CallStub(&igostub, 2); |
905 // The result is actually returned in eax. | 904 exit()->Jump(&arg); |
906 exit()->Jump(); | |
907 } | 905 } |
908 | 906 |
909 private: | 907 private: |
910 int value_; | 908 int value_; |
911 OverwriteMode overwrite_mode_; | 909 OverwriteMode overwrite_mode_; |
912 }; | 910 }; |
913 | 911 |
914 | 912 |
915 class DeferredInlinedSmiSub: public DeferredCode { | 913 class DeferredInlinedSmiSub: public DeferredCode { |
916 public: | 914 public: |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
994 | 992 |
995 switch (op) { | 993 switch (op) { |
996 case Token::ADD: { | 994 case Token::ADD: { |
997 DeferredCode* deferred = NULL; | 995 DeferredCode* deferred = NULL; |
998 if (!reversed) { | 996 if (!reversed) { |
999 deferred = new DeferredInlinedSmiAdd(this, int_value, overwrite_mode); | 997 deferred = new DeferredInlinedSmiAdd(this, int_value, overwrite_mode); |
1000 } else { | 998 } else { |
1001 deferred = new DeferredInlinedSmiAddReversed(this, int_value, | 999 deferred = new DeferredInlinedSmiAddReversed(this, int_value, |
1002 overwrite_mode); | 1000 overwrite_mode); |
1003 } | 1001 } |
1004 frame_->EmitPop(eax); | 1002 Result operand = frame_->Pop(); |
1005 __ add(Operand(eax), Immediate(value)); | 1003 operand.ToRegister(); |
1006 deferred->enter()->Branch(overflow, not_taken); | 1004 frame_->Spill(operand.reg()); |
1007 __ test(eax, Immediate(kSmiTagMask)); | 1005 __ add(Operand(operand.reg()), Immediate(value)); |
1008 deferred->enter()->Branch(not_zero, not_taken); | 1006 deferred->enter()->Branch(overflow, &operand, not_taken); |
1009 deferred->exit()->Bind(); | 1007 __ test(Operand(operand.reg()), Immediate(kSmiTagMask)); |
1010 frame_->EmitPush(eax); | 1008 deferred->enter()->Branch(not_zero, &operand, not_taken); |
| 1009 deferred->exit()->Bind(&operand); |
| 1010 frame_->Push(&operand); |
1011 break; | 1011 break; |
1012 } | 1012 } |
1013 | 1013 |
1014 case Token::SUB: { | 1014 case Token::SUB: { |
1015 DeferredCode* deferred = NULL; | 1015 DeferredCode* deferred = NULL; |
1016 frame_->EmitPop(eax); | 1016 frame_->EmitPop(eax); |
1017 if (!reversed) { | 1017 if (!reversed) { |
1018 deferred = new DeferredInlinedSmiSub(this, int_value, overwrite_mode); | 1018 deferred = new DeferredInlinedSmiSub(this, int_value, overwrite_mode); |
1019 __ sub(Operand(eax), Immediate(value)); | 1019 __ sub(Operand(eax), Immediate(value)); |
1020 } else { | 1020 } else { |
(...skipping 1987 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3008 | 3008 |
3009 | 3009 |
3010 void CodeGenerator::VisitAssignment(Assignment* node) { | 3010 void CodeGenerator::VisitAssignment(Assignment* node) { |
3011 Comment cmnt(masm_, "[ Assignment"); | 3011 Comment cmnt(masm_, "[ Assignment"); |
3012 CodeForStatement(node); | 3012 CodeForStatement(node); |
3013 | 3013 |
3014 { Reference target(this, node->target()); | 3014 { Reference target(this, node->target()); |
3015 if (target.is_illegal()) { | 3015 if (target.is_illegal()) { |
3016 // Fool the virtual frame into thinking that we left the assignment's | 3016 // Fool the virtual frame into thinking that we left the assignment's |
3017 // value on the frame. | 3017 // value on the frame. |
3018 frame_->Push(Handle<Object>(Smi::FromInt(0))); | 3018 frame_->Push(Smi::FromInt(0)); |
3019 return; | 3019 return; |
3020 } | 3020 } |
3021 | 3021 |
3022 if (node->op() == Token::ASSIGN || | 3022 if (node->op() == Token::ASSIGN || |
3023 node->op() == Token::INIT_VAR || | 3023 node->op() == Token::INIT_VAR || |
3024 node->op() == Token::INIT_CONST) { | 3024 node->op() == Token::INIT_CONST) { |
3025 Load(node->value()); | 3025 Load(node->value()); |
3026 | 3026 |
3027 } else { | 3027 } else { |
3028 VirtualFrame::SpilledScope spilled_scope(this); | 3028 VirtualFrame::SpilledScope spilled_scope(this); |
(...skipping 829 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3858 Comment cmnt(masm_, "[ CountOperation"); | 3858 Comment cmnt(masm_, "[ CountOperation"); |
3859 | 3859 |
3860 bool is_postfix = node->is_postfix(); | 3860 bool is_postfix = node->is_postfix(); |
3861 bool is_increment = node->op() == Token::INC; | 3861 bool is_increment = node->op() == Token::INC; |
3862 | 3862 |
3863 Variable* var = node->expression()->AsVariableProxy()->AsVariable(); | 3863 Variable* var = node->expression()->AsVariableProxy()->AsVariable(); |
3864 bool is_const = (var != NULL && var->mode() == Variable::CONST); | 3864 bool is_const = (var != NULL && var->mode() == Variable::CONST); |
3865 | 3865 |
3866 // Postfix: Make room for the result. | 3866 // Postfix: Make room for the result. |
3867 if (is_postfix) { | 3867 if (is_postfix) { |
3868 frame_->Push(Handle<Object>(Smi::FromInt(0))); | 3868 frame_->Push(Smi::FromInt(0)); |
3869 } | 3869 } |
3870 | 3870 |
3871 { Reference target(this, node->expression()); | 3871 { Reference target(this, node->expression()); |
3872 if (target.is_illegal()) { | 3872 if (target.is_illegal()) { |
3873 // Spoof the virtual frame to have the expected height (one higher | 3873 // Spoof the virtual frame to have the expected height (one higher |
3874 // than on entry). | 3874 // than on entry). |
3875 if (!is_postfix) { | 3875 if (!is_postfix) { |
3876 frame_->Push(Handle<Object>(Smi::FromInt(0))); | 3876 frame_->Push(Smi::FromInt(0)); |
3877 } | 3877 } |
3878 return; | 3878 return; |
3879 } | 3879 } |
3880 target.TakeValue(NOT_INSIDE_TYPEOF); | 3880 target.TakeValue(NOT_INSIDE_TYPEOF); |
3881 | 3881 |
3882 DeferredCountOperation* deferred = | 3882 DeferredCountOperation* deferred = |
3883 new DeferredCountOperation(this, is_postfix, is_increment, | 3883 new DeferredCountOperation(this, is_postfix, is_increment, |
3884 target.size() * kPointerSize); | 3884 target.size() * kPointerSize); |
3885 | 3885 |
3886 Result value = frame_->Pop(); | 3886 Result value = frame_->Pop(); |
(...skipping 2222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6109 | 6109 |
6110 // Slow-case: Go through the JavaScript implementation. | 6110 // Slow-case: Go through the JavaScript implementation. |
6111 __ bind(&slow); | 6111 __ bind(&slow); |
6112 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 6112 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
6113 } | 6113 } |
6114 | 6114 |
6115 | 6115 |
6116 #undef __ | 6116 #undef __ |
6117 | 6117 |
6118 } } // namespace v8::internal | 6118 } } // namespace v8::internal |
OLD | NEW |