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

Side by Side Diff: src/codegen-arm.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 | « no previous file | src/codegen-ia32.cc » ('j') | 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 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 94
95 bool is_illegal() const { return type_ == ILLEGAL; } 95 bool is_illegal() const { return type_ == ILLEGAL; }
96 96
97 private: 97 private:
98 ArmCodeGenerator* cgen_; 98 ArmCodeGenerator* cgen_;
99 Expression* expression_; 99 Expression* expression_;
100 Type type_; 100 Type type_;
101 }; 101 };
102 102
103 103
104 // ----------------------------------------------------------------------------- 104 // -------------------------------------------------------------------------
105 // Code generation state 105 // Code generation state
106 106
107 // The state is passed down the AST by the code generator. It is passed
108 // implicitly (in a member variable) to the non-static code generator member
109 // functions, and explicitly (as an argument) to the static member functions
110 // and the AST node member functions.
111 //
112 // The state is threaded through the call stack. Constructing a state
113 // implicitly pushes it on the owning code generator's stack of states, and
114 // destroying one implicitly pops it.
115
107 class CodeGenState BASE_EMBEDDED { 116 class CodeGenState BASE_EMBEDDED {
108 public: 117 public:
109 enum AccessType { 118 enum AccessType {
110 UNDEFINED, 119 UNDEFINED,
111 LOAD, 120 LOAD,
112 LOAD_TYPEOF_EXPR 121 LOAD_TYPEOF_EXPR
113 }; 122 };
114 123
115 CodeGenState() 124 // Create an initial code generator state. Destroying the initial state
116 : access_(UNDEFINED), 125 // leaves the code generator with a NULL state.
117 ref_(NULL), 126 CodeGenState(ArmCodeGenerator* owner);
118 true_target_(NULL),
119 false_target_(NULL) {
120 }
121 127
122 CodeGenState(AccessType access, 128 // Create a code generator state based on a code generator's current
123 Reference* ref, 129 // state. The new state has its own access type and pair of branch
130 // labels, and no reference.
131 CodeGenState(ArmCodeGenerator* owner,
132 AccessType access,
124 Label* true_target, 133 Label* true_target,
125 Label* false_target) 134 Label* false_target);
126 : access_(access), 135
127 ref_(ref), 136 // Create a code generator state based on a code generator's current
128 true_target_(true_target), 137 // state. The new state has an access type of LOAD, its own reference,
129 false_target_(false_target) { 138 // and inherits the pair of branch labels of the current state.
130 } 139 CodeGenState(ArmCodeGenerator* owner, Reference* ref);
140
141 // Destroy a code generator state and restore the owning code generator's
142 // previous state.
143 ~CodeGenState();
131 144
132 AccessType access() const { return access_; } 145 AccessType access() const { return access_; }
133 Reference* ref() const { return ref_; } 146 Reference* ref() const { return ref_; }
134 Label* true_target() const { return true_target_; } 147 Label* true_target() const { return true_target_; }
135 Label* false_target() const { return false_target_; } 148 Label* false_target() const { return false_target_; }
136 149
137 private: 150 private:
151 ArmCodeGenerator* owner_;
138 AccessType access_; 152 AccessType access_;
139 Reference* ref_; 153 Reference* ref_;
140 Label* true_target_; 154 Label* true_target_;
141 Label* false_target_; 155 Label* false_target_;
156 CodeGenState* previous_;
142 }; 157 };
143 158
144 159
145 // ----------------------------------------------------------------------------- 160 // -----------------------------------------------------------------------------
146 // ArmCodeGenerator 161 // ArmCodeGenerator
147 162
148 class ArmCodeGenerator: public CodeGenerator { 163 class ArmCodeGenerator: public CodeGenerator {
149 public: 164 public:
150 static Handle<Code> MakeCode(FunctionLiteral* fun, 165 static Handle<Code> MakeCode(FunctionLiteral* fun,
151 Handle<Script> script, 166 Handle<Script> script,
152 bool is_eval); 167 bool is_eval);
153 168
154 MacroAssembler* masm() { return masm_; } 169 MacroAssembler* masm() { return masm_; }
155 170
171 CodeGenState* state() { return state_; }
172 void set_state(CodeGenState* state) { state_ = state; }
173
156 private: 174 private:
157 // Assembler 175 // Assembler
158 MacroAssembler* masm_; // to generate code 176 MacroAssembler* masm_; // to generate code
159 177
160 // Code generation state 178 // Code generation state
161 Scope* scope_; 179 Scope* scope_;
162 Condition cc_reg_; 180 Condition cc_reg_;
163 CodeGenState* state_; 181 CodeGenState* state_;
164 int break_stack_height_; 182 int break_stack_height_;
165 183
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 // look like an explicit property access, instead of an access 254 // look like an explicit property access, instead of an access
237 // through the context chain. 255 // through the context chain.
238 void LoadTypeofExpression(Expression* x); 256 void LoadTypeofExpression(Expression* x);
239 257
240 258
241 // References 259 // References
242 260
243 // Generate code to fetch the value of a reference. The reference is 261 // Generate code to fetch the value of a reference. The reference is
244 // expected to be on top of the expression stack. It is left in place and 262 // expected to be on top of the expression stack. It is left in place and
245 // its value is pushed on top of it. 263 // its value is pushed on top of it.
246 void GetValue(Reference* ref); 264 void GetValue(Reference* ref) {
265 ASSERT(!has_cc());
266 ASSERT(!ref->is_illegal());
267 CodeGenState new_state(this, ref);
268 Visit(ref->expression());
269 }
247 270
248 // Generate code to store a value in a reference. The stored value is 271 // Generate code to store a value in a reference. The stored value is
249 // expected on top of the expression stack, with the reference immediately 272 // expected on top of the expression stack, with the reference immediately
250 // below it. The expression stack is left unchanged. 273 // below it. The expression stack is left unchanged.
251 void SetValue(Reference* ref) { 274 void SetValue(Reference* ref) {
252 ASSERT(!has_cc()); 275 ASSERT(!has_cc());
253 ASSERT(!ref->is_illegal()); 276 ASSERT(!ref->is_illegal());
254 ref->expression()->GenerateStoreCode(masm_, scope_, ref, NOT_CONST_INIT); 277 ref->expression()->GenerateStoreCode(masm_, scope_, ref, NOT_CONST_INIT);
255 } 278 }
256 279
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 357
335 virtual void GenerateObjectEquals(ZoneList<Expression*>* args); 358 virtual void GenerateObjectEquals(ZoneList<Expression*>* args);
336 359
337 friend class Reference; 360 friend class Reference;
338 friend class Property; 361 friend class Property;
339 friend class VariableProxy; 362 friend class VariableProxy;
340 friend class Slot; 363 friend class Slot;
341 }; 364 };
342 365
343 366
367 // -------------------------------------------------------------------------
368 // CodeGenState implementation.
369
370 CodeGenState::CodeGenState(ArmCodeGenerator* owner)
371 : owner_(owner),
372 access_(UNDEFINED),
373 ref_(NULL),
374 true_target_(NULL),
375 false_target_(NULL),
376 previous_(NULL) {
377 owner_->set_state(this);
378 }
379
380
381 CodeGenState::CodeGenState(ArmCodeGenerator* owner,
382 AccessType access,
383 Label* true_target,
384 Label* false_target)
385 : owner_(owner),
386 access_(access),
387 ref_(NULL),
388 true_target_(true_target),
389 false_target_(false_target),
390 previous_(owner->state()) {
391 owner_->set_state(this);
392 }
393
394
395 CodeGenState::CodeGenState(ArmCodeGenerator* owner, Reference* ref)
396 : owner_(owner),
397 access_(LOAD),
398 ref_(ref),
399 true_target_(owner->state()->true_target_),
400 false_target_(owner->state()->false_target_),
401 previous_(owner->state()) {
402 owner_->set_state(this);
403 }
404
405
406 CodeGenState::~CodeGenState() {
407 ASSERT(owner_->state() == this);
408 owner_->set_state(previous_);
409 }
410
411
344 // ----------------------------------------------------------------------------- 412 // -----------------------------------------------------------------------------
345 // ArmCodeGenerator implementation 413 // ArmCodeGenerator implementation
346 414
347 #define __ masm_-> 415 #define __ masm_->
348 416
349 417
350 Handle<Code> ArmCodeGenerator::MakeCode(FunctionLiteral* flit, 418 Handle<Code> ArmCodeGenerator::MakeCode(FunctionLiteral* flit,
351 Handle<Script> script, 419 Handle<Script> script,
352 bool is_eval) { 420 bool is_eval) {
353 #ifdef ENABLE_DISASSEMBLER 421 #ifdef ENABLE_DISASSEMBLER
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
449 // fp: frame pointer 517 // fp: frame pointer
450 // sp: stack pointer 518 // sp: stack pointer
451 // pp: caller's parameter pointer 519 // pp: caller's parameter pointer
452 // cp: callee's context 520 // cp: callee's context
453 521
454 void ArmCodeGenerator::GenCode(FunctionLiteral* fun) { 522 void ArmCodeGenerator::GenCode(FunctionLiteral* fun) {
455 Scope* scope = fun->scope(); 523 Scope* scope = fun->scope();
456 ZoneList<Statement*>* body = fun->body(); 524 ZoneList<Statement*>* body = fun->body();
457 525
458 // Initialize state. 526 // Initialize state.
459 { CodeGenState state; 527 { CodeGenState state(this);
460 state_ = &state;
461 scope_ = scope; 528 scope_ = scope;
462 cc_reg_ = al; 529 cc_reg_ = al;
463 530
464 // Entry 531 // Entry
465 // stack: function, receiver, arguments, return address 532 // stack: function, receiver, arguments, return address
466 // r0: number of arguments 533 // r0: number of arguments
467 // sp: stack pointer 534 // sp: stack pointer
468 // fp: frame pointer 535 // fp: frame pointer
469 // pp: caller's parameter pointer 536 // pp: caller's parameter pointer
470 // cp: callee's context 537 // cp: callee's context
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
602 if (should_trace) { 669 if (should_trace) {
603 // Push a valid value as the parameter. The runtime call only uses 670 // Push a valid value as the parameter. The runtime call only uses
604 // it as the return value to indicate non-failure. 671 // it as the return value to indicate non-failure.
605 __ mov(r0, Operand(Smi::FromInt(0))); 672 __ mov(r0, Operand(Smi::FromInt(0)));
606 __ push(r0); 673 __ push(r0);
607 __ CallRuntime(Runtime::kDebugTrace, 1); 674 __ CallRuntime(Runtime::kDebugTrace, 1);
608 } 675 }
609 #endif 676 #endif
610 VisitStatements(body); 677 VisitStatements(body);
611 } 678 }
612
613 state_ = NULL;
614 } 679 }
615 680
616 // exit 681 // exit
617 // r0: result 682 // r0: result
618 // sp: stack pointer 683 // sp: stack pointer
619 // fp: frame pointer 684 // fp: frame pointer
620 // pp: parameter pointer 685 // pp: parameter pointer
621 // cp: callee's context 686 // cp: callee's context
622 __ mov(r0, Operand(Factory::undefined_value())); 687 __ mov(r0, Operand(Factory::undefined_value()));
623 688
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
710 // has_cc() is true and cc_reg_ contains the condition to test for 'true'. 775 // has_cc() is true and cc_reg_ contains the condition to test for 'true'.
711 void ArmCodeGenerator::LoadCondition(Expression* x, 776 void ArmCodeGenerator::LoadCondition(Expression* x,
712 CodeGenState::AccessType access, 777 CodeGenState::AccessType access,
713 Label* true_target, 778 Label* true_target,
714 Label* false_target, 779 Label* false_target,
715 bool force_cc) { 780 bool force_cc) {
716 ASSERT(access == CodeGenState::LOAD || 781 ASSERT(access == CodeGenState::LOAD ||
717 access == CodeGenState::LOAD_TYPEOF_EXPR); 782 access == CodeGenState::LOAD_TYPEOF_EXPR);
718 ASSERT(!has_cc() && !is_referenced()); 783 ASSERT(!has_cc() && !is_referenced());
719 784
720 CodeGenState* old_state = state_; 785 { CodeGenState new_state(this, access, true_target, false_target);
721 CodeGenState new_state(access, NULL, true_target, false_target); 786 Visit(x);
722 state_ = &new_state; 787 }
723 Visit(x);
724 state_ = old_state;
725 if (force_cc && !has_cc()) { 788 if (force_cc && !has_cc()) {
726 // Convert the TOS value to a boolean in the condition code register. 789 // Convert the TOS value to a boolean in the condition code register.
727 ToBoolean(true_target, false_target); 790 ToBoolean(true_target, false_target);
728 } 791 }
729 ASSERT(has_cc() || !force_cc); 792 ASSERT(has_cc() || !force_cc);
730 } 793 }
731 794
732 795
733 void ArmCodeGenerator::Load(Expression* x, CodeGenState::AccessType access) { 796 void ArmCodeGenerator::Load(Expression* x, CodeGenState::AccessType access) {
734 ASSERT(access == CodeGenState::LOAD || 797 ASSERT(access == CodeGenState::LOAD ||
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
862 if (size <= 0) { 925 if (size <= 0) {
863 // Do nothing. No popping is necessary. 926 // Do nothing. No popping is necessary.
864 } else { 927 } else {
865 __ pop(r0); 928 __ pop(r0);
866 __ add(sp, sp, Operand(size * kPointerSize)); 929 __ add(sp, sp, Operand(size * kPointerSize));
867 __ push(r0); 930 __ push(r0);
868 } 931 }
869 } 932 }
870 933
871 934
872 void ArmCodeGenerator::GetValue(Reference* ref) {
873 ASSERT(!has_cc());
874 ASSERT(!ref->is_illegal());
875 CodeGenState* old_state = state_;
876 CodeGenState new_state(CodeGenState::LOAD, ref, true_target(),
877 false_target());
878 state_ = &new_state;
879 Visit(ref->expression());
880 state_ = old_state;
881 }
882
883
884 void Property::GenerateStoreCode(MacroAssembler* masm, 935 void Property::GenerateStoreCode(MacroAssembler* masm,
885 Scope* scope, 936 Scope* scope,
886 Reference* ref, 937 Reference* ref,
887 InitState init_state) { 938 InitState init_state) {
888 Comment cmnt(masm, "[ Store to Property"); 939 Comment cmnt(masm, "[ Store to Property");
889 masm->RecordPosition(position()); 940 masm->RecordPosition(position());
890 ArmCodeGenerator::SetReferenceProperty(masm, ref, key()); 941 ArmCodeGenerator::SetReferenceProperty(masm, ref, key());
891 } 942 }
892 943
893 944
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
946 masm->CallRuntime(Runtime::kStoreContextSlot, 3); 997 masm->CallRuntime(Runtime::kStoreContextSlot, 3);
947 } 998 }
948 // Storing a variable must keep the (new) value on the expression 999 // Storing a variable must keep the (new) value on the expression
949 // stack. This is necessary for compiling assignment expressions. 1000 // stack. This is necessary for compiling assignment expressions.
950 masm->push(r0); 1001 masm->push(r0);
951 1002
952 } else { 1003 } else {
953 ASSERT(var()->mode() != Variable::DYNAMIC); 1004 ASSERT(var()->mode() != Variable::DYNAMIC);
954 1005
955 Label exit; 1006 Label exit;
956 bool may_skip_write = false;
957 if (init_state == CONST_INIT) { 1007 if (init_state == CONST_INIT) {
958 ASSERT(var()->mode() == Variable::CONST); 1008 ASSERT(var()->mode() == Variable::CONST);
959 // Only the first const initialization must be executed (the slot 1009 // Only the first const initialization must be executed (the slot
960 // still contains 'the hole' value). When the assignment is executed, 1010 // still contains 'the hole' value). When the assignment is executed,
961 // the code is identical to a normal store (see below). 1011 // the code is identical to a normal store (see below).
962 Comment cmnt(masm, "[ Init const"); 1012 Comment cmnt(masm, "[ Init const");
963 masm->ldr(r2, ArmCodeGenerator::SlotOperand(masm, scope, this, r2)); 1013 masm->ldr(r2, ArmCodeGenerator::SlotOperand(masm, scope, this, r2));
964 masm->cmp(r2, Operand(Factory::the_hole_value())); 1014 masm->cmp(r2, Operand(Factory::the_hole_value()));
965 masm->b(ne, &exit); 1015 masm->b(ne, &exit);
966 may_skip_write = true;
967 } 1016 }
968 1017
969 // We must execute the store. 1018 // We must execute the store.
970 // r2 may be loaded with context; used below in RecordWrite. 1019 // r2 may be loaded with context; used below in RecordWrite.
971 // Storing a variable must keep the (new) value on the stack. This is 1020 // Storing a variable must keep the (new) value on the stack. This is
972 // necessary for compiling assignment expressions. 1021 // necessary for compiling assignment expressions.
973 // 1022 //
974 // Note: We will reach here even with var()->mode() == Variable::CONST 1023 // Note: We will reach here even with var()->mode() == Variable::CONST
975 // because of const declarations which will initialize consts to 'the 1024 // because of const declarations which will initialize consts to 'the
976 // hole' value and by doing so, end up calling this code. r2 may be 1025 // hole' value and by doing so, end up calling this code. r2 may be
977 // loaded with context; used below in RecordWrite. 1026 // loaded with context; used below in RecordWrite.
978 masm->pop(r0); 1027 masm->pop(r0);
979 masm->str(r0, ArmCodeGenerator::SlotOperand(masm, scope, this, r2)); 1028 masm->str(r0, ArmCodeGenerator::SlotOperand(masm, scope, this, r2));
980 masm->push(r0); 1029 masm->push(r0);
981 1030
982 if (type() == Slot::CONTEXT) { 1031 if (type() == Slot::CONTEXT) {
983 // Skip write barrier if the written value is a smi. 1032 // Skip write barrier if the written value is a smi.
984 masm->tst(r0, Operand(kSmiTagMask)); 1033 masm->tst(r0, Operand(kSmiTagMask));
985 masm->b(eq, &exit); 1034 masm->b(eq, &exit);
986 may_skip_write = true;
987 // r2 is loaded with context when calling SlotOperand above. 1035 // r2 is loaded with context when calling SlotOperand above.
988 int offset = FixedArray::kHeaderSize + index() * kPointerSize; 1036 int offset = FixedArray::kHeaderSize + index() * kPointerSize;
989 masm->mov(r3, Operand(offset)); 1037 masm->mov(r3, Operand(offset));
990 masm->RecordWrite(r2, r3, r1); 1038 masm->RecordWrite(r2, r3, r1);
991 } 1039 }
992 // If we definitely did not jump over the assignment, we do not need to 1040 // If we definitely did not jump over the assignment, we do not need to
993 // bind the exit label. Doing so can defeat peephole optimization. 1041 // bind the exit label. Doing so can defeat peephole optimization.
994 if (may_skip_write) masm->bind(&exit); 1042 if (init_state == CONST_INIT || type() == Slot::CONTEXT) {
1043 masm->bind(&exit);
1044 }
995 } 1045 }
996 } 1046 }
997 1047
998 1048
999 // ECMA-262, section 9.2, page 30: ToBoolean(). Convert the given 1049 // ECMA-262, section 9.2, page 30: ToBoolean(). Convert the given
1000 // register to a boolean in the condition code register. The code 1050 // register to a boolean in the condition code register. The code
1001 // may jump to 'false_target' in case the register converts to 'false'. 1051 // may jump to 'false_target' in case the register converts to 'false'.
1002 void ArmCodeGenerator::ToBoolean(Label* true_target, 1052 void ArmCodeGenerator::ToBoolean(Label* true_target,
1003 Label* false_target) { 1053 Label* false_target) {
1004 // Note: The generated code snippet does not change stack variables. 1054 // Note: The generated code snippet does not change stack variables.
(...skipping 3613 matching lines...) Expand 10 before | Expand all | Expand 10 after
4618 bool is_eval) { 4668 bool is_eval) {
4619 Handle<Code> code = ArmCodeGenerator::MakeCode(fun, script, is_eval); 4669 Handle<Code> code = ArmCodeGenerator::MakeCode(fun, script, is_eval);
4620 if (!code.is_null()) { 4670 if (!code.is_null()) {
4621 Counters::total_compiled_code_size.Increment(code->instruction_size()); 4671 Counters::total_compiled_code_size.Increment(code->instruction_size());
4622 } 4672 }
4623 return code; 4673 return code;
4624 } 4674 }
4625 4675
4626 4676
4627 } } // namespace v8::internal 4677 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698