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

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

Issue 6538: Moved the function GetValue from the code generator to the Reference... (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
« no previous file with comments | « no previous file | src/codegen-ia32.cc » ('j') | src/codegen-ia32.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 // Reference support 44 // Reference support
45 45
46 // A reference is a C++ stack-allocated object that keeps an ECMA 46 // A reference is a C++ stack-allocated object that keeps an ECMA
47 // reference on the execution stack while in scope. For variables 47 // reference on the execution stack while in scope. For variables
48 // the reference is empty, indicating that it isn't necessary to 48 // the reference is empty, indicating that it isn't necessary to
49 // store state on the stack for keeping track of references to those. 49 // store state on the stack for keeping track of references to those.
50 // For properties, we keep either one (named) or two (indexed) values 50 // For properties, we keep either one (named) or two (indexed) values
51 // on the execution stack to represent the reference. 51 // on the execution stack to represent the reference.
52 52
53 enum InitState { CONST_INIT, NOT_CONST_INIT }; 53 enum InitState { CONST_INIT, NOT_CONST_INIT };
54 enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
54 55
55 class Reference BASE_EMBEDDED { 56 class Reference BASE_EMBEDDED {
56 public: 57 public:
57 // The values of the types is important, see size(). 58 // The values of the types is important, see size().
58 enum Type { ILLEGAL = -1, SLOT = 0, NAMED = 1, KEYED = 2 }; 59 enum Type { ILLEGAL = -1, SLOT = 0, NAMED = 1, KEYED = 2 };
59 Reference(ArmCodeGenerator* cgen, Expression* expression); 60 Reference(ArmCodeGenerator* cgen, Expression* expression);
60 ~Reference(); 61 ~Reference();
61 62
62 Expression* expression() const { return expression_; } 63 Expression* expression() const { return expression_; }
63 Type type() const { return type_; } 64 Type type() const { return type_; }
64 void set_type(Type value) { 65 void set_type(Type value) {
65 ASSERT(type_ == ILLEGAL); 66 ASSERT(type_ == ILLEGAL);
66 type_ = value; 67 type_ = value;
67 } 68 }
68 // The size of the reference or -1 if the reference is illegal. 69 // The size of the reference or -1 if the reference is illegal.
69 int size() const { return type_; } 70 int size() const { return type_; }
70 71
71 bool is_illegal() const { return type_ == ILLEGAL; } 72 bool is_illegal() const { return type_ == ILLEGAL; }
72 bool is_slot() const { return type_ == SLOT; } 73 bool is_slot() const { return type_ == SLOT; }
73 bool is_property() const { return type_ == NAMED || type_ == KEYED; } 74 bool is_property() const { return type_ == NAMED || type_ == KEYED; }
74 75
76 // Return the name. Only valid for named property references.
77 Handle<String> GetName();
78
79 // Generate code to push the value of the reference on top of the
80 // expression stack. The reference is expected to be already on top of
81 // the expression stack, and it is left in place with its value above it.
82 void GetValue(TypeofState typeof_state);
83
84 // Generate code to store the value on top of the expression stack in the
85 // reference. The reference is expected to be immediately below the value
86 // on the expression stack. The stored value is left in place (with the
87 // reference intact below it) to support chained assignments.
75 void SetValue(InitState init_state); 88 void SetValue(InitState init_state);
76 89
77 private: 90 private:
78 ArmCodeGenerator* cgen_; 91 ArmCodeGenerator* cgen_;
79 Expression* expression_; 92 Expression* expression_;
80 Type type_; 93 Type type_;
81 }; 94 };
82 95
83 96
84 // ------------------------------------------------------------------------- 97 // -------------------------------------------------------------------------
85 // Code generation state 98 // Code generation state
86 99
87 // The state is passed down the AST by the code generator (and back up, in 100 // The state is passed down the AST by the code generator (and back up, in
88 // the form of the state of the label pair). It is threaded through the 101 // the form of the state of the label pair). It is threaded through the
89 // call stack. Constructing a state implicitly pushes it on the owning code 102 // call stack. Constructing a state implicitly pushes it on the owning code
90 // generator's stack of states, and destroying one implicitly pops it. 103 // generator's stack of states, and destroying one implicitly pops it.
91 104
92 class CodeGenState BASE_EMBEDDED { 105 class CodeGenState BASE_EMBEDDED {
93 public: 106 public:
94 enum AccessType {
95 UNDEFINED,
96 LOAD,
97 LOAD_TYPEOF_EXPR
98 };
99
100 // Create an initial code generator state. Destroying the initial state 107 // Create an initial code generator state. Destroying the initial state
101 // leaves the code generator with a NULL state. 108 // leaves the code generator with a NULL state.
102 explicit CodeGenState(ArmCodeGenerator* owner); 109 explicit CodeGenState(ArmCodeGenerator* owner);
103 110
104 // Create a code generator state based on a code generator's current 111 // Create a code generator state based on a code generator's current
105 // state. The new state has its own access type and pair of branch 112 // state. The new state has its own typeof state and pair of branch
106 // labels, and no reference. 113 // labels.
107 CodeGenState(ArmCodeGenerator* owner, 114 CodeGenState(ArmCodeGenerator* owner,
108 AccessType access, 115 TypeofState typeof_state,
109 Label* true_target, 116 Label* true_target,
110 Label* false_target); 117 Label* false_target);
111 118
112 // Create a code generator state based on a code generator's current
113 // state. The new state has an access type of LOAD, its own reference,
114 // and inherits the pair of branch labels of the current state.
115 CodeGenState(ArmCodeGenerator* owner, Reference* ref);
116
117 // Destroy a code generator state and restore the owning code generator's 119 // Destroy a code generator state and restore the owning code generator's
118 // previous state. 120 // previous state.
119 ~CodeGenState(); 121 ~CodeGenState();
120 122
121 AccessType access() const { return access_; } 123 TypeofState typeof_state() const { return typeof_state_; }
122 Reference* ref() const { return ref_; }
123 Label* true_target() const { return true_target_; } 124 Label* true_target() const { return true_target_; }
124 Label* false_target() const { return false_target_; } 125 Label* false_target() const { return false_target_; }
125 126
126 private: 127 private:
127 ArmCodeGenerator* owner_; 128 ArmCodeGenerator* owner_;
128 AccessType access_; 129 TypeofState typeof_state_;
129 Reference* ref_;
130 Label* true_target_; 130 Label* true_target_;
131 Label* false_target_; 131 Label* false_target_;
132 CodeGenState* previous_; 132 CodeGenState* previous_;
133 }; 133 };
134 134
135 135
136 // ----------------------------------------------------------------------------- 136 // -----------------------------------------------------------------------------
137 // ArmCodeGenerator 137 // ArmCodeGenerator
138 138
139 class ArmCodeGenerator: public CodeGenerator { 139 class ArmCodeGenerator: public CodeGenerator {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 171
172 // Main code generation function 172 // Main code generation function
173 void GenCode(FunctionLiteral* fun); 173 void GenCode(FunctionLiteral* fun);
174 174
175 // The following are used by class Reference. 175 // The following are used by class Reference.
176 void LoadReference(Reference* ref); 176 void LoadReference(Reference* ref);
177 void UnloadReference(Reference* ref); 177 void UnloadReference(Reference* ref);
178 178
179 // State 179 // State
180 bool has_cc() const { return cc_reg_ != al; } 180 bool has_cc() const { return cc_reg_ != al; }
181 CodeGenState::AccessType access() const { return state_->access(); } 181 TypeofState typeof_state() const { return state_->typeof_state(); }
182 Reference* ref() const { return state_->ref(); }
183 bool is_referenced() const { return state_->ref() != NULL; }
184 Label* true_target() const { return state_->true_target(); } 182 Label* true_target() const { return state_->true_target(); }
185 Label* false_target() const { return state_->false_target(); } 183 Label* false_target() const { return state_->false_target(); }
186 184
187 185
188 // Expressions 186 // Expressions
189 MemOperand GlobalObject() const { 187 MemOperand GlobalObject() const {
190 return ContextOperand(cp, Context::GLOBAL_INDEX); 188 return ContextOperand(cp, Context::GLOBAL_INDEX);
191 } 189 }
192 190
193 MemOperand ContextOperand(Register context, int index) const { 191 MemOperand ContextOperand(Register context, int index) const {
194 return MemOperand(context, Context::SlotOffset(index)); 192 return MemOperand(context, Context::SlotOffset(index));
195 } 193 }
196 194
197 MemOperand ParameterOperand(int index) const { 195 MemOperand ParameterOperand(int index) const {
198 int num_parameters = scope()->num_parameters(); 196 int num_parameters = scope()->num_parameters();
199 // index -2 corresponds to the activated closure, -1 corresponds 197 // index -2 corresponds to the activated closure, -1 corresponds
200 // to the receiver 198 // to the receiver
201 ASSERT(-2 <= index && index < num_parameters); 199 ASSERT(-2 <= index && index < num_parameters);
202 int offset = (1 + num_parameters - index) * kPointerSize; 200 int offset = (1 + num_parameters - index) * kPointerSize;
203 return MemOperand(fp, offset); 201 return MemOperand(fp, offset);
204 } 202 }
205 203
206 MemOperand FunctionOperand() const { 204 MemOperand FunctionOperand() const {
207 return MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset); 205 return MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset);
208 } 206 }
209 207
210 MemOperand SlotOperand(Slot* slot, Register tmp); 208 MemOperand SlotOperand(Slot* slot, Register tmp);
211 209
212 void LoadCondition(Expression* x, CodeGenState::AccessType access, 210 void LoadCondition(Expression* x,
213 Label* true_target, Label* false_target, bool force_cc); 211 TypeofState typeof_state,
214 void Load(Expression* x, 212 Label* true_target,
215 CodeGenState::AccessType access = CodeGenState::LOAD); 213 Label* false_target,
214 bool force_cc);
215 void Load(Expression* x, TypeofState typeof_state = NOT_INSIDE_TYPEOF);
216 void LoadGlobal(); 216 void LoadGlobal();
217 217
218 // Read a value from a slot and leave it on top of the expression stack.
219 void LoadFromSlot(Slot* slot, TypeofState typeof_state);
220
218 // Special code for typeof expressions: Unfortunately, we must 221 // Special code for typeof expressions: Unfortunately, we must
219 // be careful when loading the expression in 'typeof' 222 // be careful when loading the expression in 'typeof'
220 // expressions. We are not allowed to throw reference errors for 223 // expressions. We are not allowed to throw reference errors for
221 // non-existing properties of the global object, so we must make it 224 // non-existing properties of the global object, so we must make it
222 // look like an explicit property access, instead of an access 225 // look like an explicit property access, instead of an access
223 // through the context chain. 226 // through the context chain.
224 void LoadTypeofExpression(Expression* x); 227 void LoadTypeofExpression(Expression* x);
225 228
226
227 // References
228
229 // Generate code to fetch the value of a reference. The reference is
230 // expected to be on top of the expression stack. It is left in place and
231 // its value is pushed on top of it.
232 void GetValue(Reference* ref) {
233 ASSERT(!has_cc());
234 ASSERT(!ref->is_illegal());
235 CodeGenState new_state(this, ref);
236 Visit(ref->expression());
237 }
238
239 // Generate code to fetch a value from a property of a reference. The
240 // reference is expected on top of the expression stack. It is left in
241 // place and its value is pushed on top of it.
242 void GetReferenceProperty(Expression* key);
243
244 void ToBoolean(Label* true_target, Label* false_target); 229 void ToBoolean(Label* true_target, Label* false_target);
245 230
246 void GenericBinaryOperation(Token::Value op); 231 void GenericBinaryOperation(Token::Value op);
247 void Comparison(Condition cc, bool strict = false); 232 void Comparison(Condition cc, bool strict = false);
248 233
249 void SmiOperation(Token::Value op, Handle<Object> value, bool reversed); 234 void SmiOperation(Token::Value op, Handle<Object> value, bool reversed);
250 235
251 void CallWithArguments(ZoneList<Expression*>* arguments, int position); 236 void CallWithArguments(ZoneList<Expression*>* arguments, int position);
252 237
253 // Declare global variables and functions in the given array of 238 // Declare global variables and functions in the given array of
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 friend class VariableProxy; 287 friend class VariableProxy;
303 friend class Slot; 288 friend class Slot;
304 }; 289 };
305 290
306 291
307 // ------------------------------------------------------------------------- 292 // -------------------------------------------------------------------------
308 // CodeGenState implementation. 293 // CodeGenState implementation.
309 294
310 CodeGenState::CodeGenState(ArmCodeGenerator* owner) 295 CodeGenState::CodeGenState(ArmCodeGenerator* owner)
311 : owner_(owner), 296 : owner_(owner),
312 access_(UNDEFINED), 297 typeof_state_(NOT_INSIDE_TYPEOF),
313 ref_(NULL),
314 true_target_(NULL), 298 true_target_(NULL),
315 false_target_(NULL), 299 false_target_(NULL),
316 previous_(NULL) { 300 previous_(NULL) {
317 owner_->set_state(this); 301 owner_->set_state(this);
318 } 302 }
319 303
320 304
321 CodeGenState::CodeGenState(ArmCodeGenerator* owner, 305 CodeGenState::CodeGenState(ArmCodeGenerator* owner,
322 AccessType access, 306 TypeofState typeof_state,
323 Label* true_target, 307 Label* true_target,
324 Label* false_target) 308 Label* false_target)
325 : owner_(owner), 309 : owner_(owner),
326 access_(access), 310 typeof_state_(typeof_state),
327 ref_(NULL),
328 true_target_(true_target), 311 true_target_(true_target),
329 false_target_(false_target), 312 false_target_(false_target),
330 previous_(owner->state()) { 313 previous_(owner->state()) {
331 owner_->set_state(this); 314 owner_->set_state(this);
332 } 315 }
333 316
334 317
335 CodeGenState::CodeGenState(ArmCodeGenerator* owner, Reference* ref)
336 : owner_(owner),
337 access_(LOAD),
338 ref_(ref),
339 true_target_(owner->state()->true_target_),
340 false_target_(owner->state()->false_target_),
341 previous_(owner->state()) {
342 owner_->set_state(this);
343 }
344
345
346 CodeGenState::~CodeGenState() { 318 CodeGenState::~CodeGenState() {
347 ASSERT(owner_->state() == this); 319 ASSERT(owner_->state() == this);
348 owner_->set_state(previous_); 320 owner_->set_state(previous_);
349 } 321 }
350 322
351 323
352 // ----------------------------------------------------------------------------- 324 // -----------------------------------------------------------------------------
353 // ArmCodeGenerator implementation 325 // ArmCodeGenerator implementation
354 326
355 #define __ masm_-> 327 #define __ masm_->
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
701 } 673 }
702 } 674 }
703 675
704 676
705 // Loads a value on the stack. If it is a boolean value, the result may have 677 // Loads a value on the stack. If it is a boolean value, the result may have
706 // been (partially) translated into branches, or it may have set the condition 678 // been (partially) translated into branches, or it may have set the condition
707 // code register. If force_cc is set, the value is forced to set the condition 679 // code register. If force_cc is set, the value is forced to set the condition
708 // code register and no value is pushed. If the condition code register was set, 680 // code register and no value is pushed. If the condition code register was set,
709 // has_cc() is true and cc_reg_ contains the condition to test for 'true'. 681 // has_cc() is true and cc_reg_ contains the condition to test for 'true'.
710 void ArmCodeGenerator::LoadCondition(Expression* x, 682 void ArmCodeGenerator::LoadCondition(Expression* x,
711 CodeGenState::AccessType access, 683 TypeofState typeof_state,
712 Label* true_target, 684 Label* true_target,
713 Label* false_target, 685 Label* false_target,
714 bool force_cc) { 686 bool force_cc) {
715 ASSERT(access == CodeGenState::LOAD || 687 ASSERT(!has_cc());
716 access == CodeGenState::LOAD_TYPEOF_EXPR);
717 ASSERT(!has_cc() && !is_referenced());
718 688
719 { CodeGenState new_state(this, access, true_target, false_target); 689 { CodeGenState new_state(this, typeof_state, true_target, false_target);
720 Visit(x); 690 Visit(x);
721 } 691 }
722 if (force_cc && !has_cc()) { 692 if (force_cc && !has_cc()) {
723 // Convert the TOS value to a boolean in the condition code register. 693 // Convert the TOS value to a boolean in the condition code register.
724 ToBoolean(true_target, false_target); 694 ToBoolean(true_target, false_target);
725 } 695 }
726 ASSERT(has_cc() || !force_cc); 696 ASSERT(has_cc() || !force_cc);
727 } 697 }
728 698
729 699
730 void ArmCodeGenerator::Load(Expression* x, CodeGenState::AccessType access) { 700 void ArmCodeGenerator::Load(Expression* x, TypeofState typeof_state) {
731 ASSERT(access == CodeGenState::LOAD ||
732 access == CodeGenState::LOAD_TYPEOF_EXPR);
733
734 Label true_target; 701 Label true_target;
735 Label false_target; 702 Label false_target;
736 LoadCondition(x, access, &true_target, &false_target, false); 703 LoadCondition(x, typeof_state, &true_target, &false_target, false);
737 704
738 if (has_cc()) { 705 if (has_cc()) {
739 // convert cc_reg_ into a bool 706 // convert cc_reg_ into a bool
740 Label loaded, materialize_true; 707 Label loaded, materialize_true;
741 __ b(cc_reg_, &materialize_true); 708 __ b(cc_reg_, &materialize_true);
742 __ mov(r0, Operand(Factory::false_value())); 709 __ mov(r0, Operand(Factory::false_value()));
743 __ push(r0); 710 __ push(r0);
744 __ b(&loaded); 711 __ b(&loaded);
745 __ bind(&materialize_true); 712 __ bind(&materialize_true);
746 __ mov(r0, Operand(Factory::true_value())); 713 __ mov(r0, Operand(Factory::true_value()));
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
779 } 746 }
780 747
781 748
782 void ArmCodeGenerator::LoadGlobal() { 749 void ArmCodeGenerator::LoadGlobal() {
783 __ ldr(r0, GlobalObject()); 750 __ ldr(r0, GlobalObject());
784 __ push(r0); 751 __ push(r0);
785 } 752 }
786 753
787 754
788 // TODO(1241834): Get rid of this function in favor of just using Load, now 755 // TODO(1241834): Get rid of this function in favor of just using Load, now
789 // that we have the LOAD_TYPEOF_EXPR access type. => Need to handle 756 // that we have the INSIDE_TYPEOF typeof state. => Need to handle global
790 // global variables w/o reference errors elsewhere. 757 // variables w/o reference errors elsewhere.
791 void ArmCodeGenerator::LoadTypeofExpression(Expression* x) { 758 void ArmCodeGenerator::LoadTypeofExpression(Expression* x) {
792 Variable* variable = x->AsVariableProxy()->AsVariable(); 759 Variable* variable = x->AsVariableProxy()->AsVariable();
793 if (variable != NULL && !variable->is_this() && variable->is_global()) { 760 if (variable != NULL && !variable->is_this() && variable->is_global()) {
794 // NOTE: This is somewhat nasty. We force the compiler to load 761 // NOTE: This is somewhat nasty. We force the compiler to load
795 // the variable as if through '<global>.<variable>' to make sure we 762 // the variable as if through '<global>.<variable>' to make sure we
796 // do not get reference errors. 763 // do not get reference errors.
797 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX); 764 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX);
798 Literal key(variable->name()); 765 Literal key(variable->name());
799 // TODO(1241834): Fetch the position from the variable instead of using 766 // TODO(1241834): Fetch the position from the variable instead of using
800 // no position. 767 // no position.
801 Property property(&global, &key, RelocInfo::kNoPosition); 768 Property property(&global, &key, RelocInfo::kNoPosition);
802 Load(&property); 769 Load(&property);
803 } else { 770 } else {
804 Load(x, CodeGenState::LOAD_TYPEOF_EXPR); 771 Load(x, INSIDE_TYPEOF);
805 } 772 }
806 } 773 }
807 774
808 775
809 Reference::Reference(ArmCodeGenerator* cgen, Expression* expression) 776 Reference::Reference(ArmCodeGenerator* cgen, Expression* expression)
810 : cgen_(cgen), expression_(expression), type_(ILLEGAL) { 777 : cgen_(cgen), expression_(expression), type_(ILLEGAL) {
811 cgen->LoadReference(this); 778 cgen->LoadReference(this);
812 } 779 }
813 780
814 781
815 Reference::~Reference() { 782 Reference::~Reference() {
816 cgen_->UnloadReference(this); 783 cgen_->UnloadReference(this);
817 } 784 }
818 785
819 786
820 void ArmCodeGenerator::LoadReference(Reference* ref) { 787 void ArmCodeGenerator::LoadReference(Reference* ref) {
788 Comment cmnt(masm_, "[ LoadReference");
821 Expression* e = ref->expression(); 789 Expression* e = ref->expression();
822 Property* property = e->AsProperty(); 790 Property* property = e->AsProperty();
823 Variable* var = e->AsVariableProxy()->AsVariable(); 791 Variable* var = e->AsVariableProxy()->AsVariable();
824 792
825 if (property != NULL) { 793 if (property != NULL) {
826 // The expression is either a property or a variable proxy that rewrites 794 // The expression is either a property or a variable proxy that rewrites
827 // to a property. 795 // to a property.
828 Load(property->obj()); 796 Load(property->obj());
829 // We use a named reference if the key is a literal symbol, unless it is 797 // We use a named reference if the key is a literal symbol, unless it is
830 // a string that can be legally parsed as an integer. This is because 798 // a string that can be legally parsed as an integer. This is because
(...skipping 21 matching lines...) Expand all
852 } 820 }
853 } else { 821 } else {
854 // Anything else is a runtime error. 822 // Anything else is a runtime error.
855 Load(e); 823 Load(e);
856 __ CallRuntime(Runtime::kThrowReferenceError, 1); 824 __ CallRuntime(Runtime::kThrowReferenceError, 1);
857 } 825 }
858 } 826 }
859 827
860 828
861 void ArmCodeGenerator::UnloadReference(Reference* ref) { 829 void ArmCodeGenerator::UnloadReference(Reference* ref) {
830 Comment cmnt(masm_, "[ UnloadReference");
862 int size = ref->size(); 831 int size = ref->size();
863 if (size <= 0) { 832 if (size <= 0) {
864 // Do nothing. No popping is necessary. 833 // Do nothing. No popping is necessary.
865 } else { 834 } else {
866 __ pop(r0); 835 __ pop(r0);
867 __ add(sp, sp, Operand(size * kPointerSize)); 836 __ add(sp, sp, Operand(size * kPointerSize));
868 __ push(r0); 837 __ push(r0);
869 } 838 }
870 } 839 }
871 840
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
987 #ifdef DEBUG 956 #ifdef DEBUG
988 void Print() { 957 void Print() {
989 PrintF("InvokeBuiltinStub (kind %d, argc, %d)\n", 958 PrintF("InvokeBuiltinStub (kind %d, argc, %d)\n",
990 static_cast<int>(kind_), 959 static_cast<int>(kind_),
991 argc_); 960 argc_);
992 } 961 }
993 #endif 962 #endif
994 }; 963 };
995 964
996 965
997 void ArmCodeGenerator::GetReferenceProperty(Expression* key) {
998 ASSERT(!ref()->is_illegal());
999
1000 // TODO(1241834): Make sure that this it is safe to ignore the distinction
1001 // between access types LOAD and LOAD_TYPEOF_EXPR. If there is a chance
1002 // that reference errors can be thrown below, we must distinguish between
1003 // the two kinds of loads (typeof expression loads must not throw a
1004 // reference error).
1005 if (ref()->type() == Reference::NAMED) {
1006 // Compute the name of the property.
1007 Literal* literal = key->AsLiteral();
1008 Handle<String> name(String::cast(*literal->handle()));
1009
1010 // Call the appropriate IC code.
1011 // Setup the name register.
1012 __ mov(r2, Operand(name));
1013 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
1014 Variable* var = ref()->expression()->AsVariableProxy()->AsVariable();
1015 if (var != NULL) {
1016 ASSERT(var->is_global());
1017 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
1018 } else {
1019 __ Call(ic, RelocInfo::CODE_TARGET);
1020 }
1021
1022 } else {
1023 // Access keyed property.
1024 ASSERT(ref()->type() == Reference::KEYED);
1025
1026 // TODO(1224671): Implement inline caching for keyed loads as on ia32.
1027 GetPropertyStub stub;
1028 __ CallStub(&stub);
1029 }
1030 __ push(r0);
1031 }
1032
1033
1034 void ArmCodeGenerator::GenericBinaryOperation(Token::Value op) { 966 void ArmCodeGenerator::GenericBinaryOperation(Token::Value op) {
1035 // sp[0] : y 967 // sp[0] : y
1036 // sp[1] : x 968 // sp[1] : x
1037 // result : r0 969 // result : r0
1038 970
1039 // Stub is entered with a call: 'return address' is in lr. 971 // Stub is entered with a call: 'return address' is in lr.
1040 switch (op) { 972 switch (op) {
1041 case Token::ADD: // fall through. 973 case Token::ADD: // fall through.
1042 case Token::SUB: // fall through. 974 case Token::SUB: // fall through.
1043 case Token::MUL: 975 case Token::MUL:
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after
1520 bool has_else_stm = node->HasElseStatement(); 1452 bool has_else_stm = node->HasElseStatement();
1521 1453
1522 if (FLAG_debug_info) RecordStatementPosition(node); 1454 if (FLAG_debug_info) RecordStatementPosition(node);
1523 1455
1524 Label exit; 1456 Label exit;
1525 if (has_then_stm && has_else_stm) { 1457 if (has_then_stm && has_else_stm) {
1526 Comment cmnt(masm_, "[ IfThenElse"); 1458 Comment cmnt(masm_, "[ IfThenElse");
1527 Label then; 1459 Label then;
1528 Label else_; 1460 Label else_;
1529 // if (cond) 1461 // if (cond)
1530 LoadCondition(node->condition(), CodeGenState::LOAD, &then, &else_, true); 1462 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true);
1531 Branch(false, &else_); 1463 Branch(false, &else_);
1532 // then 1464 // then
1533 __ bind(&then); 1465 __ bind(&then);
1534 Visit(node->then_statement()); 1466 Visit(node->then_statement());
1535 __ b(&exit); 1467 __ b(&exit);
1536 // else 1468 // else
1537 __ bind(&else_); 1469 __ bind(&else_);
1538 Visit(node->else_statement()); 1470 Visit(node->else_statement());
1539 1471
1540 } else if (has_then_stm) { 1472 } else if (has_then_stm) {
1541 Comment cmnt(masm_, "[ IfThen"); 1473 Comment cmnt(masm_, "[ IfThen");
1542 ASSERT(!has_else_stm); 1474 ASSERT(!has_else_stm);
1543 Label then; 1475 Label then;
1544 // if (cond) 1476 // if (cond)
1545 LoadCondition(node->condition(), CodeGenState::LOAD, &then, &exit, true); 1477 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &exit, true);
1546 Branch(false, &exit); 1478 Branch(false, &exit);
1547 // then 1479 // then
1548 __ bind(&then); 1480 __ bind(&then);
1549 Visit(node->then_statement()); 1481 Visit(node->then_statement());
1550 1482
1551 } else if (has_else_stm) { 1483 } else if (has_else_stm) {
1552 Comment cmnt(masm_, "[ IfElse"); 1484 Comment cmnt(masm_, "[ IfElse");
1553 ASSERT(!has_then_stm); 1485 ASSERT(!has_then_stm);
1554 Label else_; 1486 Label else_;
1555 // if (!cond) 1487 // if (!cond)
1556 LoadCondition(node->condition(), CodeGenState::LOAD, &exit, &else_, true); 1488 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &exit, &else_, true);
1557 Branch(true, &exit); 1489 Branch(true, &exit);
1558 // else 1490 // else
1559 __ bind(&else_); 1491 __ bind(&else_);
1560 Visit(node->else_statement()); 1492 Visit(node->else_statement());
1561 1493
1562 } else { 1494 } else {
1563 Comment cmnt(masm_, "[ If"); 1495 Comment cmnt(masm_, "[ If");
1564 ASSERT(!has_then_stm && !has_else_stm); 1496 ASSERT(!has_then_stm && !has_else_stm);
1565 // if (cond) 1497 // if (cond)
1566 LoadCondition(node->condition(), CodeGenState::LOAD, &exit, &exit, false); 1498 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &exit, &exit, false);
1567 if (has_cc()) { 1499 if (has_cc()) {
1568 cc_reg_ = al; 1500 cc_reg_ = al;
1569 } else { 1501 } else {
1570 __ pop(r0); // __ Pop(no_reg) 1502 __ pop(r0); // __ Pop(no_reg)
1571 } 1503 }
1572 } 1504 }
1573 1505
1574 // end 1506 // end
1575 __ bind(&exit); 1507 __ bind(&exit);
1576 } 1508 }
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
1799 switch (info) { 1731 switch (info) {
1800 case ALWAYS_TRUE: 1732 case ALWAYS_TRUE:
1801 CheckStack(); // TODO(1222600): ignore if body contains calls. 1733 CheckStack(); // TODO(1222600): ignore if body contains calls.
1802 __ b(&loop); 1734 __ b(&loop);
1803 break; 1735 break;
1804 case ALWAYS_FALSE: 1736 case ALWAYS_FALSE:
1805 break; 1737 break;
1806 case DONT_KNOW: 1738 case DONT_KNOW:
1807 CheckStack(); // TODO(1222600): ignore if body contains calls. 1739 CheckStack(); // TODO(1222600): ignore if body contains calls.
1808 LoadCondition(node->cond(), 1740 LoadCondition(node->cond(),
1809 CodeGenState::LOAD, 1741 NOT_INSIDE_TYPEOF,
1810 &loop, 1742 &loop,
1811 node->break_target(), 1743 node->break_target(),
1812 true); 1744 true);
1813 Branch(true, &loop); 1745 Branch(true, &loop);
1814 break; 1746 break;
1815 } 1747 }
1816 1748
1817 // exit 1749 // exit
1818 __ bind(node->break_target()); 1750 __ bind(node->break_target());
1819 } 1751 }
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
1965 1897
1966 1898
1967 __ bind(&end_del_check); 1899 __ bind(&end_del_check);
1968 1900
1969 // Store the entry in the 'each' expression and take another spin in the loop. 1901 // Store the entry in the 'each' expression and take another spin in the loop.
1970 // r3: i'th entry of the enum cache (or string there of) 1902 // r3: i'th entry of the enum cache (or string there of)
1971 __ push(r3); // push entry 1903 __ push(r3); // push entry
1972 { Reference each(this, node->each()); 1904 { Reference each(this, node->each());
1973 if (!each.is_illegal()) { 1905 if (!each.is_illegal()) {
1974 if (each.size() > 0) { 1906 if (each.size() > 0) {
1975 // Reference's size is positive.
1976 __ ldr(r0, MemOperand(sp, kPointerSize * each.size())); 1907 __ ldr(r0, MemOperand(sp, kPointerSize * each.size()));
1977 __ push(r0); 1908 __ push(r0);
1978 } 1909 }
1979 // If the reference was to a slot we rely on the convenient property 1910 // If the reference was to a slot we rely on the convenient property
1980 // that it doesn't matter whether a value (eg, r3 pushed above) is 1911 // that it doesn't matter whether a value (eg, r3 pushed above) is
1981 // right on top of or right underneath a zero-sized reference. 1912 // right on top of or right underneath a zero-sized reference.
1982 each.SetValue(NOT_CONST_INIT); 1913 each.SetValue(NOT_CONST_INIT);
1983 if (each.size() > 0) { 1914 if (each.size() > 0) {
1984 // It's safe to pop the value lying on top of the reference before 1915 // It's safe to pop the value lying on top of the reference before
1985 // unloading the reference itself (which preserves the top of stack, 1916 // unloading the reference itself (which preserves the top of stack,
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after
2266 void ArmCodeGenerator::VisitFunctionBoilerplateLiteral( 2197 void ArmCodeGenerator::VisitFunctionBoilerplateLiteral(
2267 FunctionBoilerplateLiteral* node) { 2198 FunctionBoilerplateLiteral* node) {
2268 Comment cmnt(masm_, "[ FunctionBoilerplateLiteral"); 2199 Comment cmnt(masm_, "[ FunctionBoilerplateLiteral");
2269 InstantiateBoilerplate(node->boilerplate()); 2200 InstantiateBoilerplate(node->boilerplate());
2270 } 2201 }
2271 2202
2272 2203
2273 void ArmCodeGenerator::VisitConditional(Conditional* node) { 2204 void ArmCodeGenerator::VisitConditional(Conditional* node) {
2274 Comment cmnt(masm_, "[ Conditional"); 2205 Comment cmnt(masm_, "[ Conditional");
2275 Label then, else_, exit; 2206 Label then, else_, exit;
2276 LoadCondition(node->condition(), CodeGenState::LOAD, &then, &else_, true); 2207 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true);
2277 Branch(false, &else_); 2208 Branch(false, &else_);
2278 __ bind(&then); 2209 __ bind(&then);
2279 Load(node->then_expression(), access()); 2210 Load(node->then_expression(), typeof_state());
2280 __ b(&exit); 2211 __ b(&exit);
2281 __ bind(&else_); 2212 __ bind(&else_);
2282 Load(node->else_expression(), access()); 2213 Load(node->else_expression(), typeof_state());
2283 __ bind(&exit); 2214 __ bind(&exit);
2284 } 2215 }
2285 2216
2286 2217
2287 void ArmCodeGenerator::VisitSlot(Slot* node) { 2218 void ArmCodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
2288 ASSERT(access() != CodeGenState::UNDEFINED); 2219 if (slot->type() == Slot::LOOKUP) {
2289 Comment cmnt(masm_, "[ Slot"); 2220 ASSERT(slot->var()->mode() == Variable::DYNAMIC);
2290
2291 if (node->type() == Slot::LOOKUP) {
2292 ASSERT(node->var()->mode() == Variable::DYNAMIC);
2293 2221
2294 // For now, just do a runtime call. 2222 // For now, just do a runtime call.
2295 __ push(cp); 2223 __ push(cp);
2296 __ mov(r0, Operand(node->var()->name())); 2224 __ mov(r0, Operand(slot->var()->name()));
2297 __ push(r0); 2225 __ push(r0);
2298 2226
2299 if (access() == CodeGenState::LOAD) { 2227 if (typeof_state == INSIDE_TYPEOF) {
2228 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
2229 } else {
2300 __ CallRuntime(Runtime::kLoadContextSlot, 2); 2230 __ CallRuntime(Runtime::kLoadContextSlot, 2);
2301 } else {
2302 ASSERT(access() == CodeGenState::LOAD_TYPEOF_EXPR);
2303 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
2304 } 2231 }
2305 __ push(r0); 2232 __ push(r0);
2306 2233
2307 } else { 2234 } else {
2308 // Note: We would like to keep the assert below, but it fires because of 2235 // Note: We would like to keep the assert below, but it fires because of
2309 // some nasty code in LoadTypeofExpression() which should be removed... 2236 // some nasty code in LoadTypeofExpression() which should be removed...
2310 // ASSERT(node->var()->mode() != Variable::DYNAMIC); 2237 // ASSERT(slot->var()->mode() != Variable::DYNAMIC);
2311 2238
2312 // Special handling for locals allocated in registers. 2239 // Special handling for locals allocated in registers.
2313 __ ldr(r0, SlotOperand(node, r2)); 2240 __ ldr(r0, SlotOperand(slot, r2));
2314 __ push(r0); 2241 __ push(r0);
2315 if (node->var()->mode() == Variable::CONST) { 2242 if (slot->var()->mode() == Variable::CONST) {
2316 // Const slots may contain 'the hole' value (the constant hasn't been 2243 // Const slots may contain 'the hole' value (the constant hasn't been
2317 // initialized yet) which needs to be converted into the 'undefined' 2244 // initialized yet) which needs to be converted into the 'undefined'
2318 // value. 2245 // value.
2319 Comment cmnt(masm_, "[ Unhole const"); 2246 Comment cmnt(masm_, "[ Unhole const");
2320 __ pop(r0); 2247 __ pop(r0);
2321 __ cmp(r0, Operand(Factory::the_hole_value())); 2248 __ cmp(r0, Operand(Factory::the_hole_value()));
2322 __ mov(r0, Operand(Factory::undefined_value()), LeaveCC, eq); 2249 __ mov(r0, Operand(Factory::undefined_value()), LeaveCC, eq);
2323 __ push(r0); 2250 __ push(r0);
2324 } 2251 }
2325 } 2252 }
2326 } 2253 }
2327 2254
2328 2255
2256 void ArmCodeGenerator::VisitSlot(Slot* node) {
2257 Comment cmnt(masm_, "[ Slot");
2258 LoadFromSlot(node, typeof_state());
2259 }
2260
2261
2329 void ArmCodeGenerator::VisitVariableProxy(VariableProxy* node) { 2262 void ArmCodeGenerator::VisitVariableProxy(VariableProxy* node) {
2330 Comment cmnt(masm_, "[ VariableProxy"); 2263 Comment cmnt(masm_, "[ VariableProxy");
2331 Variable* var_node = node->var(); 2264 Variable* var = node->var();
2332 2265 Expression* expr = var->rewrite();
2333 Expression* expr = var_node->rewrite();
2334 if (expr != NULL) { 2266 if (expr != NULL) {
2335 Visit(expr); 2267 Visit(expr);
2336 } else { 2268 } else {
2337 ASSERT(var_node->is_global()); 2269 ASSERT(var->is_global());
2338 if (is_referenced()) { 2270 Reference ref(this, node);
2339 if (var_node->AsProperty() != NULL) { 2271 ref.GetValue(typeof_state());
2340 __ RecordPosition(var_node->AsProperty()->position());
2341 }
2342 GetReferenceProperty(new Literal(var_node->name()));
2343 } else {
2344 Reference property(this, node);
2345 GetValue(&property);
2346 }
2347 } 2272 }
2348 } 2273 }
2349 2274
2350 2275
2351 void ArmCodeGenerator::VisitLiteral(Literal* node) { 2276 void ArmCodeGenerator::VisitLiteral(Literal* node) {
2352 Comment cmnt(masm_, "[ Literal"); 2277 Comment cmnt(masm_, "[ Literal");
2353 __ mov(r0, Operand(node->handle())); 2278 __ mov(r0, Operand(node->handle()));
2354 __ push(r0); 2279 __ push(r0);
2355 } 2280 }
2356 2281
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
2549 2474
2550 Reference target(this, node->target()); 2475 Reference target(this, node->target());
2551 if (target.is_illegal()) return; 2476 if (target.is_illegal()) return;
2552 2477
2553 if (node->op() == Token::ASSIGN || 2478 if (node->op() == Token::ASSIGN ||
2554 node->op() == Token::INIT_VAR || 2479 node->op() == Token::INIT_VAR ||
2555 node->op() == Token::INIT_CONST) { 2480 node->op() == Token::INIT_CONST) {
2556 Load(node->value()); 2481 Load(node->value());
2557 2482
2558 } else { 2483 } else {
2559 GetValue(&target); 2484 target.GetValue(NOT_INSIDE_TYPEOF);
2560 Literal* literal = node->value()->AsLiteral(); 2485 Literal* literal = node->value()->AsLiteral();
2561 if (literal != NULL && literal->handle()->IsSmi()) { 2486 if (literal != NULL && literal->handle()->IsSmi()) {
2562 SmiOperation(node->binary_op(), literal->handle(), false); 2487 SmiOperation(node->binary_op(), literal->handle(), false);
2563 __ push(r0); 2488 __ push(r0);
2564 2489
2565 } else { 2490 } else {
2566 Load(node->value()); 2491 Load(node->value());
2567 GenericBinaryOperation(node->binary_op()); 2492 GenericBinaryOperation(node->binary_op());
2568 __ push(r0); 2493 __ push(r0);
2569 } 2494 }
(...skipping 24 matching lines...) Expand all
2594 2519
2595 Load(node->exception()); 2520 Load(node->exception());
2596 __ RecordPosition(node->position()); 2521 __ RecordPosition(node->position());
2597 __ CallRuntime(Runtime::kThrow, 1); 2522 __ CallRuntime(Runtime::kThrow, 1);
2598 __ push(r0); 2523 __ push(r0);
2599 } 2524 }
2600 2525
2601 2526
2602 void ArmCodeGenerator::VisitProperty(Property* node) { 2527 void ArmCodeGenerator::VisitProperty(Property* node) {
2603 Comment cmnt(masm_, "[ Property"); 2528 Comment cmnt(masm_, "[ Property");
2604 2529 Reference property(this, node);
2605 if (is_referenced()) { 2530 property.GetValue(typeof_state());
2606 __ RecordPosition(node->position());
2607 GetReferenceProperty(node->key());
2608 } else {
2609 Reference property(this, node);
2610 __ RecordPosition(node->position());
2611 GetValue(&property);
2612 }
2613 } 2531 }
2614 2532
2615 2533
2616 void ArmCodeGenerator::VisitCall(Call* node) { 2534 void ArmCodeGenerator::VisitCall(Call* node) {
2617 Comment cmnt(masm_, "[ Call"); 2535 Comment cmnt(masm_, "[ Call");
2618 2536
2619 ZoneList<Expression*>* args = node->arguments(); 2537 ZoneList<Expression*>* args = node->arguments();
2620 2538
2621 if (FLAG_debug_info) RecordStatementPosition(node); 2539 if (FLAG_debug_info) RecordStatementPosition(node);
2622 // Standard function call. 2540 // Standard function call.
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
2706 2624
2707 __ push(r0); // push after get rid of function from the stack 2625 __ push(r0); // push after get rid of function from the stack
2708 2626
2709 } else { 2627 } else {
2710 // ------------------------------------------- 2628 // -------------------------------------------
2711 // JavaScript example: 'array[index](1, 2, 3)' 2629 // JavaScript example: 'array[index](1, 2, 3)'
2712 // ------------------------------------------- 2630 // -------------------------------------------
2713 2631
2714 // Load the function to call from the property through a reference. 2632 // Load the function to call from the property through a reference.
2715 Reference ref(this, property); 2633 Reference ref(this, property);
2716 GetValue(&ref); // receiver 2634 ref.GetValue(NOT_INSIDE_TYPEOF); // receiver
2717 2635
2718 // Pass receiver to called function. 2636 // Pass receiver to called function.
2719 __ ldr(r0, MemOperand(sp, ref.size() * kPointerSize)); 2637 __ ldr(r0, MemOperand(sp, ref.size() * kPointerSize));
2720 __ push(r0); 2638 __ push(r0);
2721 // Call the function. 2639 // Call the function.
2722 CallWithArguments(args, node->position()); 2640 CallWithArguments(args, node->position());
2723 __ push(r0); 2641 __ push(r0);
2724 } 2642 }
2725 2643
2726 } else { 2644 } else {
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
2950 } 2868 }
2951 2869
2952 2870
2953 void ArmCodeGenerator::VisitUnaryOperation(UnaryOperation* node) { 2871 void ArmCodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
2954 Comment cmnt(masm_, "[ UnaryOperation"); 2872 Comment cmnt(masm_, "[ UnaryOperation");
2955 2873
2956 Token::Value op = node->op(); 2874 Token::Value op = node->op();
2957 2875
2958 if (op == Token::NOT) { 2876 if (op == Token::NOT) {
2959 LoadCondition(node->expression(), 2877 LoadCondition(node->expression(),
2960 CodeGenState::LOAD, 2878 NOT_INSIDE_TYPEOF,
2961 false_target(), 2879 false_target(),
2962 true_target(), 2880 true_target(),
2963 true); 2881 true);
2964 cc_reg_ = NegateCondition(cc_reg_); 2882 cc_reg_ = NegateCondition(cc_reg_);
2965 2883
2966 } else if (op == Token::DELETE) { 2884 } else if (op == Token::DELETE) {
2967 Property* property = node->expression()->AsProperty(); 2885 Property* property = node->expression()->AsProperty();
2968 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); 2886 Variable* variable = node->expression()->AsVariableProxy()->AsVariable();
2969 if (property != NULL) { 2887 if (property != NULL) {
2970 Load(property->obj()); 2888 Load(property->obj());
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
3085 bool is_const = (var != NULL && var->mode() == Variable::CONST); 3003 bool is_const = (var != NULL && var->mode() == Variable::CONST);
3086 3004
3087 // Postfix: Make room for the result. 3005 // Postfix: Make room for the result.
3088 if (is_postfix) { 3006 if (is_postfix) {
3089 __ mov(r0, Operand(0)); 3007 __ mov(r0, Operand(0));
3090 __ push(r0); 3008 __ push(r0);
3091 } 3009 }
3092 3010
3093 { Reference target(this, node->expression()); 3011 { Reference target(this, node->expression());
3094 if (target.is_illegal()) return; 3012 if (target.is_illegal()) return;
3095 GetValue(&target); 3013 target.GetValue(NOT_INSIDE_TYPEOF);
3096 __ pop(r0); 3014 __ pop(r0);
3097 3015
3098 Label slow, exit; 3016 Label slow, exit;
3099 3017
3100 // Load the value (1) into register r1. 3018 // Load the value (1) into register r1.
3101 __ mov(r1, Operand(Smi::FromInt(1))); 3019 __ mov(r1, Operand(Smi::FromInt(1)));
3102 3020
3103 // Check for smi operand. 3021 // Check for smi operand.
3104 __ tst(r0, Operand(kSmiTagMask)); 3022 __ tst(r0, Operand(kSmiTagMask));
3105 __ b(ne, &slow); 3023 __ b(ne, &slow);
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
3167 // NOTE: If the left hand side produces a materialized value (not in 3085 // NOTE: If the left hand side produces a materialized value (not in
3168 // the CC register), we force the right hand side to do the 3086 // the CC register), we force the right hand side to do the
3169 // same. This is necessary because we may have to branch to the exit 3087 // same. This is necessary because we may have to branch to the exit
3170 // after evaluating the left hand side (due to the shortcut 3088 // after evaluating the left hand side (due to the shortcut
3171 // semantics), but the compiler must (statically) know if the result 3089 // semantics), but the compiler must (statically) know if the result
3172 // of compiling the binary operation is materialized or not. 3090 // of compiling the binary operation is materialized or not.
3173 3091
3174 if (op == Token::AND) { 3092 if (op == Token::AND) {
3175 Label is_true; 3093 Label is_true;
3176 LoadCondition(node->left(), 3094 LoadCondition(node->left(),
3177 CodeGenState::LOAD, 3095 NOT_INSIDE_TYPEOF,
3178 &is_true, 3096 &is_true,
3179 false_target(), 3097 false_target(),
3180 false); 3098 false);
3181 if (has_cc()) { 3099 if (has_cc()) {
3182 Branch(false, false_target()); 3100 Branch(false, false_target());
3183 3101
3184 // Evaluate right side expression. 3102 // Evaluate right side expression.
3185 __ bind(&is_true); 3103 __ bind(&is_true);
3186 LoadCondition(node->right(), 3104 LoadCondition(node->right(),
3187 CodeGenState::LOAD, 3105 NOT_INSIDE_TYPEOF,
3188 true_target(), 3106 true_target(),
3189 false_target(), 3107 false_target(),
3190 false); 3108 false);
3191 3109
3192 } else { 3110 } else {
3193 Label pop_and_continue, exit; 3111 Label pop_and_continue, exit;
3194 3112
3195 __ ldr(r0, MemOperand(sp, 0)); // dup the stack top 3113 __ ldr(r0, MemOperand(sp, 0)); // dup the stack top
3196 __ push(r0); 3114 __ push(r0);
3197 // Avoid popping the result if it converts to 'false' using the 3115 // Avoid popping the result if it converts to 'false' using the
(...skipping 10 matching lines...) Expand all
3208 __ bind(&is_true); 3126 __ bind(&is_true);
3209 Load(node->right()); 3127 Load(node->right());
3210 3128
3211 // Exit (always with a materialized value). 3129 // Exit (always with a materialized value).
3212 __ bind(&exit); 3130 __ bind(&exit);
3213 } 3131 }
3214 3132
3215 } else if (op == Token::OR) { 3133 } else if (op == Token::OR) {
3216 Label is_false; 3134 Label is_false;
3217 LoadCondition(node->left(), 3135 LoadCondition(node->left(),
3218 CodeGenState::LOAD, 3136 NOT_INSIDE_TYPEOF,
3219 true_target(), 3137 true_target(),
3220 &is_false, 3138 &is_false,
3221 false); 3139 false);
3222 if (has_cc()) { 3140 if (has_cc()) {
3223 Branch(true, true_target()); 3141 Branch(true, true_target());
3224 3142
3225 // Evaluate right side expression. 3143 // Evaluate right side expression.
3226 __ bind(&is_false); 3144 __ bind(&is_false);
3227 LoadCondition(node->right(), 3145 LoadCondition(node->right(),
3228 CodeGenState::LOAD, 3146 NOT_INSIDE_TYPEOF,
3229 true_target(), 3147 true_target(),
3230 false_target(), 3148 false_target(),
3231 false); 3149 false);
3232 3150
3233 } else { 3151 } else {
3234 Label pop_and_continue, exit; 3152 Label pop_and_continue, exit;
3235 3153
3236 __ ldr(r0, MemOperand(sp, 0)); 3154 __ ldr(r0, MemOperand(sp, 0));
3237 __ push(r0); 3155 __ push(r0);
3238 // Avoid popping the result if it converts to 'true' using the 3156 // Avoid popping the result if it converts to 'true' using the
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
3510 // Drop the execution stack down to the frame pointer and restore the caller 3428 // Drop the execution stack down to the frame pointer and restore the caller
3511 // frame pointer and return address. 3429 // frame pointer and return address.
3512 __ mov(sp, fp); 3430 __ mov(sp, fp);
3513 __ ldm(ia_w, sp, fp.bit() | lr.bit()); 3431 __ ldm(ia_w, sp, fp.bit() | lr.bit());
3514 } 3432 }
3515 3433
3516 3434
3517 #undef __ 3435 #undef __
3518 #define __ masm-> 3436 #define __ masm->
3519 3437
3438 Handle<String> Reference::GetName() {
3439 ASSERT(type_ == NAMED);
3440 Property* property = expression_->AsProperty();
3441 if (property == NULL) {
3442 // Global variable reference treated as a named property reference.
3443 VariableProxy* proxy = expression_->AsVariableProxy();
3444 ASSERT(proxy->AsVariable() != NULL);
3445 ASSERT(proxy->AsVariable()->is_global());
3446 return proxy->name();
3447 } else {
3448 Literal* raw_name = property->key()->AsLiteral();
3449 ASSERT(raw_name != NULL);
3450 return Handle<String>(String::cast(*raw_name->handle()));
3451 }
3452 }
3453
3454
3455 void Reference::GetValue(TypeofState typeof_state) {
3456 ASSERT(!is_illegal());
3457 ASSERT(!cgen_->has_cc());
3458 MacroAssembler* masm = cgen_->masm();
3459 Property* property = expression_->AsProperty();
3460 if (property != NULL) {
3461 __ RecordPosition(property->position());
3462 }
3463
3464 switch (type_) {
3465 case SLOT: {
3466 Comment cmnt(masm, "[ Load from Slot");
3467 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
3468 ASSERT(slot != NULL);
3469 cgen_->LoadFromSlot(slot, typeof_state);
3470 break;
3471 }
3472
3473 case NAMED: {
3474 // TODO(1241834): Make sure that this it is safe to ignore the
3475 // distinction between expressions ina typeof and not in a typeof. If
iposva 2008/10/07 19:43:31 ina -> in a
3476 // there is a chance that reference errors can be thrown below, we
3477 // must distinguish between the two kinds of loads (typeof expression
3478 // loads must not throw a reference error).
3479 Comment cmnt(masm, "[ Load from named Property");
3480 // Setup the name register.
3481 Handle<String> name(GetName());
3482 __ mov(r2, Operand(name));
3483 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
3484
3485 Variable* var = expression_->AsVariableProxy()->AsVariable();
3486 if (var != NULL) {
3487 ASSERT(var->is_global());
3488 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
3489 } else {
3490 __ Call(ic, RelocInfo::CODE_TARGET);
3491 }
3492 __ push(r0);
3493 break;
3494 }
3495
3496 case KEYED: {
3497 // TODO(1241834): Make sure that this it is safe to ignore the
3498 // distinction between expressions ina typeof and not in a typeof.
iposva 2008/10/07 19:43:31 ina -> in a
3499 Comment cmnt(masm, "[ Load from keyed Property");
3500 ASSERT(property != NULL);
3501 // TODO(1224671): Implement inline caching for keyed loads as on ia32.
3502 GetPropertyStub stub;
3503 __ CallStub(&stub);
3504 __ push(r0);
3505 break;
3506 }
3507
3508 default:
3509 UNREACHABLE();
3510 }
3511 }
3512
3513
3520 void Reference::SetValue(InitState init_state) { 3514 void Reference::SetValue(InitState init_state) {
3521 ASSERT(!is_illegal()); 3515 ASSERT(!is_illegal());
3522 ASSERT(!cgen_->has_cc()); 3516 ASSERT(!cgen_->has_cc());
3523 MacroAssembler* masm = cgen_->masm(); 3517 MacroAssembler* masm = cgen_->masm();
3518 Property* property = expression_->AsProperty();
3519 if (property != NULL) {
3520 __ RecordPosition(property->position());
3521 }
3522
3524 switch (type_) { 3523 switch (type_) {
3525 case SLOT: { 3524 case SLOT: {
3526 Comment cmnt(masm, "[ Store to Slot"); 3525 Comment cmnt(masm, "[ Store to Slot");
3527 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); 3526 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
3528 ASSERT(slot != NULL); 3527 ASSERT(slot != NULL);
3529 if (slot->type() == Slot::LOOKUP) { 3528 if (slot->type() == Slot::LOOKUP) {
3530 ASSERT(slot->var()->mode() == Variable::DYNAMIC); 3529 ASSERT(slot->var()->mode() == Variable::DYNAMIC);
3531 3530
3532 // For now, just do a runtime call. 3531 // For now, just do a runtime call.
3533 __ push(cp); 3532 __ push(cp);
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
3599 // optimization. 3598 // optimization.
3600 if (init_state == CONST_INIT || slot->type() == Slot::CONTEXT) { 3599 if (init_state == CONST_INIT || slot->type() == Slot::CONTEXT) {
3601 __ bind(&exit); 3600 __ bind(&exit);
3602 } 3601 }
3603 } 3602 }
3604 break; 3603 break;
3605 } 3604 }
3606 3605
3607 case NAMED: { 3606 case NAMED: {
3608 Comment cmnt(masm, "[ Store to named Property"); 3607 Comment cmnt(masm, "[ Store to named Property");
3609 Property* property = expression_->AsProperty();
3610 Handle<String> name;
3611 if (property == NULL) {
3612 // Global variable reference treated as named property access.
3613 VariableProxy* proxy = expression_->AsVariableProxy();
3614 ASSERT(proxy->AsVariable() != NULL);
3615 ASSERT(proxy->AsVariable()->is_global());
3616 name = proxy->name();
3617 } else {
3618 Literal* raw_name = property->key()->AsLiteral();
3619 ASSERT(raw_name != NULL);
3620 name = Handle<String>(String::cast(*raw_name->handle()));
3621 __ RecordPosition(property->position());
3622 }
3623
3624 // Call the appropriate IC code. 3608 // Call the appropriate IC code.
3625 __ pop(r0); // value 3609 __ pop(r0); // value
3626 // Setup the name register. 3610 // Setup the name register.
3611 Handle<String> name(GetName());
3627 __ mov(r2, Operand(name)); 3612 __ mov(r2, Operand(name));
3628 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 3613 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
3629 __ Call(ic, RelocInfo::CODE_TARGET); 3614 __ Call(ic, RelocInfo::CODE_TARGET);
3630 __ push(r0); 3615 __ push(r0);
3631 break; 3616 break;
3632 } 3617 }
3633 3618
3634 case KEYED: { 3619 case KEYED: {
3635 Comment cmnt(masm, "[ Store to keyed Property"); 3620 Comment cmnt(masm, "[ Store to keyed Property");
3636 Property* property = expression_->AsProperty(); 3621 Property* property = expression_->AsProperty();
(...skipping 895 matching lines...) Expand 10 before | Expand all | Expand 10 after
4532 bool is_eval) { 4517 bool is_eval) {
4533 Handle<Code> code = ArmCodeGenerator::MakeCode(fun, script, is_eval); 4518 Handle<Code> code = ArmCodeGenerator::MakeCode(fun, script, is_eval);
4534 if (!code.is_null()) { 4519 if (!code.is_null()) {
4535 Counters::total_compiled_code_size.Increment(code->instruction_size()); 4520 Counters::total_compiled_code_size.Increment(code->instruction_size());
4536 } 4521 }
4537 return code; 4522 return code;
4538 } 4523 }
4539 4524
4540 4525
4541 } } // namespace v8::internal 4526 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/codegen-ia32.cc » ('j') | src/codegen-ia32.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698