| 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 |