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

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

Issue 3002: Change the code generator state constructor to implicitly push the state on... (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
« no previous file with comments | « 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 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 100
101 bool is_illegal() const { return type_ == ILLEGAL; } 101 bool is_illegal() const { return type_ == ILLEGAL; }
102 102
103 private: 103 private:
104 Ia32CodeGenerator* cgen_; 104 Ia32CodeGenerator* cgen_;
105 Expression* expression_; 105 Expression* expression_;
106 Type type_; 106 Type type_;
107 }; 107 };
108 108
109 109
110 // ----------------------------------------------------------------------------- 110 // -------------------------------------------------------------------------
111 // Code generation state 111 // Code generation state
112 112
113 // The state is passed down the AST by the code generator. It is passed
114 // implicitly (in a member variable) to the non-static code generator member
115 // functions, and explicitly (as an argument) to the static member functions
116 // and the AST node member functions.
117 //
118 // The state is threaded through the call stack. Constructing a state
119 // implicitly pushes it on the owning code generator's stack of states, and
120 // destroying one implicitly pops it.
121
113 class CodeGenState BASE_EMBEDDED { 122 class CodeGenState BASE_EMBEDDED {
114 public: 123 public:
115 enum AccessType { 124 enum AccessType {
116 UNDEFINED, 125 UNDEFINED,
117 LOAD, 126 LOAD,
118 LOAD_TYPEOF_EXPR 127 LOAD_TYPEOF_EXPR
119 }; 128 };
120 129
121 CodeGenState() 130 // Create an initial code generator state. Destroying the initial state
122 : access_(UNDEFINED), 131 // leaves the code generator with a NULL state.
123 ref_(NULL), 132 CodeGenState(Ia32CodeGenerator* owner);
124 true_target_(NULL),
125 false_target_(NULL) {
126 }
127 133
128 CodeGenState(AccessType access, 134 // Create a code generator state based on a code generator's current
129 Reference* ref, 135 // state. The new state has its own access type and pair of branch
136 // labels, and no reference.
137 CodeGenState(Ia32CodeGenerator* owner,
138 AccessType access,
130 Label* true_target, 139 Label* true_target,
131 Label* false_target) 140 Label* false_target);
132 : access_(access), 141
133 ref_(ref), 142 // Create a code generator state based on a code generator's current
134 true_target_(true_target), 143 // state. The new state has an access type of LOAD, its own reference,
135 false_target_(false_target) { 144 // and inherits the pair of branch labels of the current state.
136 } 145 CodeGenState(Ia32CodeGenerator* owner, Reference* ref);
146
147 // Destroy a code generator state and restore the owning code generator's
148 // previous state.
149 ~CodeGenState();
137 150
138 AccessType access() const { return access_; } 151 AccessType access() const { return access_; }
139 Reference* ref() const { return ref_; } 152 Reference* ref() const { return ref_; }
140 Label* true_target() const { return true_target_; } 153 Label* true_target() const { return true_target_; }
141 Label* false_target() const { return false_target_; } 154 Label* false_target() const { return false_target_; }
142 155
143 private: 156 private:
157 Ia32CodeGenerator* owner_;
144 AccessType access_; 158 AccessType access_;
145 Reference* ref_; 159 Reference* ref_;
146 Label* true_target_; 160 Label* true_target_;
147 Label* false_target_; 161 Label* false_target_;
162 CodeGenState* previous_;
148 }; 163 };
149 164
150 165
151 // ----------------------------------------------------------------------------- 166 // -----------------------------------------------------------------------------
152 // Ia32CodeGenerator 167 // Ia32CodeGenerator
153 168
154 class Ia32CodeGenerator: public CodeGenerator { 169 class Ia32CodeGenerator: public CodeGenerator {
155 public: 170 public:
156 static Handle<Code> MakeCode(FunctionLiteral* fun, 171 static Handle<Code> MakeCode(FunctionLiteral* fun,
157 Handle<Script> script, 172 Handle<Script> script,
158 bool is_eval); 173 bool is_eval);
159 174
160 MacroAssembler* masm() { return masm_; } 175 MacroAssembler* masm() { return masm_; }
161 176
177 CodeGenState* state() { return state_; }
178 void set_state(CodeGenState* state) { state_ = state; }
179
162 private: 180 private:
163 // Assembler 181 // Assembler
164 MacroAssembler* masm_; // to generate code 182 MacroAssembler* masm_; // to generate code
165 183
166 // Code generation state 184 // Code generation state
167 Scope* scope_; 185 Scope* scope_;
168 Condition cc_reg_; 186 Condition cc_reg_;
169 CodeGenState* state_; 187 CodeGenState* state_;
170 bool is_inside_try_; 188 bool is_inside_try_;
171 int break_stack_height_; 189 int break_stack_height_;
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 // non-existing properties of the global object, so we must make it 262 // non-existing properties of the global object, so we must make it
245 // look like an explicit property access, instead of an access 263 // look like an explicit property access, instead of an access
246 // through the context chain. 264 // through the context chain.
247 void LoadTypeofExpression(Expression* x); 265 void LoadTypeofExpression(Expression* x);
248 266
249 // References 267 // References
250 268
251 // Generate code to fetch the value of a reference. The reference is 269 // Generate code to fetch the value of a reference. The reference is
252 // expected to be on top of the expression stack. It is left in place and 270 // expected to be on top of the expression stack. It is left in place and
253 // its value is pushed on top of it. 271 // its value is pushed on top of it.
254 void GetValue(Reference* ref); 272 void GetValue(Reference* ref) {
273 ASSERT(!has_cc());
274 ASSERT(!ref->is_illegal());
275 CodeGenState new_state(this, ref);
276 Visit(ref->expression());
277 }
255 278
256 // Generate code to store a value in a reference. The stored value is 279 // 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 280 // expected on top of the expression stack, with the reference immediately
258 // below it. The expression stack is left unchanged. 281 // below it. The expression stack is left unchanged.
259 void SetValue(Reference* ref) { 282 void SetValue(Reference* ref) {
260 ASSERT(!has_cc()); 283 ASSERT(!has_cc());
261 ASSERT(!ref->is_illegal()); 284 ASSERT(!ref->is_illegal());
262 ref->expression()->GenerateStoreCode(masm_, scope_, ref, NOT_CONST_INIT); 285 ref->expression()->GenerateStoreCode(masm_, scope_, ref, NOT_CONST_INIT);
263 } 286 }
264 287
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 372
350 virtual void GenerateObjectEquals(ZoneList<Expression*>* args); 373 virtual void GenerateObjectEquals(ZoneList<Expression*>* args);
351 374
352 friend class Reference; 375 friend class Reference;
353 friend class Property; 376 friend class Property;
354 friend class VariableProxy; 377 friend class VariableProxy;
355 friend class Slot; 378 friend class Slot;
356 }; 379 };
357 380
358 381
382 // -------------------------------------------------------------------------
383 // CodeGenState implementation.
384
385 CodeGenState::CodeGenState(Ia32CodeGenerator* owner)
386 : owner_(owner),
387 access_(UNDEFINED),
388 ref_(NULL),
389 true_target_(NULL),
390 false_target_(NULL),
391 previous_(NULL) {
392 owner_->set_state(this);
393 }
394
395
396 CodeGenState::CodeGenState(Ia32CodeGenerator* owner,
397 AccessType access,
398 Label* true_target,
399 Label* false_target)
400 : owner_(owner),
401 access_(access),
402 ref_(NULL),
403 true_target_(true_target),
404 false_target_(false_target),
405 previous_(owner->state()) {
406 owner_->set_state(this);
407 }
408
409
410 CodeGenState::CodeGenState(Ia32CodeGenerator* owner, Reference* ref)
411 : owner_(owner),
412 access_(LOAD),
413 ref_(ref),
414 true_target_(owner->state()->true_target_),
415 false_target_(owner->state()->false_target_),
416 previous_(owner->state()) {
417 owner_->set_state(this);
418 }
419
420
421 CodeGenState::~CodeGenState() {
422 ASSERT(owner_->state() == this);
423 owner_->set_state(previous_);
424 }
425
426
359 // ----------------------------------------------------------------------------- 427 // -----------------------------------------------------------------------------
360 // Ia32CodeGenerator implementation 428 // Ia32CodeGenerator implementation
361 429
362 #define __ masm_-> 430 #define __ masm_->
363 431
364 432
365 Handle<Code> Ia32CodeGenerator::MakeCode(FunctionLiteral* flit, 433 Handle<Code> Ia32CodeGenerator::MakeCode(FunctionLiteral* flit,
366 Handle<Script> script, 434 Handle<Script> script,
367 bool is_eval) { 435 bool is_eval) {
368 #ifdef ENABLE_DISASSEMBLER 436 #ifdef ENABLE_DISASSEMBLER
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 535
468 536
469 void Ia32CodeGenerator::GenCode(FunctionLiteral* fun) { 537 void Ia32CodeGenerator::GenCode(FunctionLiteral* fun) {
470 // Record the position for debugging purposes. 538 // Record the position for debugging purposes.
471 __ RecordPosition(fun->start_position()); 539 __ RecordPosition(fun->start_position());
472 540
473 Scope* scope = fun->scope(); 541 Scope* scope = fun->scope();
474 ZoneList<Statement*>* body = fun->body(); 542 ZoneList<Statement*>* body = fun->body();
475 543
476 // Initialize state. 544 // Initialize state.
477 { CodeGenState state; 545 { CodeGenState state(this);
478 state_ = &state;
479 scope_ = scope; 546 scope_ = scope;
480 cc_reg_ = no_condition; 547 cc_reg_ = no_condition;
481 548
482 // Entry 549 // Entry
483 // stack: function, receiver, arguments, return address 550 // stack: function, receiver, arguments, return address
484 // esp: stack pointer 551 // esp: stack pointer
485 // ebp: frame pointer 552 // ebp: frame pointer
486 // edi: caller's parameter pointer 553 // edi: caller's parameter pointer
487 // esi: callee's context 554 // esi: callee's context
488 555
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
652 VisitStatements(body); 719 VisitStatements(body);
653 720
654 // Generate a return statement if necessary. 721 // Generate a return statement if necessary.
655 if (body->is_empty() || body->last()->AsReturnStatement() == NULL) { 722 if (body->is_empty() || body->last()->AsReturnStatement() == NULL) {
656 Literal undefined(Factory::undefined_value()); 723 Literal undefined(Factory::undefined_value());
657 ReturnStatement statement(&undefined); 724 ReturnStatement statement(&undefined);
658 statement.set_statement_pos(fun->end_position()); 725 statement.set_statement_pos(fun->end_position());
659 VisitReturnStatement(&statement); 726 VisitReturnStatement(&statement);
660 } 727 }
661 } 728 }
662
663 state_ = NULL;
664 } 729 }
665 730
666 // Code generation state must be reset. 731 // Code generation state must be reset.
667 scope_ = NULL; 732 scope_ = NULL;
668 ASSERT(!has_cc()); 733 ASSERT(!has_cc());
669 ASSERT(state_ == NULL); 734 ASSERT(state_ == NULL);
670 } 735 }
671 736
672 737
673 Operand Ia32CodeGenerator::SlotOperand(MacroAssembler* masm, 738 Operand Ia32CodeGenerator::SlotOperand(MacroAssembler* masm,
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
733 // has_cc() is true and cc_reg_ contains the condition to test for 'true'. 798 // has_cc() is true and cc_reg_ contains the condition to test for 'true'.
734 void Ia32CodeGenerator::LoadCondition(Expression* x, 799 void Ia32CodeGenerator::LoadCondition(Expression* x,
735 CodeGenState::AccessType access, 800 CodeGenState::AccessType access,
736 Label* true_target, 801 Label* true_target,
737 Label* false_target, 802 Label* false_target,
738 bool force_cc) { 803 bool force_cc) {
739 ASSERT(access == CodeGenState::LOAD || 804 ASSERT(access == CodeGenState::LOAD ||
740 access == CodeGenState::LOAD_TYPEOF_EXPR); 805 access == CodeGenState::LOAD_TYPEOF_EXPR);
741 ASSERT(!has_cc() && !is_referenced()); 806 ASSERT(!has_cc() && !is_referenced());
742 807
743 CodeGenState* old_state = state_; 808 { CodeGenState new_state(this, access, true_target, false_target);
744 CodeGenState new_state(access, NULL, true_target, false_target); 809 Visit(x);
745 state_ = &new_state; 810 }
746 Visit(x);
747 state_ = old_state;
748 if (force_cc && !has_cc()) { 811 if (force_cc && !has_cc()) {
749 ToBoolean(true_target, false_target); 812 ToBoolean(true_target, false_target);
750 } 813 }
751 ASSERT(has_cc() || !force_cc); 814 ASSERT(has_cc() || !force_cc);
752 } 815 }
753 816
754 817
755 void Ia32CodeGenerator::Load(Expression* x, CodeGenState::AccessType access) { 818 void Ia32CodeGenerator::Load(Expression* x, CodeGenState::AccessType access) {
756 ASSERT(access == CodeGenState::LOAD || 819 ASSERT(access == CodeGenState::LOAD ||
757 access == CodeGenState::LOAD_TYPEOF_EXPR); 820 access == CodeGenState::LOAD_TYPEOF_EXPR);
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
885 __ pop(eax); 948 __ pop(eax);
886 __ mov(TOS, eax); 949 __ mov(TOS, eax);
887 } else { 950 } else {
888 __ pop(eax); 951 __ pop(eax);
889 __ add(Operand(esp), Immediate(size * kPointerSize)); 952 __ add(Operand(esp), Immediate(size * kPointerSize));
890 __ push(eax); 953 __ push(eax);
891 } 954 }
892 } 955 }
893 956
894 957
895 void Ia32CodeGenerator::GetValue(Reference* ref) {
896 ASSERT(!has_cc());
897 ASSERT(ref->type() != Reference::ILLEGAL);
898 CodeGenState* old_state = state_;
899 CodeGenState new_state(CodeGenState::LOAD, ref, true_target(),
900 false_target());
901 state_ = &new_state;
902 Visit(ref->expression());
903 state_ = old_state;
904 }
905
906
907 void Property::GenerateStoreCode(MacroAssembler* masm, 958 void Property::GenerateStoreCode(MacroAssembler* masm,
908 Scope* scope, 959 Scope* scope,
909 Reference* ref, 960 Reference* ref,
910 InitState init_state) { 961 InitState init_state) {
911 Comment cmnt(masm, "[ Store to Property"); 962 Comment cmnt(masm, "[ Store to Property");
912 masm->RecordPosition(position()); 963 masm->RecordPosition(position());
913 Ia32CodeGenerator::SetReferenceProperty(masm, ref, key()); 964 Ia32CodeGenerator::SetReferenceProperty(masm, ref, key());
914 } 965 }
915 966
916 967
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
968 masm->CallRuntime(Runtime::kStoreContextSlot, 3); 1019 masm->CallRuntime(Runtime::kStoreContextSlot, 3);
969 } 1020 }
970 // Storing a variable must keep the (new) value on the expression 1021 // Storing a variable must keep the (new) value on the expression
971 // stack. This is necessary for compiling assignment expressions. 1022 // stack. This is necessary for compiling assignment expressions.
972 masm->push(eax); 1023 masm->push(eax);
973 1024
974 } else { 1025 } else {
975 ASSERT(var()->mode() != Variable::DYNAMIC); 1026 ASSERT(var()->mode() != Variable::DYNAMIC);
976 1027
977 Label exit; 1028 Label exit;
978 bool may_skip_write = false;
979 if (init_state == CONST_INIT) { 1029 if (init_state == CONST_INIT) {
980 ASSERT(var()->mode() == Variable::CONST); 1030 ASSERT(var()->mode() == Variable::CONST);
981 // Only the first const initialization must be executed (the slot 1031 // Only the first const initialization must be executed (the slot
982 // still contains 'the hole' value). When the assignment is executed, 1032 // still contains 'the hole' value). When the assignment is executed,
983 // the code is identical to a normal store (see below). 1033 // the code is identical to a normal store (see below).
984 Comment cmnt(masm, "[ Init const"); 1034 Comment cmnt(masm, "[ Init const");
985 masm->mov(eax, Ia32CodeGenerator::SlotOperand(masm, scope, this, ecx)); 1035 masm->mov(eax, Ia32CodeGenerator::SlotOperand(masm, scope, this, ecx));
986 masm->cmp(eax, Factory::the_hole_value()); 1036 masm->cmp(eax, Factory::the_hole_value());
987 masm->j(not_equal, &exit); 1037 masm->j(not_equal, &exit);
988 may_skip_write = true;
989 } 1038 }
990 1039
991 // We must execute the store. 1040 // We must execute the store.
992 // Storing a variable must keep the (new) value on the stack. This is 1041 // Storing a variable must keep the (new) value on the stack. This is
993 // necessary for compiling assignment expressions. ecx may be loaded 1042 // necessary for compiling assignment expressions. ecx may be loaded
994 // with context; used below in RecordWrite. 1043 // with context; used below in RecordWrite.
995 // 1044 //
996 // Note: We will reach here even with node->var()->mode() == 1045 // Note: We will reach here even with node->var()->mode() ==
997 // Variable::CONST because of const declarations which will initialize 1046 // Variable::CONST because of const declarations which will initialize
998 // consts to 'the hole' value and by doing so, end up calling this 1047 // consts to 'the hole' value and by doing so, end up calling this
999 // code. 1048 // code.
1000 masm->pop(eax); 1049 masm->pop(eax);
1001 masm->mov(Ia32CodeGenerator::SlotOperand(masm, scope, this, ecx), eax); 1050 masm->mov(Ia32CodeGenerator::SlotOperand(masm, scope, this, ecx), eax);
1002 masm->push(eax); // RecordWrite may destroy the value in eax. 1051 masm->push(eax); // RecordWrite may destroy the value in eax.
1003 if (type() == Slot::CONTEXT) { 1052 if (type() == Slot::CONTEXT) {
1004 // ecx is loaded with context when calling SlotOperand above. 1053 // ecx is loaded with context when calling SlotOperand above.
1005 int offset = FixedArray::kHeaderSize + index() * kPointerSize; 1054 int offset = FixedArray::kHeaderSize + index() * kPointerSize;
1006 masm->RecordWrite(ecx, offset, eax, ebx); 1055 masm->RecordWrite(ecx, offset, eax, ebx);
1007 } 1056 }
1008 // If we definitely did not jump over the assignment, we do not need to 1057 // If we definitely did not jump over the assignment, we do not need to
1009 // bind the exit label. Doing so can defeat peephole optimization. 1058 // bind the exit label. Doing so can defeat peephole optimization.
1010 if (may_skip_write) masm->bind(&exit); 1059 if (init_state == CONST_INIT) masm->bind(&exit);
1011 } 1060 }
1012 } 1061 }
1013 1062
1014 1063
1015 #undef __ 1064 #undef __
1016 #define __ masm-> 1065 #define __ masm->
1017 1066
1018 class ToBooleanStub: public CodeStub { 1067 class ToBooleanStub: public CodeStub {
1019 public: 1068 public:
1020 ToBooleanStub() { } 1069 ToBooleanStub() { }
(...skipping 4427 matching lines...) Expand 10 before | Expand all | Expand 10 after
5448 bool is_eval) { 5497 bool is_eval) {
5449 Handle<Code> code = Ia32CodeGenerator::MakeCode(fun, script, is_eval); 5498 Handle<Code> code = Ia32CodeGenerator::MakeCode(fun, script, is_eval);
5450 if (!code.is_null()) { 5499 if (!code.is_null()) {
5451 Counters::total_compiled_code_size.Increment(code->instruction_size()); 5500 Counters::total_compiled_code_size.Increment(code->instruction_size());
5452 } 5501 }
5453 return code; 5502 return code;
5454 } 5503 }
5455 5504
5456 5505
5457 } } // namespace v8::internal 5506 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/codegen-arm.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698