Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Side by Side Diff: src/codegen-arm.cc

Issue 5663: Small cleanup of the code generator: make the static code gen... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 12 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/codegen.h ('k') | src/codegen-ia32.cc » ('j') | src/codegen-ia32.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698