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

Side by Side Diff: src/arm/virtual-frame-arm.h

Issue 1604002: Simple register allocation for ARM. Only top of expression... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 8 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
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 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 27 matching lines...) Expand all
38 // Virtual frames 38 // Virtual frames
39 // 39 //
40 // The virtual frame is an abstraction of the physical stack frame. It 40 // The virtual frame is an abstraction of the physical stack frame. It
41 // encapsulates the parameters, frame-allocated locals, and the expression 41 // encapsulates the parameters, frame-allocated locals, and the expression
42 // stack. It supports push/pop operations on the expression stack, as well 42 // stack. It supports push/pop operations on the expression stack, as well
43 // as random access to the expression stack elements, locals, and 43 // as random access to the expression stack elements, locals, and
44 // parameters. 44 // parameters.
45 45
46 class VirtualFrame : public ZoneObject { 46 class VirtualFrame : public ZoneObject {
47 public: 47 public:
48 class RegisterAllocationScope;
48 // A utility class to introduce a scope where the virtual frame is 49 // A utility class to introduce a scope where the virtual frame is
49 // expected to remain spilled. The constructor spills the code 50 // expected to remain spilled. The constructor spills the code
50 // generator's current frame, but no attempt is made to require it 51 // generator's current frame, and keeps it spilled.
51 // to stay spilled. It is intended as documentation while the code
52 // generator is being transformed.
53 class SpilledScope BASE_EMBEDDED { 52 class SpilledScope BASE_EMBEDDED {
54 public: 53 public:
55 SpilledScope() {} 54 inline SpilledScope(VirtualFrame* frame)
Kasper Lund 2010/04/07 08:09:50 Why put inline here? It needs to be explicit thoug
Erik Corry 2010/04/07 12:49:17 Done.
55 : old_is_spilled_(is_spilled_) {
56 if (frame != NULL) {
57 if (!is_spilled_) {
58 frame->SpillAll();
59 } else {
60 frame->AssertIsSpilled();
61 }
62 }
63 is_spilled_ = true;
64 }
65 inline ~SpilledScope() {
Kasper Lund 2010/04/07 08:09:50 Why put inline here?
Erik Corry 2010/04/07 12:49:17 Done.
66 is_spilled_ = old_is_spilled_;
67 }
68 static inline bool is_spilled() { return is_spilled_; }
Kasper Lund 2010/04/07 08:09:50 Why put inline here?
Erik Corry 2010/04/07 12:49:17 Done.
69
70 private:
71 static bool is_spilled_;
72 int old_is_spilled_;
73
74 SpilledScope() { }
75
76 friend class RegisterAllocationScope;
77 };
78
79 class RegisterAllocationScope BASE_EMBEDDED {
80 public:
81 // A utility class to introduce a scope where the virtual frame
82 // is not spilled, ie where register allocation occurs. Eventually
Søren Thygesen Gjesse 2010/04/07 07:53:37 Dot after ie?
Erik Corry 2010/04/07 12:49:17 Done.
83 // when RegisterAllocationScope is ubiquitous it can be removed
84 // along with the (by then unused) SpilledScope class.
85 explicit RegisterAllocationScope(CodeGenerator* cgen)
86 : cgen_(cgen),
87 old_is_spilled_(SpilledScope::is_spilled_) {
88 SpilledScope::is_spilled_ = false;
89 if (old_is_spilled_) {
90 VirtualFrame* frame = cgen->frame();
91 if (frame != NULL) {
92 frame->AssertIsSpilled();
93 }
94 }
95 }
96 ~RegisterAllocationScope() {
97 SpilledScope::is_spilled_ = old_is_spilled_;
98 if (old_is_spilled_) {
99 VirtualFrame* frame = cgen_->frame();
100 if (frame != NULL) {
101 frame->SpillAll();
102 }
103 }
104 }
105
106 private:
107 CodeGenerator* cgen_;
108 bool old_is_spilled_;
109
110 RegisterAllocationScope() { }
56 }; 111 };
57 112
58 // An illegal index into the virtual frame. 113 // An illegal index into the virtual frame.
59 static const int kIllegalIndex = -1; 114 static const int kIllegalIndex = -1;
60 115
61 // Construct an initial virtual frame on entry to a JS function. 116 // Construct an initial virtual frame on entry to a JS function.
62 inline VirtualFrame(); 117 inline VirtualFrame();
63 118
64 // Construct a virtual frame as a clone of an existing one. 119 // Construct a virtual frame as a clone of an existing one.
65 explicit inline VirtualFrame(VirtualFrame* original); 120 explicit inline VirtualFrame(VirtualFrame* original);
66 121
67 CodeGenerator* cgen() { return CodeGeneratorScope::Current(); } 122 CodeGenerator* cgen() { return CodeGeneratorScope::Current(); }
68 MacroAssembler* masm() { return cgen()->masm(); } 123 MacroAssembler* masm() { return cgen()->masm(); }
69 124
70 // The number of elements on the virtual frame. 125 // The number of elements on the virtual frame.
71 int element_count() { return element_count_; } 126 int element_count() { return element_count_; }
72 127
73 // The height of the virtual expression stack. 128 // The height of the virtual expression stack.
74 int height() { 129 int height() {
75 return element_count() - expression_base_index(); 130 return element_count() - expression_base_index();
76 } 131 }
77 132
78 int register_location(int num) {
79 ASSERT(num >= 0 && num < RegisterAllocator::kNumRegisters);
80 return register_locations_[num];
81 }
82
83 int register_location(Register reg) {
84 return register_locations_[RegisterAllocator::ToNumber(reg)];
85 }
86
87 void set_register_location(Register reg, int index) {
88 register_locations_[RegisterAllocator::ToNumber(reg)] = index;
89 }
90
91 bool is_used(int num) { 133 bool is_used(int num) {
92 ASSERT(num >= 0 && num < RegisterAllocator::kNumRegisters); 134 switch (num) {
93 return register_locations_[num] != kIllegalIndex; 135 case 0: { // r0.
136 return kR0InUse[top_of_stack_state_];
137 }
138 case 1: { // r1.
139 return kR1InUse[top_of_stack_state_];
140 }
141 case 2:
142 case 3:
143 case 4:
144 case 5:
145 case 6: { // r2 to r6.
146 ASSERT(num - kFirstAllocatedRegister < kNumberOfAllocatedRegisters);
147 ASSERT(num >= kFirstAllocatedRegister);
148 if ((register_allocation_map_ &
149 (1 << (num - kFirstAllocatedRegister))) == 0) {
150 return false;
151 } else {
152 return true;
153 }
154 }
155 default: {
156 ASSERT(num < kFirstAllocatedRegister ||
157 num >= kFirstAllocatedRegister + kNumberOfAllocatedRegisters);
158 return false;
159 }
160 }
94 } 161 }
95 162
96 bool is_used(Register reg) { 163 bool is_used(Register reg) {
97 return register_locations_[RegisterAllocator::ToNumber(reg)] 164 return is_used(RegisterAllocator::ToNumber(reg));
98 != kIllegalIndex;
99 } 165 }
100 166
101 // Add extra in-memory elements to the top of the frame to match an actual 167 // Add extra in-memory elements to the top of the frame to match an actual
102 // frame (eg, the frame after an exception handler is pushed). No code is 168 // frame (eg, the frame after an exception handler is pushed). No code is
103 // emitted. 169 // emitted.
104 void Adjust(int count); 170 void Adjust(int count);
105 171
106 // Forget elements from the top of the frame to match an actual frame (eg, 172 // Forget elements from the top of the frame to match an actual frame (eg,
107 // the frame after a runtime call). No code is emitted. 173 // the frame after a runtime call). No code is emitted except to bring the
174 // frame to a spilled state.
108 void Forget(int count) { 175 void Forget(int count) {
109 ASSERT(count >= 0); 176 SpillAll();
110 ASSERT(stack_pointer_ == element_count() - 1);
111 stack_pointer_ -= count;
112 // On ARM, all elements are in memory, so there is no extra bookkeeping
113 // (registers, copies, etc.) beyond dropping the elements.
114 element_count_ -= count; 177 element_count_ -= count;
115 } 178 }
116 179
117 // Forget count elements from the top of the frame and adjust the stack 180 // Spill all values from the frame to memory.
118 // pointer downward. This is used, for example, before merging frames at 181 inline void SpillAll() {
119 // break, continue, and return targets. 182 switch (top_of_stack_state_) {
120 void ForgetElements(int count); 183 case R0_R1_TOS:
Søren Thygesen Gjesse 2010/04/07 07:53:37 Maybe it is just me, but my initial assumption was
Erik Corry 2010/04/07 12:49:17 Reversed. Lets see how that works.
184 masm()->push(r0);
185 // Fall through.
186 case R1_TOS:
187 masm()->push(r1);
188 top_of_stack_state_ = NO_TOS_REGISTERS;
189 break;
190 case R1_R0_TOS:
191 masm()->push(r1);
192 // Fall through.
193 case R0_TOS:
194 masm()->push(r0);
195 top_of_stack_state_ = NO_TOS_REGISTERS;
196 // Fall through.
197 case NO_TOS_REGISTERS:
198 break;
199 }
200 ASSERT(register_allocation_map_ == 0); // Not yet implemented.
201 }
121 202
122 // Spill all values from the frame to memory. 203 inline void AssertIsSpilled() {
Kasper Lund 2010/04/07 08:09:50 Remove inline?
Erik Corry 2010/04/07 12:49:17 Done.
123 inline void SpillAll(); 204 ASSERT(top_of_stack_state_ == NO_TOS_REGISTERS);
205 ASSERT(register_allocation_map_ == 0);
206 }
207
208 inline void AssertIsNotSpilled() {
Kasper Lund 2010/04/07 08:09:50 Remove inline?
Erik Corry 2010/04/07 12:49:17 Done.
209 ASSERT(!SpilledScope::is_spilled());
210 }
124 211
125 // Spill all occurrences of a specific register from the frame. 212 // Spill all occurrences of a specific register from the frame.
126 void Spill(Register reg) { 213 void Spill(Register reg) {
127 if (is_used(reg)) SpillElementAt(register_location(reg)); 214 UNIMPLEMENTED();
128 } 215 }
129 216
130 // Spill all occurrences of an arbitrary register if possible. Return the 217 // Spill all occurrences of an arbitrary register if possible. Return the
131 // register spilled or no_reg if it was not possible to free any register 218 // register spilled or no_reg if it was not possible to free any register
132 // (ie, they all have frame-external references). 219 // (ie, they all have frame-external references). Unimplemented.
133 Register SpillAnyRegister(); 220 Register SpillAnyRegister();
134 221
135 // Prepare this virtual frame for merging to an expected frame by
136 // performing some state changes that do not require generating
137 // code. It is guaranteed that no code will be generated.
138 void PrepareMergeTo(VirtualFrame* expected);
139
140 // Make this virtual frame have a state identical to an expected virtual 222 // Make this virtual frame have a state identical to an expected virtual
141 // frame. As a side effect, code may be emitted to make this frame match 223 // frame. As a side effect, code may be emitted to make this frame match
142 // the expected one. 224 // the expected one.
143 void MergeTo(VirtualFrame* expected); 225 void MergeTo(VirtualFrame* expected);
144 226
145 // Detach a frame from its code generator, perhaps temporarily. This 227 // Detach a frame from its code generator, perhaps temporarily. This
146 // tells the register allocator that it is free to use frame-internal 228 // tells the register allocator that it is free to use frame-internal
147 // registers. Used when the code generator's frame is switched from this 229 // registers. Used when the code generator's frame is switched from this
148 // one to NULL by an unconditional jump. 230 // one to NULL by an unconditional jump.
149 void DetachFromCodeGenerator() { 231 void DetachFromCodeGenerator() {
150 RegisterAllocator* cgen_allocator = cgen()->allocator(); 232 AssertIsSpilled();
151 for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
152 if (is_used(i)) cgen_allocator->Unuse(i);
153 }
154 } 233 }
155 234
156 // (Re)attach a frame to its code generator. This informs the register 235 // (Re)attach a frame to its code generator. This informs the register
157 // allocator that the frame-internal register references are active again. 236 // allocator that the frame-internal register references are active again.
158 // Used when a code generator's frame is switched from NULL to this one by 237 // Used when a code generator's frame is switched from NULL to this one by
159 // binding a label. 238 // binding a label.
160 void AttachToCodeGenerator() { 239 void AttachToCodeGenerator() {
161 RegisterAllocator* cgen_allocator = cgen()->allocator(); 240 AssertIsSpilled();
162 for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
163 if (is_used(i)) cgen_allocator->Unuse(i);
164 }
165 } 241 }
166 242
167 // Emit code for the physical JS entry and exit frame sequences. After 243 // Emit code for the physical JS entry and exit frame sequences. After
168 // calling Enter, the virtual frame is ready for use; and after calling 244 // calling Enter, the virtual frame is ready for use; and after calling
169 // Exit it should not be used. Note that Enter does not allocate space in 245 // Exit it should not be used. Note that Enter does not allocate space in
170 // the physical frame for storing frame-allocated locals. 246 // the physical frame for storing frame-allocated locals.
171 void Enter(); 247 void Enter();
172 void Exit(); 248 void Exit();
173 249
174 // Prepare for returning from the frame by spilling locals and 250 // Prepare for returning from the frame by spilling locals and
175 // dropping all non-locals elements in the virtual frame. This 251 // dropping all non-locals elements in the virtual frame. This
176 // avoids generating unnecessary merge code when jumping to the 252 // avoids generating unnecessary merge code when jumping to the
177 // shared return site. Emits code for spills. 253 // shared return site. Emits code for spills.
178 inline void PrepareForReturn(); 254 inline void PrepareForReturn();
179 255
180 // Number of local variables after when we use a loop for allocating. 256 // Number of local variables after when we use a loop for allocating.
181 static const int kLocalVarBound = 5; 257 static const int kLocalVarBound = 5;
182 258
183 // Allocate and initialize the frame-allocated locals. 259 // Allocate and initialize the frame-allocated locals.
184 void AllocateStackSlots(); 260 void AllocateStackSlots();
185 261
186 // The current top of the expression stack as an assembly operand. 262 // The current top of the expression stack as an assembly operand.
187 MemOperand Top() { return MemOperand(sp, 0); } 263 MemOperand Top() {
264 AssertIsSpilled();
265 return MemOperand(sp, 0);
266 }
188 267
189 // An element of the expression stack as an assembly operand. 268 // An element of the expression stack as an assembly operand.
190 MemOperand ElementAt(int index) { 269 MemOperand ElementAt(int index) {
270 AssertIsSpilled();
191 return MemOperand(sp, index * kPointerSize); 271 return MemOperand(sp, index * kPointerSize);
192 } 272 }
193 273
194 // Random-access store to a frame-top relative frame element. The result
195 // becomes owned by the frame and is invalidated.
196 void SetElementAt(int index, Result* value);
197
198 // Set a frame element to a constant. The index is frame-top relative.
199 void SetElementAt(int index, Handle<Object> value) {
200 Result temp(value);
201 SetElementAt(index, &temp);
202 }
203
204 // A frame-allocated local as an assembly operand. 274 // A frame-allocated local as an assembly operand.
205 MemOperand LocalAt(int index) { 275 MemOperand LocalAt(int index) {
206 ASSERT(0 <= index); 276 ASSERT(0 <= index);
207 ASSERT(index < local_count()); 277 ASSERT(index < local_count());
208 return MemOperand(fp, kLocal0Offset - index * kPointerSize); 278 return MemOperand(fp, kLocal0Offset - index * kPointerSize);
209 } 279 }
210 280
211 // Push the value of a local frame slot on top of the frame and invalidate
212 // the local slot. The slot should be written to before trying to read
213 // from it again.
214 void TakeLocalAt(int index) {
215 TakeFrameSlotAt(local0_index() + index);
216 }
217
218 // Push the address of the receiver slot on the frame. 281 // Push the address of the receiver slot on the frame.
219 void PushReceiverSlotAddress(); 282 void PushReceiverSlotAddress();
220 283
221 // The function frame slot. 284 // The function frame slot.
222 MemOperand Function() { return MemOperand(fp, kFunctionOffset); } 285 MemOperand Function() { return MemOperand(fp, kFunctionOffset); }
223 286
224 // The context frame slot. 287 // The context frame slot.
225 MemOperand Context() { return MemOperand(fp, kContextOffset); } 288 MemOperand Context() { return MemOperand(fp, kContextOffset); }
226 289
227 // Save the value of the esi register to the context frame slot.
228 void SaveContextRegister();
229
230 // Restore the esi register from the value of the context frame
231 // slot.
232 void RestoreContextRegister();
233
234 // A parameter as an assembly operand. 290 // A parameter as an assembly operand.
235 MemOperand ParameterAt(int index) { 291 MemOperand ParameterAt(int index) {
236 // Index -1 corresponds to the receiver. 292 // Index -1 corresponds to the receiver.
237 ASSERT(-1 <= index); // -1 is the receiver. 293 ASSERT(-1 <= index); // -1 is the receiver.
238 ASSERT(index <= parameter_count()); 294 ASSERT(index <= parameter_count());
239 return MemOperand(fp, (1 + parameter_count() - index) * kPointerSize); 295 return MemOperand(fp, (1 + parameter_count() - index) * kPointerSize);
240 } 296 }
241 297
242 // Push the value of a paramter frame slot on top of the frame and
243 // invalidate the parameter slot. The slot should be written to before
244 // trying to read from it again.
245 void TakeParameterAt(int index) {
246 TakeFrameSlotAt(param0_index() + index);
247 }
248
249 // Store the top value on the virtual frame into a parameter frame slot.
250 // The value is left in place on top of the frame.
251 void StoreToParameterAt(int index) {
252 StoreToFrameSlotAt(param0_index() + index);
253 }
254
255 // The receiver frame slot. 298 // The receiver frame slot.
256 MemOperand Receiver() { return ParameterAt(-1); } 299 MemOperand Receiver() { return ParameterAt(-1); }
257 300
258 // Push a try-catch or try-finally handler on top of the virtual frame. 301 // Push a try-catch or try-finally handler on top of the virtual frame.
259 void PushTryHandler(HandlerType type); 302 void PushTryHandler(HandlerType type);
260 303
261 // Call stub given the number of arguments it expects on (and 304 // Call stub given the number of arguments it expects on (and
262 // removes from) the stack. 305 // removes from) the stack.
263 void CallStub(CodeStub* stub, int arg_count) { 306 void CallStub(CodeStub* stub, int arg_count) {
264 Forget(arg_count); 307 if (arg_count != 0) Forget(arg_count);
265 ASSERT(cgen()->HasValidEntryRegisters()); 308 ASSERT(cgen()->HasValidEntryRegisters());
266 masm()->CallStub(stub); 309 masm()->CallStub(stub);
267 } 310 }
268 311
269 // Call runtime given the number of arguments expected on (and 312 // Call runtime given the number of arguments expected on (and
270 // removed from) the stack. 313 // removed from) the stack.
271 void CallRuntime(Runtime::Function* f, int arg_count); 314 void CallRuntime(Runtime::Function* f, int arg_count);
272 void CallRuntime(Runtime::FunctionId id, int arg_count); 315 void CallRuntime(Runtime::FunctionId id, int arg_count);
273 316
274 #ifdef ENABLE_DEBUGGER_SUPPORT 317 #ifdef ENABLE_DEBUGGER_SUPPORT
(...skipping 14 matching lines...) Expand all
289 int dropped_args); 332 int dropped_args);
290 333
291 // Drop a number of elements from the top of the expression stack. May 334 // Drop a number of elements from the top of the expression stack. May
292 // emit code to affect the physical frame. Does not clobber any registers 335 // emit code to affect the physical frame. Does not clobber any registers
293 // excepting possibly the stack pointer. 336 // excepting possibly the stack pointer.
294 void Drop(int count); 337 void Drop(int count);
295 338
296 // Drop one element. 339 // Drop one element.
297 void Drop() { Drop(1); } 340 void Drop() { Drop(1); }
298 341
299 // Pop an element from the top of the expression stack. Returns a 342 // Pop an element from the top of the expression stack. Discards
300 // Result, which may be a constant or a register. 343 // the result.
301 Result Pop(); 344 void Pop();
345
346 // Pop an element from the top of the expression stack. The register
347 // will be one normally used for the top of stack register allocation
348 // so you can't hold on to it if you push on the stack.
349 Register PopToRegister(Register but_not_to_this_one = no_reg);
350
351 // Look at the top of the stack. The register returned is aliased and
352 // must be copied to a scratch register before modification.
353 Register Peek();
302 354
303 // Pop and save an element from the top of the expression stack and 355 // Pop and save an element from the top of the expression stack and
304 // emit a corresponding pop instruction. 356 // emit a corresponding pop instruction.
305 void EmitPop(Register reg); 357 void EmitPop(Register reg);
306 358
359 // Takes the top two elements and puts them in r0 (top element) and r1
360 // (second element).
361 void PopToR1R0();
362
363 // Takes the top element and puts it in r1.
364 void PopToR1();
365
366 // Takes the top element and puts it in r0.
367 void PopToR0();
368
307 // Push an element on top of the expression stack and emit a 369 // Push an element on top of the expression stack and emit a
308 // corresponding push instruction. 370 // corresponding push instruction.
309 void EmitPush(Register reg); 371 void EmitPush(Register reg);
372 void EmitPush(MemOperand operand);
373
374 // Get a register which is free and which must be immediately used to
375 // push on the top of the stack.
376 Register GetTOSRegister();
310 377
311 // Push multiple registers on the stack and the virtual frame 378 // Push multiple registers on the stack and the virtual frame
312 // Register are selected by setting bit in src_regs and 379 // Register are selected by setting bit in src_regs and
313 // are pushed in decreasing order: r15 .. r0. 380 // are pushed in decreasing order: r15 .. r0.
314 void EmitPushMultiple(int count, int src_regs); 381 void EmitPushMultiple(int count, int src_regs);
315 382
316 // Push an element on the virtual frame. 383 static inline Register scratch0() { return r7; }
Kasper Lund 2010/04/07 08:09:50 inline?
Erik Corry 2010/04/07 12:49:17 Done.
317 inline void Push(Handle<Object> value); 384 static inline Register scratch1() { return r8; }
318 inline void Push(Smi* value); 385 static inline Register scratch2() { return r9; }
319
320 // Nip removes zero or more elements from immediately below the top
321 // of the frame, leaving the previous top-of-frame value on top of
322 // the frame. Nip(k) is equivalent to x = Pop(), Drop(k), Push(x).
323 inline void Nip(int num_dropped);
324
325 inline void SetTypeForLocalAt(int index, TypeInfo info);
326 inline void SetTypeForParamAt(int index, TypeInfo info);
327 386
328 private: 387 private:
329 static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset; 388 static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset;
330 static const int kFunctionOffset = JavaScriptFrameConstants::kFunctionOffset; 389 static const int kFunctionOffset = JavaScriptFrameConstants::kFunctionOffset;
331 static const int kContextOffset = StandardFrameConstants::kContextOffset; 390 static const int kContextOffset = StandardFrameConstants::kContextOffset;
332 391
333 static const int kHandlerSize = StackHandlerConstants::kSize / kPointerSize; 392 static const int kHandlerSize = StackHandlerConstants::kSize / kPointerSize;
334 static const int kPreallocatedElements = 5 + 8; // 8 expression stack slots. 393 static const int kPreallocatedElements = 5 + 8; // 8 expression stack slots.
335 394
395 // 5 states for the top of stack, which can be in memory or in r0 and r1.
396 enum TopOfStack { NO_TOS_REGISTERS, R0_TOS, R1_TOS, R0_R1_TOS, R1_R0_TOS,
397 TOS_STATES};
398 static const int kMaxTOSRegisters = 2;
399
Søren Thygesen Gjesse 2010/04/07 10:46:51 Most of the names of these constants are self-expl
Erik Corry 2010/04/07 12:49:17 Done (with a rename and a comment in the .cc file)
400 static const bool kR0InUse[TOS_STATES];
401 static const bool kR1InUse[TOS_STATES];
402 static const int kVirtualElements[TOS_STATES];
403 static const TopOfStack kPopState[TOS_STATES];
404 static const TopOfStack kPushState[TOS_STATES];
405 static const Register kTopRegister[TOS_STATES];
406 static const Register kBottomRegister[TOS_STATES];
407
408 // We allocate up to 5 locals in registers.
409 static const int kNumberOfAllocatedRegisters = 5;
410 // r2 to r6 are allocated to locals.
411 static const int kFirstAllocatedRegister = 2;
412
413 static const Register kAllocatedRegisters[kNumberOfAllocatedRegisters];
414
415 static Register AllocatedRegister(int r) {
416 ASSERT(r >= 0 && r < kNumberOfAllocatedRegisters);
417 return kAllocatedRegisters[r];
418 }
419
336 // The number of elements on the stack frame. 420 // The number of elements on the stack frame.
337 int element_count_; 421 int element_count_;
422 TopOfStack top_of_stack_state_:3;
423 int register_allocation_map_:kNumberOfAllocatedRegisters;
338 424
339 // The index of the element that is at the processor's stack pointer 425 // The index of the element that is at the processor's stack pointer
340 // (the sp register). 426 // (the sp register). For now since everything is in memory it is given
341 int stack_pointer_; 427 // by the number of elements on the not-very-virtual stack frame.
342 428 int stack_pointer() { return element_count_ - 1; }
343 // The index of the register frame element using each register, or
344 // kIllegalIndex if a register is not on the frame.
345 int register_locations_[RegisterAllocator::kNumRegisters];
346 429
347 // The number of frame-allocated locals and parameters respectively. 430 // The number of frame-allocated locals and parameters respectively.
348 int parameter_count() { return cgen()->scope()->num_parameters(); } 431 int parameter_count() { return cgen()->scope()->num_parameters(); }
349 int local_count() { return cgen()->scope()->num_stack_slots(); } 432 int local_count() { return cgen()->scope()->num_stack_slots(); }
350 433
351 // The index of the element that is at the processor's frame pointer 434 // The index of the element that is at the processor's frame pointer
352 // (the fp register). The parameters, receiver, function, and context 435 // (the fp register). The parameters, receiver, function, and context
353 // are below the frame pointer. 436 // are below the frame pointer.
354 int frame_pointer() { return parameter_count() + 3; } 437 int frame_pointer() { return parameter_count() + 3; }
355 438
(...skipping 17 matching lines...) Expand all
373 int expression_base_index() { return local0_index() + local_count(); } 456 int expression_base_index() { return local0_index() + local_count(); }
374 457
375 // Convert a frame index into a frame pointer relative offset into the 458 // Convert a frame index into a frame pointer relative offset into the
376 // actual stack. 459 // actual stack.
377 int fp_relative(int index) { 460 int fp_relative(int index) {
378 ASSERT(index < element_count()); 461 ASSERT(index < element_count());
379 ASSERT(frame_pointer() < element_count()); // FP is on the frame. 462 ASSERT(frame_pointer() < element_count()); // FP is on the frame.
380 return (frame_pointer() - index) * kPointerSize; 463 return (frame_pointer() - index) * kPointerSize;
381 } 464 }
382 465
383 // Record an occurrence of a register in the virtual frame. This has the
384 // effect of incrementing the register's external reference count and
385 // of updating the index of the register's location in the frame.
386 void Use(Register reg, int index) {
387 ASSERT(!is_used(reg));
388 set_register_location(reg, index);
389 cgen()->allocator()->Use(reg);
390 }
391
392 // Record that a register reference has been dropped from the frame. This
393 // decrements the register's external reference count and invalidates the
394 // index of the register's location in the frame.
395 void Unuse(Register reg) {
396 ASSERT(is_used(reg));
397 set_register_location(reg, kIllegalIndex);
398 cgen()->allocator()->Unuse(reg);
399 }
400
401 // Spill the element at a particular index---write it to memory if
402 // necessary, free any associated register, and forget its value if
403 // constant.
404 void SpillElementAt(int index);
405
406 // Sync the element at a particular index. If it is a register or
407 // constant that disagrees with the value on the stack, write it to memory.
408 // Keep the element type as register or constant, and clear the dirty bit.
409 void SyncElementAt(int index);
410
411 // Sync a single unsynced element that lies beneath or at the stack pointer.
412 void SyncElementBelowStackPointer(int index);
413
414 // Sync a single unsynced element that lies just above the stack pointer.
415 void SyncElementByPushing(int index);
416
417 // Push a the value of a frame slot (typically a local or parameter) on
418 // top of the frame and invalidate the slot.
419 void TakeFrameSlotAt(int index);
420
421 // Store the value on top of the frame to a frame slot (typically a local
422 // or parameter).
423 void StoreToFrameSlotAt(int index);
424
425 // Spill all elements in registers. Spill the top spilled_args elements 466 // Spill all elements in registers. Spill the top spilled_args elements
426 // on the frame. Sync all other frame elements. 467 // on the frame. Sync all other frame elements.
427 // Then drop dropped_args elements from the virtual frame, to match 468 // Then drop dropped_args elements from the virtual frame, to match
428 // the effect of an upcoming call that will drop them from the stack. 469 // the effect of an upcoming call that will drop them from the stack.
429 void PrepareForCall(int spilled_args, int dropped_args); 470 void PrepareForCall(int spilled_args, int dropped_args);
430 471
431 // Move frame elements currently in registers or constants, that
432 // should be in memory in the expected frame, to memory.
433 void MergeMoveRegistersToMemory(VirtualFrame* expected);
434
435 // Make the register-to-register moves necessary to
436 // merge this frame with the expected frame.
437 // Register to memory moves must already have been made,
438 // and memory to register moves must follow this call.
439 // This is because some new memory-to-register moves are
440 // created in order to break cycles of register moves.
441 // Used in the implementation of MergeTo().
442 void MergeMoveRegistersToRegisters(VirtualFrame* expected);
443
444 // Make the memory-to-register and constant-to-register moves
445 // needed to make this frame equal the expected frame.
446 // Called after all register-to-memory and register-to-register
447 // moves have been made. After this function returns, the frames
448 // should be equal.
449 void MergeMoveMemoryToRegisters(VirtualFrame* expected);
450
451 // Invalidates a frame slot (puts an invalid frame element in it).
452 // Copies on the frame are correctly handled, and if this slot was
453 // the backing store of copies, the index of the new backing store
454 // is returned. Otherwise, returns kIllegalIndex.
455 // Register counts are correctly updated.
456 int InvalidateFrameSlotAt(int index);
457
458 inline bool Equals(VirtualFrame* other); 472 inline bool Equals(VirtualFrame* other);
459 473
460 friend class JumpTarget; 474 friend class JumpTarget;
461 friend class DeferredCode; 475 friend class DeferredCode;
462 }; 476 };
463 477
464 478
465 } } // namespace v8::internal 479 } } // namespace v8::internal
466 480
467 #endif // V8_ARM_VIRTUAL_FRAME_ARM_H_ 481 #endif // V8_ARM_VIRTUAL_FRAME_ARM_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698