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

Side by Side Diff: src/codegen-ia32.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
« src/codegen-arm.cc ('K') | « src/codegen-arm.cc ('k') | no next file » | no next file with comments »
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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 // Reference support 50 // Reference support
51 51
52 // A reference is a C++ stack-allocated object that keeps an ECMA 52 // A reference is a C++ stack-allocated object that keeps an ECMA
53 // reference on the execution stack while in scope. For variables 53 // reference on the execution stack while in scope. For variables
54 // the reference is empty, indicating that it isn't necessary to 54 // the reference is empty, indicating that it isn't necessary to
55 // store state on the stack for keeping track of references to those. 55 // store state on the stack for keeping track of references to those.
56 // For properties, we keep either one (named) or two (indexed) values 56 // For properties, we keep either one (named) or two (indexed) values
57 // on the execution stack to represent the reference. 57 // on the execution stack to represent the reference.
58 58
59 enum InitState { CONST_INIT, NOT_CONST_INIT }; 59 enum InitState { CONST_INIT, NOT_CONST_INIT };
60 enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
60 61
61 class Reference BASE_EMBEDDED { 62 class Reference BASE_EMBEDDED {
62 public: 63 public:
63 // The values of the types is important, see size(). 64 // The values of the types is important, see size().
64 enum Type { ILLEGAL = -1, SLOT = 0, NAMED = 1, KEYED = 2 }; 65 enum Type { ILLEGAL = -1, SLOT = 0, NAMED = 1, KEYED = 2 };
65 Reference(Ia32CodeGenerator* cgen, Expression* expression); 66 Reference(Ia32CodeGenerator* cgen, Expression* expression);
66 ~Reference(); 67 ~Reference();
67 68
68 Expression* expression() const { return expression_; } 69 Expression* expression() const { return expression_; }
69 Type type() const { return type_; } 70 Type type() const { return type_; }
70 void set_type(Type value) { 71 void set_type(Type value) {
71 ASSERT(type_ == ILLEGAL); 72 ASSERT(type_ == ILLEGAL);
72 type_ = value; 73 type_ = value;
73 } 74 }
74 75
75 // The size of the reference or -1 if the reference is illegal. 76 // The size of the reference or -1 if the reference is illegal.
76 int size() const { return type_; } 77 int size() const { return type_; }
77 78
78 bool is_illegal() const { return type_ == ILLEGAL; } 79 bool is_illegal() const { return type_ == ILLEGAL; }
79 bool is_slot() const { return type_ == SLOT; } 80 bool is_slot() const { return type_ == SLOT; }
80 bool is_property() const { return type_ == NAMED || type_ == KEYED; } 81 bool is_property() const { return type_ == NAMED || type_ == KEYED; }
81 82
83 // Return the name. Only valid for named property references.
84 Handle<String> GetName();
85
86 // Generate code to push the value of the reference on top of the
87 // expression stack. The reference is expected to be already on top of
88 // the expression stack, and it is left in place with its value above it.
89 void GetValue(TypeofState typeof_state);
90
91 // Generate code to store the value on top of the expression stack in the
92 // reference. The reference is expected to be immediately below the value
93 // on the expression stack. The stored value is left in place (with the
94 // reference intact below it) to support chained assignments.
82 void SetValue(InitState init_state); 95 void SetValue(InitState init_state);
83 96
84 private: 97 private:
85 Ia32CodeGenerator* cgen_; 98 Ia32CodeGenerator* cgen_;
86 Expression* expression_; 99 Expression* expression_;
87 Type type_; 100 Type type_;
88 }; 101 };
89 102
90 103
91 // ------------------------------------------------------------------------- 104 // -------------------------------------------------------------------------
92 // Code generation state 105 // Code generation state
93 106
94 // The state is passed down the AST by the code generator (and back up, in 107 // The state is passed down the AST by the code generator (and back up, in
95 // the form of the state of the label pair). It is threaded through the 108 // the form of the state of the label pair). It is threaded through the
96 // call stack. Constructing a state implicitly pushes it on the owning code 109 // call stack. Constructing a state implicitly pushes it on the owning code
97 // generator's stack of states, and destroying one implicitly pops it. 110 // generator's stack of states, and destroying one implicitly pops it.
98 111
99 class CodeGenState BASE_EMBEDDED { 112 class CodeGenState BASE_EMBEDDED {
100 public: 113 public:
101 enum AccessType {
102 UNDEFINED,
103 LOAD,
104 LOAD_TYPEOF_EXPR
105 };
106
107 // Create an initial code generator state. Destroying the initial state 114 // Create an initial code generator state. Destroying the initial state
108 // leaves the code generator with a NULL state. 115 // leaves the code generator with a NULL state.
109 explicit CodeGenState(Ia32CodeGenerator* owner); 116 explicit CodeGenState(Ia32CodeGenerator* owner);
110 117
111 // Create a code generator state based on a code generator's current 118 // Create a code generator state based on a code generator's current
112 // state. The new state has its own access type and pair of branch 119 // state. The new state has its own typeof state and pair of branch
113 // labels, and no reference. 120 // labels.
114 CodeGenState(Ia32CodeGenerator* owner, 121 CodeGenState(Ia32CodeGenerator* owner,
115 AccessType access, 122 TypeofState typeof_state,
116 Label* true_target, 123 Label* true_target,
117 Label* false_target); 124 Label* false_target);
118 125
119 // Create a code generator state based on a code generator's current
120 // state. The new state has an access type of LOAD, its own reference,
121 // and inherits the pair of branch labels of the current state.
122 CodeGenState(Ia32CodeGenerator* owner, Reference* ref);
123
124 // Destroy a code generator state and restore the owning code generator's 126 // Destroy a code generator state and restore the owning code generator's
125 // previous state. 127 // previous state.
126 ~CodeGenState(); 128 ~CodeGenState();
127 129
128 AccessType access() const { return access_; } 130 TypeofState typeof_state() const { return typeof_state_; }
129 Reference* ref() const { return ref_; }
130 Label* true_target() const { return true_target_; } 131 Label* true_target() const { return true_target_; }
131 Label* false_target() const { return false_target_; } 132 Label* false_target() const { return false_target_; }
132 133
133 private: 134 private:
134 Ia32CodeGenerator* owner_; 135 Ia32CodeGenerator* owner_;
135 AccessType access_; 136 TypeofState typeof_state_;
136 Reference* ref_;
137 Label* true_target_; 137 Label* true_target_;
138 Label* false_target_; 138 Label* false_target_;
139 CodeGenState* previous_; 139 CodeGenState* previous_;
140 }; 140 };
141 141
142 142
143 // ----------------------------------------------------------------------------- 143 // -----------------------------------------------------------------------------
144 // Ia32CodeGenerator 144 // Ia32CodeGenerator
145 145
146 class Ia32CodeGenerator: public CodeGenerator { 146 class Ia32CodeGenerator: public CodeGenerator {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 178
179 // Main code generation function 179 // Main code generation function
180 void GenCode(FunctionLiteral* fun); 180 void GenCode(FunctionLiteral* fun);
181 181
182 // The following are used by class Reference. 182 // The following are used by class Reference.
183 void LoadReference(Reference* ref); 183 void LoadReference(Reference* ref);
184 void UnloadReference(Reference* ref); 184 void UnloadReference(Reference* ref);
185 185
186 // State 186 // State
187 bool has_cc() const { return cc_reg_ >= 0; } 187 bool has_cc() const { return cc_reg_ >= 0; }
188 CodeGenState::AccessType access() const { return state_->access(); } 188 TypeofState typeof_state() const { return state_->typeof_state(); }
189 Reference* ref() const { return state_->ref(); }
190 bool is_referenced() const { return state_->ref() != NULL; }
191 Label* true_target() const { return state_->true_target(); } 189 Label* true_target() const { return state_->true_target(); }
192 Label* false_target() const { return state_->false_target(); } 190 Label* false_target() const { return state_->false_target(); }
193 191
194 // Expressions 192 // Expressions
195 Operand GlobalObject() const { 193 Operand GlobalObject() const {
196 return ContextOperand(esi, Context::GLOBAL_INDEX); 194 return ContextOperand(esi, Context::GLOBAL_INDEX);
197 } 195 }
198 196
199 // Support functions for accessing parameters. 197 // Support functions for accessing parameters.
200 Operand ParameterOperand(int index) const { 198 Operand ParameterOperand(int index) const {
201 int num_parameters = scope()->num_parameters(); 199 int num_parameters = scope()->num_parameters();
202 ASSERT(-2 <= index && index < num_parameters); 200 ASSERT(-2 <= index && index < num_parameters);
203 return Operand(ebp, (1 + num_parameters - index) * kPointerSize); 201 return Operand(ebp, (1 + num_parameters - index) * kPointerSize);
204 } 202 }
205 203
206 Operand ReceiverOperand() const { return ParameterOperand(-1); } 204 Operand ReceiverOperand() const { return ParameterOperand(-1); }
207 205
208 Operand FunctionOperand() const { 206 Operand FunctionOperand() const {
209 return Operand(ebp, JavaScriptFrameConstants::kFunctionOffset); 207 return Operand(ebp, JavaScriptFrameConstants::kFunctionOffset);
210 } 208 }
211 209
212 Operand ContextOperand(Register context, int index) const { 210 Operand ContextOperand(Register context, int index) const {
213 return Operand(context, Context::SlotOffset(index)); 211 return Operand(context, Context::SlotOffset(index));
214 } 212 }
215 213
216 Operand SlotOperand(Slot* slot, Register tmp); 214 Operand SlotOperand(Slot* slot, Register tmp);
217 215
218 void LoadCondition(Expression* x, 216 void LoadCondition(Expression* x,
219 CodeGenState::AccessType access, 217 TypeofState typeof_state,
220 Label* true_target, 218 Label* true_target,
221 Label* false_target, 219 Label* false_target,
222 bool force_cc); 220 bool force_cc);
223 void Load(Expression* x, 221 void Load(Expression* x, TypeofState typeof_state = NOT_INSIDE_TYPEOF);
224 CodeGenState::AccessType access = CodeGenState::LOAD);
225 void LoadGlobal(); 222 void LoadGlobal();
226 223
224 // Read a value from a slot and leave it on top of the expression stack.
225 void LoadFromSlot(Slot* slot, TypeofState typeof_state);
226
227 // Special code for typeof expressions: Unfortunately, we must 227 // Special code for typeof expressions: Unfortunately, we must
228 // be careful when loading the expression in 'typeof' 228 // be careful when loading the expression in 'typeof'
229 // expressions. We are not allowed to throw reference errors for 229 // expressions. We are not allowed to throw reference errors for
230 // non-existing properties of the global object, so we must make it 230 // non-existing properties of the global object, so we must make it
231 // look like an explicit property access, instead of an access 231 // look like an explicit property access, instead of an access
232 // through the context chain. 232 // through the context chain.
233 void LoadTypeofExpression(Expression* x); 233 void LoadTypeofExpression(Expression* x);
234 234
235 // References
236
237 // Generate code to fetch the value of a reference. The reference is
238 // expected to be on top of the expression stack. It is left in place and
239 // its value is pushed on top of it.
240 void GetValue(Reference* ref) {
241 ASSERT(!has_cc());
242 ASSERT(!ref->is_illegal());
243 CodeGenState new_state(this, ref);
244 Visit(ref->expression());
245 }
246
247 // Generate code to fetch a value from a property of a reference. The
248 // reference is expected on top of the expression stack. It is left in
249 // place and its value is pushed on top of it.
250 void GetReferenceProperty(Expression* key);
251
252 void ToBoolean(Label* true_target, Label* false_target); 235 void ToBoolean(Label* true_target, Label* false_target);
253 236
254 void GenericBinaryOperation( 237 void GenericBinaryOperation(
255 Token::Value op, 238 Token::Value op,
256 const OverwriteMode overwrite_mode = NO_OVERWRITE); 239 const OverwriteMode overwrite_mode = NO_OVERWRITE);
257 void Comparison(Condition cc, bool strict = false); 240 void Comparison(Condition cc, bool strict = false);
258 241
259 // Inline small integer literals. To prevent long attacker-controlled byte 242 // Inline small integer literals. To prevent long attacker-controlled byte
260 // sequences, we only inline small Smi:s. 243 // sequences, we only inline small Smi:s.
261 static const int kMaxSmiInlinedBits = 16; 244 static const int kMaxSmiInlinedBits = 16;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 friend class VariableProxy; 316 friend class VariableProxy;
334 friend class Slot; 317 friend class Slot;
335 }; 318 };
336 319
337 320
338 // ------------------------------------------------------------------------- 321 // -------------------------------------------------------------------------
339 // CodeGenState implementation. 322 // CodeGenState implementation.
340 323
341 CodeGenState::CodeGenState(Ia32CodeGenerator* owner) 324 CodeGenState::CodeGenState(Ia32CodeGenerator* owner)
342 : owner_(owner), 325 : owner_(owner),
343 access_(UNDEFINED), 326 typeof_state_(NOT_INSIDE_TYPEOF),
344 ref_(NULL),
345 true_target_(NULL), 327 true_target_(NULL),
346 false_target_(NULL), 328 false_target_(NULL),
347 previous_(NULL) { 329 previous_(NULL) {
348 owner_->set_state(this); 330 owner_->set_state(this);
349 } 331 }
350 332
351 333
352 CodeGenState::CodeGenState(Ia32CodeGenerator* owner, 334 CodeGenState::CodeGenState(Ia32CodeGenerator* owner,
353 AccessType access, 335 TypeofState typeof_state,
354 Label* true_target, 336 Label* true_target,
355 Label* false_target) 337 Label* false_target)
356 : owner_(owner), 338 : owner_(owner),
357 access_(access), 339 typeof_state_(typeof_state),
358 ref_(NULL),
359 true_target_(true_target), 340 true_target_(true_target),
360 false_target_(false_target), 341 false_target_(false_target),
361 previous_(owner->state()) { 342 previous_(owner->state()) {
362 owner_->set_state(this); 343 owner_->set_state(this);
363 } 344 }
364 345
365 346
366 CodeGenState::CodeGenState(Ia32CodeGenerator* owner, Reference* ref)
367 : owner_(owner),
368 access_(LOAD),
369 ref_(ref),
370 true_target_(owner->state()->true_target_),
371 false_target_(owner->state()->false_target_),
372 previous_(owner->state()) {
373 owner_->set_state(this);
374 }
375
376
377 CodeGenState::~CodeGenState() { 347 CodeGenState::~CodeGenState() {
378 ASSERT(owner_->state() == this); 348 ASSERT(owner_->state() == this);
379 owner_->set_state(previous_); 349 owner_->set_state(previous_);
380 } 350 }
381 351
382 352
383 // ----------------------------------------------------------------------------- 353 // -----------------------------------------------------------------------------
384 // Ia32CodeGenerator implementation 354 // Ia32CodeGenerator implementation
385 355
386 #define __ masm_-> 356 #define __ masm_->
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after
752 } 722 }
753 } 723 }
754 724
755 725
756 // Loads a value on TOS. If it is a boolean value, the result may have been 726 // Loads a value on TOS. If it is a boolean value, the result may have been
757 // (partially) translated into branches, or it may have set the condition code 727 // (partially) translated into branches, or it may have set the condition code
758 // register. If force_cc is set, the value is forced to set the condition code 728 // register. If force_cc is set, the value is forced to set the condition code
759 // register and no value is pushed. If the condition code register was set, 729 // register and no value is pushed. If the condition code register was set,
760 // has_cc() is true and cc_reg_ contains the condition to test for 'true'. 730 // has_cc() is true and cc_reg_ contains the condition to test for 'true'.
761 void Ia32CodeGenerator::LoadCondition(Expression* x, 731 void Ia32CodeGenerator::LoadCondition(Expression* x,
762 CodeGenState::AccessType access, 732 TypeofState typeof_state,
763 Label* true_target, 733 Label* true_target,
764 Label* false_target, 734 Label* false_target,
765 bool force_cc) { 735 bool force_cc) {
766 ASSERT(access == CodeGenState::LOAD || 736 ASSERT(!has_cc());
767 access == CodeGenState::LOAD_TYPEOF_EXPR);
768 ASSERT(!has_cc() && !is_referenced());
769 737
770 { CodeGenState new_state(this, access, true_target, false_target); 738 { CodeGenState new_state(this, typeof_state, true_target, false_target);
771 Visit(x); 739 Visit(x);
772 } 740 }
773 if (force_cc && !has_cc()) { 741 if (force_cc && !has_cc()) {
774 ToBoolean(true_target, false_target); 742 ToBoolean(true_target, false_target);
775 } 743 }
776 ASSERT(has_cc() || !force_cc); 744 ASSERT(has_cc() || !force_cc);
777 } 745 }
778 746
779 747
780 void Ia32CodeGenerator::Load(Expression* x, CodeGenState::AccessType access) { 748 void Ia32CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
781 ASSERT(access == CodeGenState::LOAD ||
782 access == CodeGenState::LOAD_TYPEOF_EXPR);
783
784 Label true_target; 749 Label true_target;
785 Label false_target; 750 Label false_target;
786 LoadCondition(x, access, &true_target, &false_target, false); 751 LoadCondition(x, typeof_state, &true_target, &false_target, false);
787 752
788 if (has_cc()) { 753 if (has_cc()) {
789 // convert cc_reg_ into a bool 754 // convert cc_reg_ into a bool
790 755
791 Label loaded, materialize_true; 756 Label loaded, materialize_true;
792 __ j(cc_reg_, &materialize_true); 757 __ j(cc_reg_, &materialize_true);
793 __ push(Immediate(Factory::false_value())); 758 __ push(Immediate(Factory::false_value()));
794 __ jmp(&loaded); 759 __ jmp(&loaded);
795 __ bind(&materialize_true); 760 __ bind(&materialize_true);
796 __ push(Immediate(Factory::true_value())); 761 __ push(Immediate(Factory::true_value()));
(...skipping 28 matching lines...) Expand all
825 ASSERT(!has_cc()); 790 ASSERT(!has_cc());
826 } 791 }
827 792
828 793
829 void Ia32CodeGenerator::LoadGlobal() { 794 void Ia32CodeGenerator::LoadGlobal() {
830 __ push(GlobalObject()); 795 __ push(GlobalObject());
831 } 796 }
832 797
833 798
834 // TODO(1241834): Get rid of this function in favor of just using Load, now 799 // TODO(1241834): Get rid of this function in favor of just using Load, now
835 // that we have the LOAD_TYPEOF_EXPR access type. => Need to handle 800 // that we have the INSIDE_TYPEOF typeof state. => Need to handle global
836 // global variables w/o reference errors elsewhere. 801 // variables w/o reference errors elsewhere.
837 void Ia32CodeGenerator::LoadTypeofExpression(Expression* x) { 802 void Ia32CodeGenerator::LoadTypeofExpression(Expression* x) {
838 Variable* variable = x->AsVariableProxy()->AsVariable(); 803 Variable* variable = x->AsVariableProxy()->AsVariable();
839 if (variable != NULL && !variable->is_this() && variable->is_global()) { 804 if (variable != NULL && !variable->is_this() && variable->is_global()) {
840 // NOTE: This is somewhat nasty. We force the compiler to load 805 // NOTE: This is somewhat nasty. We force the compiler to load
841 // the variable as if through '<global>.<variable>' to make sure we 806 // the variable as if through '<global>.<variable>' to make sure we
842 // do not get reference errors. 807 // do not get reference errors.
843 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX); 808 Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX);
844 Literal key(variable->name()); 809 Literal key(variable->name());
845 // TODO(1241834): Fetch the position from the variable instead of using 810 // TODO(1241834): Fetch the position from the variable instead of using
846 // no position. 811 // no position.
847 Property property(&global, &key, RelocInfo::kNoPosition); 812 Property property(&global, &key, RelocInfo::kNoPosition);
848 Load(&property); 813 Load(&property);
849 } else { 814 } else {
850 Load(x, CodeGenState::LOAD_TYPEOF_EXPR); 815 Load(x, INSIDE_TYPEOF);
851 } 816 }
852 } 817 }
853 818
854 819
855 Reference::Reference(Ia32CodeGenerator* cgen, Expression* expression) 820 Reference::Reference(Ia32CodeGenerator* cgen, Expression* expression)
856 : cgen_(cgen), expression_(expression), type_(ILLEGAL) { 821 : cgen_(cgen), expression_(expression), type_(ILLEGAL) {
857 cgen->LoadReference(this); 822 cgen->LoadReference(this);
858 } 823 }
859 824
860 825
861 Reference::~Reference() { 826 Reference::~Reference() {
862 cgen_->UnloadReference(this); 827 cgen_->UnloadReference(this);
863 } 828 }
864 829
865 830
866 void Ia32CodeGenerator::LoadReference(Reference* ref) { 831 void Ia32CodeGenerator::LoadReference(Reference* ref) {
832 Comment cmnt(masm_, "[ LoadReference");
867 Expression* e = ref->expression(); 833 Expression* e = ref->expression();
868 Property* property = e->AsProperty(); 834 Property* property = e->AsProperty();
869 Variable* var = e->AsVariableProxy()->AsVariable(); 835 Variable* var = e->AsVariableProxy()->AsVariable();
870 836
871 if (property != NULL) { 837 if (property != NULL) {
872 // The expression is either a property or a variable proxy that rewrites 838 // The expression is either a property or a variable proxy that rewrites
873 // to a property. 839 // to a property.
874 Load(property->obj()); 840 Load(property->obj());
875 // We use a named reference if the key is a literal symbol, unless it is 841 // We use a named reference if the key is a literal symbol, unless it is
876 // a string that can be legally parsed as an integer. This is because 842 // a string that can be legally parsed as an integer. This is because
(...skipping 21 matching lines...) Expand all
898 } 864 }
899 } else { 865 } else {
900 // Anything else is a runtime error. 866 // Anything else is a runtime error.
901 Load(e); 867 Load(e);
902 __ CallRuntime(Runtime::kThrowReferenceError, 1); 868 __ CallRuntime(Runtime::kThrowReferenceError, 1);
903 } 869 }
904 } 870 }
905 871
906 872
907 void Ia32CodeGenerator::UnloadReference(Reference* ref) { 873 void Ia32CodeGenerator::UnloadReference(Reference* ref) {
908 // Pop n references on the stack while preserving TOS 874 // Pop a reference from the stack while preserving TOS.
909 Comment cmnt(masm_, "[ UnloadReference"); 875 Comment cmnt(masm_, "[ UnloadReference");
910 int size = ref->size(); 876 int size = ref->size();
911 if (size <= 0) { 877 if (size <= 0) {
912 // Do nothing. No popping is necessary. 878 // Do nothing. No popping is necessary.
913 } else if (size == 1) { 879 } else if (size == 1) {
914 __ pop(eax); 880 __ pop(eax);
915 __ mov(TOS, eax); 881 __ mov(TOS, eax);
916 } else { 882 } else {
917 __ pop(eax); 883 __ pop(eax);
918 __ add(Operand(esp), Immediate(size * kPointerSize)); 884 __ add(Operand(esp), Immediate(size * kPointerSize));
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
978 ToBooleanStub stub; 944 ToBooleanStub stub;
979 __ CallStub(&stub); 945 __ CallStub(&stub);
980 // Convert result (eax) to condition code. 946 // Convert result (eax) to condition code.
981 __ test(eax, Operand(eax)); 947 __ test(eax, Operand(eax));
982 948
983 ASSERT(not_equal == not_zero); 949 ASSERT(not_equal == not_zero);
984 cc_reg_ = not_equal; 950 cc_reg_ = not_equal;
985 } 951 }
986 952
987 953
988 void Ia32CodeGenerator::GetReferenceProperty(Expression* key) {
989 ASSERT(!ref()->is_illegal());
990
991 // TODO(1241834): Make sure that this it is safe to ignore the distinction
992 // between access types LOAD and LOAD_TYPEOF_EXPR. If there is a chance
993 // that reference errors can be thrown below, we must distinguish between
994 // the two kinds of loads (typeof expression loads must not throw a
995 // reference error).
996 if (ref()->type() == Reference::NAMED) {
997 // Compute the name of the property.
998 Literal* literal = key->AsLiteral();
999 Handle<String> name(String::cast(*literal->handle()));
1000
1001 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
1002 Variable* var = ref()->expression()->AsVariableProxy()->AsVariable();
1003 // Setup the name register.
1004 __ Set(ecx, Immediate(name));
1005 if (var != NULL) {
1006 ASSERT(var->is_global());
1007 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
1008 } else {
1009 __ call(ic, RelocInfo::CODE_TARGET);
1010 }
1011 } else {
1012 // Access keyed property.
1013 ASSERT(ref()->type() == Reference::KEYED);
1014
1015 // Call IC code.
1016 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1017 Variable* var = ref()->expression()->AsVariableProxy()->AsVariable();
1018 if (var != NULL) {
1019 ASSERT(var->is_global());
1020 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
1021 } else {
1022 __ call(ic, RelocInfo::CODE_TARGET);
1023 }
1024 }
1025 __ push(eax); // IC call leaves result in eax, push it out
1026 }
1027
1028
1029 class FloatingPointHelper : public AllStatic { 954 class FloatingPointHelper : public AllStatic {
1030 public: 955 public:
1031 // Code pattern for loading floating point values. Input values must 956 // Code pattern for loading floating point values. Input values must
1032 // be either smi or heap number objects (fp values). Requirements: 957 // be either smi or heap number objects (fp values). Requirements:
1033 // operand_1 on TOS+1 , operand_2 on TOS+2; Returns operands as 958 // operand_1 on TOS+1 , operand_2 on TOS+2; Returns operands as
1034 // floating point numbers on FPU stack. 959 // floating point numbers on FPU stack.
1035 static void LoadFloatOperands(MacroAssembler* masm, Register scratch); 960 static void LoadFloatOperands(MacroAssembler* masm, Register scratch);
1036 // Test if operands are smi or number objects (fp). Requirements: 961 // Test if operands are smi or number objects (fp). Requirements:
1037 // operand_1 in eax, operand_2 in edx; falls through on float 962 // operand_1 in eax, operand_2 in edx; falls through on float
1038 // operands, jumps to the non_float label otherwise. 963 // operands, jumps to the non_float label otherwise.
(...skipping 630 matching lines...) Expand 10 before | Expand all | Expand 10 after
1669 Major MajorKey() { return CallFunction; } 1594 Major MajorKey() { return CallFunction; }
1670 int MinorKey() { return argc_; } 1595 int MinorKey() { return argc_; }
1671 }; 1596 };
1672 1597
1673 1598
1674 // Call the function just below TOS on the stack with the given 1599 // Call the function just below TOS on the stack with the given
1675 // arguments. The receiver is the TOS. 1600 // arguments. The receiver is the TOS.
1676 void Ia32CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, 1601 void Ia32CodeGenerator::CallWithArguments(ZoneList<Expression*>* args,
1677 int position) { 1602 int position) {
1678 // Push the arguments ("left-to-right") on the stack. 1603 // Push the arguments ("left-to-right") on the stack.
1679 for (int i = 0; i < args->length(); i++) Load(args->at(i)); 1604 for (int i = 0; i < args->length(); i++) {
1605 Load(args->at(i));
1606 }
iposva 2008/10/07 19:43:31 Thanks!
1680 1607
1681 // Record the position for debugging purposes. 1608 // Record the position for debugging purposes.
1682 __ RecordPosition(position); 1609 __ RecordPosition(position);
1683 1610
1684 // Use the shared code stub to call the function. 1611 // Use the shared code stub to call the function.
1685 CallFunctionStub call_function(args->length()); 1612 CallFunctionStub call_function(args->length());
1686 __ CallStub(&call_function); 1613 __ CallStub(&call_function);
1687 1614
1688 // Restore context and pop function from the stack. 1615 // Restore context and pop function from the stack.
1689 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 1616 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
1814 // parts of the if statement are present or not. 1741 // parts of the if statement are present or not.
1815 bool has_then_stm = node->HasThenStatement(); 1742 bool has_then_stm = node->HasThenStatement();
1816 bool has_else_stm = node->HasElseStatement(); 1743 bool has_else_stm = node->HasElseStatement();
1817 1744
1818 RecordStatementPosition(node); 1745 RecordStatementPosition(node);
1819 Label exit; 1746 Label exit;
1820 if (has_then_stm && has_else_stm) { 1747 if (has_then_stm && has_else_stm) {
1821 Label then; 1748 Label then;
1822 Label else_; 1749 Label else_;
1823 // if (cond) 1750 // if (cond)
1824 LoadCondition(node->condition(), CodeGenState::LOAD, &then, &else_, true); 1751 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true);
1825 Branch(false, &else_); 1752 Branch(false, &else_);
1826 // then 1753 // then
1827 __ bind(&then); 1754 __ bind(&then);
1828 Visit(node->then_statement()); 1755 Visit(node->then_statement());
1829 __ jmp(&exit); 1756 __ jmp(&exit);
1830 // else 1757 // else
1831 __ bind(&else_); 1758 __ bind(&else_);
1832 Visit(node->else_statement()); 1759 Visit(node->else_statement());
1833 1760
1834 } else if (has_then_stm) { 1761 } else if (has_then_stm) {
1835 ASSERT(!has_else_stm); 1762 ASSERT(!has_else_stm);
1836 Label then; 1763 Label then;
1837 // if (cond) 1764 // if (cond)
1838 LoadCondition(node->condition(), CodeGenState::LOAD, &then, &exit, true); 1765 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &exit, true);
1839 Branch(false, &exit); 1766 Branch(false, &exit);
1840 // then 1767 // then
1841 __ bind(&then); 1768 __ bind(&then);
1842 Visit(node->then_statement()); 1769 Visit(node->then_statement());
1843 1770
1844 } else if (has_else_stm) { 1771 } else if (has_else_stm) {
1845 ASSERT(!has_then_stm); 1772 ASSERT(!has_then_stm);
1846 Label else_; 1773 Label else_;
1847 // if (!cond) 1774 // if (!cond)
1848 LoadCondition(node->condition(), CodeGenState::LOAD, &exit, &else_, true); 1775 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &exit, &else_, true);
1849 Branch(true, &exit); 1776 Branch(true, &exit);
1850 // else 1777 // else
1851 __ bind(&else_); 1778 __ bind(&else_);
1852 Visit(node->else_statement()); 1779 Visit(node->else_statement());
1853 1780
1854 } else { 1781 } else {
1855 ASSERT(!has_then_stm && !has_else_stm); 1782 ASSERT(!has_then_stm && !has_else_stm);
1856 // if (cond) 1783 // if (cond)
1857 LoadCondition(node->condition(), CodeGenState::LOAD, &exit, &exit, false); 1784 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &exit, &exit, false);
1858 if (has_cc()) { 1785 if (has_cc()) {
1859 cc_reg_ = no_condition; 1786 cc_reg_ = no_condition;
1860 } else { 1787 } else {
1861 // No cc value set up, that means the boolean was pushed. 1788 // No cc value set up, that means the boolean was pushed.
1862 // Pop it again, since it is not going to be used. 1789 // Pop it again, since it is not going to be used.
1863 __ pop(eax); 1790 __ pop(eax);
1864 } 1791 }
1865 } 1792 }
1866 1793
1867 // end 1794 // end
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
2132 2059
2133 // cond 2060 // cond
2134 __ bind(&entry); 2061 __ bind(&entry);
2135 switch (info) { 2062 switch (info) {
2136 case ALWAYS_TRUE: 2063 case ALWAYS_TRUE:
2137 __ jmp(&loop); 2064 __ jmp(&loop);
2138 break; 2065 break;
2139 case ALWAYS_FALSE: 2066 case ALWAYS_FALSE:
2140 break; 2067 break;
2141 case DONT_KNOW: 2068 case DONT_KNOW:
2142 LoadCondition(node->cond(), CodeGenState::LOAD, &loop, 2069 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &loop,
2143 node->break_target(), true); 2070 node->break_target(), true);
2144 Branch(true, &loop); 2071 Branch(true, &loop);
2145 break; 2072 break;
2146 } 2073 }
2147 2074
2148 // exit 2075 // exit
2149 __ bind(node->break_target()); 2076 __ bind(node->break_target());
2150 } 2077 }
2151 2078
2152 2079
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after
2601 void Ia32CodeGenerator::VisitFunctionBoilerplateLiteral( 2528 void Ia32CodeGenerator::VisitFunctionBoilerplateLiteral(
2602 FunctionBoilerplateLiteral* node) { 2529 FunctionBoilerplateLiteral* node) {
2603 Comment cmnt(masm_, "[ FunctionBoilerplateLiteral"); 2530 Comment cmnt(masm_, "[ FunctionBoilerplateLiteral");
2604 InstantiateBoilerplate(node->boilerplate()); 2531 InstantiateBoilerplate(node->boilerplate());
2605 } 2532 }
2606 2533
2607 2534
2608 void Ia32CodeGenerator::VisitConditional(Conditional* node) { 2535 void Ia32CodeGenerator::VisitConditional(Conditional* node) {
2609 Comment cmnt(masm_, "[ Conditional"); 2536 Comment cmnt(masm_, "[ Conditional");
2610 Label then, else_, exit; 2537 Label then, else_, exit;
2611 LoadCondition(node->condition(), CodeGenState::LOAD, &then, &else_, true); 2538 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true);
2612 Branch(false, &else_); 2539 Branch(false, &else_);
2613 __ bind(&then); 2540 __ bind(&then);
2614 Load(node->then_expression(), access()); 2541 Load(node->then_expression(), typeof_state());
2615 __ jmp(&exit); 2542 __ jmp(&exit);
2616 __ bind(&else_); 2543 __ bind(&else_);
2617 Load(node->else_expression(), access()); 2544 Load(node->else_expression(), typeof_state());
2618 __ bind(&exit); 2545 __ bind(&exit);
2619 } 2546 }
2620 2547
2621 2548
2622 void Ia32CodeGenerator::VisitSlot(Slot* node) { 2549 void Ia32CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
2623 ASSERT(access() != CodeGenState::UNDEFINED); 2550 if (slot->type() == Slot::LOOKUP) {
2624 Comment cmnt(masm_, "[ Slot"); 2551 ASSERT(slot->var()->mode() == Variable::DYNAMIC);
2625
2626 if (node->type() == Slot::LOOKUP) {
2627 ASSERT(node->var()->mode() == Variable::DYNAMIC);
2628 2552
2629 // For now, just do a runtime call. 2553 // For now, just do a runtime call.
2630 __ push(Operand(esi)); 2554 __ push(esi);
2631 __ push(Immediate(node->var()->name())); 2555 __ push(Immediate(slot->var()->name()));
2632 2556
2633 if (access() == CodeGenState::LOAD) { 2557 if (typeof_state == INSIDE_TYPEOF) {
2558 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
2559 } else {
2634 __ CallRuntime(Runtime::kLoadContextSlot, 2); 2560 __ CallRuntime(Runtime::kLoadContextSlot, 2);
2635 } else {
2636 ASSERT(access() == CodeGenState::LOAD_TYPEOF_EXPR);
2637 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
2638 } 2561 }
2639 __ push(eax); 2562 __ push(eax);
2640 2563
2641 } else { 2564 } else {
2642 // Note: We would like to keep the assert below, but it fires because of 2565 // Note: We would like to keep the assert below, but it fires because of
2643 // some nasty code in LoadTypeofExpression() which should be removed... 2566 // some nasty code in LoadTypeofExpression() which should be removed...
2644 // ASSERT(node->var()->mode() != Variable::DYNAMIC); 2567 // ASSERT(slot->var()->mode() != Variable::DYNAMIC);
2645 2568 if (slot->var()->mode() == Variable::CONST) {
2646 if (node->var()->mode() == Variable::CONST) {
2647 // Const slots may contain 'the hole' value (the constant hasn't been 2569 // Const slots may contain 'the hole' value (the constant hasn't been
2648 // initialized yet) which needs to be converted into the 'undefined' 2570 // initialized yet) which needs to be converted into the 'undefined'
2649 // value. 2571 // value.
2650 Comment cmnt(masm_, "[ Load const"); 2572 Comment cmnt(masm_, "[ Load const");
2651 Label L; 2573 Label exit;
2652 __ mov(eax, SlotOperand(node, ecx)); 2574 __ mov(eax, SlotOperand(slot, ecx));
2653 __ cmp(eax, Factory::the_hole_value()); 2575 __ cmp(eax, Factory::the_hole_value());
2654 __ j(not_equal, &L); 2576 __ j(not_equal, &exit);
2655 __ mov(eax, Factory::undefined_value()); 2577 __ mov(eax, Factory::undefined_value());
2656 __ bind(&L); 2578 __ bind(&exit);
2657 __ push(eax); 2579 __ push(eax);
2658 } else { 2580 } else {
2659 __ push(SlotOperand(node, ecx)); 2581 __ push(SlotOperand(slot, ecx));
2660 } 2582 }
2661 } 2583 }
2662 } 2584 }
2663 2585
2664 2586
2587 void Ia32CodeGenerator::VisitSlot(Slot* node) {
2588 Comment cmnt(masm_, "[ Slot");
2589 LoadFromSlot(node, typeof_state());
2590 }
2591
2592
2665 void Ia32CodeGenerator::VisitVariableProxy(VariableProxy* node) { 2593 void Ia32CodeGenerator::VisitVariableProxy(VariableProxy* node) {
2666 Comment cmnt(masm_, "[ VariableProxy"); 2594 Comment cmnt(masm_, "[ VariableProxy");
2667 Variable* var_node = node->var(); 2595 Variable* var = node->var();
2668 2596 Expression* expr = var->rewrite();
2669 Expression* expr = var_node->rewrite();
2670 if (expr != NULL) { 2597 if (expr != NULL) {
2671 Visit(expr); 2598 Visit(expr);
2672 } else { 2599 } else {
2673 ASSERT(var_node->is_global()); 2600 ASSERT(var->is_global());
2674 if (is_referenced()) { 2601 Reference ref(this, node);
2675 if (var_node->AsProperty() != NULL) { 2602 ref.GetValue(typeof_state());
2676 __ RecordPosition(var_node->AsProperty()->position());
2677 }
2678 GetReferenceProperty(new Literal(var_node->name()));
2679 } else {
2680 Reference property(this, node);
2681 GetValue(&property);
2682 }
2683 } 2603 }
2684 } 2604 }
2685 2605
2686 2606
2687 void Ia32CodeGenerator::VisitLiteral(Literal* node) { 2607 void Ia32CodeGenerator::VisitLiteral(Literal* node) {
2688 Comment cmnt(masm_, "[ Literal"); 2608 Comment cmnt(masm_, "[ Literal");
2689 if (node->handle()->IsSmi() && !IsInlineSmi(node)) { 2609 if (node->handle()->IsSmi() && !IsInlineSmi(node)) {
2690 // To prevent long attacker-controlled byte sequences in code, larger 2610 // To prevent long attacker-controlled byte sequences in code, larger
2691 // Smis are loaded in two steps. 2611 // Smis are loaded in two steps.
2692 int bits = reinterpret_cast<int>(*node->handle()); 2612 int bits = reinterpret_cast<int>(*node->handle());
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
2935 RecordStatementPosition(node); 2855 RecordStatementPosition(node);
2936 Reference target(this, node->target()); 2856 Reference target(this, node->target());
2937 if (target.is_illegal()) return; 2857 if (target.is_illegal()) return;
2938 2858
2939 if (node->op() == Token::ASSIGN || 2859 if (node->op() == Token::ASSIGN ||
2940 node->op() == Token::INIT_VAR || 2860 node->op() == Token::INIT_VAR ||
2941 node->op() == Token::INIT_CONST) { 2861 node->op() == Token::INIT_CONST) {
2942 Load(node->value()); 2862 Load(node->value());
2943 2863
2944 } else { 2864 } else {
2945 GetValue(&target); 2865 target.GetValue(NOT_INSIDE_TYPEOF);
2946 Literal* literal = node->value()->AsLiteral(); 2866 Literal* literal = node->value()->AsLiteral();
2947 if (IsInlineSmi(literal)) { 2867 if (IsInlineSmi(literal)) {
2948 SmiOperation(node->binary_op(), literal->handle(), false, NO_OVERWRITE); 2868 SmiOperation(node->binary_op(), literal->handle(), false, NO_OVERWRITE);
2949 } else { 2869 } else {
2950 Load(node->value()); 2870 Load(node->value());
2951 GenericBinaryOperation(node->binary_op()); 2871 GenericBinaryOperation(node->binary_op());
2952 } 2872 }
2953 } 2873 }
2954 2874
2955 Variable* var = node->target()->AsVariableProxy()->AsVariable(); 2875 Variable* var = node->target()->AsVariableProxy()->AsVariable();
(...skipping 20 matching lines...) Expand all
2976 2896
2977 Load(node->exception()); 2897 Load(node->exception());
2978 __ RecordPosition(node->position()); 2898 __ RecordPosition(node->position());
2979 __ CallRuntime(Runtime::kThrow, 1); 2899 __ CallRuntime(Runtime::kThrow, 1);
2980 __ push(eax); 2900 __ push(eax);
2981 } 2901 }
2982 2902
2983 2903
2984 void Ia32CodeGenerator::VisitProperty(Property* node) { 2904 void Ia32CodeGenerator::VisitProperty(Property* node) {
2985 Comment cmnt(masm_, "[ Property"); 2905 Comment cmnt(masm_, "[ Property");
2986 2906 Reference property(this, node);
2987 if (is_referenced()) { 2907 property.GetValue(typeof_state());
2988 __ RecordPosition(node->position());
2989 GetReferenceProperty(node->key());
2990 } else {
2991 Reference property(this, node);
2992 __ RecordPosition(node->position());
2993 GetValue(&property);
2994 }
2995 } 2908 }
2996 2909
2997 2910
2998 void Ia32CodeGenerator::VisitCall(Call* node) { 2911 void Ia32CodeGenerator::VisitCall(Call* node) {
2999 Comment cmnt(masm_, "[ Call"); 2912 Comment cmnt(masm_, "[ Call");
3000 2913
3001 ZoneList<Expression*>* args = node->arguments(); 2914 ZoneList<Expression*>* args = node->arguments();
3002 2915
3003 RecordStatementPosition(node); 2916 RecordStatementPosition(node);
3004 2917
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
3083 // Overwrite the function on the stack with the result. 2996 // Overwrite the function on the stack with the result.
3084 __ mov(TOS, eax); 2997 __ mov(TOS, eax);
3085 2998
3086 } else { 2999 } else {
3087 // ------------------------------------------- 3000 // -------------------------------------------
3088 // JavaScript example: 'array[index](1, 2, 3)' 3001 // JavaScript example: 'array[index](1, 2, 3)'
3089 // ------------------------------------------- 3002 // -------------------------------------------
3090 3003
3091 // Load the function to call from the property through a reference. 3004 // Load the function to call from the property through a reference.
3092 Reference ref(this, property); 3005 Reference ref(this, property);
3093 GetValue(&ref); 3006 ref.GetValue(NOT_INSIDE_TYPEOF);
3094 3007
3095 // Pass receiver to called function. 3008 // Pass receiver to called function.
3096 // The reference's size is non-negative. 3009 // The reference's size is non-negative.
3097 __ push(Operand(esp, ref.size() * kPointerSize)); 3010 __ push(Operand(esp, ref.size() * kPointerSize));
3098 3011
3099 // Call the function. 3012 // Call the function.
3100 CallWithArguments(args, node->position()); 3013 CallWithArguments(args, node->position());
3101 } 3014 }
3102 3015
3103 } else { 3016 } else {
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
3449 } 3362 }
3450 } 3363 }
3451 3364
3452 3365
3453 void Ia32CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { 3366 void Ia32CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
3454 Comment cmnt(masm_, "[ UnaryOperation"); 3367 Comment cmnt(masm_, "[ UnaryOperation");
3455 3368
3456 Token::Value op = node->op(); 3369 Token::Value op = node->op();
3457 3370
3458 if (op == Token::NOT) { 3371 if (op == Token::NOT) {
3459 LoadCondition(node->expression(), CodeGenState::LOAD, 3372 LoadCondition(node->expression(), NOT_INSIDE_TYPEOF,
3460 false_target(), true_target(), true); 3373 false_target(), true_target(), true);
3461 cc_reg_ = NegateCondition(cc_reg_); 3374 cc_reg_ = NegateCondition(cc_reg_);
3462 3375
3463 } else if (op == Token::DELETE) { 3376 } else if (op == Token::DELETE) {
3464 Property* property = node->expression()->AsProperty(); 3377 Property* property = node->expression()->AsProperty();
3465 if (property != NULL) { 3378 if (property != NULL) {
3466 Load(property->obj()); 3379 Load(property->obj());
3467 Load(property->key()); 3380 Load(property->key());
3468 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 3381 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3469 __ push(eax); 3382 __ push(eax);
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
3670 bool is_increment = node->op() == Token::INC; 3583 bool is_increment = node->op() == Token::INC;
3671 3584
3672 Variable* var = node->expression()->AsVariableProxy()->AsVariable(); 3585 Variable* var = node->expression()->AsVariableProxy()->AsVariable();
3673 bool is_const = (var != NULL && var->mode() == Variable::CONST); 3586 bool is_const = (var != NULL && var->mode() == Variable::CONST);
3674 3587
3675 // Postfix: Make room for the result. 3588 // Postfix: Make room for the result.
3676 if (is_postfix) __ push(Immediate(0)); 3589 if (is_postfix) __ push(Immediate(0));
3677 3590
3678 { Reference target(this, node->expression()); 3591 { Reference target(this, node->expression());
3679 if (target.is_illegal()) return; 3592 if (target.is_illegal()) return;
3680 GetValue(&target); 3593 target.GetValue(NOT_INSIDE_TYPEOF);
3681 3594
3682 int result_offset = target.size() * kPointerSize; 3595 int result_offset = target.size() * kPointerSize;
3683 CountOperationDeferred* deferred = 3596 CountOperationDeferred* deferred =
3684 new CountOperationDeferred(this, is_postfix, 3597 new CountOperationDeferred(this, is_postfix,
3685 is_increment, result_offset); 3598 is_increment, result_offset);
3686 3599
3687 __ pop(eax); // Load TOS into eax for calculations below 3600 __ pop(eax); // Load TOS into eax for calculations below
3688 3601
3689 // Postfix: Store the old value as the result. 3602 // Postfix: Store the old value as the result.
3690 if (is_postfix) __ mov(Operand(esp, result_offset), eax); 3603 if (is_postfix) __ mov(Operand(esp, result_offset), eax);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
3725 3638
3726 // NOTE: If the left hand side produces a materialized value (not in 3639 // NOTE: If the left hand side produces a materialized value (not in
3727 // the CC register), we force the right hand side to do the 3640 // the CC register), we force the right hand side to do the
3728 // same. This is necessary because we may have to branch to the exit 3641 // same. This is necessary because we may have to branch to the exit
3729 // after evaluating the left hand side (due to the shortcut 3642 // after evaluating the left hand side (due to the shortcut
3730 // semantics), but the compiler must (statically) know if the result 3643 // semantics), but the compiler must (statically) know if the result
3731 // of compiling the binary operation is materialized or not. 3644 // of compiling the binary operation is materialized or not.
3732 3645
3733 if (op == Token::AND) { 3646 if (op == Token::AND) {
3734 Label is_true; 3647 Label is_true;
3735 LoadCondition(node->left(), CodeGenState::LOAD, &is_true, 3648 LoadCondition(node->left(), NOT_INSIDE_TYPEOF, &is_true,
3736 false_target(), false); 3649 false_target(), false);
3737 if (has_cc()) { 3650 if (has_cc()) {
3738 Branch(false, false_target()); 3651 Branch(false, false_target());
3739 3652
3740 // Evaluate right side expression. 3653 // Evaluate right side expression.
3741 __ bind(&is_true); 3654 __ bind(&is_true);
3742 LoadCondition(node->right(), CodeGenState::LOAD, true_target(), 3655 LoadCondition(node->right(), NOT_INSIDE_TYPEOF, true_target(),
3743 false_target(), false); 3656 false_target(), false);
3744 3657
3745 } else { 3658 } else {
3746 Label pop_and_continue, exit; 3659 Label pop_and_continue, exit;
3747 3660
3748 // Avoid popping the result if it converts to 'false' using the 3661 // Avoid popping the result if it converts to 'false' using the
3749 // standard ToBoolean() conversion as described in ECMA-262, 3662 // standard ToBoolean() conversion as described in ECMA-262,
3750 // section 9.2, page 30. 3663 // section 9.2, page 30.
3751 // Duplicate the TOS value. The duplicate will be popped by ToBoolean. 3664 // Duplicate the TOS value. The duplicate will be popped by ToBoolean.
3752 __ mov(eax, TOS); 3665 __ mov(eax, TOS);
3753 __ push(eax); 3666 __ push(eax);
3754 ToBoolean(&pop_and_continue, &exit); 3667 ToBoolean(&pop_and_continue, &exit);
3755 Branch(false, &exit); 3668 Branch(false, &exit);
3756 3669
3757 // Pop the result of evaluating the first part. 3670 // Pop the result of evaluating the first part.
3758 __ bind(&pop_and_continue); 3671 __ bind(&pop_and_continue);
3759 __ pop(eax); 3672 __ pop(eax);
3760 3673
3761 // Evaluate right side expression. 3674 // Evaluate right side expression.
3762 __ bind(&is_true); 3675 __ bind(&is_true);
3763 Load(node->right()); 3676 Load(node->right());
3764 3677
3765 // Exit (always with a materialized value). 3678 // Exit (always with a materialized value).
3766 __ bind(&exit); 3679 __ bind(&exit);
3767 } 3680 }
3768 3681
3769 } else if (op == Token::OR) { 3682 } else if (op == Token::OR) {
3770 Label is_false; 3683 Label is_false;
3771 LoadCondition(node->left(), CodeGenState::LOAD, true_target(), 3684 LoadCondition(node->left(), NOT_INSIDE_TYPEOF, true_target(),
3772 &is_false, false); 3685 &is_false, false);
3773 if (has_cc()) { 3686 if (has_cc()) {
3774 Branch(true, true_target()); 3687 Branch(true, true_target());
3775 3688
3776 // Evaluate right side expression. 3689 // Evaluate right side expression.
3777 __ bind(&is_false); 3690 __ bind(&is_false);
3778 LoadCondition(node->right(), CodeGenState::LOAD, true_target(), 3691 LoadCondition(node->right(), NOT_INSIDE_TYPEOF, true_target(),
3779 false_target(), false); 3692 false_target(), false);
3780 3693
3781 } else { 3694 } else {
3782 Label pop_and_continue, exit; 3695 Label pop_and_continue, exit;
3783 3696
3784 // Avoid popping the result if it converts to 'true' using the 3697 // Avoid popping the result if it converts to 'true' using the
3785 // standard ToBoolean() conversion as described in ECMA-262, 3698 // standard ToBoolean() conversion as described in ECMA-262,
3786 // section 9.2, page 30. 3699 // section 9.2, page 30.
3787 // Duplicate the TOS value. The duplicate will be popped by ToBoolean. 3700 // Duplicate the TOS value. The duplicate will be popped by ToBoolean.
3788 __ mov(eax, TOS); 3701 __ mov(eax, TOS);
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after
4083 // call instruction to support patching the exit code in the 3996 // call instruction to support patching the exit code in the
4084 // debugger. See VisitReturnStatement for the full return sequence. 3997 // debugger. See VisitReturnStatement for the full return sequence.
4085 __ mov(esp, Operand(ebp)); 3998 __ mov(esp, Operand(ebp));
4086 __ pop(ebp); 3999 __ pop(ebp);
4087 } 4000 }
4088 4001
4089 4002
4090 #undef __ 4003 #undef __
4091 #define __ masm-> 4004 #define __ masm->
4092 4005
4006 Handle<String> Reference::GetName() {
4007 ASSERT(type_ == NAMED);
4008 Property* property = expression_->AsProperty();
4009 if (property == NULL) {
4010 // Global variable reference treated as a named property reference.
4011 VariableProxy* proxy = expression_->AsVariableProxy();
4012 ASSERT(proxy->AsVariable() != NULL);
4013 ASSERT(proxy->AsVariable()->is_global());
4014 return proxy->name();
4015 } else {
4016 MacroAssembler* masm = cgen_->masm();
4017 __ RecordPosition(property->position());
4018 Literal* raw_name = property->key()->AsLiteral();
4019 ASSERT(raw_name != NULL);
4020 return Handle<String>(String::cast(*raw_name->handle()));
4021 }
4022 }
4023
4024
4025 void Reference::GetValue(TypeofState typeof_state) {
4026 ASSERT(!is_illegal());
4027 ASSERT(!cgen_->has_cc());
4028 MacroAssembler* masm = cgen_->masm();
4029 switch (type_) {
4030 case SLOT: {
4031 Comment cmnt(masm, "[ Load from Slot");
4032 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
4033 ASSERT(slot != NULL);
4034 cgen_->LoadFromSlot(slot, typeof_state);
4035 break;
4036 }
4037
4038 case NAMED: {
4039 // TODO(1241834): Make sure that this it is safe to ignore the
4040 // distinction between expressions in a typeof and not in a typeof. If
4041 // there is a chance that reference errors can be thrown below, we
4042 // must distinguish between the two kinds of loads (typeof expression
4043 // loads must not throw a reference error).
4044 Comment cmnt(masm, "[ Load from named Property");
4045 Handle<String> name(GetName());
4046 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
4047 // Setup the name register.
4048 __ mov(ecx, name);
4049
4050 Variable* var = expression_->AsVariableProxy()->AsVariable();
4051 if (var != NULL) {
4052 ASSERT(var->is_global());
4053 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
4054 } else {
4055 __ call(ic, RelocInfo::CODE_TARGET);
4056 }
4057 __ push(eax); // IC call leaves result in eax, push it out
4058 break;
4059 }
4060
4061 case KEYED: {
4062 // TODO(1241834): Make sure that this it is safe to ignore the
4063 // distinction between expressions in a typeof and not in a typeof.
4064 Comment cmnt(masm, "[ Load from keyed Property");
4065 Property* property = expression_->AsProperty();
4066 ASSERT(property != NULL);
4067 __ RecordPosition(property->position());
4068 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
4069
4070 Variable* var = expression_->AsVariableProxy()->AsVariable();
4071 if (var != NULL) {
4072 ASSERT(var->is_global());
4073 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
4074 } else {
4075 __ call(ic, RelocInfo::CODE_TARGET);
4076 }
4077 __ push(eax); // IC call leaves result in eax, push it out
4078 break;
4079 }
4080
4081 default:
4082 UNREACHABLE();
4083 }
4084 }
4085
4086
4093 void Reference::SetValue(InitState init_state) { 4087 void Reference::SetValue(InitState init_state) {
4094 ASSERT(!is_illegal()); 4088 ASSERT(!is_illegal());
4095 ASSERT(!cgen_->has_cc()); 4089 ASSERT(!cgen_->has_cc());
4096 MacroAssembler* masm = cgen_->masm(); 4090 MacroAssembler* masm = cgen_->masm();
4097 switch (type_) { 4091 switch (type_) {
4098 case SLOT: { 4092 case SLOT: {
4099 Comment cmnt(masm, "[ Store to Slot"); 4093 Comment cmnt(masm, "[ Store to Slot");
4100 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); 4094 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
4101 ASSERT(slot != NULL); 4095 ASSERT(slot != NULL);
4102 if (slot->type() == Slot::LOOKUP) { 4096 if (slot->type() == Slot::LOOKUP) {
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
4165 // If we definitely did not jump over the assignment, we do not need 4159 // If we definitely did not jump over the assignment, we do not need
4166 // to bind the exit label. Doing so can defeat peephole 4160 // to bind the exit label. Doing so can defeat peephole
4167 // optimization. 4161 // optimization.
4168 if (init_state == CONST_INIT) __ bind(&exit); 4162 if (init_state == CONST_INIT) __ bind(&exit);
4169 } 4163 }
4170 break; 4164 break;
4171 } 4165 }
4172 4166
4173 case NAMED: { 4167 case NAMED: {
4174 Comment cmnt(masm, "[ Store to named Property"); 4168 Comment cmnt(masm, "[ Store to named Property");
4175 Property* property = expression_->AsProperty();
4176 Handle<String> name;
4177 if (property == NULL) {
4178 // Global variable reference treated as named property access.
4179 VariableProxy* proxy = expression_->AsVariableProxy();
4180 ASSERT(proxy->AsVariable() != NULL);
4181 ASSERT(proxy->AsVariable()->is_global());
4182 name = proxy->name();
4183 } else {
4184 Literal* raw_name = property->key()->AsLiteral();
4185 ASSERT(raw_name != NULL);
4186 name = Handle<String>(String::cast(*raw_name->handle()));
4187 __ RecordPosition(property->position());
4188 }
4189
4190 // Call the appropriate IC code. 4169 // Call the appropriate IC code.
4170 Handle<String> name(GetName());
4191 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 4171 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
4192 // TODO(1222589): Make the IC grab the values from the stack. 4172 // TODO(1222589): Make the IC grab the values from the stack.
4193 __ pop(eax); 4173 __ pop(eax);
4194 // Setup the name register. 4174 // Setup the name register.
4195 __ mov(ecx, name); 4175 __ mov(ecx, name);
4196 __ call(ic, RelocInfo::CODE_TARGET); 4176 __ call(ic, RelocInfo::CODE_TARGET);
4197 __ push(eax); // IC call leaves result in eax, push it out 4177 __ push(eax); // IC call leaves result in eax, push it out
4198 break; 4178 break;
4199 } 4179 }
4200 4180
(...skipping 1121 matching lines...) Expand 10 before | Expand all | Expand 10 after
5322 bool is_eval) { 5302 bool is_eval) {
5323 Handle<Code> code = Ia32CodeGenerator::MakeCode(fun, script, is_eval); 5303 Handle<Code> code = Ia32CodeGenerator::MakeCode(fun, script, is_eval);
5324 if (!code.is_null()) { 5304 if (!code.is_null()) {
5325 Counters::total_compiled_code_size.Increment(code->instruction_size()); 5305 Counters::total_compiled_code_size.Increment(code->instruction_size());
5326 } 5306 }
5327 return code; 5307 return code;
5328 } 5308 }
5329 5309
5330 5310
5331 } } // namespace v8::internal 5311 } } // namespace v8::internal
OLDNEW
« src/codegen-arm.cc ('K') | « src/codegen-arm.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698