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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
57 // on the execution stack to represent the reference. | 57 // on the execution stack to represent the reference. |
58 | 58 |
59 class Reference BASE_EMBEDDED { | 59 class Reference BASE_EMBEDDED { |
60 public: | 60 public: |
61 enum Type { ILLEGAL = -1, EMPTY = 0, NAMED = 1, KEYED = 2 }; | 61 enum Type { ILLEGAL = -1, EMPTY = 0, NAMED = 1, KEYED = 2 }; |
62 Reference(Ia32CodeGenerator* cgen, Expression* expression); | 62 Reference(Ia32CodeGenerator* cgen, Expression* expression); |
63 ~Reference(); | 63 ~Reference(); |
64 | 64 |
65 Expression* expression() const { return expression_; } | 65 Expression* expression() const { return expression_; } |
66 Type type() const { return type_; } | 66 Type type() const { return type_; } |
67 void set_type(Type value) { | 67 void set_type(Type value) { |
68 ASSERT(type_ == ILLEGAL); | 68 ASSERT(type_ == ILLEGAL); |
69 type_ = value; | 69 type_ = value; |
70 } | 70 } |
71 int size() const { return type_; } | 71 int size() const { return type_; } |
72 | 72 |
73 bool is_illegal() const { return type_ == ILLEGAL; } | 73 bool is_illegal() const { return type_ == ILLEGAL; } |
74 | 74 |
75 private: | 75 private: |
76 Ia32CodeGenerator* cgen_; | 76 Ia32CodeGenerator* cgen_; |
77 Expression* expression_; | 77 Expression* expression_; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
137 | 137 |
138 // ----------------------------------------------------------------------------- | 138 // ----------------------------------------------------------------------------- |
139 // Ia32CodeGenerator | 139 // Ia32CodeGenerator |
140 | 140 |
141 class Ia32CodeGenerator: public CodeGenerator { | 141 class Ia32CodeGenerator: public CodeGenerator { |
142 public: | 142 public: |
143 static Handle<Code> MakeCode(FunctionLiteral* fun, | 143 static Handle<Code> MakeCode(FunctionLiteral* fun, |
144 Handle<Script> script, | 144 Handle<Script> script, |
145 bool is_eval); | 145 bool is_eval); |
146 | 146 |
147 MacroAssembler* masm() { return masm_; } | 147 MacroAssembler* masm() { return masm_; } |
148 | |
149 Scope* scope() const { return scope_; } | |
148 | 150 |
149 CodeGenState* state() { return state_; } | 151 CodeGenState* state() { return state_; } |
150 void set_state(CodeGenState* state) { state_ = state; } | 152 void set_state(CodeGenState* state) { state_ = state; } |
151 | 153 |
152 private: | 154 private: |
153 // Assembler | 155 // Assembler |
154 MacroAssembler* masm_; // to generate code | 156 MacroAssembler* masm_; // to generate code |
155 | 157 |
156 // Code generation state | 158 // Code generation state |
157 Scope* scope_; | 159 Scope* scope_; |
158 Condition cc_reg_; | 160 Condition cc_reg_; |
159 CodeGenState* state_; | 161 CodeGenState* state_; |
160 bool is_inside_try_; | 162 bool is_inside_try_; |
161 int break_stack_height_; | 163 int break_stack_height_; |
162 | 164 |
163 // Labels | 165 // Labels |
164 Label function_return_; | 166 Label function_return_; |
165 | 167 |
166 // Construction/destruction | 168 // Construction/destruction |
167 Ia32CodeGenerator(int buffer_size, | 169 Ia32CodeGenerator(int buffer_size, |
168 Handle<Script> script, | 170 Handle<Script> script, |
169 bool is_eval); | 171 bool is_eval); |
170 virtual ~Ia32CodeGenerator() { delete masm_; } | 172 virtual ~Ia32CodeGenerator() { delete masm_; } |
171 | 173 |
172 // Main code generation function | 174 // Main code generation function |
173 void GenCode(FunctionLiteral* fun); | 175 void GenCode(FunctionLiteral* fun); |
174 | 176 |
175 // The following are used by class Reference. | 177 // The following are used by class Reference. |
176 void LoadReference(Reference* ref); | 178 void LoadReference(Reference* ref); |
177 void UnloadReference(Reference* ref); | 179 void UnloadReference(Reference* ref); |
178 | 180 |
179 // State | 181 // State |
180 bool has_cc() const { return cc_reg_ >= 0; } | 182 bool has_cc() const { return cc_reg_ >= 0; } |
181 CodeGenState::AccessType access() const { return state_->access(); } | 183 CodeGenState::AccessType access() const { return state_->access(); } |
182 Reference* ref() const { return state_->ref(); } | 184 Reference* ref() const { return state_->ref(); } |
183 bool is_referenced() const { return state_->ref() != NULL; } | 185 bool is_referenced() const { return state_->ref() != NULL; } |
184 Label* true_target() const { return state_->true_target(); } | 186 Label* true_target() const { return state_->true_target(); } |
185 Label* false_target() const { return state_->false_target(); } | 187 Label* false_target() const { return state_->false_target(); } |
186 | 188 |
187 // Expressions | 189 // Expressions |
188 Operand GlobalObject() const { | 190 Operand GlobalObject() const { |
189 return ContextOperand(esi, Context::GLOBAL_INDEX); | 191 return ContextOperand(esi, Context::GLOBAL_INDEX); |
190 } | 192 } |
191 | 193 |
192 // Support functions for accessing parameters. Static versions can | 194 // Support functions for accessing parameters. Static versions can |
193 // require some code generator state to be passed in as arguments. | 195 // require some code generator state to be passed in as arguments. |
194 static Operand ParameterOperand(Scope* scope, int index) { | 196 static Operand ParameterOperand(const CodeGenerator* cgen, int index) { |
Kasper Lund
2008/10/02 08:57:58
Extra whitespace at end of line?
| |
195 ASSERT(-2 <= index && index < scope->num_parameters()); | 197 int num_parameters = cgen->scope()->num_parameters(); |
196 return Operand(ebp, (1 + scope->num_parameters() - index) * kPointerSize); | 198 ASSERT(-2 <= index && index < num_parameters); |
199 return Operand(ebp, (1 + num_parameters - index) * kPointerSize); | |
197 } | 200 } |
198 | 201 |
199 Operand ParameterOperand(int index) const { | 202 Operand ParameterOperand(int index) const { |
200 return ParameterOperand(scope_, index); | 203 return ParameterOperand(this, index); |
201 } | 204 } |
202 | 205 |
203 Operand ReceiverOperand() const { return ParameterOperand(-1); } | 206 Operand ReceiverOperand() const { return ParameterOperand(-1); } |
204 | 207 |
205 Operand FunctionOperand() const { | 208 Operand FunctionOperand() const { |
206 return Operand(ebp, JavaScriptFrameConstants::kFunctionOffset); | 209 return Operand(ebp, JavaScriptFrameConstants::kFunctionOffset); |
207 } | 210 } |
208 | 211 |
209 static Operand ContextOperand(Register context, int index) { | 212 static Operand ContextOperand(Register context, int index) { |
210 return Operand(context, Context::SlotOffset(index)); | 213 return Operand(context, Context::SlotOffset(index)); |
211 } | 214 } |
212 | 215 |
213 static Operand SlotOperand(MacroAssembler* masm, | 216 static Operand SlotOperand(CodeGenerator* cgen, |
214 Scope* scope, | |
215 Slot* slot, | 217 Slot* slot, |
216 Register tmp); | 218 Register tmp); |
217 | 219 |
218 Operand SlotOperand(Slot* slot, Register tmp) { | 220 Operand SlotOperand(Slot* slot, Register tmp) { |
219 return SlotOperand(masm_, scope_, slot, tmp); | 221 return SlotOperand(this, slot, tmp); |
220 } | 222 } |
221 | 223 |
222 void LoadCondition(Expression* x, | 224 void LoadCondition(Expression* x, |
223 CodeGenState::AccessType access, | 225 CodeGenState::AccessType access, |
224 Label* true_target, | 226 Label* true_target, |
225 Label* false_target, | 227 Label* false_target, |
226 bool force_cc); | 228 bool force_cc); |
227 void Load(Expression* x, | 229 void Load(Expression* x, |
228 CodeGenState::AccessType access = CodeGenState::LOAD); | 230 CodeGenState::AccessType access = CodeGenState::LOAD); |
229 void LoadGlobal(); | 231 void LoadGlobal(); |
(...skipping 17 matching lines...) Expand all Loading... | |
247 CodeGenState new_state(this, ref); | 249 CodeGenState new_state(this, ref); |
248 Visit(ref->expression()); | 250 Visit(ref->expression()); |
249 } | 251 } |
250 | 252 |
251 // Generate code to store a value in a reference. The stored value is | 253 // Generate code to store a value in a reference. The stored value is |
252 // expected on top of the expression stack, with the reference immediately | 254 // expected on top of the expression stack, with the reference immediately |
253 // below it. The expression stack is left unchanged. | 255 // below it. The expression stack is left unchanged. |
254 void SetValue(Reference* ref) { | 256 void SetValue(Reference* ref) { |
255 ASSERT(!has_cc()); | 257 ASSERT(!has_cc()); |
256 ASSERT(!ref->is_illegal()); | 258 ASSERT(!ref->is_illegal()); |
257 ref->expression()->GenerateStoreCode(masm_, scope_, ref, NOT_CONST_INIT); | 259 ref->expression()->GenerateStoreCode(this, ref, NOT_CONST_INIT); |
258 } | 260 } |
259 | 261 |
260 // Same as SetValue, used to set the initial value of a constant. | 262 // Same as SetValue, used to set the initial value of a constant. |
261 void InitConst(Reference* ref) { | 263 void InitConst(Reference* ref) { |
262 ASSERT(!has_cc()); | 264 ASSERT(!has_cc()); |
263 ASSERT(!ref->is_illegal()); | 265 ASSERT(!ref->is_illegal()); |
264 ref->expression()->GenerateStoreCode(masm_, scope_, ref, CONST_INIT); | 266 ref->expression()->GenerateStoreCode(this, ref, CONST_INIT); |
265 } | 267 } |
266 | 268 |
267 // Generate code to fetch a value from a property of a reference. The | 269 // Generate code to fetch a value from a property of a reference. The |
268 // reference is expected on top of the expression stack. It is left in | 270 // reference is expected on top of the expression stack. It is left in |
269 // place and its value is pushed on top of it. | 271 // place and its value is pushed on top of it. |
270 void GetReferenceProperty(Expression* key); | 272 void GetReferenceProperty(Expression* key); |
271 | 273 |
272 // Generate code to store a value in a property of a reference. The | 274 // Generate code to store a value in a property of a reference. The |
273 // stored value is expected on top of the expression stack, with the | 275 // stored value is expected on top of the expression stack, with the |
274 // reference immediately below it. The expression stack is left | 276 // reference immediately below it. The expression stack is left |
275 // unchanged. | 277 // unchanged. |
276 static void SetReferenceProperty(MacroAssembler* masm, | 278 static void SetReferenceProperty(CodeGenerator* cgen, |
277 Reference* ref, | 279 Reference* ref, |
278 Expression* key); | 280 Expression* key); |
279 | 281 |
280 void ToBoolean(Label* true_target, Label* false_target); | 282 void ToBoolean(Label* true_target, Label* false_target); |
281 | 283 |
282 void GenericBinaryOperation( | 284 void GenericBinaryOperation( |
283 Token::Value op, | 285 Token::Value op, |
284 const OverwriteMode overwrite_mode = NO_OVERWRITE); | 286 const OverwriteMode overwrite_mode = NO_OVERWRITE); |
285 void Comparison(Condition cc, bool strict = false); | 287 void Comparison(Condition cc, bool strict = false); |
286 | 288 |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
416 | 418 |
417 CodeGenState::~CodeGenState() { | 419 CodeGenState::~CodeGenState() { |
418 ASSERT(owner_->state() == this); | 420 ASSERT(owner_->state() == this); |
419 owner_->set_state(previous_); | 421 owner_->set_state(previous_); |
420 } | 422 } |
421 | 423 |
422 | 424 |
423 // ----------------------------------------------------------------------------- | 425 // ----------------------------------------------------------------------------- |
424 // Ia32CodeGenerator implementation | 426 // Ia32CodeGenerator implementation |
425 | 427 |
426 #define __ masm_-> | 428 #define __ masm_-> |
427 | |
428 | 429 |
429 Handle<Code> Ia32CodeGenerator::MakeCode(FunctionLiteral* flit, | 430 Handle<Code> Ia32CodeGenerator::MakeCode(FunctionLiteral* flit, |
430 Handle<Script> script, | 431 Handle<Script> script, |
431 bool is_eval) { | 432 bool is_eval) { |
432 #ifdef ENABLE_DISASSEMBLER | 433 #ifdef ENABLE_DISASSEMBLER |
433 bool print_code = FLAG_print_code && !Bootstrapper::IsActive(); | 434 bool print_code = FLAG_print_code && !Bootstrapper::IsActive(); |
434 #endif | 435 #endif |
435 | 436 |
436 #ifdef DEBUG | 437 #ifdef DEBUG |
437 bool print_source = false; | 438 bool print_source = false; |
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
724 } | 725 } |
725 } | 726 } |
726 | 727 |
727 // Code generation state must be reset. | 728 // Code generation state must be reset. |
728 scope_ = NULL; | 729 scope_ = NULL; |
729 ASSERT(!has_cc()); | 730 ASSERT(!has_cc()); |
730 ASSERT(state_ == NULL); | 731 ASSERT(state_ == NULL); |
731 } | 732 } |
732 | 733 |
733 | 734 |
734 Operand Ia32CodeGenerator::SlotOperand(MacroAssembler* masm, | 735 #undef __ |
735 Scope* scope, | 736 #define __ masm-> |
737 | |
738 Operand Ia32CodeGenerator::SlotOperand(CodeGenerator* cgen, | |
736 Slot* slot, | 739 Slot* slot, |
737 Register tmp) { | 740 Register tmp) { |
738 // Currently, this assertion will fail if we try to assign to | 741 // Currently, this assertion will fail if we try to assign to |
739 // a constant variable that is constant because it is read-only | 742 // a constant variable that is constant because it is read-only |
740 // (such as the variable referring to a named function expression). | 743 // (such as the variable referring to a named function expression). |
741 // We need to implement assignments to read-only variables. | 744 // We need to implement assignments to read-only variables. |
742 // Ideally, we should do this during AST generation (by converting | 745 // Ideally, we should do this during AST generation (by converting |
743 // such assignments into expression statements); however, in general | 746 // such assignments into expression statements); however, in general |
744 // we may not be able to make the decision until past AST generation, | 747 // we may not be able to make the decision until past AST generation, |
745 // that is when the entire program is known. | 748 // that is when the entire program is known. |
746 ASSERT(slot != NULL); | 749 ASSERT(slot != NULL); |
747 int index = slot->index(); | 750 int index = slot->index(); |
748 switch (slot->type()) { | 751 switch (slot->type()) { |
749 case Slot::PARAMETER: return ParameterOperand(scope, index); | 752 case Slot::PARAMETER: return ParameterOperand(cgen, index); |
750 | 753 |
751 case Slot::LOCAL: { | 754 case Slot::LOCAL: { |
752 ASSERT(0 <= index && index < scope->num_stack_slots()); | 755 ASSERT(0 <= index && index < cgen->scope()->num_stack_slots()); |
753 const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset; | 756 const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset; |
754 return Operand(ebp, kLocal0Offset - index * kPointerSize); | 757 return Operand(ebp, kLocal0Offset - index * kPointerSize); |
755 } | 758 } |
756 | 759 |
757 case Slot::CONTEXT: { | 760 case Slot::CONTEXT: { |
761 MacroAssembler* masm = cgen->masm(); | |
758 // Follow the context chain if necessary. | 762 // Follow the context chain if necessary. |
759 ASSERT(!tmp.is(esi)); // do not overwrite context register | 763 ASSERT(!tmp.is(esi)); // do not overwrite context register |
760 Register context = esi; | 764 Register context = esi; |
761 int chain_length = scope->ContextChainLength(slot->var()->scope()); | 765 int chain_length = |
766 cgen->scope()->ContextChainLength(slot->var()->scope()); | |
762 for (int i = chain_length; i-- > 0;) { | 767 for (int i = chain_length; i-- > 0;) { |
763 // Load the closure. | 768 // Load the closure. |
764 // (All contexts, even 'with' contexts, have a closure, | 769 // (All contexts, even 'with' contexts, have a closure, |
765 // and it is the same for all contexts inside a function. | 770 // and it is the same for all contexts inside a function. |
766 // There is no need to go to the function context first.) | 771 // There is no need to go to the function context first.) |
767 masm->mov(tmp, ContextOperand(context, Context::CLOSURE_INDEX)); | 772 __ mov(tmp, ContextOperand(context, Context::CLOSURE_INDEX)); |
768 // Load the function context (which is the incoming, outer context). | 773 // Load the function context (which is the incoming, outer context). |
769 masm->mov(tmp, FieldOperand(tmp, JSFunction::kContextOffset)); | 774 __ mov(tmp, FieldOperand(tmp, JSFunction::kContextOffset)); |
770 context = tmp; | 775 context = tmp; |
771 } | 776 } |
772 // We may have a 'with' context now. Get the function context. | 777 // We may have a 'with' context now. Get the function context. |
773 // (In fact this mov may never be the needed, since the scope analysis | 778 // (In fact this mov may never be the needed, since the scope analysis |
774 // may not permit a direct context access in this case and thus we are | 779 // may not permit a direct context access in this case and thus we are |
775 // always at a function context. However it is safe to dereference be- | 780 // always at a function context. However it is safe to dereference be- |
776 // cause the function context of a function context is itself. Before | 781 // cause the function context of a function context is itself. Before |
777 // deleting this mov we should try to create a counter-example first, | 782 // deleting this mov we should try to create a counter-example first, |
778 // though...) | 783 // though...) |
779 masm->mov(tmp, ContextOperand(context, Context::FCONTEXT_INDEX)); | 784 __ mov(tmp, ContextOperand(context, Context::FCONTEXT_INDEX)); |
780 return ContextOperand(tmp, index); | 785 return ContextOperand(tmp, index); |
781 } | 786 } |
782 | 787 |
783 default: | 788 default: |
784 UNREACHABLE(); | 789 UNREACHABLE(); |
785 return Operand(eax); | 790 return Operand(eax); |
786 } | 791 } |
787 } | 792 } |
788 | 793 |
789 | 794 |
795 #undef __ | |
796 #define __ masm_-> | |
797 | |
790 // Loads a value on TOS. If it is a boolean value, the result may have been | 798 // Loads a value on TOS. If it is a boolean value, the result may have been |
791 // (partially) translated into branches, or it may have set the condition code | 799 // (partially) translated into branches, or it may have set the condition code |
792 // register. If force_cc is set, the value is forced to set the condition code | 800 // register. If force_cc is set, the value is forced to set the condition code |
793 // register and no value is pushed. If the condition code register was set, | 801 // register and no value is pushed. If the condition code register was set, |
794 // has_cc() is true and cc_reg_ contains the condition to test for 'true'. | 802 // has_cc() is true and cc_reg_ contains the condition to test for 'true'. |
795 void Ia32CodeGenerator::LoadCondition(Expression* x, | 803 void Ia32CodeGenerator::LoadCondition(Expression* x, |
796 CodeGenState::AccessType access, | 804 CodeGenState::AccessType access, |
797 Label* true_target, | 805 Label* true_target, |
798 Label* false_target, | 806 Label* false_target, |
799 bool force_cc) { | 807 bool force_cc) { |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
944 __ pop(eax); | 952 __ pop(eax); |
945 __ mov(TOS, eax); | 953 __ mov(TOS, eax); |
946 } else { | 954 } else { |
947 __ pop(eax); | 955 __ pop(eax); |
948 __ add(Operand(esp), Immediate(size * kPointerSize)); | 956 __ add(Operand(esp), Immediate(size * kPointerSize)); |
949 __ push(eax); | 957 __ push(eax); |
950 } | 958 } |
951 } | 959 } |
952 | 960 |
953 | 961 |
954 void Property::GenerateStoreCode(MacroAssembler* masm, | 962 #undef __ |
955 Scope* scope, | 963 #define __ masm-> |
964 | |
965 void Property::GenerateStoreCode(CodeGenerator* cgen, | |
956 Reference* ref, | 966 Reference* ref, |
957 InitState init_state) { | 967 InitState init_state) { |
968 MacroAssembler* masm = cgen->masm(); | |
958 Comment cmnt(masm, "[ Store to Property"); | 969 Comment cmnt(masm, "[ Store to Property"); |
959 masm->RecordPosition(position()); | 970 __ RecordPosition(position()); |
960 Ia32CodeGenerator::SetReferenceProperty(masm, ref, key()); | 971 Ia32CodeGenerator::SetReferenceProperty(cgen, ref, key()); |
961 } | 972 } |
962 | 973 |
963 | 974 |
964 void VariableProxy::GenerateStoreCode(MacroAssembler* masm, | 975 void VariableProxy::GenerateStoreCode(CodeGenerator* cgen, |
965 Scope* scope, | |
966 Reference* ref, | 976 Reference* ref, |
967 InitState init_state) { | 977 InitState init_state) { |
978 MacroAssembler* masm = cgen->masm(); | |
968 Comment cmnt(masm, "[ Store to VariableProxy"); | 979 Comment cmnt(masm, "[ Store to VariableProxy"); |
969 Variable* node = var(); | 980 Variable* node = var(); |
970 | 981 |
971 Expression* expr = node->rewrite(); | 982 Expression* expr = node->rewrite(); |
972 if (expr != NULL) { | 983 if (expr != NULL) { |
973 expr->GenerateStoreCode(masm, scope, ref, init_state); | 984 expr->GenerateStoreCode(cgen, ref, init_state); |
974 } else { | 985 } else { |
975 ASSERT(node->is_global()); | 986 ASSERT(node->is_global()); |
976 if (node->AsProperty() != NULL) { | 987 if (node->AsProperty() != NULL) { |
977 masm->RecordPosition(node->AsProperty()->position()); | 988 __ RecordPosition(node->AsProperty()->position()); |
978 } | 989 } |
979 Ia32CodeGenerator::SetReferenceProperty(masm, ref, | 990 Expression* key = new Literal(node->name()); |
980 new Literal(node->name())); | 991 Ia32CodeGenerator::SetReferenceProperty(cgen, ref, key); |
981 } | 992 } |
982 } | 993 } |
983 | 994 |
984 | 995 |
985 void Slot::GenerateStoreCode(MacroAssembler* masm, | 996 void Slot::GenerateStoreCode(CodeGenerator* cgen, |
986 Scope* scope, | |
987 Reference* ref, | 997 Reference* ref, |
988 InitState init_state) { | 998 InitState init_state) { |
999 MacroAssembler* masm = cgen->masm(); | |
989 Comment cmnt(masm, "[ Store to Slot"); | 1000 Comment cmnt(masm, "[ Store to Slot"); |
990 | 1001 |
991 if (type() == Slot::LOOKUP) { | 1002 if (type() == Slot::LOOKUP) { |
992 ASSERT(var()->mode() == Variable::DYNAMIC); | 1003 ASSERT(var()->mode() == Variable::DYNAMIC); |
993 | 1004 |
994 // For now, just do a runtime call. | 1005 // For now, just do a runtime call. |
995 masm->push(Operand(esi)); | 1006 __ push(esi); |
996 masm->push(Immediate(var()->name())); | 1007 __ push(Immediate(var()->name())); |
997 | 1008 |
998 if (init_state == CONST_INIT) { | 1009 if (init_state == CONST_INIT) { |
999 // Same as the case for a normal store, but ignores attribute | 1010 // Same as the case for a normal store, but ignores attribute |
1000 // (e.g. READ_ONLY) of context slot so that we can initialize const | 1011 // (e.g. READ_ONLY) of context slot so that we can initialize const |
1001 // properties (introduced via eval("const foo = (some expr);")). Also, | 1012 // properties (introduced via eval("const foo = (some expr);")). Also, |
1002 // uses the current function context instead of the top context. | 1013 // uses the current function context instead of the top context. |
1003 // | 1014 // |
1004 // Note that we must declare the foo upon entry of eval(), via a | 1015 // Note that we must declare the foo upon entry of eval(), via a |
1005 // context slot declaration, but we cannot initialize it at the same | 1016 // context slot declaration, but we cannot initialize it at the same |
1006 // time, because the const declaration may be at the end of the eval | 1017 // time, because the const declaration may be at the end of the eval |
1007 // code (sigh...) and the const variable may have been used before | 1018 // code (sigh...) and the const variable may have been used before |
1008 // (where its value is 'undefined'). Thus, we can only do the | 1019 // (where its value is 'undefined'). Thus, we can only do the |
1009 // initialization when we actually encounter the expression and when | 1020 // initialization when we actually encounter the expression and when |
1010 // the expression operands are defined and valid, and thus we need the | 1021 // the expression operands are defined and valid, and thus we need the |
1011 // split into 2 operations: declaration of the context slot followed | 1022 // split into 2 operations: declaration of the context slot followed |
1012 // by initialization. | 1023 // by initialization. |
1013 masm->CallRuntime(Runtime::kInitializeConstContextSlot, 3); | 1024 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); |
1014 } else { | 1025 } else { |
1015 masm->CallRuntime(Runtime::kStoreContextSlot, 3); | 1026 __ CallRuntime(Runtime::kStoreContextSlot, 3); |
1016 } | 1027 } |
1017 // Storing a variable must keep the (new) value on the expression | 1028 // Storing a variable must keep the (new) value on the expression |
1018 // stack. This is necessary for compiling assignment expressions. | 1029 // stack. This is necessary for compiling assignment expressions. |
1019 masm->push(eax); | 1030 __ push(eax); |
1020 | 1031 |
1021 } else { | 1032 } else { |
1022 ASSERT(var()->mode() != Variable::DYNAMIC); | 1033 ASSERT(var()->mode() != Variable::DYNAMIC); |
1023 | 1034 |
1024 Label exit; | 1035 Label exit; |
1025 if (init_state == CONST_INIT) { | 1036 if (init_state == CONST_INIT) { |
1026 ASSERT(var()->mode() == Variable::CONST); | 1037 ASSERT(var()->mode() == Variable::CONST); |
1027 // Only the first const initialization must be executed (the slot | 1038 // Only the first const initialization must be executed (the slot |
1028 // still contains 'the hole' value). When the assignment is executed, | 1039 // still contains 'the hole' value). When the assignment is executed, |
1029 // the code is identical to a normal store (see below). | 1040 // the code is identical to a normal store (see below). |
1030 Comment cmnt(masm, "[ Init const"); | 1041 Comment cmnt(masm, "[ Init const"); |
1031 masm->mov(eax, Ia32CodeGenerator::SlotOperand(masm, scope, this, ecx)); | 1042 __ mov(eax, Ia32CodeGenerator::SlotOperand(cgen, this, ecx)); |
1032 masm->cmp(eax, Factory::the_hole_value()); | 1043 __ cmp(eax, Factory::the_hole_value()); |
1033 masm->j(not_equal, &exit); | 1044 __ j(not_equal, &exit); |
1034 } | 1045 } |
1035 | 1046 |
1036 // We must execute the store. | 1047 // We must execute the store. |
1037 // Storing a variable must keep the (new) value on the stack. This is | 1048 // Storing a variable must keep the (new) value on the stack. This is |
1038 // necessary for compiling assignment expressions. ecx may be loaded | 1049 // necessary for compiling assignment expressions. ecx may be loaded |
1039 // with context; used below in RecordWrite. | 1050 // with context; used below in RecordWrite. |
1040 // | 1051 // |
1041 // Note: We will reach here even with node->var()->mode() == | 1052 // Note: We will reach here even with node->var()->mode() == |
1042 // Variable::CONST because of const declarations which will initialize | 1053 // Variable::CONST because of const declarations which will initialize |
1043 // consts to 'the hole' value and by doing so, end up calling this | 1054 // consts to 'the hole' value and by doing so, end up calling this |
1044 // code. | 1055 // code. |
1045 masm->pop(eax); | 1056 __ pop(eax); |
1046 masm->mov(Ia32CodeGenerator::SlotOperand(masm, scope, this, ecx), eax); | 1057 __ mov(Ia32CodeGenerator::SlotOperand(cgen, this, ecx), eax); |
1047 masm->push(eax); // RecordWrite may destroy the value in eax. | 1058 __ push(eax); // RecordWrite may destroy the value in eax. |
1048 if (type() == Slot::CONTEXT) { | 1059 if (type() == Slot::CONTEXT) { |
1049 // ecx is loaded with context when calling SlotOperand above. | 1060 // ecx is loaded with context when calling SlotOperand above. |
1050 int offset = FixedArray::kHeaderSize + index() * kPointerSize; | 1061 int offset = FixedArray::kHeaderSize + index() * kPointerSize; |
1051 masm->RecordWrite(ecx, offset, eax, ebx); | 1062 __ RecordWrite(ecx, offset, eax, ebx); |
1052 } | 1063 } |
1053 // If we definitely did not jump over the assignment, we do not need to | 1064 // If we definitely did not jump over the assignment, we do not need to |
1054 // bind the exit label. Doing so can defeat peephole optimization. | 1065 // bind the exit label. Doing so can defeat peephole optimization. |
1055 if (init_state == CONST_INIT) masm->bind(&exit); | 1066 if (init_state == CONST_INIT) __ bind(&exit); |
1056 } | 1067 } |
1057 } | 1068 } |
1058 | 1069 |
1059 | 1070 |
1060 #undef __ | |
1061 #define __ masm-> | |
1062 | |
1063 class ToBooleanStub: public CodeStub { | 1071 class ToBooleanStub: public CodeStub { |
1064 public: | 1072 public: |
1065 ToBooleanStub() { } | 1073 ToBooleanStub() { } |
1066 | 1074 |
1067 void Generate(MacroAssembler* masm); | 1075 void Generate(MacroAssembler* masm); |
1068 | 1076 |
1069 private: | 1077 private: |
1070 | 1078 |
1071 Major MajorKey() { return ToBoolean; } | 1079 Major MajorKey() { return ToBoolean; } |
1072 | 1080 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1131 | 1139 |
1132 // Return 1/0 for true/false in eax. | 1140 // Return 1/0 for true/false in eax. |
1133 __ bind(&true_result); | 1141 __ bind(&true_result); |
1134 __ mov(eax, 1); | 1142 __ mov(eax, 1); |
1135 __ ret(1 * kPointerSize); | 1143 __ ret(1 * kPointerSize); |
1136 __ bind(&false_result); | 1144 __ bind(&false_result); |
1137 __ mov(eax, 0); | 1145 __ mov(eax, 0); |
1138 __ ret(1 * kPointerSize); | 1146 __ ret(1 * kPointerSize); |
1139 } | 1147 } |
1140 | 1148 |
1149 | |
1141 #undef __ | 1150 #undef __ |
1142 #define __ masm_-> | 1151 #define __ masm_-> |
1143 | |
1144 | 1152 |
1145 // ECMA-262, section 9.2, page 30: ToBoolean(). Pop the top of stack and | 1153 // ECMA-262, section 9.2, page 30: ToBoolean(). Pop the top of stack and |
1146 // convert it to a boolean in the condition code register or jump to | 1154 // convert it to a boolean in the condition code register or jump to |
1147 // 'false_target'/'true_target' as appropriate. | 1155 // 'false_target'/'true_target' as appropriate. |
1148 void Ia32CodeGenerator::ToBoolean(Label* true_target, Label* false_target) { | 1156 void Ia32CodeGenerator::ToBoolean(Label* true_target, Label* false_target) { |
1149 Comment cmnt(masm_, "[ ToBoolean"); | 1157 Comment cmnt(masm_, "[ ToBoolean"); |
1150 | 1158 |
1151 // The value to convert should be popped from the stack. | 1159 // The value to convert should be popped from the stack. |
1152 __ pop(eax); | 1160 __ pop(eax); |
1153 | 1161 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1219 ASSERT(var->is_global()); | 1227 ASSERT(var->is_global()); |
1220 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 1228 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
1221 } else { | 1229 } else { |
1222 __ call(ic, RelocInfo::CODE_TARGET); | 1230 __ call(ic, RelocInfo::CODE_TARGET); |
1223 } | 1231 } |
1224 } | 1232 } |
1225 __ push(eax); // IC call leaves result in eax, push it out | 1233 __ push(eax); // IC call leaves result in eax, push it out |
1226 } | 1234 } |
1227 | 1235 |
1228 | 1236 |
1229 void Ia32CodeGenerator::SetReferenceProperty(MacroAssembler* masm, | 1237 #undef __ |
1238 #define __ masm-> | |
1239 | |
1240 void Ia32CodeGenerator::SetReferenceProperty(CodeGenerator* cgen, | |
1230 Reference* ref, | 1241 Reference* ref, |
1231 Expression* key) { | 1242 Expression* key) { |
1232 ASSERT(!ref->is_illegal()); | 1243 ASSERT(!ref->is_illegal()); |
1233 Reference::Type type = ref->type(); | 1244 MacroAssembler* masm = cgen->masm(); |
1234 | 1245 |
1235 if (type == Reference::NAMED) { | 1246 if (ref->type() == Reference::NAMED) { |
1236 // Compute the name of the property. | 1247 // Compute the name of the property. |
1237 Literal* literal = key->AsLiteral(); | 1248 Literal* literal = key->AsLiteral(); |
1238 Handle<String> name(String::cast(*literal->handle())); | 1249 Handle<String> name(String::cast(*literal->handle())); |
1239 | 1250 |
1240 // Call the appropriate IC code. | 1251 // Call the appropriate IC code. |
1241 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1252 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
1242 // TODO(1222589): Make the IC grab the values from the stack. | 1253 // TODO(1222589): Make the IC grab the values from the stack. |
1243 masm->pop(eax); | 1254 __ pop(eax); |
1244 // Setup the name register. | 1255 // Setup the name register. |
1245 masm->Set(ecx, Immediate(name)); | 1256 __ Set(ecx, Immediate(name)); |
1246 masm->call(ic, RelocInfo::CODE_TARGET); | 1257 __ call(ic, RelocInfo::CODE_TARGET); |
1247 } else { | 1258 } else { |
1248 // Access keyed property. | 1259 // Access keyed property. |
1249 ASSERT(type == Reference::KEYED); | 1260 ASSERT(ref->type() == Reference::KEYED); |
1250 | 1261 |
1251 // Call IC code. | 1262 // Call IC code. |
1252 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 1263 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
1253 // TODO(1222589): Make the IC grab the values from the stack. | 1264 // TODO(1222589): Make the IC grab the values from the stack. |
1254 masm->pop(eax); | 1265 __ pop(eax); |
1255 masm->call(ic, RelocInfo::CODE_TARGET); | 1266 __ call(ic, RelocInfo::CODE_TARGET); |
1256 } | 1267 } |
1257 masm->push(eax); // IC call leaves result in eax, push it out | 1268 __ push(eax); // IC call leaves result in eax, push it out |
1258 } | 1269 } |
1259 | 1270 |
1260 | 1271 |
1261 #undef __ | |
1262 #define __ masm-> | |
1263 | |
1264 | |
1265 class FloatingPointHelper : public AllStatic { | 1272 class FloatingPointHelper : public AllStatic { |
1266 public: | 1273 public: |
1267 // Code pattern for loading floating point values. Input values must | 1274 // Code pattern for loading floating point values. Input values must |
1268 // be either smi or heap number objects (fp values). Requirements: | 1275 // be either smi or heap number objects (fp values). Requirements: |
1269 // operand_1 on TOS+1 , operand_2 on TOS+2; Returns operands as | 1276 // operand_1 on TOS+1 , operand_2 on TOS+2; Returns operands as |
1270 // floating point numbers on FPU stack. | 1277 // floating point numbers on FPU stack. |
1271 static void LoadFloatOperands(MacroAssembler* masm, Register scratch); | 1278 static void LoadFloatOperands(MacroAssembler* masm, Register scratch); |
1272 // Test if operands are smi or number objects (fp). Requirements: | 1279 // Test if operands are smi or number objects (fp). Requirements: |
1273 // operand_1 in eax, operand_2 in edx; falls through on float | 1280 // operand_1 in eax, operand_2 in edx; falls through on float |
1274 // operands, jumps to the non_float label otherwise. | 1281 // operands, jumps to the non_float label otherwise. |
(...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1764 __ j(zero, &done); // argument in eax is OK | 1771 __ j(zero, &done); // argument in eax is OK |
1765 __ mov(scratch, FieldOperand(eax, HeapObject::kMapOffset)); | 1772 __ mov(scratch, FieldOperand(eax, HeapObject::kMapOffset)); |
1766 __ cmp(scratch, Factory::heap_number_map()); | 1773 __ cmp(scratch, Factory::heap_number_map()); |
1767 __ j(not_equal, non_float); // argument in eax is not a number -> NaN | 1774 __ j(not_equal, non_float); // argument in eax is not a number -> NaN |
1768 | 1775 |
1769 // Fall-through: Both operands are numbers. | 1776 // Fall-through: Both operands are numbers. |
1770 __ bind(&done); | 1777 __ bind(&done); |
1771 } | 1778 } |
1772 | 1779 |
1773 | 1780 |
1774 #undef __ | |
1775 #define __ masm-> | |
1776 | |
1777 | |
1778 void UnarySubStub::Generate(MacroAssembler* masm) { | 1781 void UnarySubStub::Generate(MacroAssembler* masm) { |
1779 Label undo; | 1782 Label undo; |
1780 Label slow; | 1783 Label slow; |
1781 Label done; | 1784 Label done; |
1782 Label try_float; | 1785 Label try_float; |
1783 | 1786 |
1784 // Check whether the value is a smi. | 1787 // Check whether the value is a smi. |
1785 __ test(eax, Immediate(kSmiTagMask)); | 1788 __ test(eax, Immediate(kSmiTagMask)); |
1786 __ j(not_zero, &try_float, not_taken); | 1789 __ j(not_zero, &try_float, not_taken); |
1787 | 1790 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1820 __ mov(edx, Operand(eax)); | 1823 __ mov(edx, Operand(eax)); |
1821 // edx: operand | 1824 // edx: operand |
1822 FloatingPointHelper::AllocateHeapNumber(masm, &undo, ebx, ecx); | 1825 FloatingPointHelper::AllocateHeapNumber(masm, &undo, ebx, ecx); |
1823 // eax: allocated 'empty' number | 1826 // eax: allocated 'empty' number |
1824 __ fld_d(FieldOperand(edx, HeapNumber::kValueOffset)); | 1827 __ fld_d(FieldOperand(edx, HeapNumber::kValueOffset)); |
1825 __ fchs(); | 1828 __ fchs(); |
1826 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 1829 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
1827 | 1830 |
1828 __ bind(&done); | 1831 __ bind(&done); |
1829 | 1832 |
1830 masm->StubReturn(1); | 1833 __ StubReturn(1); |
1831 } | 1834 } |
1832 | 1835 |
1833 | 1836 |
1834 class ArgumentsAccessStub: public CodeStub { | 1837 class ArgumentsAccessStub: public CodeStub { |
1835 public: | 1838 public: |
1836 explicit ArgumentsAccessStub(bool is_length) : is_length_(is_length) { } | 1839 explicit ArgumentsAccessStub(bool is_length) : is_length_(is_length) { } |
1837 | 1840 |
1838 private: | 1841 private: |
1839 bool is_length_; | 1842 bool is_length_; |
1840 | 1843 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1919 // Slow-case: Handle non-smi or out-of-bounds access to arguments | 1922 // Slow-case: Handle non-smi or out-of-bounds access to arguments |
1920 // by calling the runtime system. | 1923 // by calling the runtime system. |
1921 if (!is_length_) { | 1924 if (!is_length_) { |
1922 __ bind(&slow); | 1925 __ bind(&slow); |
1923 __ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1); | 1926 __ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1); |
1924 } | 1927 } |
1925 } | 1928 } |
1926 | 1929 |
1927 | 1930 |
1928 #undef __ | 1931 #undef __ |
1929 #define __ masm_-> | 1932 #define __ masm_-> |
1930 | |
1931 | 1933 |
1932 void Ia32CodeGenerator::GenericBinaryOperation(Token::Value op, | 1934 void Ia32CodeGenerator::GenericBinaryOperation(Token::Value op, |
1933 OverwriteMode overwrite_mode) { | 1935 OverwriteMode overwrite_mode) { |
1934 Comment cmnt(masm_, "[ BinaryOperation"); | 1936 Comment cmnt(masm_, "[ BinaryOperation"); |
1935 Comment cmnt_token(masm_, Token::String(op)); | 1937 Comment cmnt_token(masm_, Token::String(op)); |
1936 switch (op) { | 1938 switch (op) { |
1937 case Token::ADD: | 1939 case Token::ADD: |
1938 case Token::SUB: | 1940 case Token::SUB: |
1939 case Token::MUL: | 1941 case Token::MUL: |
1940 case Token::DIV: | 1942 case Token::DIV: |
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2358 __ push(eax); | 2360 __ push(eax); |
2359 } | 2361 } |
2360 GenericBinaryOperation(op, overwrite_mode); | 2362 GenericBinaryOperation(op, overwrite_mode); |
2361 break; | 2363 break; |
2362 } | 2364 } |
2363 } | 2365 } |
2364 } | 2366 } |
2365 | 2367 |
2366 | 2368 |
2367 #undef __ | 2369 #undef __ |
2368 #define __ masm-> | 2370 #define __ masm-> |
2369 | 2371 |
2370 class CompareStub: public CodeStub { | 2372 class CompareStub: public CodeStub { |
2371 public: | 2373 public: |
2372 CompareStub(Condition cc, bool strict) : cc_(cc), strict_(strict) { } | 2374 CompareStub(Condition cc, bool strict) : cc_(cc), strict_(strict) { } |
2373 | 2375 |
2374 void Generate(MacroAssembler* masm); | 2376 void Generate(MacroAssembler* masm); |
2375 | 2377 |
2376 private: | 2378 private: |
2377 Condition cc_; | 2379 Condition cc_; |
2378 bool strict_; | 2380 bool strict_; |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2474 __ pop(eax); | 2476 __ pop(eax); |
2475 __ push(Immediate(Smi::FromInt(0))); | 2477 __ push(Immediate(Smi::FromInt(0))); |
2476 __ push(eax); | 2478 __ push(eax); |
2477 | 2479 |
2478 // Do tail-call to runtime routine. | 2480 // Do tail-call to runtime routine. |
2479 __ TailCallRuntime(ExternalReference(Runtime::kStackGuard), 1); | 2481 __ TailCallRuntime(ExternalReference(Runtime::kStackGuard), 1); |
2480 } | 2482 } |
2481 | 2483 |
2482 | 2484 |
2483 #undef __ | 2485 #undef __ |
2484 #define __ masm_-> | 2486 #define __ masm_-> |
2485 | |
2486 | 2487 |
2487 void Ia32CodeGenerator::Comparison(Condition cc, bool strict) { | 2488 void Ia32CodeGenerator::Comparison(Condition cc, bool strict) { |
2488 // Strict only makes sense for equality comparisons. | 2489 // Strict only makes sense for equality comparisons. |
2489 ASSERT(!strict || cc == equal); | 2490 ASSERT(!strict || cc == equal); |
2490 | 2491 |
2491 // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order. | 2492 // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order. |
2492 if (cc == greater || cc == less_equal) { | 2493 if (cc == greater || cc == less_equal) { |
2493 cc = ReverseCondition(cc); | 2494 cc = ReverseCondition(cc); |
2494 __ pop(edx); | 2495 __ pop(edx); |
2495 __ pop(eax); | 2496 __ pop(eax); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2585 | 2586 |
2586 #ifdef DEBUG | 2587 #ifdef DEBUG |
2587 void Print() { PrintF("CallFunctionStub (args %d)\n", argc_); } | 2588 void Print() { PrintF("CallFunctionStub (args %d)\n", argc_); } |
2588 #endif | 2589 #endif |
2589 | 2590 |
2590 Major MajorKey() { return CallFunction; } | 2591 Major MajorKey() { return CallFunction; } |
2591 int MinorKey() { return argc_; } | 2592 int MinorKey() { return argc_; } |
2592 }; | 2593 }; |
2593 | 2594 |
2594 | 2595 |
2596 #undef __ | |
2597 #define __ masm-> | |
2598 | |
2595 void CallFunctionStub::Generate(MacroAssembler* masm) { | 2599 void CallFunctionStub::Generate(MacroAssembler* masm) { |
2596 Label slow; | 2600 Label slow; |
2597 | 2601 |
2598 // Get the function to call from the stack. | 2602 // Get the function to call from the stack. |
2599 // +2 ~ receiver, return address | 2603 // +2 ~ receiver, return address |
2600 masm->mov(edi, Operand(esp, (argc_ + 2) * kPointerSize)); | 2604 __ mov(edi, Operand(esp, (argc_ + 2) * kPointerSize)); |
2601 | 2605 |
2602 // Check that the function really is a JavaScript function. | 2606 // Check that the function really is a JavaScript function. |
2603 masm->test(edi, Immediate(kSmiTagMask)); | 2607 __ test(edi, Immediate(kSmiTagMask)); |
2604 masm->j(zero, &slow, not_taken); | 2608 __ j(zero, &slow, not_taken); |
2605 // Get the map. | 2609 // Get the map. |
2606 masm->mov(ecx, FieldOperand(edi, HeapObject::kMapOffset)); | 2610 __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset)); |
2607 masm->movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); | 2611 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); |
2608 masm->cmp(ecx, JS_FUNCTION_TYPE); | 2612 __ cmp(ecx, JS_FUNCTION_TYPE); |
2609 masm->j(not_equal, &slow, not_taken); | 2613 __ j(not_equal, &slow, not_taken); |
2610 | 2614 |
2611 // Fast-case: Just invoke the function. | 2615 // Fast-case: Just invoke the function. |
2612 ParameterCount actual(argc_); | 2616 ParameterCount actual(argc_); |
2613 masm->InvokeFunction(edi, actual, JUMP_FUNCTION); | 2617 __ InvokeFunction(edi, actual, JUMP_FUNCTION); |
2614 | 2618 |
2615 // Slow-case: Non-function called. | 2619 // Slow-case: Non-function called. |
2616 masm->bind(&slow); | 2620 __ bind(&slow); |
2617 masm->Set(eax, Immediate(argc_)); | 2621 __ Set(eax, Immediate(argc_)); |
2618 masm->Set(ebx, Immediate(0)); | 2622 __ Set(ebx, Immediate(0)); |
2619 masm->GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); | 2623 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); |
2620 Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)); | 2624 Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)); |
2621 masm->jmp(adaptor, RelocInfo::CODE_TARGET); | 2625 __ jmp(adaptor, RelocInfo::CODE_TARGET); |
2622 } | 2626 } |
2623 | 2627 |
2624 | 2628 |
2629 #undef __ | |
2630 #define __ masm_-> | |
2631 | |
2625 // Call the function just below TOS on the stack with the given | 2632 // Call the function just below TOS on the stack with the given |
2626 // arguments. The receiver is the TOS. | 2633 // arguments. The receiver is the TOS. |
2627 void Ia32CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, | 2634 void Ia32CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, |
2628 int position) { | 2635 int position) { |
2629 // Push the arguments ("left-to-right") on the stack. | 2636 // Push the arguments ("left-to-right") on the stack. |
2630 for (int i = 0; i < args->length(); i++) Load(args->at(i)); | 2637 for (int i = 0; i < args->length(); i++) Load(args->at(i)); |
2631 | 2638 |
2632 // Record the position for debugging purposes. | 2639 // Record the position for debugging purposes. |
2633 __ RecordPosition(position); | 2640 __ RecordPosition(position); |
2634 | 2641 |
(...skipping 1986 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4621 virtual void Generate(); | 4628 virtual void Generate(); |
4622 | 4629 |
4623 private: | 4630 private: |
4624 bool is_postfix_; | 4631 bool is_postfix_; |
4625 bool is_increment_; | 4632 bool is_increment_; |
4626 int result_offset_; | 4633 int result_offset_; |
4627 }; | 4634 }; |
4628 | 4635 |
4629 | 4636 |
4630 #undef __ | 4637 #undef __ |
4631 #define __ masm-> | 4638 #define __ masm-> |
4632 | |
4633 | 4639 |
4634 class RevertToNumberStub: public CodeStub { | 4640 class RevertToNumberStub: public CodeStub { |
4635 public: | 4641 public: |
4636 explicit RevertToNumberStub(bool is_increment) | 4642 explicit RevertToNumberStub(bool is_increment) |
4637 : is_increment_(is_increment) { } | 4643 : is_increment_(is_increment) { } |
4638 | 4644 |
4639 private: | 4645 private: |
4640 bool is_increment_; | 4646 bool is_increment_; |
4641 | 4647 |
4642 Major MajorKey() { return RevertToNumber; } | 4648 Major MajorKey() { return RevertToNumber; } |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4726 __ pop(ecx); | 4732 __ pop(ecx); |
4727 __ push(eax); | 4733 __ push(eax); |
4728 __ push(ecx); | 4734 __ push(ecx); |
4729 Builtins::JavaScript builtin = is_increment_ ? Builtins::INC : Builtins::DEC; | 4735 Builtins::JavaScript builtin = is_increment_ ? Builtins::INC : Builtins::DEC; |
4730 __ InvokeBuiltin(builtin, JUMP_FUNCTION); | 4736 __ InvokeBuiltin(builtin, JUMP_FUNCTION); |
4731 // Code never returns due to JUMP_FUNCTION. | 4737 // Code never returns due to JUMP_FUNCTION. |
4732 } | 4738 } |
4733 | 4739 |
4734 | 4740 |
4735 #undef __ | 4741 #undef __ |
4736 #define __ masm_-> | 4742 #define __ masm_-> |
4737 | |
4738 | 4743 |
4739 void CountOperationDeferred::Generate() { | 4744 void CountOperationDeferred::Generate() { |
4740 if (is_postfix_) { | 4745 if (is_postfix_) { |
4741 RevertToNumberStub to_number_stub(is_increment_); | 4746 RevertToNumberStub to_number_stub(is_increment_); |
4742 __ CallStub(&to_number_stub); | 4747 __ CallStub(&to_number_stub); |
4743 } | 4748 } |
4744 CounterOpStub stub(result_offset_, is_postfix_, is_increment_); | 4749 CounterOpStub stub(result_offset_, is_postfix_, is_increment_); |
4745 __ CallStub(&stub); | 4750 __ CallStub(&stub); |
4746 } | 4751 } |
4747 | 4752 |
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5164 // Avoid using the leave instruction here, because it is too | 5169 // Avoid using the leave instruction here, because it is too |
5165 // short. We need the return sequence to be a least the size of a | 5170 // short. We need the return sequence to be a least the size of a |
5166 // call instruction to support patching the exit code in the | 5171 // call instruction to support patching the exit code in the |
5167 // debugger. See VisitReturnStatement for the full return sequence. | 5172 // debugger. See VisitReturnStatement for the full return sequence. |
5168 __ mov(esp, Operand(ebp)); | 5173 __ mov(esp, Operand(ebp)); |
5169 __ pop(ebp); | 5174 __ pop(ebp); |
5170 } | 5175 } |
5171 | 5176 |
5172 | 5177 |
5173 #undef __ | 5178 #undef __ |
5174 #define __ masm-> | 5179 #define __ masm-> |
5175 | |
5176 | 5180 |
5177 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { | 5181 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { |
5178 ASSERT(StackHandlerConstants::kSize == 6 * kPointerSize); // adjust this code | 5182 ASSERT(StackHandlerConstants::kSize == 6 * kPointerSize); // adjust this code |
5179 ExternalReference handler_address(Top::k_handler_address); | 5183 ExternalReference handler_address(Top::k_handler_address); |
5180 __ mov(edx, Operand::StaticVariable(handler_address)); | 5184 __ mov(edx, Operand::StaticVariable(handler_address)); |
5181 __ mov(ecx, Operand(edx, -1 * kPointerSize)); // get next in chain | 5185 __ mov(ecx, Operand(edx, -1 * kPointerSize)); // get next in chain |
5182 __ mov(Operand::StaticVariable(handler_address), ecx); | 5186 __ mov(Operand::StaticVariable(handler_address), ecx); |
5183 __ mov(esp, Operand(edx)); | 5187 __ mov(esp, Operand(edx)); |
5184 __ pop(edi); | 5188 __ pop(edi); |
5185 __ pop(ebp); | 5189 __ pop(ebp); |
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5473 bool is_eval) { | 5477 bool is_eval) { |
5474 Handle<Code> code = Ia32CodeGenerator::MakeCode(fun, script, is_eval); | 5478 Handle<Code> code = Ia32CodeGenerator::MakeCode(fun, script, is_eval); |
5475 if (!code.is_null()) { | 5479 if (!code.is_null()) { |
5476 Counters::total_compiled_code_size.Increment(code->instruction_size()); | 5480 Counters::total_compiled_code_size.Increment(code->instruction_size()); |
5477 } | 5481 } |
5478 return code; | 5482 return code; |
5479 } | 5483 } |
5480 | 5484 |
5481 | 5485 |
5482 } } // namespace v8::internal | 5486 } } // namespace v8::internal |
OLD | NEW |