Chromium Code Reviews| 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 |