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

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

Issue 1889: Remove some of the state-dependent behavior from the code generator.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 12 years, 3 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 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 102
103 103
104 // ----------------------------------------------------------------------------- 104 // -----------------------------------------------------------------------------
105 // Code generation state 105 // Code generation state
106 106
107 class CodeGenState BASE_EMBEDDED { 107 class CodeGenState BASE_EMBEDDED {
108 public: 108 public:
109 enum AccessType { 109 enum AccessType {
110 UNDEFINED, 110 UNDEFINED,
111 LOAD, 111 LOAD,
112 LOAD_TYPEOF_EXPR, 112 LOAD_TYPEOF_EXPR
113 STORE,
114 INIT_CONST
115 }; 113 };
116 114
117 CodeGenState() 115 CodeGenState()
118 : access_(UNDEFINED), 116 : access_(UNDEFINED),
119 ref_(NULL), 117 ref_(NULL),
120 true_target_(NULL), 118 true_target_(NULL),
121 false_target_(NULL) { 119 false_target_(NULL) {
122 } 120 }
123 121
124 CodeGenState(AccessType access, 122 CodeGenState(AccessType access,
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 bool is_eval); 172 bool is_eval);
175 173
176 virtual ~ArmCodeGenerator() { delete masm_; } 174 virtual ~ArmCodeGenerator() { delete masm_; }
177 175
178 // Main code generation function 176 // Main code generation function
179 void GenCode(FunctionLiteral* fun); 177 void GenCode(FunctionLiteral* fun);
180 178
181 // The following are used by class Reference. 179 // The following are used by class Reference.
182 void LoadReference(Reference* ref); 180 void LoadReference(Reference* ref);
183 void UnloadReference(Reference* ref); 181 void UnloadReference(Reference* ref);
184 friend class Reference;
185 182
186 // State 183 // State
187 bool has_cc() const { return cc_reg_ != al; } 184 bool has_cc() const { return cc_reg_ != al; }
188 CodeGenState::AccessType access() const { return state_->access(); } 185 CodeGenState::AccessType access() const { return state_->access(); }
189 Reference* ref() const { return state_->ref(); } 186 Reference* ref() const { return state_->ref(); }
190 bool is_referenced() const { return state_->ref() != NULL; } 187 bool is_referenced() const { return state_->ref() != NULL; }
191 Label* true_target() const { return state_->true_target(); } 188 Label* true_target() const { return state_->true_target(); }
192 Label* false_target() const { return state_->false_target(); } 189 Label* false_target() const { return state_->false_target(); }
193 190
194 191
195 // Expressions 192 // Expressions
196 MemOperand GlobalObject() const { 193 MemOperand GlobalObject() const {
197 return ContextOperand(cp, Context::GLOBAL_INDEX); 194 return ContextOperand(cp, Context::GLOBAL_INDEX);
198 } 195 }
199 196
200 MemOperand ContextOperand(Register context, int index) const { 197 static MemOperand ContextOperand(Register context, int index) {
201 return MemOperand(context, Context::SlotOffset(index)); 198 return MemOperand(context, Context::SlotOffset(index));
202 } 199 }
203 200
204 MemOperand ParameterOperand(int index) const { 201 static MemOperand ParameterOperand(Scope* scope, int index) {
205 // index -2 corresponds to the activated closure, -1 corresponds 202 // index -2 corresponds to the activated closure, -1 corresponds
206 // to the receiver 203 // to the receiver
207 ASSERT(-2 <= index && index < scope_->num_parameters()); 204 ASSERT(-2 <= index && index < scope->num_parameters());
208 int offset = JavaScriptFrameConstants::kParam0Offset - index * kPointerSize; 205 int offset = JavaScriptFrameConstants::kParam0Offset - index * kPointerSize;
209 return MemOperand(pp, offset); 206 return MemOperand(pp, offset);
210 } 207 }
211 208
209 MemOperand ParameterOperand(int index) const {
210 return ParameterOperand(scope_, index);
211 }
212
212 MemOperand FunctionOperand() const { return ParameterOperand(-2); } 213 MemOperand FunctionOperand() const { return ParameterOperand(-2); }
213 214
214 MemOperand SlotOperand(Slot* slot, Register tmp); 215 static MemOperand SlotOperand(MacroAssembler* masm,
216 Scope* scope,
217 Slot* slot,
218 Register tmp);
219
220 MemOperand SlotOperand(Slot* slot, Register tmp) {
221 return SlotOperand(masm_, scope_, slot, tmp);
222 }
215 223
216 void LoadCondition(Expression* x, CodeGenState::AccessType access, 224 void LoadCondition(Expression* x, CodeGenState::AccessType access,
217 Label* true_target, Label* false_target, bool force_cc); 225 Label* true_target, Label* false_target, bool force_cc);
218 void Load(Expression* x, 226 void Load(Expression* x,
219 CodeGenState::AccessType access = CodeGenState::LOAD); 227 CodeGenState::AccessType access = CodeGenState::LOAD);
220 void LoadGlobal(); 228 void LoadGlobal();
221 229
222 // Special code for typeof expressions: Unfortunately, we must 230 // Special code for typeof expressions: Unfortunately, we must
223 // be careful when loading the expression in 'typeof' 231 // be careful when loading the expression in 'typeof'
224 // expressions. We are not allowed to throw reference errors for 232 // expressions. We are not allowed to throw reference errors for
225 // non-existing properties of the global object, so we must make it 233 // non-existing properties of the global object, so we must make it
226 // look like an explicit property access, instead of an access 234 // look like an explicit property access, instead of an access
227 // through the context chain. 235 // through the context chain.
228 void LoadTypeofExpression(Expression* x); 236 void LoadTypeofExpression(Expression* x);
229 237
238
230 // References 239 // References
231 void AccessReference(Reference* ref, CodeGenState::AccessType access);
232 240
233 void GetValue(Reference* ref) { AccessReference(ref, CodeGenState::LOAD); } 241 // Generate code to fetch the value of a reference. The reference is
234 void SetValue(Reference* ref) { AccessReference(ref, CodeGenState::STORE); } 242 // expected to be on top of the expression stack. It is left in place and
235 void InitConst(Reference* ref) { 243 // its value is pushed on top of it.
236 AccessReference(ref, CodeGenState::INIT_CONST); 244 void GetValue(Reference* ref);
245
246 // Generate code to store a value in a reference. The stored value is
247 // expected on top of the expression stack, with the reference immediately
248 // below it. The expression stack is left unchanged.
249 void SetValue(Reference* ref) {
250 ASSERT(!has_cc());
251 ASSERT(!ref->is_illegal());
252 ref->expression()->GenerateStoreCode(masm_, scope_, ref, false);
237 } 253 }
238 254
239 void ToBoolean(Label* true_target, Label* false_target); 255 // Generate code to store a value in a reference. The stored value is
256 // expected on top of the expression stack, with the reference immediately
257 // below it. The expression stack is left unchanged.
258 void InitConst(Reference* ref) {
259 ASSERT(!has_cc());
260 ASSERT(!ref->is_illegal());
261 ref->expression()->GenerateStoreCode(masm_, scope_, ref, true);
262 }
263
264 // Generate code to fetch a value from a property of a reference. The
265 // reference is expected on top of the expression stack. It is left in
266 // place and its value is pushed on top of it.
267 void GetReferenceProperty(Expression* key);
268
269 // Generate code to store a value in a property of a reference. The
270 // stored value is expected on top of the expression stack, with the
271 // reference immediately below it. The expression stack is left
272 // unchanged.
273 static void SetReferenceProperty(MacroAssembler* masm,
274 Reference* ref,
275 Expression* key);
240 276
241 277
242 // Access property from the reference (must be at the TOS). 278 void ToBoolean(Label* true_target, Label* false_target);
243 void AccessReferenceProperty(Expression* key,
244 CodeGenState::AccessType access);
245 279
246 void GenericBinaryOperation(Token::Value op); 280 void GenericBinaryOperation(Token::Value op);
247 void Comparison(Condition cc, bool strict = false); 281 void Comparison(Condition cc, bool strict = false);
248 282
249 void SmiOperation(Token::Value op, Handle<Object> value, bool reversed); 283 void SmiOperation(Token::Value op, Handle<Object> value, bool reversed);
250 284
251 void CallWithArguments(ZoneList<Expression*>* arguments, int position); 285 void CallWithArguments(ZoneList<Expression*>* arguments, int position);
252 286
253 // Declare global variables and functions in the given array of 287 // Declare global variables and functions in the given array of
254 // name/value pairs. 288 // name/value pairs.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 324
291 virtual void GenerateArgumentsLength(ZoneList<Expression*>* args); 325 virtual void GenerateArgumentsLength(ZoneList<Expression*>* args);
292 virtual void GenerateArgumentsAccess(ZoneList<Expression*>* args); 326 virtual void GenerateArgumentsAccess(ZoneList<Expression*>* args);
293 327
294 virtual void GenerateValueOf(ZoneList<Expression*>* args); 328 virtual void GenerateValueOf(ZoneList<Expression*>* args);
295 virtual void GenerateSetValueOf(ZoneList<Expression*>* args); 329 virtual void GenerateSetValueOf(ZoneList<Expression*>* args);
296 330
297 virtual void GenerateFastCharCodeAt(ZoneList<Expression*>* args); 331 virtual void GenerateFastCharCodeAt(ZoneList<Expression*>* args);
298 332
299 virtual void GenerateObjectEquals(ZoneList<Expression*>* args); 333 virtual void GenerateObjectEquals(ZoneList<Expression*>* args);
334
335 friend class Reference;
336 friend class Property;
337 friend class VariableProxy;
338 friend class Slot;
300 }; 339 };
301 340
302 341
303 // ----------------------------------------------------------------------------- 342 // -----------------------------------------------------------------------------
304 // ArmCodeGenerator implementation 343 // ArmCodeGenerator implementation
305 344
306 #define __ masm_-> 345 #define __ masm_->
307 346
308 347
309 Handle<Code> ArmCodeGenerator::MakeCode(FunctionLiteral* flit, 348 Handle<Code> ArmCodeGenerator::MakeCode(FunctionLiteral* flit,
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
592 631
593 ExitJSFrame(); 632 ExitJSFrame();
594 633
595 // Code generation state must be reset. 634 // Code generation state must be reset.
596 scope_ = NULL; 635 scope_ = NULL;
597 ASSERT(!has_cc()); 636 ASSERT(!has_cc());
598 ASSERT(state_ == NULL); 637 ASSERT(state_ == NULL);
599 } 638 }
600 639
601 640
602 MemOperand ArmCodeGenerator::SlotOperand(Slot* slot, Register tmp) { 641 MemOperand ArmCodeGenerator::SlotOperand(MacroAssembler* masm,
642 Scope* scope,
643 Slot* slot,
644 Register tmp) {
603 // Currently, this assertion will fail if we try to assign to 645 // Currently, this assertion will fail if we try to assign to
604 // a constant variable that is constant because it is read-only 646 // a constant variable that is constant because it is read-only
605 // (such as the variable referring to a named function expression). 647 // (such as the variable referring to a named function expression).
606 // We need to implement assignments to read-only variables. 648 // We need to implement assignments to read-only variables.
607 // Ideally, we should do this during AST generation (by converting 649 // Ideally, we should do this during AST generation (by converting
608 // such assignments into expression statements); however, in general 650 // such assignments into expression statements); however, in general
609 // we may not be able to make the decision until past AST generation, 651 // we may not be able to make the decision until past AST generation,
610 // that is when the entire program is known. 652 // that is when the entire program is known.
611 ASSERT(slot != NULL); 653 ASSERT(slot != NULL);
612 int index = slot->index(); 654 int index = slot->index();
613 switch (slot->type()) { 655 switch (slot->type()) {
614 case Slot::PARAMETER: 656 case Slot::PARAMETER:
615 return ParameterOperand(index); 657 return ParameterOperand(scope, index);
616 658
617 case Slot::LOCAL: { 659 case Slot::LOCAL: {
618 ASSERT(0 <= index && 660 ASSERT(0 <= index &&
619 index < scope_->num_stack_slots() && 661 index < scope->num_stack_slots() &&
620 index >= 0); 662 index >= 0);
621 int local_offset = JavaScriptFrameConstants::kLocal0Offset - 663 int local_offset = JavaScriptFrameConstants::kLocal0Offset -
622 index * kPointerSize; 664 index * kPointerSize;
623 return MemOperand(fp, local_offset); 665 return MemOperand(fp, local_offset);
624 } 666 }
625 667
626 case Slot::CONTEXT: { 668 case Slot::CONTEXT: {
627 // Follow the context chain if necessary. 669 // Follow the context chain if necessary.
628 ASSERT(!tmp.is(cp)); // do not overwrite context register 670 ASSERT(!tmp.is(cp)); // do not overwrite context register
629 Register context = cp; 671 Register context = cp;
630 int chain_length = scope_->ContextChainLength(slot->var()->scope()); 672 int chain_length = scope->ContextChainLength(slot->var()->scope());
631 for (int i = chain_length; i-- > 0;) { 673 for (int i = chain_length; i-- > 0;) {
632 // Load the closure. 674 // Load the closure.
633 // (All contexts, even 'with' contexts, have a closure, 675 // (All contexts, even 'with' contexts, have a closure,
634 // and it is the same for all contexts inside a function. 676 // and it is the same for all contexts inside a function.
635 // There is no need to go to the function context first.) 677 // There is no need to go to the function context first.)
636 __ ldr(tmp, ContextOperand(context, Context::CLOSURE_INDEX)); 678 masm->ldr(tmp, ContextOperand(context, Context::CLOSURE_INDEX));
637 // Load the function context (which is the incoming, outer context). 679 // Load the function context (which is the incoming, outer context).
638 __ ldr(tmp, FieldMemOperand(tmp, JSFunction::kContextOffset)); 680 masm->ldr(tmp, FieldMemOperand(tmp, JSFunction::kContextOffset));
639 context = tmp; 681 context = tmp;
640 } 682 }
641 // We may have a 'with' context now. Get the function context. 683 // We may have a 'with' context now. Get the function context.
642 // (In fact this mov may never be the needed, since the scope analysis 684 // (In fact this mov may never be the needed, since the scope analysis
643 // may not permit a direct context access in this case and thus we are 685 // may not permit a direct context access in this case and thus we are
644 // always at a function context. However it is safe to dereference be- 686 // always at a function context. However it is safe to dereference be-
645 // cause the function context of a function context is itself. Before 687 // cause the function context of a function context is itself. Before
646 // deleting this mov we should try to create a counter-example first, 688 // deleting this mov we should try to create a counter-example first,
647 // though...) 689 // though...)
648 __ ldr(tmp, ContextOperand(context, Context::FCONTEXT_INDEX)); 690 masm->ldr(tmp, ContextOperand(context, Context::FCONTEXT_INDEX));
649 return ContextOperand(tmp, index); 691 return ContextOperand(tmp, index);
650 } 692 }
651 693
652 default: 694 default:
653 UNREACHABLE(); 695 UNREACHABLE();
654 return MemOperand(r0, 0); 696 return MemOperand(r0, 0);
655 } 697 }
656 } 698 }
657 699
658 700
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
815 if (size <= 0) { 857 if (size <= 0) {
816 // Do nothing. No popping is necessary. 858 // Do nothing. No popping is necessary.
817 } else { 859 } else {
818 __ pop(r0); 860 __ pop(r0);
819 __ add(sp, sp, Operand(size * kPointerSize)); 861 __ add(sp, sp, Operand(size * kPointerSize));
820 __ push(r0); 862 __ push(r0);
821 } 863 }
822 } 864 }
823 865
824 866
825 void ArmCodeGenerator::AccessReference(Reference* ref, 867 void ArmCodeGenerator::GetValue(Reference* ref) {
826 CodeGenState::AccessType access) {
827 ASSERT(!has_cc()); 868 ASSERT(!has_cc());
828 ASSERT(ref->type() != Reference::ILLEGAL); 869 ASSERT(!ref->is_illegal());
829 CodeGenState* old_state = state_; 870 CodeGenState* old_state = state_;
830 CodeGenState new_state(access, ref, true_target(), false_target()); 871 CodeGenState new_state(CodeGenState::LOAD, ref, true_target(),
872 false_target());
831 state_ = &new_state; 873 state_ = &new_state;
832 Visit(ref->expression()); 874 Visit(ref->expression());
833 state_ = old_state; 875 state_ = old_state;
834 } 876 }
835 877
836 878
879 void Property::GenerateStoreCode(MacroAssembler* masm,
880 Scope* scope,
881 Reference* ref,
882 bool is_const_init) {
883 Comment cmnt(masm, "[ Store to Property");
884 masm->RecordPosition(position());
885 ArmCodeGenerator::SetReferenceProperty(masm, ref, key());
886 }
887
888
889 void VariableProxy::GenerateStoreCode(MacroAssembler* masm,
890 Scope* scope,
891 Reference* ref,
892 bool is_const_init) {
893 Comment cmnt(masm, "[ Store to VariableProxy");
894 Variable* node = var();
895
896 Expression* expr = node->rewrite();
897 if (expr != NULL) {
898 expr->GenerateStoreCode(masm, scope, ref, is_const_init);
899 } else {
900 ASSERT(node->is_global());
901 if (node->AsProperty() != NULL) {
902 masm->RecordPosition(node->AsProperty()->position());
903 }
904 ArmCodeGenerator::SetReferenceProperty(masm, ref,
905 new Literal(node->name()));
906 }
907 }
908
909
910 void Slot::GenerateStoreCode(MacroAssembler* masm,
911 Scope* scope,
912 Reference* ref,
913 bool is_const_init) {
914 Comment cmnt(masm, "[ Store to Slot");
915
916 if (type() == Slot::LOOKUP) {
917 ASSERT(var()->mode() == Variable::DYNAMIC);
918
919 // For now, just do a runtime call.
920 masm->push(cp);
921 masm->mov(r0, Operand(var()->name()));
922 masm->push(r0);
923
924 if (is_const_init) {
925 // Same as the case for a normal store, but ignores attribute
926 // (e.g. READ_ONLY) of context slot so that we can initialize const
927 // properties (introduced via eval("const foo = (some expr);")). Also,
928 // uses the current function context instead of the top context.
929 //
930 // Note that we must declare the foo upon entry of eval(), via a
931 // context slot declaration, but we cannot initialize it at the same
932 // time, because the const declaration may be at the end of the eval
933 // code (sigh...) and the const variable may have been used before
934 // (where its value is 'undefined'). Thus, we can only do the
935 // initialization when we actually encounter the expression and when
936 // the expression operands are defined and valid, and thus we need the
937 // split into 2 operations: declaration of the context slot followed
938 // by initialization.
939 masm->CallRuntime(Runtime::kInitializeConstContextSlot, 3);
940 } else {
941 masm->CallRuntime(Runtime::kStoreContextSlot, 3);
942 }
943 // Storing a variable must keep the (new) value on the expression
944 // stack. This is necessary for compiling assignment expressions.
945 masm->push(r0);
946
947 } else {
948 ASSERT(var()->mode() != Variable::DYNAMIC);
949
950 Label exit;
951 if (is_const_init) {
952 ASSERT(var()->mode() == Variable::CONST);
953 // Only the first const initialization must be executed (the slot
954 // still contains 'the hole' value). When the assignment is executed,
955 // the code is identical to a normal store (see below).
956 Comment cmnt(masm, "[ Init const");
957 masm->ldr(r2, ArmCodeGenerator::SlotOperand(masm, scope, this, r2));
958 masm->cmp(r2, Operand(Factory::the_hole_value()));
959 masm->b(ne, &exit);
960 }
961
962 // We must execute the store.
963 // r2 may be loaded with context; used below in RecordWrite.
964 // Storing a variable must keep the (new) value on the stack. This is
965 // necessary for compiling assignment expressions.
966 //
967 // Note: We will reach here even with var()->mode() == Variable::CONST
968 // because of const declarations which will initialize consts to 'the
969 // hole' value and by doing so, end up calling this code. r2 may be
970 // loaded with context; used below in RecordWrite.
971 masm->pop(r0);
972 masm->str(r0, ArmCodeGenerator::SlotOperand(masm, scope, this, r2));
973 masm->push(r0);
974
975 if (type() == Slot::CONTEXT) {
976 // Skip write barrier if the written value is a smi.
977 masm->tst(r0, Operand(kSmiTagMask));
978 masm->b(eq, &exit);
979 // r2 is loaded with context when calling SlotOperand above.
980 int offset = FixedArray::kHeaderSize + index() * kPointerSize;
981 masm->mov(r3, Operand(offset));
982 masm->RecordWrite(r2, r3, r1);
983 }
984 masm->bind(&exit);
985 }
986 }
987
988
837 // ECMA-262, section 9.2, page 30: ToBoolean(). Convert the given 989 // ECMA-262, section 9.2, page 30: ToBoolean(). Convert the given
838 // register to a boolean in the condition code register. The code 990 // register to a boolean in the condition code register. The code
839 // may jump to 'false_target' in case the register converts to 'false'. 991 // may jump to 'false_target' in case the register converts to 'false'.
840 void ArmCodeGenerator::ToBoolean(Label* true_target, 992 void ArmCodeGenerator::ToBoolean(Label* true_target,
841 Label* false_target) { 993 Label* false_target) {
842 // Note: The generated code snippet does not change stack variables. 994 // Note: The generated code snippet does not change stack variables.
843 // Only the condition code should be set. 995 // Only the condition code should be set.
844 __ pop(r0); 996 __ pop(r0);
845 997
846 // Fast case checks 998 // Fast case checks
(...skipping 982 matching lines...) Expand 10 before | Expand all | Expand 10 after
1829 __ push(r0); 1981 __ push(r0);
1830 __ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1); 1982 __ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1);
1831 } 1983 }
1832 } 1984 }
1833 1985
1834 1986
1835 #undef __ 1987 #undef __
1836 #define __ masm_-> 1988 #define __ masm_->
1837 1989
1838 1990
1839 void ArmCodeGenerator::AccessReferenceProperty( 1991 void ArmCodeGenerator::GetReferenceProperty(Expression* key) {
1840 Expression* key,
1841 CodeGenState::AccessType access) {
1842 Reference::Type type = ref()->type(); 1992 Reference::Type type = ref()->type();
1843 ASSERT(type != Reference::ILLEGAL); 1993 ASSERT(!ref()->is_illegal());
1844 1994
1845 // TODO(1241834): Make sure that this is sufficient. If there is a chance 1995 // TODO(1241834): Make sure that this it is safe to ignore the distinction
1846 // that reference errors can be thrown below, we must distinguish 1996 // between access types LOAD and LOAD_TYPEOF_EXPR. If there is a chance
1847 // between the 2 kinds of loads (typeof expression loads must not 1997 // that reference errors can be thrown below, we must distinguish between
1848 // throw a reference error). 1998 // the two kinds of loads (typeof expression loads must not throw a
1849 bool is_load = (access == CodeGenState::LOAD || 1999 // reference error).
1850 access == CodeGenState::LOAD_TYPEOF_EXPR);
1851
1852 if (type == Reference::NAMED) { 2000 if (type == Reference::NAMED) {
1853 // Compute the name of the property. 2001 // Compute the name of the property.
1854 Literal* literal = key->AsLiteral(); 2002 Literal* literal = key->AsLiteral();
1855 Handle<String> name(String::cast(*literal->handle())); 2003 Handle<String> name(String::cast(*literal->handle()));
1856 2004
1857 // Call the appropriate IC code. 2005 // Call the appropriate IC code.
1858 if (is_load) { 2006 // Setup the name register.
1859 // Setup the name register. 2007 __ mov(r2, Operand(name));
1860 __ mov(r2, Operand(name)); 2008 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
1861 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 2009 Variable* var = ref()->expression()->AsVariableProxy()->AsVariable();
1862 Variable* var = ref()->expression()->AsVariableProxy()->AsVariable(); 2010 if (var != NULL) {
1863 if (var != NULL) { 2011 ASSERT(var->is_global());
1864 ASSERT(var->is_global()); 2012 __ Call(ic, code_target_context);
1865 __ Call(ic, code_target_context);
1866 } else {
1867 __ Call(ic, code_target);
1868 }
1869
1870 } else { 2013 } else {
1871 __ pop(r0); // value
1872 // Setup the name register.
1873 __ mov(r2, Operand(name));
1874 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1875 __ Call(ic, code_target); 2014 __ Call(ic, code_target);
1876 } 2015 }
1877 2016
1878 } else { 2017 } else {
1879 // Access keyed property. 2018 // Access keyed property.
1880 ASSERT(type == Reference::KEYED); 2019 ASSERT(type == Reference::KEYED);
1881 2020
1882 if (is_load) { 2021 // TODO(1224671): Implement inline caching for keyed loads as on ia32.
1883 // TODO(1224671): Implement inline caching for keyed loads as on ia32. 2022 GetPropertyStub stub;
1884 GetPropertyStub stub; 2023 __ CallStub(&stub);
1885 __ CallStub(&stub);
1886
1887 } else {
1888 __ pop(r0); // value
1889 SetPropertyStub stub;
1890 __ CallStub(&stub);
1891 }
1892 } 2024 }
1893 __ push(r0); 2025 __ push(r0);
1894 } 2026 }
1895 2027
1896 2028
2029 void ArmCodeGenerator::SetReferenceProperty(MacroAssembler* masm,
2030 Reference* ref,
2031 Expression* key) {
2032 Reference::Type type = ref->type();
2033 ASSERT(!ref->is_illegal());
iposva 2008/09/10 18:01:44 Nit: Don't you want to assert before accessing any
Kevin Millikin (Chromium) 2008/09/11 07:15:55 Changed. Illegal references have a type, so it's
2034
2035 if (type == Reference::NAMED) {
2036 // Compute the name of the property.
2037 Literal* literal = key->AsLiteral();
2038 Handle<String> name(String::cast(*literal->handle()));
2039
2040 // Call the appropriate IC code.
2041 masm->pop(r0); // value
2042 // Setup the name register.
2043 masm->mov(r2, Operand(name));
2044 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
2045 masm->Call(ic, code_target);
2046
2047 } else {
2048 // Access keyed property.
2049 ASSERT(type == Reference::KEYED);
2050
2051 masm->pop(r0); // value
2052 SetPropertyStub stub;
2053 masm->CallStub(&stub);
2054 }
2055 masm->push(r0);
2056 }
2057
2058
1897 void ArmCodeGenerator::GenericBinaryOperation(Token::Value op) { 2059 void ArmCodeGenerator::GenericBinaryOperation(Token::Value op) {
1898 // sp[0] : y 2060 // sp[0] : y
1899 // sp[1] : x 2061 // sp[1] : x
1900 // result : r0 2062 // result : r0
1901 2063
1902 // Stub is entered with a call: 'return address' is in lr. 2064 // Stub is entered with a call: 'return address' is in lr.
1903 switch (op) { 2065 switch (op) {
1904 case Token::ADD: // fall through. 2066 case Token::ADD: // fall through.
1905 case Token::SUB: // fall through. 2067 case Token::SUB: // fall through.
1906 case Token::MUL: 2068 case Token::MUL:
(...skipping 1202 matching lines...) Expand 10 before | Expand all | Expand 10 after
3109 __ bind(&then); 3271 __ bind(&then);
3110 Load(node->then_expression(), access()); 3272 Load(node->then_expression(), access());
3111 __ b(&exit); 3273 __ b(&exit);
3112 __ bind(&else_); 3274 __ bind(&else_);
3113 Load(node->else_expression(), access()); 3275 Load(node->else_expression(), access());
3114 __ bind(&exit); 3276 __ bind(&exit);
3115 } 3277 }
3116 3278
3117 3279
3118 void ArmCodeGenerator::VisitSlot(Slot* node) { 3280 void ArmCodeGenerator::VisitSlot(Slot* node) {
3281 ASSERT(access() != CodeGenState::UNDEFINED);
3119 Comment cmnt(masm_, "[ Slot"); 3282 Comment cmnt(masm_, "[ Slot");
3120 3283
3121 if (node->type() == Slot::LOOKUP) { 3284 if (node->type() == Slot::LOOKUP) {
3122 ASSERT(node->var()->mode() == Variable::DYNAMIC); 3285 ASSERT(node->var()->mode() == Variable::DYNAMIC);
3123 3286
3124 // For now, just do a runtime call. 3287 // For now, just do a runtime call.
3125 __ push(cp); 3288 __ push(cp);
3126 __ mov(r0, Operand(node->var()->name())); 3289 __ mov(r0, Operand(node->var()->name()));
3127 __ push(r0); 3290 __ push(r0);
3128 3291
3129 switch (access()) { 3292 if (access() == CodeGenState::LOAD) {
3130 case CodeGenState::UNDEFINED: 3293 __ CallRuntime(Runtime::kLoadContextSlot, 2);
3131 UNREACHABLE(); 3294 } else {
3132 break; 3295 // CodeGenState::LOAD_TYPEOF_EXPR.
iposva 2008/09/10 18:01:44 Please assert that the CodeGenState is LOAD_TYPEOF
Kevin Millikin (Chromium) 2008/09/11 07:15:55 Done. Earlier assert already ruled out UNDEFINED,
3133 3296 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
3134 case CodeGenState::LOAD:
3135 __ CallRuntime(Runtime::kLoadContextSlot, 2);
3136 __ push(r0);
3137 break;
3138
3139 case CodeGenState::LOAD_TYPEOF_EXPR:
3140 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
3141 __ push(r0);
3142 break;
3143
3144 case CodeGenState::STORE:
3145 // Storing a variable must keep the (new) value on the stack. This
3146 // is necessary for compiling assignment expressions.
3147 __ CallRuntime(Runtime::kStoreContextSlot, 3);
3148 __ push(r0);
3149 // result (TOS) is the value that was stored
3150 break;
3151
3152 case CodeGenState::INIT_CONST:
3153 // Same as STORE but ignores attribute (e.g. READ_ONLY) of
3154 // context slot so that we can initialize const properties
3155 // (introduced via eval("const foo = (some expr);")). Also,
3156 // uses the current function context instead of the top
3157 // context.
3158 //
3159 // Note that we must declare the foo upon entry of eval(),
3160 // via a context slot declaration, but we cannot initialize
3161 // it at the same time, because the const declaration may
3162 // be at the end of the eval code (sigh...) and the const
3163 // variable may have been used before (where its value is
3164 // 'undefined'). Thus, we can only do the initialization
3165 // when we actually encounter the expression and when the
3166 // expression operands are defined and valid, and thus we
3167 // need the split into 2 operations: declaration of the
3168 // context slot followed by initialization.
3169 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
3170 __ push(r0);
3171 break;
3172 } 3297 }
3298 __ push(r0);
3173 3299
3174 } else { 3300 } else {
3175 // Note: We would like to keep the assert below, but it fires because 3301 // Note: We would like to keep the assert below, but it fires because of
3176 // of some nasty code in LoadTypeofExpression() which should be removed... 3302 // some nasty code in LoadTypeofExpression() which should be removed...
3177 // ASSERT(node->var()->mode() != Variable::DYNAMIC); 3303 // ASSERT(node->var()->mode() != Variable::DYNAMIC);
3178 3304
3179 switch (access()) { 3305 // Special handling for locals allocated in registers.
3180 case CodeGenState::UNDEFINED: 3306 __ ldr(r0, SlotOperand(node, r2));
3181 UNREACHABLE(); 3307 __ push(r0);
3182 break; 3308 if (node->var()->mode() == Variable::CONST) {
3183 3309 // Const slots may contain 'the hole' value (the constant hasn't been
3184 case CodeGenState::LOAD: // fall through 3310 // initialized yet) which needs to be converted into the 'undefined'
3185 case CodeGenState::LOAD_TYPEOF_EXPR: 3311 // value.
3186 // Special handling for locals allocated in registers. 3312 Comment cmnt(masm_, "[ Unhole const");
3187 __ ldr(r0, SlotOperand(node, r2)); 3313 __ pop(r0);
3188 __ push(r0); 3314 __ cmp(r0, Operand(Factory::the_hole_value()));
3189 if (node->var()->mode() == Variable::CONST) { 3315 __ mov(r0, Operand(Factory::undefined_value()), LeaveCC, eq);
3190 // Const slots may contain 'the hole' value (the constant hasn't 3316 __ push(r0);
3191 // been initialized yet) which needs to be converted into the
3192 // 'undefined' value.
3193 Comment cmnt(masm_, "[ Unhole const");
3194 __ pop(r0);
3195 __ cmp(r0, Operand(Factory::the_hole_value()));
3196 __ mov(r0, Operand(Factory::undefined_value()), LeaveCC, eq);
3197 __ push(r0);
3198 }
3199 break;
3200
3201 case CodeGenState::INIT_CONST: {
3202 ASSERT(node->var()->mode() == Variable::CONST);
3203 // Only the first const initialization must be executed (the slot
3204 // still contains 'the hole' value). When the assignment is executed,
3205 // the code is identical to a normal store (see below).
3206 { Comment cmnt(masm_, "[ Init const");
3207 Label L;
3208 __ ldr(r2, SlotOperand(node, r2));
3209 __ cmp(r2, Operand(Factory::the_hole_value()));
3210 __ b(ne, &L);
3211 // We must execute the store.
3212 // r2 may be loaded with context; used below in RecordWrite.
3213 __ ldr(r0, MemOperand(sp, 0));
3214 __ str(r0, SlotOperand(node, r2));
3215 if (node->type() == Slot::CONTEXT) {
3216 // Skip write barrier if the written value is a smi.
3217 Label exit;
3218 __ tst(r0, Operand(kSmiTagMask));
3219 __ b(eq, &exit);
3220 // r2 is loaded with context when calling SlotOperand above.
3221 int offset = FixedArray::kHeaderSize + node->index() * kPointerSize;
3222 __ mov(r3, Operand(offset));
3223 __ RecordWrite(r2, r3, r1);
3224 __ bind(&exit);
3225 }
3226 __ bind(&L);
3227 }
3228 break;
3229 }
3230
3231 case CodeGenState::STORE: {
3232 // Storing a variable must keep the (new) value on the stack. This
3233 // is necessary for compiling assignment expressions.
3234 // Special handling for locals allocated in registers.
3235 //
3236 // Note: We will reach here even with node->var()->mode() ==
3237 // Variable::CONST because of const declarations which will
3238 // initialize consts to 'the hole' value and by doing so, end
3239 // up calling this code.
3240 // r2 may be loaded with context; used below in RecordWrite.
3241 __ pop(r0);
3242 __ str(r0, SlotOperand(node, r2));
3243 __ push(r0);
3244 if (node->type() == Slot::CONTEXT) {
3245 // Skip write barrier if the written value is a smi.
3246 Label exit;
3247 __ tst(r0, Operand(kSmiTagMask));
3248 __ b(eq, &exit);
3249 // r2 is loaded with context when calling SlotOperand above.
3250 int offset = FixedArray::kHeaderSize + node->index() * kPointerSize;
3251 __ mov(r3, Operand(offset));
3252 __ RecordWrite(r2, r3, r1);
3253 __ bind(&exit);
3254 }
3255 break;
3256 }
3257 } 3317 }
3258 } 3318 }
3259 } 3319 }
3260 3320
3261 3321
3262 void ArmCodeGenerator::VisitVariableProxy(VariableProxy* proxy_node) { 3322 void ArmCodeGenerator::VisitVariableProxy(VariableProxy* node) {
3263 Comment cmnt(masm_, "[ VariableProxy"); 3323 Comment cmnt(masm_, "[ VariableProxy");
3264 Variable* node = proxy_node->var(); 3324 Variable* var_node = node->var();
3265 3325
3266 Expression* x = node->rewrite(); 3326 Expression* expr = var_node->rewrite();
3267 if (x != NULL) { 3327 if (expr != NULL) {
3268 Visit(x); 3328 Visit(expr);
3269 return; 3329 } else {
3270 } 3330 ASSERT(var_node->is_global());
3271 3331 if (is_referenced()) {
3272 ASSERT(node->is_global()); 3332 if (var_node->AsProperty() != NULL) {
3273 if (is_referenced()) { 3333 __ RecordPosition(var_node->AsProperty()->position());
3274 if (node->AsProperty() != NULL) { 3334 }
3275 __ RecordPosition(node->AsProperty()->position()); 3335 GetReferenceProperty(new Literal(var_node->name()));
3336 } else {
3337 Reference property(this, node);
3338 GetValue(&property);
3276 } 3339 }
3277 AccessReferenceProperty(new Literal(node->name()), access());
3278
3279 } else {
3280 // All stores are through references.
3281 ASSERT(access() != CodeGenState::STORE);
3282 Reference property(this, proxy_node);
3283 GetValue(&property);
3284 } 3340 }
3285 } 3341 }
3286 3342
3287 3343
3288 void ArmCodeGenerator::VisitLiteral(Literal* node) { 3344 void ArmCodeGenerator::VisitLiteral(Literal* node) {
3289 Comment cmnt(masm_, "[ Literal"); 3345 Comment cmnt(masm_, "[ Literal");
3290 __ mov(r0, Operand(node->handle())); 3346 __ mov(r0, Operand(node->handle()));
3291 __ push(r0); 3347 __ push(r0);
3292 } 3348 }
3293 3349
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after
3534 3590
3535 Load(node->exception()); 3591 Load(node->exception());
3536 __ RecordPosition(node->position()); 3592 __ RecordPosition(node->position());
3537 __ CallRuntime(Runtime::kThrow, 1); 3593 __ CallRuntime(Runtime::kThrow, 1);
3538 __ push(r0); 3594 __ push(r0);
3539 } 3595 }
3540 3596
3541 3597
3542 void ArmCodeGenerator::VisitProperty(Property* node) { 3598 void ArmCodeGenerator::VisitProperty(Property* node) {
3543 Comment cmnt(masm_, "[ Property"); 3599 Comment cmnt(masm_, "[ Property");
3600
3544 if (is_referenced()) { 3601 if (is_referenced()) {
3545 __ RecordPosition(node->position()); 3602 __ RecordPosition(node->position());
3546 AccessReferenceProperty(node->key(), access()); 3603 GetReferenceProperty(node->key());
3547
3548 } else { 3604 } else {
3549 // All stores are through references.
3550 ASSERT(access() != CodeGenState::STORE);
3551 Reference property(this, node); 3605 Reference property(this, node);
3552 __ RecordPosition(node->position()); 3606 __ RecordPosition(node->position());
3553 GetValue(&property); 3607 GetValue(&property);
3554 } 3608 }
3555 } 3609 }
3556 3610
3557 3611
3558 void ArmCodeGenerator::VisitCall(Call* node) { 3612 void ArmCodeGenerator::VisitCall(Call* node) {
3559 Comment cmnt(masm_, "[ Call"); 3613 Comment cmnt(masm_, "[ Call");
3560 3614
(...skipping 1089 matching lines...) Expand 10 before | Expand all | Expand 10 after
4650 bool is_eval) { 4704 bool is_eval) {
4651 Handle<Code> code = ArmCodeGenerator::MakeCode(fun, script, is_eval); 4705 Handle<Code> code = ArmCodeGenerator::MakeCode(fun, script, is_eval);
4652 if (!code.is_null()) { 4706 if (!code.is_null()) {
4653 Counters::total_compiled_code_size.Increment(code->instruction_size()); 4707 Counters::total_compiled_code_size.Increment(code->instruction_size());
4654 } 4708 }
4655 return code; 4709 return code;
4656 } 4710 }
4657 4711
4658 4712
4659 } } // namespace v8::internal 4713 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698