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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
51 // on the execution stack to represent the reference. | 51 // on the execution stack to represent the reference. |
52 | 52 |
53 class Reference BASE_EMBEDDED { | 53 class Reference BASE_EMBEDDED { |
54 public: | 54 public: |
55 enum Type { ILLEGAL = -1, EMPTY = 0, NAMED = 1, KEYED = 2 }; | 55 enum Type { ILLEGAL = -1, EMPTY = 0, NAMED = 1, KEYED = 2 }; |
56 Reference(ArmCodeGenerator* cgen, Expression* expression); | 56 Reference(ArmCodeGenerator* cgen, Expression* expression); |
57 ~Reference(); | 57 ~Reference(); |
58 | 58 |
59 Expression* expression() const { return expression_; } | 59 Expression* expression() const { return expression_; } |
60 Type type() const { return type_; } | 60 Type type() const { return type_; } |
61 void set_type(Type value) { | 61 void set_type(Type value) { |
62 ASSERT(type_ == ILLEGAL); | 62 ASSERT(type_ == ILLEGAL); |
63 type_ = value; | 63 type_ = value; |
64 } | 64 } |
65 int size() const { return type_; } | 65 int size() const { return type_; } |
66 | 66 |
67 bool is_illegal() const { return type_ == ILLEGAL; } | 67 bool is_illegal() const { return type_ == ILLEGAL; } |
68 | 68 |
69 private: | 69 private: |
70 ArmCodeGenerator* cgen_; | 70 ArmCodeGenerator* cgen_; |
71 Expression* expression_; | 71 Expression* expression_; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
131 | 131 |
132 // ----------------------------------------------------------------------------- | 132 // ----------------------------------------------------------------------------- |
133 // ArmCodeGenerator | 133 // ArmCodeGenerator |
134 | 134 |
135 class ArmCodeGenerator: public CodeGenerator { | 135 class ArmCodeGenerator: public CodeGenerator { |
136 public: | 136 public: |
137 static Handle<Code> MakeCode(FunctionLiteral* fun, | 137 static Handle<Code> MakeCode(FunctionLiteral* fun, |
138 Handle<Script> script, | 138 Handle<Script> script, |
139 bool is_eval); | 139 bool is_eval); |
140 | 140 |
141 MacroAssembler* masm() { return masm_; } | 141 MacroAssembler* masm() { return masm_; } |
142 | |
143 Scope* scope() const { return scope_; } | |
142 | 144 |
143 CodeGenState* state() { return state_; } | 145 CodeGenState* state() { return state_; } |
144 void set_state(CodeGenState* state) { state_ = state; } | 146 void set_state(CodeGenState* state) { state_ = state; } |
145 | 147 |
146 private: | 148 private: |
147 // Assembler | 149 // Assembler |
148 MacroAssembler* masm_; // to generate code | 150 MacroAssembler* masm_; // to generate code |
149 | 151 |
150 // Code generation state | 152 // Code generation state |
151 Scope* scope_; | 153 Scope* scope_; |
152 Condition cc_reg_; | 154 Condition cc_reg_; |
153 CodeGenState* state_; | 155 CodeGenState* state_; |
154 int break_stack_height_; | 156 int break_stack_height_; |
155 | 157 |
156 // Labels | 158 // Labels |
157 Label function_return_; | 159 Label function_return_; |
158 | 160 |
159 // Construction/destruction | 161 // Construction/destruction |
160 ArmCodeGenerator(int buffer_size, | 162 ArmCodeGenerator(int buffer_size, |
161 Handle<Script> script, | 163 Handle<Script> script, |
162 bool is_eval); | 164 bool is_eval); |
163 | 165 |
164 virtual ~ArmCodeGenerator() { delete masm_; } | 166 virtual ~ArmCodeGenerator() { delete masm_; } |
165 | 167 |
166 // Main code generation function | 168 // Main code generation function |
167 void GenCode(FunctionLiteral* fun); | 169 void GenCode(FunctionLiteral* fun); |
168 | 170 |
169 // The following are used by class Reference. | 171 // The following are used by class Reference. |
170 void LoadReference(Reference* ref); | 172 void LoadReference(Reference* ref); |
171 void UnloadReference(Reference* ref); | 173 void UnloadReference(Reference* ref); |
172 | 174 |
173 // State | 175 // State |
174 bool has_cc() const { return cc_reg_ != al; } | 176 bool has_cc() const { return cc_reg_ != al; } |
175 CodeGenState::AccessType access() const { return state_->access(); } | 177 CodeGenState::AccessType access() const { return state_->access(); } |
176 Reference* ref() const { return state_->ref(); } | 178 Reference* ref() const { return state_->ref(); } |
177 bool is_referenced() const { return state_->ref() != NULL; } | 179 bool is_referenced() const { return state_->ref() != NULL; } |
178 Label* true_target() const { return state_->true_target(); } | 180 Label* true_target() const { return state_->true_target(); } |
179 Label* false_target() const { return state_->false_target(); } | 181 Label* false_target() const { return state_->false_target(); } |
180 | 182 |
181 | 183 |
182 // Expressions | 184 // Expressions |
183 MemOperand GlobalObject() const { | 185 MemOperand GlobalObject() const { |
184 return ContextOperand(cp, Context::GLOBAL_INDEX); | 186 return ContextOperand(cp, Context::GLOBAL_INDEX); |
185 } | 187 } |
186 | 188 |
187 static MemOperand ContextOperand(Register context, int index) { | 189 static MemOperand ContextOperand(Register context, int index) { |
188 return MemOperand(context, Context::SlotOffset(index)); | 190 return MemOperand(context, Context::SlotOffset(index)); |
189 } | 191 } |
190 | 192 |
191 static MemOperand ParameterOperand(Scope* scope, int index) { | 193 static MemOperand ParameterOperand(const CodeGenerator* cgen, int index) { |
194 int num_parameters = cgen->scope()->num_parameters(); | |
192 // index -2 corresponds to the activated closure, -1 corresponds | 195 // index -2 corresponds to the activated closure, -1 corresponds |
193 // to the receiver | 196 // to the receiver |
194 ASSERT(-2 <= index && index < scope->num_parameters()); | 197 ASSERT(-2 <= index && index < num_parameters); |
195 int offset = (1 + scope->num_parameters() - index) * kPointerSize; | 198 int offset = (1 + num_parameters - index) * kPointerSize; |
196 return MemOperand(fp, offset); | 199 return MemOperand(fp, offset); |
197 } | 200 } |
198 | 201 |
199 MemOperand ParameterOperand(int index) const { | 202 MemOperand ParameterOperand(int index) const { |
200 return ParameterOperand(scope_, index); | 203 return ParameterOperand(this, index); |
201 } | 204 } |
202 | 205 |
203 MemOperand FunctionOperand() const { | 206 MemOperand FunctionOperand() const { |
204 return MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset); | 207 return MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset); |
205 } | 208 } |
206 | 209 |
207 static MemOperand SlotOperand(MacroAssembler* masm, | 210 static MemOperand SlotOperand(CodeGenerator* cgen, |
208 Scope* scope, | |
209 Slot* slot, | 211 Slot* slot, |
210 Register tmp); | 212 Register tmp); |
211 | 213 |
212 MemOperand SlotOperand(Slot* slot, Register tmp) { | 214 MemOperand SlotOperand(Slot* slot, Register tmp) { |
213 return SlotOperand(masm_, scope_, slot, tmp); | 215 return SlotOperand(this, slot, tmp); |
214 } | 216 } |
215 | 217 |
216 void LoadCondition(Expression* x, CodeGenState::AccessType access, | 218 void LoadCondition(Expression* x, CodeGenState::AccessType access, |
217 Label* true_target, Label* false_target, bool force_cc); | 219 Label* true_target, Label* false_target, bool force_cc); |
218 void Load(Expression* x, | 220 void Load(Expression* x, |
219 CodeGenState::AccessType access = CodeGenState::LOAD); | 221 CodeGenState::AccessType access = CodeGenState::LOAD); |
220 void LoadGlobal(); | 222 void LoadGlobal(); |
221 | 223 |
222 // Special code for typeof expressions: Unfortunately, we must | 224 // Special code for typeof expressions: Unfortunately, we must |
223 // be careful when loading the expression in 'typeof' | 225 // be careful when loading the expression in 'typeof' |
(...skipping 15 matching lines...) Expand all Loading... | |
239 CodeGenState new_state(this, ref); | 241 CodeGenState new_state(this, ref); |
240 Visit(ref->expression()); | 242 Visit(ref->expression()); |
241 } | 243 } |
242 | 244 |
243 // Generate code to store a value in a reference. The stored value is | 245 // Generate code to store a value in a reference. The stored value is |
244 // expected on top of the expression stack, with the reference immediately | 246 // expected on top of the expression stack, with the reference immediately |
245 // below it. The expression stack is left unchanged. | 247 // below it. The expression stack is left unchanged. |
246 void SetValue(Reference* ref) { | 248 void SetValue(Reference* ref) { |
247 ASSERT(!has_cc()); | 249 ASSERT(!has_cc()); |
248 ASSERT(!ref->is_illegal()); | 250 ASSERT(!ref->is_illegal()); |
249 ref->expression()->GenerateStoreCode(masm_, scope_, ref, NOT_CONST_INIT); | 251 ref->expression()->GenerateStoreCode(this, ref, NOT_CONST_INIT); |
250 } | 252 } |
251 | 253 |
252 // Generate code to store a value in a reference. The stored value is | 254 // Generate code to store a value in a reference. The stored value is |
253 // expected on top of the expression stack, with the reference immediately | 255 // expected on top of the expression stack, with the reference immediately |
254 // below it. The expression stack is left unchanged. | 256 // below it. The expression stack is left unchanged. |
255 void InitConst(Reference* ref) { | 257 void InitConst(Reference* ref) { |
256 ASSERT(!has_cc()); | 258 ASSERT(!has_cc()); |
257 ASSERT(!ref->is_illegal()); | 259 ASSERT(!ref->is_illegal()); |
258 ref->expression()->GenerateStoreCode(masm_, scope_, ref, CONST_INIT); | 260 ref->expression()->GenerateStoreCode(this, ref, CONST_INIT); |
259 } | 261 } |
260 | 262 |
261 // Generate code to fetch a value from a property of a reference. The | 263 // Generate code to fetch a value from a property of a reference. The |
262 // reference is expected on top of the expression stack. It is left in | 264 // reference is expected on top of the expression stack. It is left in |
263 // place and its value is pushed on top of it. | 265 // place and its value is pushed on top of it. |
264 void GetReferenceProperty(Expression* key); | 266 void GetReferenceProperty(Expression* key); |
265 | 267 |
266 // Generate code to store a value in a property of a reference. The | 268 // Generate code to store a value in a property of a reference. The |
267 // stored value is expected on top of the expression stack, with the | 269 // stored value is expected on top of the expression stack, with the |
268 // reference immediately below it. The expression stack is left | 270 // reference immediately below it. The expression stack is left |
269 // unchanged. | 271 // unchanged. |
270 static void SetReferenceProperty(MacroAssembler* masm, | 272 static void SetReferenceProperty(CodeGenerator* cgen, |
271 Reference* ref, | 273 Reference* ref, |
272 Expression* key); | 274 Expression* key); |
273 | 275 |
274 | 276 |
275 void ToBoolean(Label* true_target, Label* false_target); | 277 void ToBoolean(Label* true_target, Label* false_target); |
276 | 278 |
277 void GenericBinaryOperation(Token::Value op); | 279 void GenericBinaryOperation(Token::Value op); |
278 void Comparison(Condition cc, bool strict = false); | 280 void Comparison(Condition cc, bool strict = false); |
279 | 281 |
280 void SmiOperation(Token::Value op, Handle<Object> value, bool reversed); | 282 void SmiOperation(Token::Value op, Handle<Object> value, bool reversed); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
367 | 369 |
368 CodeGenState::~CodeGenState() { | 370 CodeGenState::~CodeGenState() { |
369 ASSERT(owner_->state() == this); | 371 ASSERT(owner_->state() == this); |
370 owner_->set_state(previous_); | 372 owner_->set_state(previous_); |
371 } | 373 } |
372 | 374 |
373 | 375 |
374 // ----------------------------------------------------------------------------- | 376 // ----------------------------------------------------------------------------- |
375 // ArmCodeGenerator implementation | 377 // ArmCodeGenerator implementation |
376 | 378 |
377 #define __ masm_-> | 379 #define __ masm_-> |
378 | |
379 | 380 |
380 Handle<Code> ArmCodeGenerator::MakeCode(FunctionLiteral* flit, | 381 Handle<Code> ArmCodeGenerator::MakeCode(FunctionLiteral* flit, |
381 Handle<Script> script, | 382 Handle<Script> script, |
382 bool is_eval) { | 383 bool is_eval) { |
383 #ifdef ENABLE_DISASSEMBLER | 384 #ifdef ENABLE_DISASSEMBLER |
384 bool print_code = FLAG_print_code && !Bootstrapper::IsActive(); | 385 bool print_code = FLAG_print_code && !Bootstrapper::IsActive(); |
385 #endif // ENABLE_DISASSEMBLER | 386 #endif // ENABLE_DISASSEMBLER |
386 | 387 |
387 #ifdef DEBUG | 388 #ifdef DEBUG |
388 bool print_source = false; | 389 bool print_source = false; |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
663 __ add(sp, sp, Operand((scope_->num_parameters() + 1) * kPointerSize)); | 664 __ add(sp, sp, Operand((scope_->num_parameters() + 1) * kPointerSize)); |
664 __ mov(pc, lr); | 665 __ mov(pc, lr); |
665 | 666 |
666 // Code generation state must be reset. | 667 // Code generation state must be reset. |
667 scope_ = NULL; | 668 scope_ = NULL; |
668 ASSERT(!has_cc()); | 669 ASSERT(!has_cc()); |
669 ASSERT(state_ == NULL); | 670 ASSERT(state_ == NULL); |
670 } | 671 } |
671 | 672 |
672 | 673 |
673 MemOperand ArmCodeGenerator::SlotOperand(MacroAssembler* masm, | 674 #undef __ |
674 Scope* scope, | 675 #define __ masm-> |
676 | |
677 MemOperand ArmCodeGenerator::SlotOperand(CodeGenerator* cgen, | |
675 Slot* slot, | 678 Slot* slot, |
676 Register tmp) { | 679 Register tmp) { |
677 // Currently, this assertion will fail if we try to assign to | 680 // Currently, this assertion will fail if we try to assign to |
678 // a constant variable that is constant because it is read-only | 681 // a constant variable that is constant because it is read-only |
679 // (such as the variable referring to a named function expression). | 682 // (such as the variable referring to a named function expression). |
680 // We need to implement assignments to read-only variables. | 683 // We need to implement assignments to read-only variables. |
681 // Ideally, we should do this during AST generation (by converting | 684 // Ideally, we should do this during AST generation (by converting |
682 // such assignments into expression statements); however, in general | 685 // such assignments into expression statements); however, in general |
683 // we may not be able to make the decision until past AST generation, | 686 // we may not be able to make the decision until past AST generation, |
684 // that is when the entire program is known. | 687 // that is when the entire program is known. |
685 ASSERT(slot != NULL); | 688 ASSERT(slot != NULL); |
686 int index = slot->index(); | 689 int index = slot->index(); |
687 switch (slot->type()) { | 690 switch (slot->type()) { |
688 case Slot::PARAMETER: | 691 case Slot::PARAMETER: |
689 return ParameterOperand(scope, index); | 692 return ParameterOperand(cgen, index); |
690 | 693 |
691 case Slot::LOCAL: { | 694 case Slot::LOCAL: { |
692 ASSERT(0 <= index && | 695 ASSERT(0 <= index && |
693 index < scope->num_stack_slots() && | 696 index < cgen->scope()->num_stack_slots() && |
694 index >= 0); | 697 index >= 0); |
695 int local_offset = JavaScriptFrameConstants::kLocal0Offset - | 698 int local_offset = JavaScriptFrameConstants::kLocal0Offset - |
696 index * kPointerSize; | 699 index * kPointerSize; |
697 return MemOperand(fp, local_offset); | 700 return MemOperand(fp, local_offset); |
698 } | 701 } |
699 | 702 |
700 case Slot::CONTEXT: { | 703 case Slot::CONTEXT: { |
704 MacroAssembler* masm = cgen->masm(); | |
701 // Follow the context chain if necessary. | 705 // Follow the context chain if necessary. |
702 ASSERT(!tmp.is(cp)); // do not overwrite context register | 706 ASSERT(!tmp.is(cp)); // do not overwrite context register |
703 Register context = cp; | 707 Register context = cp; |
704 int chain_length = scope->ContextChainLength(slot->var()->scope()); | 708 int chain_length = |
709 cgen->scope()->ContextChainLength(slot->var()->scope()); | |
705 for (int i = chain_length; i-- > 0;) { | 710 for (int i = chain_length; i-- > 0;) { |
706 // Load the closure. | 711 // Load the closure. |
707 // (All contexts, even 'with' contexts, have a closure, | 712 // (All contexts, even 'with' contexts, have a closure, |
708 // and it is the same for all contexts inside a function. | 713 // and it is the same for all contexts inside a function. |
709 // There is no need to go to the function context first.) | 714 // There is no need to go to the function context first.) |
710 masm->ldr(tmp, ContextOperand(context, Context::CLOSURE_INDEX)); | 715 __ ldr(tmp, ContextOperand(context, Context::CLOSURE_INDEX)); |
711 // Load the function context (which is the incoming, outer context). | 716 // Load the function context (which is the incoming, outer context). |
712 masm->ldr(tmp, FieldMemOperand(tmp, JSFunction::kContextOffset)); | 717 __ ldr(tmp, FieldMemOperand(tmp, JSFunction::kContextOffset)); |
713 context = tmp; | 718 context = tmp; |
714 } | 719 } |
715 // We may have a 'with' context now. Get the function context. | 720 // We may have a 'with' context now. Get the function context. |
716 // (In fact this mov may never be the needed, since the scope analysis | 721 // (In fact this mov may never be the needed, since the scope analysis |
717 // may not permit a direct context access in this case and thus we are | 722 // may not permit a direct context access in this case and thus we are |
718 // always at a function context. However it is safe to dereference be- | 723 // always at a function context. However it is safe to dereference be- |
719 // cause the function context of a function context is itself. Before | 724 // cause the function context of a function context is itself. Before |
720 // deleting this mov we should try to create a counter-example first, | 725 // deleting this mov we should try to create a counter-example first, |
721 // though...) | 726 // though...) |
722 masm->ldr(tmp, ContextOperand(context, Context::FCONTEXT_INDEX)); | 727 __ ldr(tmp, ContextOperand(context, Context::FCONTEXT_INDEX)); |
723 return ContextOperand(tmp, index); | 728 return ContextOperand(tmp, index); |
724 } | 729 } |
725 | 730 |
726 default: | 731 default: |
727 UNREACHABLE(); | 732 UNREACHABLE(); |
728 return MemOperand(r0, 0); | 733 return MemOperand(r0, 0); |
729 } | 734 } |
730 } | 735 } |
731 | 736 |
732 | 737 |
738 #undef __ | |
739 #define __ masm_-> | |
740 | |
733 // Loads a value on the stack. If it is a boolean value, the result may have | 741 // Loads a value on the stack. If it is a boolean value, the result may have |
734 // been (partially) translated into branches, or it may have set the condition | 742 // been (partially) translated into branches, or it may have set the condition |
735 // code register. If force_cc is set, the value is forced to set the condition | 743 // code register. If force_cc is set, the value is forced to set the condition |
736 // code register and no value is pushed. If the condition code register was set, | 744 // code register and no value is pushed. If the condition code register was set, |
737 // has_cc() is true and cc_reg_ contains the condition to test for 'true'. | 745 // has_cc() is true and cc_reg_ contains the condition to test for 'true'. |
738 void ArmCodeGenerator::LoadCondition(Expression* x, | 746 void ArmCodeGenerator::LoadCondition(Expression* x, |
739 CodeGenState::AccessType access, | 747 CodeGenState::AccessType access, |
740 Label* true_target, | 748 Label* true_target, |
741 Label* false_target, | 749 Label* false_target, |
742 bool force_cc) { | 750 bool force_cc) { |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
887 if (size <= 0) { | 895 if (size <= 0) { |
888 // Do nothing. No popping is necessary. | 896 // Do nothing. No popping is necessary. |
889 } else { | 897 } else { |
890 __ pop(r0); | 898 __ pop(r0); |
891 __ add(sp, sp, Operand(size * kPointerSize)); | 899 __ add(sp, sp, Operand(size * kPointerSize)); |
892 __ push(r0); | 900 __ push(r0); |
893 } | 901 } |
894 } | 902 } |
895 | 903 |
896 | 904 |
897 void Property::GenerateStoreCode(MacroAssembler* masm, | 905 #undef __ |
898 Scope* scope, | 906 #define __ masm-> |
907 | |
908 void Property::GenerateStoreCode(CodeGenerator* cgen, | |
899 Reference* ref, | 909 Reference* ref, |
900 InitState init_state) { | 910 InitState init_state) { |
911 MacroAssembler* masm = cgen->masm(); | |
901 Comment cmnt(masm, "[ Store to Property"); | 912 Comment cmnt(masm, "[ Store to Property"); |
902 masm->RecordPosition(position()); | 913 __ RecordPosition(position()); |
903 ArmCodeGenerator::SetReferenceProperty(masm, ref, key()); | 914 ArmCodeGenerator::SetReferenceProperty(cgen, ref, key()); |
904 } | 915 } |
905 | 916 |
906 | 917 |
907 void VariableProxy::GenerateStoreCode(MacroAssembler* masm, | 918 void VariableProxy::GenerateStoreCode(CodeGenerator* cgen, |
908 Scope* scope, | |
909 Reference* ref, | 919 Reference* ref, |
910 InitState init_state) { | 920 InitState init_state) { |
921 MacroAssembler* masm = cgen->masm(); | |
911 Comment cmnt(masm, "[ Store to VariableProxy"); | 922 Comment cmnt(masm, "[ Store to VariableProxy"); |
912 Variable* node = var(); | 923 Variable* node = var(); |
913 | 924 |
914 Expression* expr = node->rewrite(); | 925 Expression* expr = node->rewrite(); |
915 if (expr != NULL) { | 926 if (expr != NULL) { |
916 expr->GenerateStoreCode(masm, scope, ref, init_state); | 927 expr->GenerateStoreCode(cgen, ref, init_state); |
917 } else { | 928 } else { |
918 ASSERT(node->is_global()); | 929 ASSERT(node->is_global()); |
919 if (node->AsProperty() != NULL) { | 930 if (node->AsProperty() != NULL) { |
920 masm->RecordPosition(node->AsProperty()->position()); | 931 __ RecordPosition(node->AsProperty()->position()); |
921 } | 932 } |
922 ArmCodeGenerator::SetReferenceProperty(masm, ref, | 933 Expression* key = new Literal(node->name()); |
923 new Literal(node->name())); | 934 ArmCodeGenerator::SetReferenceProperty(cgen, ref, key); |
924 } | 935 } |
925 } | 936 } |
926 | 937 |
927 | 938 |
928 void Slot::GenerateStoreCode(MacroAssembler* masm, | 939 void Slot::GenerateStoreCode(CodeGenerator* cgen, |
929 Scope* scope, | |
930 Reference* ref, | 940 Reference* ref, |
931 InitState init_state) { | 941 InitState init_state) { |
942 MacroAssembler* masm = cgen->masm(); | |
932 Comment cmnt(masm, "[ Store to Slot"); | 943 Comment cmnt(masm, "[ Store to Slot"); |
933 | 944 |
934 if (type() == Slot::LOOKUP) { | 945 if (type() == Slot::LOOKUP) { |
935 ASSERT(var()->mode() == Variable::DYNAMIC); | 946 ASSERT(var()->mode() == Variable::DYNAMIC); |
936 | 947 |
937 // For now, just do a runtime call. | 948 // For now, just do a runtime call. |
938 masm->push(cp); | 949 __ push(cp); |
939 masm->mov(r0, Operand(var()->name())); | 950 __ mov(r0, Operand(var()->name())); |
940 masm->push(r0); | 951 __ push(r0); |
941 | 952 |
942 if (init_state == CONST_INIT) { | 953 if (init_state == CONST_INIT) { |
943 // Same as the case for a normal store, but ignores attribute | 954 // Same as the case for a normal store, but ignores attribute |
944 // (e.g. READ_ONLY) of context slot so that we can initialize const | 955 // (e.g. READ_ONLY) of context slot so that we can initialize const |
945 // properties (introduced via eval("const foo = (some expr);")). Also, | 956 // properties (introduced via eval("const foo = (some expr);")). Also, |
946 // uses the current function context instead of the top context. | 957 // uses the current function context instead of the top context. |
947 // | 958 // |
948 // Note that we must declare the foo upon entry of eval(), via a | 959 // Note that we must declare the foo upon entry of eval(), via a |
949 // context slot declaration, but we cannot initialize it at the same | 960 // context slot declaration, but we cannot initialize it at the same |
950 // time, because the const declaration may be at the end of the eval | 961 // time, because the const declaration may be at the end of the eval |
951 // code (sigh...) and the const variable may have been used before | 962 // code (sigh...) and the const variable may have been used before |
952 // (where its value is 'undefined'). Thus, we can only do the | 963 // (where its value is 'undefined'). Thus, we can only do the |
953 // initialization when we actually encounter the expression and when | 964 // initialization when we actually encounter the expression and when |
954 // the expression operands are defined and valid, and thus we need the | 965 // the expression operands are defined and valid, and thus we need the |
955 // split into 2 operations: declaration of the context slot followed | 966 // split into 2 operations: declaration of the context slot followed |
956 // by initialization. | 967 // by initialization. |
957 masm->CallRuntime(Runtime::kInitializeConstContextSlot, 3); | 968 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); |
958 } else { | 969 } else { |
959 masm->CallRuntime(Runtime::kStoreContextSlot, 3); | 970 __ CallRuntime(Runtime::kStoreContextSlot, 3); |
960 } | 971 } |
961 // Storing a variable must keep the (new) value on the expression | 972 // Storing a variable must keep the (new) value on the expression |
962 // stack. This is necessary for compiling assignment expressions. | 973 // stack. This is necessary for compiling assignment expressions. |
963 masm->push(r0); | 974 __ push(r0); |
964 | 975 |
965 } else { | 976 } else { |
966 ASSERT(var()->mode() != Variable::DYNAMIC); | 977 ASSERT(var()->mode() != Variable::DYNAMIC); |
967 | 978 |
968 Label exit; | 979 Label exit; |
969 if (init_state == CONST_INIT) { | 980 if (init_state == CONST_INIT) { |
970 ASSERT(var()->mode() == Variable::CONST); | 981 ASSERT(var()->mode() == Variable::CONST); |
971 // Only the first const initialization must be executed (the slot | 982 // Only the first const initialization must be executed (the slot |
972 // still contains 'the hole' value). When the assignment is executed, | 983 // still contains 'the hole' value). When the assignment is executed, |
973 // the code is identical to a normal store (see below). | 984 // the code is identical to a normal store (see below). |
974 Comment cmnt(masm, "[ Init const"); | 985 Comment cmnt(masm, "[ Init const"); |
975 masm->ldr(r2, ArmCodeGenerator::SlotOperand(masm, scope, this, r2)); | 986 __ ldr(r2, ArmCodeGenerator::SlotOperand(cgen, this, r2)); |
976 masm->cmp(r2, Operand(Factory::the_hole_value())); | 987 __ cmp(r2, Operand(Factory::the_hole_value())); |
977 masm->b(ne, &exit); | 988 __ b(ne, &exit); |
978 } | 989 } |
979 | 990 |
980 // We must execute the store. | 991 // We must execute the store. |
981 // r2 may be loaded with context; used below in RecordWrite. | 992 // r2 may be loaded with context; used below in RecordWrite. |
982 // Storing a variable must keep the (new) value on the stack. This is | 993 // Storing a variable must keep the (new) value on the stack. This is |
983 // necessary for compiling assignment expressions. | 994 // necessary for compiling assignment expressions. |
984 // | 995 // |
985 // Note: We will reach here even with var()->mode() == Variable::CONST | 996 // Note: We will reach here even with var()->mode() == Variable::CONST |
986 // because of const declarations which will initialize consts to 'the | 997 // because of const declarations which will initialize consts to 'the |
987 // hole' value and by doing so, end up calling this code. r2 may be | 998 // hole' value and by doing so, end up calling this code. r2 may be |
988 // loaded with context; used below in RecordWrite. | 999 // loaded with context; used below in RecordWrite. |
989 masm->pop(r0); | 1000 __ pop(r0); |
990 masm->str(r0, ArmCodeGenerator::SlotOperand(masm, scope, this, r2)); | 1001 __ str(r0, ArmCodeGenerator::SlotOperand(cgen, this, r2)); |
991 masm->push(r0); | 1002 __ push(r0); |
992 | 1003 |
993 if (type() == Slot::CONTEXT) { | 1004 if (type() == Slot::CONTEXT) { |
994 // Skip write barrier if the written value is a smi. | 1005 // Skip write barrier if the written value is a smi. |
995 masm->tst(r0, Operand(kSmiTagMask)); | 1006 __ tst(r0, Operand(kSmiTagMask)); |
996 masm->b(eq, &exit); | 1007 __ b(eq, &exit); |
997 // r2 is loaded with context when calling SlotOperand above. | 1008 // r2 is loaded with context when calling SlotOperand above. |
998 int offset = FixedArray::kHeaderSize + index() * kPointerSize; | 1009 int offset = FixedArray::kHeaderSize + index() * kPointerSize; |
999 masm->mov(r3, Operand(offset)); | 1010 __ mov(r3, Operand(offset)); |
1000 masm->RecordWrite(r2, r3, r1); | 1011 __ RecordWrite(r2, r3, r1); |
1001 } | 1012 } |
1002 // If we definitely did not jump over the assignment, we do not need to | 1013 // If we definitely did not jump over the assignment, we do not need to |
1003 // bind the exit label. Doing so can defeat peephole optimization. | 1014 // bind the exit label. Doing so can defeat peephole optimization. |
1004 if (init_state == CONST_INIT || type() == Slot::CONTEXT) { | 1015 if (init_state == CONST_INIT || type() == Slot::CONTEXT) { |
1005 masm->bind(&exit); | 1016 __ bind(&exit); |
1006 } | 1017 } |
1007 } | 1018 } |
1008 } | 1019 } |
1009 | 1020 |
1010 | 1021 |
1022 #undef __ | |
1023 #define __ masm_-> | |
1024 | |
1011 // ECMA-262, section 9.2, page 30: ToBoolean(). Convert the given | 1025 // ECMA-262, section 9.2, page 30: ToBoolean(). Convert the given |
1012 // register to a boolean in the condition code register. The code | 1026 // register to a boolean in the condition code register. The code |
1013 // may jump to 'false_target' in case the register converts to 'false'. | 1027 // may jump to 'false_target' in case the register converts to 'false'. |
1014 void ArmCodeGenerator::ToBoolean(Label* true_target, | 1028 void ArmCodeGenerator::ToBoolean(Label* true_target, |
1015 Label* false_target) { | 1029 Label* false_target) { |
1016 // Note: The generated code snippet does not change stack variables. | 1030 // Note: The generated code snippet does not change stack variables. |
1017 // Only the condition code should be set. | 1031 // Only the condition code should be set. |
1018 __ pop(r0); | 1032 __ pop(r0); |
1019 | 1033 |
1020 // Fast case checks | 1034 // Fast case checks |
(...skipping 21 matching lines...) Expand all Loading... | |
1042 __ CallRuntime(Runtime::kToBool, 1); | 1056 __ CallRuntime(Runtime::kToBool, 1); |
1043 | 1057 |
1044 // Convert result (r0) to condition code | 1058 // Convert result (r0) to condition code |
1045 __ cmp(r0, Operand(Factory::false_value())); | 1059 __ cmp(r0, Operand(Factory::false_value())); |
1046 | 1060 |
1047 cc_reg_ = ne; | 1061 cc_reg_ = ne; |
1048 } | 1062 } |
1049 | 1063 |
1050 | 1064 |
1051 #undef __ | 1065 #undef __ |
1052 #define __ masm-> | 1066 #define __ masm-> |
1053 | |
1054 | 1067 |
1055 class GetPropertyStub : public CodeStub { | 1068 class GetPropertyStub : public CodeStub { |
1056 public: | 1069 public: |
1057 GetPropertyStub() { } | 1070 GetPropertyStub() { } |
1058 | 1071 |
1059 private: | 1072 private: |
1060 Major MajorKey() { return GetProperty; } | 1073 Major MajorKey() { return GetProperty; } |
1061 int MinorKey() { return 0; } | 1074 int MinorKey() { return 0; } |
1062 void Generate(MacroAssembler* masm); | 1075 void Generate(MacroAssembler* masm); |
1063 | 1076 |
(...skipping 920 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1984 | 1997 |
1985 if (!is_length_) { | 1998 if (!is_length_) { |
1986 __ bind(&slow); | 1999 __ bind(&slow); |
1987 __ push(r1); | 2000 __ push(r1); |
1988 __ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1); | 2001 __ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1); |
1989 } | 2002 } |
1990 } | 2003 } |
1991 | 2004 |
1992 | 2005 |
1993 #undef __ | 2006 #undef __ |
1994 #define __ masm_-> | 2007 #define __ masm_-> |
1995 | |
1996 | 2008 |
1997 void ArmCodeGenerator::GetReferenceProperty(Expression* key) { | 2009 void ArmCodeGenerator::GetReferenceProperty(Expression* key) { |
1998 ASSERT(!ref()->is_illegal()); | 2010 ASSERT(!ref()->is_illegal()); |
1999 Reference::Type type = ref()->type(); | 2011 Reference::Type type = ref()->type(); |
2000 | 2012 |
2001 // TODO(1241834): Make sure that this it is safe to ignore the distinction | 2013 // TODO(1241834): Make sure that this it is safe to ignore the distinction |
2002 // between access types LOAD and LOAD_TYPEOF_EXPR. If there is a chance | 2014 // between access types LOAD and LOAD_TYPEOF_EXPR. If there is a chance |
2003 // that reference errors can be thrown below, we must distinguish between | 2015 // that reference errors can be thrown below, we must distinguish between |
2004 // the two kinds of loads (typeof expression loads must not throw a | 2016 // the two kinds of loads (typeof expression loads must not throw a |
2005 // reference error). | 2017 // reference error). |
(...skipping 19 matching lines...) Expand all Loading... | |
2025 ASSERT(type == Reference::KEYED); | 2037 ASSERT(type == Reference::KEYED); |
2026 | 2038 |
2027 // TODO(1224671): Implement inline caching for keyed loads as on ia32. | 2039 // TODO(1224671): Implement inline caching for keyed loads as on ia32. |
2028 GetPropertyStub stub; | 2040 GetPropertyStub stub; |
2029 __ CallStub(&stub); | 2041 __ CallStub(&stub); |
2030 } | 2042 } |
2031 __ push(r0); | 2043 __ push(r0); |
2032 } | 2044 } |
2033 | 2045 |
2034 | 2046 |
2035 void ArmCodeGenerator::SetReferenceProperty(MacroAssembler* masm, | 2047 #undef __ |
2048 #define __ masm-> | |
2049 | |
2050 void ArmCodeGenerator::SetReferenceProperty(CodeGenerator* cgen, | |
2036 Reference* ref, | 2051 Reference* ref, |
2037 Expression* key) { | 2052 Expression* key) { |
2038 ASSERT(!ref->is_illegal()); | 2053 ASSERT(!ref->is_illegal()); |
2039 Reference::Type type = ref->type(); | 2054 MacroAssembler* masm = cgen->masm(); |
2040 | 2055 |
2041 if (type == Reference::NAMED) { | 2056 if (ref->type() == Reference::NAMED) { |
2042 // Compute the name of the property. | 2057 // Compute the name of the property. |
2043 Literal* literal = key->AsLiteral(); | 2058 Literal* literal = key->AsLiteral(); |
2044 Handle<String> name(String::cast(*literal->handle())); | 2059 Handle<String> name(String::cast(*literal->handle())); |
2045 | 2060 |
2046 // Call the appropriate IC code. | 2061 // Call the appropriate IC code. |
2047 masm->pop(r0); // value | 2062 masm->pop(r0); // value |
Kasper Lund
2008/10/02 08:57:58
Shouldn't this be __?
| |
2048 // Setup the name register. | 2063 // Setup the name register. |
2049 masm->mov(r2, Operand(name)); | 2064 masm->mov(r2, Operand(name)); |
2050 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 2065 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
2051 masm->Call(ic, RelocInfo::CODE_TARGET); | 2066 masm->Call(ic, RelocInfo::CODE_TARGET); |
2052 | 2067 |
2053 } else { | 2068 } else { |
2054 // Access keyed property. | 2069 // Access keyed property. |
2055 ASSERT(type == Reference::KEYED); | 2070 ASSERT(ref->type() == Reference::KEYED); |
2056 | 2071 |
2057 masm->pop(r0); // value | 2072 masm->pop(r0); // value |
2058 SetPropertyStub stub; | 2073 SetPropertyStub stub; |
2059 masm->CallStub(&stub); | 2074 masm->CallStub(&stub); |
2060 } | 2075 } |
2061 masm->push(r0); | 2076 masm->push(r0); |
2062 } | 2077 } |
2063 | 2078 |
2064 | 2079 |
2080 #undef __ | |
2081 #define __ masm_-> | |
2082 | |
2065 void ArmCodeGenerator::GenericBinaryOperation(Token::Value op) { | 2083 void ArmCodeGenerator::GenericBinaryOperation(Token::Value op) { |
2066 // sp[0] : y | 2084 // sp[0] : y |
2067 // sp[1] : x | 2085 // sp[1] : x |
2068 // result : r0 | 2086 // result : r0 |
2069 | 2087 |
2070 // Stub is entered with a call: 'return address' is in lr. | 2088 // Stub is entered with a call: 'return address' is in lr. |
2071 switch (op) { | 2089 switch (op) { |
2072 case Token::ADD: // fall through. | 2090 case Token::ADD: // fall through. |
2073 case Token::SUB: // fall through. | 2091 case Token::SUB: // fall through. |
2074 case Token::MUL: | 2092 case Token::MUL: |
(...skipping 2452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4527 bool is_eval) { | 4545 bool is_eval) { |
4528 Handle<Code> code = ArmCodeGenerator::MakeCode(fun, script, is_eval); | 4546 Handle<Code> code = ArmCodeGenerator::MakeCode(fun, script, is_eval); |
4529 if (!code.is_null()) { | 4547 if (!code.is_null()) { |
4530 Counters::total_compiled_code_size.Increment(code->instruction_size()); | 4548 Counters::total_compiled_code_size.Increment(code->instruction_size()); |
4531 } | 4549 } |
4532 return code; | 4550 return code; |
4533 } | 4551 } |
4534 | 4552 |
4535 | 4553 |
4536 } } // namespace v8::internal | 4554 } } // namespace v8::internal |
OLD | NEW |