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

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

Issue 1889: Remove some of the state-dependent behavior from the code generator.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 12 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« 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 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 108
109 109
110 // ----------------------------------------------------------------------------- 110 // -----------------------------------------------------------------------------
111 // Code generation state 111 // Code generation state
112 112
113 class CodeGenState BASE_EMBEDDED { 113 class CodeGenState BASE_EMBEDDED {
114 public: 114 public:
115 enum AccessType { 115 enum AccessType {
116 UNDEFINED, 116 UNDEFINED,
117 LOAD, 117 LOAD,
118 LOAD_TYPEOF_EXPR, 118 LOAD_TYPEOF_EXPR
119 STORE,
120 INIT_CONST
121 }; 119 };
122 120
123 CodeGenState() 121 CodeGenState()
124 : access_(UNDEFINED), 122 : access_(UNDEFINED),
125 ref_(NULL), 123 ref_(NULL),
126 true_target_(NULL), 124 true_target_(NULL),
127 false_target_(NULL) { 125 false_target_(NULL) {
128 } 126 }
129 127
130 CodeGenState(AccessType access, 128 CodeGenState(AccessType access,
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 Handle<Script> script, 178 Handle<Script> script,
181 bool is_eval); 179 bool is_eval);
182 virtual ~Ia32CodeGenerator() { delete masm_; } 180 virtual ~Ia32CodeGenerator() { delete masm_; }
183 181
184 // Main code generation function 182 // Main code generation function
185 void GenCode(FunctionLiteral* fun); 183 void GenCode(FunctionLiteral* fun);
186 184
187 // The following are used by class Reference. 185 // The following are used by class Reference.
188 void LoadReference(Reference* ref); 186 void LoadReference(Reference* ref);
189 void UnloadReference(Reference* ref); 187 void UnloadReference(Reference* ref);
190 friend class Reference;
191 188
192 // State 189 // State
193 bool has_cc() const { return cc_reg_ >= 0; } 190 bool has_cc() const { return cc_reg_ >= 0; }
194 CodeGenState::AccessType access() const { return state_->access(); } 191 CodeGenState::AccessType access() const { return state_->access(); }
195 Reference* ref() const { return state_->ref(); } 192 Reference* ref() const { return state_->ref(); }
196 bool is_referenced() const { return state_->ref() != NULL; } 193 bool is_referenced() const { return state_->ref() != NULL; }
197 Label* true_target() const { return state_->true_target(); } 194 Label* true_target() const { return state_->true_target(); }
198 Label* false_target() const { return state_->false_target(); } 195 Label* false_target() const { return state_->false_target(); }
199 196
200 // Expressions 197 // Expressions
201 Operand GlobalObject() const { 198 Operand GlobalObject() const {
202 return ContextOperand(esi, Context::GLOBAL_INDEX); 199 return ContextOperand(esi, Context::GLOBAL_INDEX);
203 } 200 }
204 201
205 // Support functions for accessing parameters. 202 // Support functions for accessing parameters. Static versions can
203 // require some code generator state to be passed in as arguments.
204 static Operand ParameterOperand(Scope* scope, int index) {
205 ASSERT(-2 <= index && index < scope->num_parameters());
206 return Operand(ebp, (1 + scope->num_parameters() - index) * kPointerSize);
207 }
208
206 Operand ParameterOperand(int index) const { 209 Operand ParameterOperand(int index) const {
207 ASSERT(-2 <= index && index < scope_->num_parameters()); 210 return ParameterOperand(scope_, index);
208 return Operand(ebp, (1 + scope_->num_parameters() - index) * kPointerSize);
209 } 211 }
210 212
211 Operand ReceiverOperand() const { return ParameterOperand(-1); } 213 Operand ReceiverOperand() const { return ParameterOperand(-1); }
214
212 Operand FunctionOperand() const { 215 Operand FunctionOperand() const {
213 return Operand(ebp, JavaScriptFrameConstants::kFunctionOffset); 216 return Operand(ebp, JavaScriptFrameConstants::kFunctionOffset);
214 } 217 }
215 218
216 Operand ContextOperand(Register context, int index) const { 219 static Operand ContextOperand(Register context, int index) {
217 return Operand(context, Context::SlotOffset(index)); 220 return Operand(context, Context::SlotOffset(index));
218 } 221 }
219 222
220 Operand SlotOperand(Slot* slot, Register tmp); 223 static Operand SlotOperand(MacroAssembler* masm,
224 Scope* scope,
225 Slot* slot,
226 Register tmp);
227
228 Operand SlotOperand(Slot* slot, Register tmp) {
229 return SlotOperand(masm_, scope_, slot, tmp);
230 }
221 231
222 void LoadCondition(Expression* x, 232 void LoadCondition(Expression* x,
223 CodeGenState::AccessType access, 233 CodeGenState::AccessType access,
224 Label* true_target, 234 Label* true_target,
225 Label* false_target, 235 Label* false_target,
226 bool force_cc); 236 bool force_cc);
227 void Load(Expression* x, 237 void Load(Expression* x,
228 CodeGenState::AccessType access = CodeGenState::LOAD); 238 CodeGenState::AccessType access = CodeGenState::LOAD);
229 void LoadGlobal(); 239 void LoadGlobal();
230 240
231 // Special code for typeof expressions: Unfortunately, we must 241 // Special code for typeof expressions: Unfortunately, we must
232 // be careful when loading the expression in 'typeof' 242 // be careful when loading the expression in 'typeof'
233 // expressions. We are not allowed to throw reference errors for 243 // expressions. We are not allowed to throw reference errors for
234 // non-existing properties of the global object, so we must make it 244 // non-existing properties of the global object, so we must make it
235 // look like an explicit property access, instead of an access 245 // look like an explicit property access, instead of an access
236 // through the context chain. 246 // through the context chain.
237 void LoadTypeofExpression(Expression* x); 247 void LoadTypeofExpression(Expression* x);
238 248
239 // References 249 // References
240 void AccessReference(Reference* ref, CodeGenState::AccessType access);
241 250
242 void GetValue(Reference* ref) { AccessReference(ref, CodeGenState::LOAD); } 251 // Generate code to fetch the value of a reference. The reference is
243 void SetValue(Reference* ref) { AccessReference(ref, CodeGenState::STORE); } 252 // expected to be on top of the expression stack. It is left in place and
253 // its value is pushed on top of it.
254 void GetValue(Reference* ref);
255
256 // Generate code to store a value in a reference. The stored value is
257 // expected on top of the expression stack, with the reference immediately
258 // below it. The expression stack is left unchanged.
259 void SetValue(Reference* ref) {
260 ASSERT(!has_cc());
261 ASSERT(!ref->is_illegal());
262 ref->expression()->GenerateStoreCode(masm_, scope_, ref, false);
263 }
264
265 // Same as SetValue, used to set the initial value of a constant.
244 void InitConst(Reference* ref) { 266 void InitConst(Reference* ref) {
245 AccessReference(ref, CodeGenState::INIT_CONST); 267 ASSERT(!has_cc());
268 ASSERT(!ref->is_illegal());
269 ref->expression()->GenerateStoreCode(masm_, scope_, ref, true);
246 } 270 }
247 271
272 // Generate code to fetch a value from a property of a reference. The
273 // reference is expected on top of the expression stack. It is left in
274 // place and its value is pushed on top of it.
275 void GetReferenceProperty(Expression* key);
276
277 // Generate code to store a value in a property of a reference. The
278 // stored value is expected on top of the expression stack, with the
279 // reference immediately below it. The expression stack is left
280 // unchanged.
281 static void SetReferenceProperty(MacroAssembler* masm,
282 Reference* ref,
283 Expression* key);
284
248 void ToBoolean(Label* true_target, Label* false_target); 285 void ToBoolean(Label* true_target, Label* false_target);
249 286
250
251 // Access property from the reference (must be at the TOS).
252 void AccessReferenceProperty(Expression* key,
253 CodeGenState::AccessType access);
254
255 void GenericBinaryOperation( 287 void GenericBinaryOperation(
256 Token::Value op, 288 Token::Value op,
257 const OverwriteMode overwrite_mode = NO_OVERWRITE); 289 const OverwriteMode overwrite_mode = NO_OVERWRITE);
258 void Comparison(Condition cc, bool strict = false); 290 void Comparison(Condition cc, bool strict = false);
259 291
260 // Inline small integer literals. To prevent long attacker-controlled byte 292 // Inline small integer literals. To prevent long attacker-controlled byte
261 // sequences, we only inline small Smi:s. 293 // sequences, we only inline small Smi:s.
262 static const int kMaxSmiInlinedBits = 16; 294 static const int kMaxSmiInlinedBits = 16;
263 bool IsInlineSmi(Literal* literal); 295 bool IsInlineSmi(Literal* literal);
264 void SmiComparison(Condition cc, Handle<Object> value, bool strict = false); 296 void SmiComparison(Condition cc, Handle<Object> value, bool strict = false);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 341
310 virtual void GenerateArgumentsLength(ZoneList<Expression*>* args); 342 virtual void GenerateArgumentsLength(ZoneList<Expression*>* args);
311 virtual void GenerateArgumentsAccess(ZoneList<Expression*>* args); 343 virtual void GenerateArgumentsAccess(ZoneList<Expression*>* args);
312 344
313 virtual void GenerateValueOf(ZoneList<Expression*>* args); 345 virtual void GenerateValueOf(ZoneList<Expression*>* args);
314 virtual void GenerateSetValueOf(ZoneList<Expression*>* args); 346 virtual void GenerateSetValueOf(ZoneList<Expression*>* args);
315 347
316 virtual void GenerateFastCharCodeAt(ZoneList<Expression*>* args); 348 virtual void GenerateFastCharCodeAt(ZoneList<Expression*>* args);
317 349
318 virtual void GenerateObjectEquals(ZoneList<Expression*>* args); 350 virtual void GenerateObjectEquals(ZoneList<Expression*>* args);
351
352 friend class Reference;
353 friend class Property;
354 friend class VariableProxy;
355 friend class Slot;
319 }; 356 };
320 357
321 358
322 // ----------------------------------------------------------------------------- 359 // -----------------------------------------------------------------------------
323 // Ia32CodeGenerator implementation 360 // Ia32CodeGenerator implementation
324 361
325 #define __ masm_-> 362 #define __ masm_->
326 363
327 364
328 Handle<Code> Ia32CodeGenerator::MakeCode(FunctionLiteral* flit, 365 Handle<Code> Ia32CodeGenerator::MakeCode(FunctionLiteral* flit,
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
626 state_ = NULL; 663 state_ = NULL;
627 } 664 }
628 665
629 // Code generation state must be reset. 666 // Code generation state must be reset.
630 scope_ = NULL; 667 scope_ = NULL;
631 ASSERT(!has_cc()); 668 ASSERT(!has_cc());
632 ASSERT(state_ == NULL); 669 ASSERT(state_ == NULL);
633 } 670 }
634 671
635 672
636 Operand Ia32CodeGenerator::SlotOperand(Slot* slot, Register tmp) { 673 Operand Ia32CodeGenerator::SlotOperand(MacroAssembler* masm,
674 Scope* scope,
675 Slot* slot,
676 Register tmp) {
637 // Currently, this assertion will fail if we try to assign to 677 // Currently, this assertion will fail if we try to assign to
638 // a constant variable that is constant because it is read-only 678 // a constant variable that is constant because it is read-only
639 // (such as the variable referring to a named function expression). 679 // (such as the variable referring to a named function expression).
640 // We need to implement assignments to read-only variables. 680 // We need to implement assignments to read-only variables.
641 // Ideally, we should do this during AST generation (by converting 681 // Ideally, we should do this during AST generation (by converting
642 // such assignments into expression statements); however, in general 682 // such assignments into expression statements); however, in general
643 // we may not be able to make the decision until past AST generation, 683 // we may not be able to make the decision until past AST generation,
644 // that is when the entire program is known. 684 // that is when the entire program is known.
645 ASSERT(slot != NULL); 685 ASSERT(slot != NULL);
646 int index = slot->index(); 686 int index = slot->index();
647 switch (slot->type()) { 687 switch (slot->type()) {
648 case Slot::PARAMETER: return ParameterOperand(index); 688 case Slot::PARAMETER: return ParameterOperand(scope, index);
649 689
650 case Slot::LOCAL: { 690 case Slot::LOCAL: {
651 ASSERT(0 <= index && index < scope_->num_stack_slots()); 691 ASSERT(0 <= index && index < scope->num_stack_slots());
652 const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset; 692 const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset;
653 return Operand(ebp, kLocal0Offset - index * kPointerSize); 693 return Operand(ebp, kLocal0Offset - index * kPointerSize);
654 } 694 }
655 695
656 case Slot::CONTEXT: { 696 case Slot::CONTEXT: {
657 // Follow the context chain if necessary. 697 // Follow the context chain if necessary.
658 ASSERT(!tmp.is(esi)); // do not overwrite context register 698 ASSERT(!tmp.is(esi)); // do not overwrite context register
659 Register context = esi; 699 Register context = esi;
660 int chain_length = scope_->ContextChainLength(slot->var()->scope()); 700 int chain_length = scope->ContextChainLength(slot->var()->scope());
661 for (int i = chain_length; i-- > 0;) { 701 for (int i = chain_length; i-- > 0;) {
662 // Load the closure. 702 // Load the closure.
663 // (All contexts, even 'with' contexts, have a closure, 703 // (All contexts, even 'with' contexts, have a closure,
664 // and it is the same for all contexts inside a function. 704 // and it is the same for all contexts inside a function.
665 // There is no need to go to the function context first.) 705 // There is no need to go to the function context first.)
666 __ mov(tmp, ContextOperand(context, Context::CLOSURE_INDEX)); 706 masm->mov(tmp, ContextOperand(context, Context::CLOSURE_INDEX));
667 // Load the function context (which is the incoming, outer context). 707 // Load the function context (which is the incoming, outer context).
668 __ mov(tmp, FieldOperand(tmp, JSFunction::kContextOffset)); 708 masm->mov(tmp, FieldOperand(tmp, JSFunction::kContextOffset));
669 context = tmp; 709 context = tmp;
670 } 710 }
671 // We may have a 'with' context now. Get the function context. 711 // We may have a 'with' context now. Get the function context.
672 // (In fact this mov may never be the needed, since the scope analysis 712 // (In fact this mov may never be the needed, since the scope analysis
673 // may not permit a direct context access in this case and thus we are 713 // may not permit a direct context access in this case and thus we are
674 // always at a function context. However it is safe to dereference be- 714 // always at a function context. However it is safe to dereference be-
675 // cause the function context of a function context is itself. Before 715 // cause the function context of a function context is itself. Before
676 // deleting this mov we should try to create a counter-example first, 716 // deleting this mov we should try to create a counter-example first,
677 // though...) 717 // though...)
678 __ mov(tmp, ContextOperand(context, Context::FCONTEXT_INDEX)); 718 masm->mov(tmp, ContextOperand(context, Context::FCONTEXT_INDEX));
679 return ContextOperand(tmp, index); 719 return ContextOperand(tmp, index);
680 } 720 }
681 721
682 default: 722 default:
683 UNREACHABLE(); 723 UNREACHABLE();
684 return Operand(eax); 724 return Operand(eax);
685 } 725 }
686 } 726 }
687 727
688 728
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
845 __ pop(eax); 885 __ pop(eax);
846 __ mov(TOS, eax); 886 __ mov(TOS, eax);
847 } else { 887 } else {
848 __ pop(eax); 888 __ pop(eax);
849 __ add(Operand(esp), Immediate(size * kPointerSize)); 889 __ add(Operand(esp), Immediate(size * kPointerSize));
850 __ push(eax); 890 __ push(eax);
851 } 891 }
852 } 892 }
853 893
854 894
855 void Ia32CodeGenerator::AccessReference(Reference* ref, 895 void Ia32CodeGenerator::GetValue(Reference* ref) {
856 CodeGenState::AccessType access) {
857 ASSERT(!has_cc()); 896 ASSERT(!has_cc());
858 ASSERT(ref->type() != Reference::ILLEGAL); 897 ASSERT(ref->type() != Reference::ILLEGAL);
859 CodeGenState* old_state = state_; 898 CodeGenState* old_state = state_;
860 CodeGenState new_state(access, ref, true_target(), false_target()); 899 CodeGenState new_state(CodeGenState::LOAD, ref, true_target(),
900 false_target());
861 state_ = &new_state; 901 state_ = &new_state;
862 Visit(ref->expression()); 902 Visit(ref->expression());
863 state_ = old_state; 903 state_ = old_state;
864 } 904 }
865 905
866 906
907 void Property::GenerateStoreCode(MacroAssembler* masm,
908 Scope* scope,
909 Reference* ref,
910 bool is_const_init) {
911 Comment cmnt(masm, "[ Store to Property");
912 masm->RecordPosition(position());
913 Ia32CodeGenerator::SetReferenceProperty(masm, ref, key());
914 }
915
916
917 void VariableProxy::GenerateStoreCode(MacroAssembler* masm,
918 Scope* scope,
919 Reference* ref,
920 bool is_const_init) {
921
922 Comment cmnt(masm, "[ Store to VariableProxy");
923 Variable* node = var();
924
925 Expression* expr = node->rewrite();
926 if (expr != NULL) {
927 expr->GenerateStoreCode(masm, scope, ref, is_const_init);
928 } else {
929 ASSERT(node->is_global());
930 if (node->AsProperty() != NULL) {
931 masm->RecordPosition(node->AsProperty()->position());
932 }
933 Ia32CodeGenerator::SetReferenceProperty(masm, ref,
934 new Literal(node->name()));
935 }
936 }
937
938
939 void Slot::GenerateStoreCode(MacroAssembler* masm,
940 Scope* scope,
941 Reference* ref,
942 bool is_const_init) {
943 Comment cmnt(masm, "[ Store to Slot");
944
945 if (type() == Slot::LOOKUP) {
946 ASSERT(var()->mode() == Variable::DYNAMIC);
947
948 // For now, just do a runtime call.
949 masm->push(Operand(esi));
950 masm->push(Immediate(var()->name()));
951
952 if (is_const_init) {
953 // Same as the case for a normal store, but ignores attribute
954 // (e.g. READ_ONLY) of context slot so that we can initialize const
955 // properties (introduced via eval("const foo = (some expr);")). Also,
956 // uses the current function context instead of the top context.
957 //
958 // Note that we must declare the foo upon entry of eval(), via a
959 // context slot declaration, but we cannot initialize it at the same
960 // time, because the const declaration may be at the end of the eval
961 // code (sigh...) and the const variable may have been used before
962 // (where its value is 'undefined'). Thus, we can only do the
963 // initialization when we actually encounter the expression and when
964 // the expression operands are defined and valid, and thus we need the
965 // split into 2 operations: declaration of the context slot followed
966 // by initialization.
967 masm->CallRuntime(Runtime::kInitializeConstContextSlot, 3);
968 } else {
969 masm->CallRuntime(Runtime::kStoreContextSlot, 3);
970 }
971 // Storing a variable must keep the (new) value on the expression
972 // stack. This is necessary for compiling assignment expressions.
973 masm->push(eax);
974
975 } else {
976 ASSERT(var()->mode() != Variable::DYNAMIC);
977
978 Label exit;
979 if (is_const_init) {
980 ASSERT(var()->mode() == Variable::CONST);
981 // Only the first const initialization must be executed (the slot
982 // still contains 'the hole' value). When the assignment is executed,
983 // the code is identical to a normal store (see below).
984 Comment cmnt(masm, "[ Init const");
985 masm->mov(eax, Ia32CodeGenerator::SlotOperand(masm, scope, this, ecx));
986 masm->cmp(eax, Factory::the_hole_value());
987 masm->j(not_equal, &exit);
988 }
989
990 // We must execute the store.
991 // Storing a variable must keep the (new) value on the stack. This is
992 // necessary for compiling assignment expressions. ecx may be loaded
993 // with context; used below in RecordWrite.
994 //
995 // Note: We will reach here even with node->var()->mode() ==
996 // Variable::CONST because of const declarations which will initialize
997 // consts to 'the hole' value and by doing so, end up calling this
998 // code.
999 masm->pop(eax);
1000 masm->mov(Ia32CodeGenerator::SlotOperand(masm, scope, this, ecx), eax);
1001 masm->push(eax); // RecordWrite may destroy the value in eax.
1002 if (type() == Slot::CONTEXT) {
1003 // ecx is loaded with context when calling SlotOperand above.
1004 int offset = FixedArray::kHeaderSize + index() * kPointerSize;
1005 masm->RecordWrite(ecx, offset, eax, ebx);
1006 }
1007 masm->bind(&exit);
1008 }
1009 }
1010
1011
867 #undef __ 1012 #undef __
868 #define __ masm-> 1013 #define __ masm->
869 1014
870 class ToBooleanStub: public CodeStub { 1015 class ToBooleanStub: public CodeStub {
871 public: 1016 public:
872 ToBooleanStub() { } 1017 ToBooleanStub() { }
873 1018
874 void Generate(MacroAssembler* masm); 1019 void Generate(MacroAssembler* masm);
875 1020
876 private: 1021 private:
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
984 ToBooleanStub stub; 1129 ToBooleanStub stub;
985 __ CallStub(&stub); 1130 __ CallStub(&stub);
986 // Convert result (eax) to condition code. 1131 // Convert result (eax) to condition code.
987 __ test(eax, Operand(eax)); 1132 __ test(eax, Operand(eax));
988 1133
989 ASSERT(not_equal == not_zero); 1134 ASSERT(not_equal == not_zero);
990 cc_reg_ = not_equal; 1135 cc_reg_ = not_equal;
991 } 1136 }
992 1137
993 1138
994 void Ia32CodeGenerator::AccessReferenceProperty( 1139 void Ia32CodeGenerator::GetReferenceProperty(Expression* key) {
995 Expression* key,
996 CodeGenState::AccessType access) {
997 Reference::Type type = ref()->type(); 1140 Reference::Type type = ref()->type();
998 ASSERT(type != Reference::ILLEGAL); 1141 ASSERT(!ref()->is_illegal());
iposva 2008/09/10 18:01:44 Same nit as on ARM: Don't you want to assert befor
Kevin Millikin (Chromium) 2008/09/11 07:15:55 Done.
999 1142
1000 // TODO(1241834): Make sure that this is sufficient. If there is a chance 1143 // TODO(1241834): Make sure that this it is safe to ignore the distinction
1001 // that reference errors can be thrown below, we must distinguish 1144 // between access types LOAD and LOAD_TYPEOF_EXPR. If there is a chance
1002 // between the 2 kinds of loads (typeof expression loads must not 1145 // that reference errors can be thrown below, we must distinguish between
1003 // throw a reference error). 1146 // the two kinds of loads (typeof expression loads must not throw a
1004 bool is_load = (access == CodeGenState::LOAD || 1147 // reference error).
1005 access == CodeGenState::LOAD_TYPEOF_EXPR);
1006
1007 if (type == Reference::NAMED) { 1148 if (type == Reference::NAMED) {
1008 // Compute the name of the property. 1149 // Compute the name of the property.
1009 Literal* literal = key->AsLiteral(); 1150 Literal* literal = key->AsLiteral();
1010 Handle<String> name(String::cast(*literal->handle())); 1151 Handle<String> name(String::cast(*literal->handle()));
1011 1152
1012 // Call the appropriate IC code. 1153 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
1013 if (is_load) { 1154 Variable* var = ref()->expression()->AsVariableProxy()->AsVariable();
1014 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 1155 // Setup the name register.
1015 Variable* var = ref()->expression()->AsVariableProxy()->AsVariable(); 1156 __ Set(ecx, Immediate(name));
1016 // Setup the name register. 1157 if (var != NULL) {
1017 __ Set(ecx, Immediate(name)); 1158 ASSERT(var->is_global());
1018 if (var != NULL) { 1159 __ call(ic, code_target_context);
1019 ASSERT(var->is_global());
1020 __ call(ic, code_target_context);
1021 } else {
1022 __ call(ic, code_target);
1023 }
1024 } else { 1160 } else {
1025 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1026 // TODO(1222589): Make the IC grab the values from the stack.
1027 __ pop(eax);
1028 // Setup the name register.
1029 __ Set(ecx, Immediate(name));
1030 __ call(ic, code_target); 1161 __ call(ic, code_target);
1031 } 1162 }
1032 } else { 1163 } else {
1033 // Access keyed property. 1164 // Access keyed property.
1034 ASSERT(type == Reference::KEYED); 1165 ASSERT(type == Reference::KEYED);
1035 1166
1036 if (is_load) { 1167 // Call IC code.
1037 // Call IC code. 1168 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1038 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 1169 Variable* var = ref()->expression()->AsVariableProxy()->AsVariable();
1039 Variable* var = ref()->expression()->AsVariableProxy()->AsVariable(); 1170 if (var != NULL) {
1040 if (var != NULL) { 1171 ASSERT(var->is_global());
1041 ASSERT(var->is_global()); 1172 __ call(ic, code_target_context);
1042 __ call(ic, code_target_context);
1043 } else {
1044 __ call(ic, code_target);
1045 }
1046 } else { 1173 } else {
1047 // Call IC code.
1048 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
1049 // TODO(1222589): Make the IC grab the values from the stack.
1050 __ pop(eax);
1051 __ call(ic, code_target); 1174 __ call(ic, code_target);
1052 } 1175 }
1053 } 1176 }
1054 __ push(eax); // IC call leaves result in eax, push it out 1177 __ push(eax); // IC call leaves result in eax, push it out
1055 } 1178 }
1056 1179
1057 1180
1181 void Ia32CodeGenerator::SetReferenceProperty(MacroAssembler* masm,
1182 Reference* ref,
1183 Expression* key) {
1184 Reference::Type type = ref->type();
1185 ASSERT(!ref->is_illegal());
1186
1187 if (type == Reference::NAMED) {
1188 // Compute the name of the property.
1189 Literal* literal = key->AsLiteral();
1190 Handle<String> name(String::cast(*literal->handle()));
1191
1192 // Call the appropriate IC code.
1193 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1194 // TODO(1222589): Make the IC grab the values from the stack.
1195 masm->pop(eax);
1196 // Setup the name register.
1197 masm->Set(ecx, Immediate(name));
1198 masm->call(ic, code_target);
1199 } else {
1200 // Access keyed property.
1201 ASSERT(type == Reference::KEYED);
1202
1203 // Call IC code.
1204 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
1205 // TODO(1222589): Make the IC grab the values from the stack.
1206 masm->pop(eax);
1207 masm->call(ic, code_target);
1208 }
1209 masm->push(eax); // IC call leaves result in eax, push it out
1210 }
1211
1212
1058 #undef __ 1213 #undef __
1059 #define __ masm-> 1214 #define __ masm->
1060 1215
1061 1216
1062 class FloatingPointHelper : public AllStatic { 1217 class FloatingPointHelper : public AllStatic {
1063 public: 1218 public:
1064 // Code pattern for loading floating point values. Input values must 1219 // Code pattern for loading floating point values. Input values must
1065 // be either smi or heap number objects (fp values). Requirements: 1220 // be either smi or heap number objects (fp values). Requirements:
1066 // operand_1 on TOS+1 , operand_2 on TOS+2; Returns operands as 1221 // operand_1 on TOS+1 , operand_2 on TOS+2; Returns operands as
1067 // floating point numbers on FPU stack. 1222 // floating point numbers on FPU stack.
(...skipping 2250 matching lines...) Expand 10 before | Expand all | Expand 10 after
3318 __ bind(&then); 3473 __ bind(&then);
3319 Load(node->then_expression(), access()); 3474 Load(node->then_expression(), access());
3320 __ jmp(&exit); 3475 __ jmp(&exit);
3321 __ bind(&else_); 3476 __ bind(&else_);
3322 Load(node->else_expression(), access()); 3477 Load(node->else_expression(), access());
3323 __ bind(&exit); 3478 __ bind(&exit);
3324 } 3479 }
3325 3480
3326 3481
3327 void Ia32CodeGenerator::VisitSlot(Slot* node) { 3482 void Ia32CodeGenerator::VisitSlot(Slot* node) {
3483 ASSERT(access() != CodeGenState::UNDEFINED);
3328 Comment cmnt(masm_, "[ Slot"); 3484 Comment cmnt(masm_, "[ Slot");
3329 3485
3330 if (node->type() == Slot::LOOKUP) { 3486 if (node->type() == Slot::LOOKUP) {
3331 ASSERT(node->var()->mode() == Variable::DYNAMIC); 3487 ASSERT(node->var()->mode() == Variable::DYNAMIC);
3332 3488
3333 // For now, just do a runtime call. 3489 // For now, just do a runtime call.
3334 __ push(Operand(esi)); 3490 __ push(Operand(esi));
3335 __ push(Immediate(node->var()->name())); 3491 __ push(Immediate(node->var()->name()));
3336 3492
3337 switch (access()) { 3493 if (access() == CodeGenState::LOAD) {
3338 case CodeGenState::UNDEFINED: 3494 __ CallRuntime(Runtime::kLoadContextSlot, 2);
3339 UNREACHABLE(); 3495 } else {
3340 break; 3496 // CodeGenState::LOAD_TYPEOF_EXPR.
iposva 2008/09/10 18:01:44 Same comment as on ARM: Please assert that the Cod
Kevin Millikin (Chromium) 2008/09/11 07:15:55 Done.
3341 3497 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
3342 case CodeGenState::LOAD:
3343 __ CallRuntime(Runtime::kLoadContextSlot, 2);
3344 __ push(eax);
3345 // result (TOS) is the value that was loaded
3346 break;
3347
3348 case CodeGenState::LOAD_TYPEOF_EXPR:
3349 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
3350 __ push(eax);
3351 // result (TOS) is the value that was loaded
3352 break;
3353
3354 case CodeGenState::STORE:
3355 // Storing a variable must keep the (new) value on the
3356 // stack. This is necessary for compiling assignment
3357 // expressions.
3358 __ CallRuntime(Runtime::kStoreContextSlot, 3);
3359 __ push(eax);
3360 // result (TOS) is the value that was stored
3361 break;
3362
3363 case CodeGenState::INIT_CONST:
3364 // Same as STORE but ignores attribute (e.g. READ_ONLY) of
3365 // context slot so that we can initialize const properties
3366 // (introduced via eval("const foo = (some expr);")). Also,
3367 // uses the current function context instead of the top
3368 // context.
3369 //
3370 // Note that we must declare the foo upon entry of eval(),
3371 // via a context slot declaration, but we cannot initialize
3372 // it at the same time, because the const declaration may
3373 // be at the end of the eval code (sigh...) and the const
3374 // variable may have been used before (where its value is
3375 // 'undefined'). Thus, we can only do the initialization
3376 // when we actually encounter the expression and when the
3377 // expression operands are defined and valid, and thus we
3378 // need the split into 2 operations: declaration of the
3379 // context slot followed by initialization.
3380 //
3381 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
3382 __ push(eax);
3383 break;
3384 } 3498 }
3499 __ push(eax);
3385 3500
3386 } else { 3501 } else {
3387 // Note: We would like to keep the assert below, but it fires because 3502 // Note: We would like to keep the assert below, but it fires because of
3388 // of some nasty code in LoadTypeofExpression() which should be removed... 3503 // some nasty code in LoadTypeofExpression() which should be removed...
3389 // ASSERT(node->var()->mode() != Variable::DYNAMIC); 3504 // ASSERT(node->var()->mode() != Variable::DYNAMIC);
3390 3505
3391 switch (access()) { 3506 if (node->var()->mode() == Variable::CONST) {
3392 case CodeGenState::UNDEFINED: 3507 // Const slots may contain 'the hole' value (the constant hasn't been
3393 UNREACHABLE(); 3508 // initialized yet) which needs to be converted into the 'undefined'
3394 break; 3509 // value.
3395 3510 Comment cmnt(masm_, "[ Load const");
3396 case CodeGenState::LOAD: // fall through 3511 Label L;
3397 case CodeGenState::LOAD_TYPEOF_EXPR: 3512 __ mov(eax, SlotOperand(node, ecx));
3398 if (node->var()->mode() == Variable::CONST) { 3513 __ cmp(eax, Factory::the_hole_value());
3399 // Const slots may contain 'the hole' value (the constant hasn't 3514 __ j(not_equal, &L);
3400 // been initialized yet) which needs to be converted into the 3515 __ mov(eax, Factory::undefined_value());
3401 // 'undefined' value. 3516 __ bind(&L);
3402 Comment cmnt(masm_, "[ Load const"); 3517 __ push(eax);
3403 Label L; 3518 } else {
3404 __ mov(eax, SlotOperand(node, ecx)); 3519 __ push(SlotOperand(node, ecx));
3405 __ cmp(eax, Factory::the_hole_value());
3406 __ j(not_equal, &L);
3407 __ mov(eax, Factory::undefined_value());
3408 __ bind(&L);
3409 __ push(eax);
3410 } else {
3411 __ push(SlotOperand(node, ecx));
3412 }
3413 break;
3414
3415 case CodeGenState::INIT_CONST:
3416 ASSERT(node->var()->mode() == Variable::CONST);
3417 // Only the first const initialization must be executed (the slot
3418 // still contains 'the hole' value). When the assignment is executed,
3419 // the code is identical to a normal store (see below).
3420 { Comment cmnt(masm_, "[ Init const");
3421 Label L;
3422 __ mov(eax, SlotOperand(node, ecx));
3423 __ cmp(eax, Factory::the_hole_value());
3424 __ j(not_equal, &L);
3425 // We must execute the store.
3426 __ mov(eax, TOS);
3427 __ mov(SlotOperand(node, ecx), eax);
3428 if (node->type() == Slot::CONTEXT) {
3429 // ecx is loaded with context when calling SlotOperand above.
3430 int offset = FixedArray::kHeaderSize + node->index() * kPointerSize;
3431 __ RecordWrite(ecx, offset, eax, ebx);
3432 }
3433 __ bind(&L);
3434 }
3435 break;
3436
3437 case CodeGenState::STORE:
3438 // Storing a variable must keep the (new) value on the stack. This
3439 // is necessary for compiling assignment expressions.
3440 // ecx may be loaded with context; used below in RecordWrite.
3441 //
3442 // Note: We will reach here even with node->var()->mode() ==
3443 // Variable::CONST because of const declarations which will
3444 // initialize consts to 'the hole' value and by doing so, end
3445 // up calling this code.
3446 __ pop(eax);
3447 __ mov(SlotOperand(node, ecx), eax);
3448 __ push(eax); // RecordWrite may destroy the value in eax.
3449 if (node->type() == Slot::CONTEXT) {
3450 // ecx is loaded with context when calling SlotOperand above.
3451 int offset = FixedArray::kHeaderSize + node->index() * kPointerSize;
3452 __ RecordWrite(ecx, offset, eax, ebx);
3453 }
3454 break;
3455 } 3520 }
3456 } 3521 }
3457 } 3522 }
3458 3523
3459 3524
3460 void Ia32CodeGenerator::VisitVariableProxy(VariableProxy* proxy_node) { 3525 void Ia32CodeGenerator::VisitVariableProxy(VariableProxy* node) {
3461 Comment cmnt(masm_, "[ VariableProxy"); 3526 Comment cmnt(masm_, "[ VariableProxy");
3462 Variable* node = proxy_node->var(); 3527 Variable* var_node = node->var();
3463 3528
3464 Expression* x = node->rewrite(); 3529 Expression* expr = var_node->rewrite();
3465 if (x != NULL) { 3530 if (expr != NULL) {
3466 Visit(x); 3531 Visit(expr);
3467 return; 3532 } else {
3468 } 3533 ASSERT(var_node->is_global());
3469 3534 if (is_referenced()) {
3470 ASSERT(node->is_global()); 3535 if (var_node->AsProperty() != NULL) {
3471 if (is_referenced()) { 3536 __ RecordPosition(var_node->AsProperty()->position());
3472 if (node->AsProperty() != NULL) { 3537 }
3473 __ RecordPosition(node->AsProperty()->position()); 3538 GetReferenceProperty(new Literal(var_node->name()));
3539 } else {
3540 Reference property(this, node);
3541 GetValue(&property);
3474 } 3542 }
3475 AccessReferenceProperty(new Literal(node->name()), access());
3476
3477 } else {
3478 // All stores are through references.
3479 ASSERT(access() != CodeGenState::STORE);
3480 Reference property(this, proxy_node);
3481 GetValue(&property);
3482 } 3543 }
3483 } 3544 }
3484 3545
3485 3546
3486 void Ia32CodeGenerator::VisitLiteral(Literal* node) { 3547 void Ia32CodeGenerator::VisitLiteral(Literal* node) {
3487 Comment cmnt(masm_, "[ Literal"); 3548 Comment cmnt(masm_, "[ Literal");
3488 if (node->handle()->IsSmi() && !IsInlineSmi(node)) { 3549 if (node->handle()->IsSmi() && !IsInlineSmi(node)) {
3489 // To prevent long attacker-controlled byte sequences in code, larger 3550 // To prevent long attacker-controlled byte sequences in code, larger
3490 // Smis are loaded in two steps. 3551 // Smis are loaded in two steps.
3491 int bits = reinterpret_cast<int>(*node->handle()); 3552 int bits = reinterpret_cast<int>(*node->handle());
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
3777 __ CallRuntime(Runtime::kThrow, 1); 3838 __ CallRuntime(Runtime::kThrow, 1);
3778 __ push(eax); 3839 __ push(eax);
3779 } 3840 }
3780 3841
3781 3842
3782 void Ia32CodeGenerator::VisitProperty(Property* node) { 3843 void Ia32CodeGenerator::VisitProperty(Property* node) {
3783 Comment cmnt(masm_, "[ Property"); 3844 Comment cmnt(masm_, "[ Property");
3784 3845
3785 if (is_referenced()) { 3846 if (is_referenced()) {
3786 __ RecordPosition(node->position()); 3847 __ RecordPosition(node->position());
3787 AccessReferenceProperty(node->key(), access()); 3848 GetReferenceProperty(node->key());
3788 } else { 3849 } else {
3789 // All stores are through references.
3790 ASSERT(access() != CodeGenState::STORE);
3791 Reference property(this, node); 3850 Reference property(this, node);
3792 __ RecordPosition(node->position()); 3851 __ RecordPosition(node->position());
3793 GetValue(&property); 3852 GetValue(&property);
3794 } 3853 }
3795 } 3854 }
3796 3855
3797 3856
3798 void Ia32CodeGenerator::VisitCall(Call* node) { 3857 void Ia32CodeGenerator::VisitCall(Call* node) {
3799 Comment cmnt(masm_, "[ Call"); 3858 Comment cmnt(masm_, "[ Call");
3800 3859
(...skipping 1585 matching lines...) Expand 10 before | Expand all | Expand 10 after
5386 bool is_eval) { 5445 bool is_eval) {
5387 Handle<Code> code = Ia32CodeGenerator::MakeCode(fun, script, is_eval); 5446 Handle<Code> code = Ia32CodeGenerator::MakeCode(fun, script, is_eval);
5388 if (!code.is_null()) { 5447 if (!code.is_null()) {
5389 Counters::total_compiled_code_size.Increment(code->instruction_size()); 5448 Counters::total_compiled_code_size.Increment(code->instruction_size());
5390 } 5449 }
5391 return code; 5450 return code;
5392 } 5451 }
5393 5452
5394 5453
5395 } } // namespace v8::internal 5454 } } // 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