OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 21 matching lines...) Expand all Loading... |
32 #include "register-allocator.h" | 32 #include "register-allocator.h" |
33 #include "scopes.h" | 33 #include "scopes.h" |
34 | 34 |
35 namespace v8 { | 35 namespace v8 { |
36 namespace internal { | 36 namespace internal { |
37 | 37 |
38 | 38 |
39 // ------------------------------------------------------------------------- | 39 // ------------------------------------------------------------------------- |
40 // Virtual frames | 40 // Virtual frames |
41 // | 41 // |
42 // The virtual frame is an abstraction of the physical stack frame. It | 42 // The virtual frame is an abstraction of the physical stack frame. It |
43 // encapsulates the parameters, frame-allocated locals, and the expression | 43 // encapsulates the parameters, frame-allocated locals, and the expression |
44 // stack. It supports push/pop operations on the expression stack, as well | 44 // stack. It supports push/pop operations on the expression stack, as well |
45 // as random access to the expression stack elements, locals, and | 45 // as random access to the expression stack elements, locals, and |
46 // parameters. | 46 // parameters. |
47 | 47 |
48 class VirtualFrame : public ZoneObject { | 48 class VirtualFrame : public ZoneObject { |
49 public: | 49 public: |
50 // A utility class to introduce a scope where the virtual frame is | 50 // A utility class to introduce a scope where the virtual frame is |
51 // expected to remain spilled. The constructor spills the code | 51 // expected to remain spilled. The constructor spills the code |
52 // generator's current frame, but no attempt is made to require it | 52 // generator's current frame, but no attempt is made to require it |
53 // to stay spilled. It is intended as documentation while the code | 53 // to stay spilled. It is intended as documentation while the code |
54 // generator is being transformed. | 54 // generator is being transformed. |
55 class SpilledScope BASE_EMBEDDED { | 55 class SpilledScope BASE_EMBEDDED { |
56 public: | 56 public: |
57 SpilledScope() {} | 57 SpilledScope() {} |
58 }; | 58 }; |
59 | 59 |
60 // An illegal index into the virtual frame. | 60 // An illegal index into the virtual frame. |
61 static const int kIllegalIndex = -1; | 61 static const int kIllegalIndex = -1; |
62 | 62 |
63 // Construct an initial virtual frame on entry to a JS function. | 63 // Construct an initial virtual frame on entry to a JS function. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 ASSERT(num >= 0 && num < RegisterAllocator::kNumRegisters); | 98 ASSERT(num >= 0 && num < RegisterAllocator::kNumRegisters); |
99 return register_locations_[num] != kIllegalIndex; | 99 return register_locations_[num] != kIllegalIndex; |
100 } | 100 } |
101 | 101 |
102 bool is_used(Register reg) { | 102 bool is_used(Register reg) { |
103 return register_locations_[RegisterAllocator::ToNumber(reg)] | 103 return register_locations_[RegisterAllocator::ToNumber(reg)] |
104 != kIllegalIndex; | 104 != kIllegalIndex; |
105 } | 105 } |
106 | 106 |
107 // Add extra in-memory elements to the top of the frame to match an actual | 107 // Add extra in-memory elements to the top of the frame to match an actual |
108 // frame (eg, the frame after an exception handler is pushed). No code is | 108 // frame (eg, the frame after an exception handler is pushed). No code is |
109 // emitted. | 109 // emitted. |
110 void Adjust(int count); | 110 void Adjust(int count); |
111 | 111 |
112 // Forget elements from the top of the frame to match an actual frame (eg, | 112 // Forget elements from the top of the frame to match an actual frame (eg, |
113 // the frame after a runtime call). No code is emitted. | 113 // the frame after a runtime call). No code is emitted. |
114 void Forget(int count) { | 114 void Forget(int count) { |
115 ASSERT(count >= 0); | 115 ASSERT(count >= 0); |
116 ASSERT(stack_pointer_ == element_count() - 1); | 116 ASSERT(stack_pointer_ == element_count() - 1); |
117 stack_pointer_ -= count; | 117 stack_pointer_ -= count; |
118 // On mips, all elements are in memory, so there is no extra bookkeeping | 118 // On mips, all elements are in memory, so there is no extra bookkeeping |
119 // (registers, copies, etc.) beyond dropping the elements. | 119 // (registers, copies, etc.) beyond dropping the elements. |
120 elements_.Rewind(stack_pointer_ + 1); | 120 elements_.Rewind(stack_pointer_ + 1); |
121 } | 121 } |
122 | 122 |
123 // Forget count elements from the top of the frame and adjust the stack | 123 // Forget count elements from the top of the frame and adjust the stack |
124 // pointer downward. This is used, for example, before merging frames at | 124 // pointer downward. This is used, for example, before merging frames at |
125 // break, continue, and return targets. | 125 // break, continue, and return targets. |
126 void ForgetElements(int count); | 126 void ForgetElements(int count); |
127 | 127 |
128 // Spill all values from the frame to memory. | 128 // Spill all values from the frame to memory. |
129 void SpillAll(); | 129 void SpillAll(); |
130 | 130 |
131 // Spill all occurrences of a specific register from the frame. | 131 // Spill all occurrences of a specific register from the frame. |
132 void Spill(Register reg) { | 132 void Spill(Register reg) { |
133 if (is_used(reg)) SpillElementAt(register_location(reg)); | 133 if (is_used(reg)) SpillElementAt(register_location(reg)); |
134 } | 134 } |
135 | 135 |
136 // Spill all occurrences of an arbitrary register if possible. Return the | 136 // Spill all occurrences of an arbitrary register if possible. Return the |
137 // register spilled or no_reg if it was not possible to free any register | 137 // register spilled or no_reg if it was not possible to free any register |
138 // (ie, they all have frame-external references). | 138 // (ie, they all have frame-external references). |
139 Register SpillAnyRegister(); | 139 Register SpillAnyRegister(); |
140 | 140 |
141 // Prepare this virtual frame for merging to an expected frame by | 141 // Prepare this virtual frame for merging to an expected frame by |
142 // performing some state changes that do not require generating | 142 // performing some state changes that do not require generating |
143 // code. It is guaranteed that no code will be generated. | 143 // code. It is guaranteed that no code will be generated. |
144 void PrepareMergeTo(VirtualFrame* expected); | 144 void PrepareMergeTo(VirtualFrame* expected); |
145 | 145 |
146 // Make this virtual frame have a state identical to an expected virtual | 146 // Make this virtual frame have a state identical to an expected virtual |
147 // frame. As a side effect, code may be emitted to make this frame match | 147 // frame. As a side effect, code may be emitted to make this frame match |
148 // the expected one. | 148 // the expected one. |
149 void MergeTo(VirtualFrame* expected); | 149 void MergeTo(VirtualFrame* expected); |
150 | 150 |
151 // Detach a frame from its code generator, perhaps temporarily. This | 151 // Detach a frame from its code generator, perhaps temporarily. This |
152 // tells the register allocator that it is free to use frame-internal | 152 // tells the register allocator that it is free to use frame-internal |
153 // registers. Used when the code generator's frame is switched from this | 153 // registers. Used when the code generator's frame is switched from this |
154 // one to NULL by an unconditional jump. | 154 // one to NULL by an unconditional jump. |
155 void DetachFromCodeGenerator() { | 155 void DetachFromCodeGenerator() { |
156 RegisterAllocator* cgen_allocator = cgen()->allocator(); | 156 RegisterAllocator* cgen_allocator = cgen()->allocator(); |
157 for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) { | 157 for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) { |
158 if (is_used(i)) cgen_allocator->Unuse(i); | 158 if (is_used(i)) cgen_allocator->Unuse(i); |
159 } | 159 } |
160 } | 160 } |
161 | 161 |
162 // (Re)attach a frame to its code generator. This informs the register | 162 // (Re)attach a frame to its code generator. This informs the register |
163 // allocator that the frame-internal register references are active again. | 163 // allocator that the frame-internal register references are active again. |
164 // Used when a code generator's frame is switched from NULL to this one by | 164 // Used when a code generator's frame is switched from NULL to this one by |
165 // binding a label. | 165 // binding a label. |
166 void AttachToCodeGenerator() { | 166 void AttachToCodeGenerator() { |
167 RegisterAllocator* cgen_allocator = cgen()->allocator(); | 167 RegisterAllocator* cgen_allocator = cgen()->allocator(); |
168 for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) { | 168 for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) { |
169 if (is_used(i)) cgen_allocator->Unuse(i); | 169 if (is_used(i)) cgen_allocator->Unuse(i); |
170 } | 170 } |
171 } | 171 } |
172 | 172 |
173 // Emit code for the physical JS entry and exit frame sequences. After | 173 // Emit code for the physical JS entry and exit frame sequences. After |
174 // calling Enter, the virtual frame is ready for use; and after calling | 174 // calling Enter, the virtual frame is ready for use; and after calling |
175 // Exit it should not be used. Note that Enter does not allocate space in | 175 // Exit it should not be used. Note that Enter does not allocate space in |
176 // the physical frame for storing frame-allocated locals. | 176 // the physical frame for storing frame-allocated locals. |
177 void Enter(); | 177 void Enter(); |
178 void Exit(); | 178 void Exit(); |
179 | 179 |
180 // Prepare for returning from the frame by spilling locals and | 180 // Prepare for returning from the frame by spilling locals and |
181 // dropping all non-locals elements in the virtual frame. This | 181 // dropping all non-locals elements in the virtual frame. This |
182 // avoids generating unnecessary merge code when jumping to the | 182 // avoids generating unnecessary merge code when jumping to the |
183 // shared return site. Emits code for spills. | 183 // shared return site. Emits code for spills. |
184 void PrepareForReturn(); | 184 void PrepareForReturn(); |
185 | 185 |
186 // Allocate and initialize the frame-allocated locals. | 186 // Allocate and initialize the frame-allocated locals. |
187 void AllocateStackSlots(); | 187 void AllocateStackSlots(); |
188 | 188 |
189 // The current top of the expression stack as an assembly operand. | 189 // The current top of the expression stack as an assembly operand. |
190 MemOperand Top() { return MemOperand(sp, 0); } | 190 MemOperand Top() { return MemOperand(sp, 0); } |
191 | 191 |
192 // An element of the expression stack as an assembly operand. | 192 // An element of the expression stack as an assembly operand. |
193 MemOperand ElementAt(int index) { | 193 MemOperand ElementAt(int index) { |
194 return MemOperand(sp, index * kPointerSize); | 194 return MemOperand(sp, index * kPointerSize); |
195 } | 195 } |
196 | 196 |
197 // Random-access store to a frame-top relative frame element. The result | 197 // Random-access store to a frame-top relative frame element. The result |
198 // becomes owned by the frame and is invalidated. | 198 // becomes owned by the frame and is invalidated. |
199 void SetElementAt(int index, Result* value); | 199 void SetElementAt(int index, Result* value); |
200 | 200 |
201 // Set a frame element to a constant. The index is frame-top relative. | 201 // Set a frame element to a constant. The index is frame-top relative. |
202 void SetElementAt(int index, Handle<Object> value) { | 202 void SetElementAt(int index, Handle<Object> value) { |
203 Result temp(value); | 203 Result temp(value); |
204 SetElementAt(index, &temp); | 204 SetElementAt(index, &temp); |
205 } | 205 } |
206 | 206 |
207 void PushElementAt(int index) { | 207 void PushElementAt(int index) { |
208 PushFrameSlotAt(element_count() - index - 1); | 208 PushFrameSlotAt(element_count() - index - 1); |
209 } | 209 } |
210 | 210 |
211 // A frame-allocated local as an assembly operand. | 211 // A frame-allocated local as an assembly operand. |
212 MemOperand LocalAt(int index) { | 212 MemOperand LocalAt(int index) { |
213 ASSERT(0 <= index); | 213 ASSERT(0 <= index); |
214 ASSERT(index < local_count()); | 214 ASSERT(index < local_count()); |
215 return MemOperand(s8_fp, kLocal0Offset - index * kPointerSize); | 215 return MemOperand(s8_fp, kLocal0Offset - index * kPointerSize); |
216 } | 216 } |
217 | 217 |
218 // Push a copy of the value of a local frame slot on top of the frame. | 218 // Push a copy of the value of a local frame slot on top of the frame. |
219 void PushLocalAt(int index) { | 219 void PushLocalAt(int index) { |
220 PushFrameSlotAt(local0_index() + index); | 220 PushFrameSlotAt(local0_index() + index); |
221 } | 221 } |
222 | 222 |
223 // Push the value of a local frame slot on top of the frame and invalidate | 223 // Push the value of a local frame slot on top of the frame and invalidate |
224 // the local slot. The slot should be written to before trying to read | 224 // the local slot. The slot should be written to before trying to read |
225 // from it again. | 225 // from it again. |
226 void TakeLocalAt(int index) { | 226 void TakeLocalAt(int index) { |
227 TakeFrameSlotAt(local0_index() + index); | 227 TakeFrameSlotAt(local0_index() + index); |
228 } | 228 } |
229 | 229 |
230 // Store the top value on the virtual frame into a local frame slot. The | 230 // Store the top value on the virtual frame into a local frame slot. The |
231 // value is left in place on top of the frame. | 231 // value is left in place on top of the frame. |
232 void StoreToLocalAt(int index) { | 232 void StoreToLocalAt(int index) { |
233 StoreToFrameSlotAt(local0_index() + index); | 233 StoreToFrameSlotAt(local0_index() + index); |
234 } | 234 } |
235 | 235 |
236 // Push the address of the receiver slot on the frame. | 236 // Push the address of the receiver slot on the frame. |
237 void PushReceiverSlotAddress(); | 237 void PushReceiverSlotAddress(); |
238 | 238 |
239 // The function frame slot. | 239 // The function frame slot. |
240 MemOperand Function() { return MemOperand(s8_fp, kFunctionOffset); } | 240 MemOperand Function() { return MemOperand(s8_fp, kFunctionOffset); } |
(...skipping 19 matching lines...) Expand all Loading... |
260 uint16_t a = 0; // Number of argument slots. | 260 uint16_t a = 0; // Number of argument slots. |
261 return MemOperand(s8_fp, (1 + parameter_count() + a - index) *kPointerSize); | 261 return MemOperand(s8_fp, (1 + parameter_count() + a - index) *kPointerSize); |
262 } | 262 } |
263 | 263 |
264 // Push a copy of the value of a parameter frame slot on top of the frame. | 264 // Push a copy of the value of a parameter frame slot on top of the frame. |
265 void PushParameterAt(int index) { | 265 void PushParameterAt(int index) { |
266 PushFrameSlotAt(param0_index() + index); | 266 PushFrameSlotAt(param0_index() + index); |
267 } | 267 } |
268 | 268 |
269 // Push the value of a paramter frame slot on top of the frame and | 269 // Push the value of a paramter frame slot on top of the frame and |
270 // invalidate the parameter slot. The slot should be written to before | 270 // invalidate the parameter slot. The slot should be written to before |
271 // trying to read from it again. | 271 // trying to read from it again. |
272 void TakeParameterAt(int index) { | 272 void TakeParameterAt(int index) { |
273 TakeFrameSlotAt(param0_index() + index); | 273 TakeFrameSlotAt(param0_index() + index); |
274 } | 274 } |
275 | 275 |
276 // Store the top value on the virtual frame into a parameter frame slot. | 276 // Store the top value on the virtual frame into a parameter frame slot. |
277 // The value is left in place on top of the frame. | 277 // The value is left in place on top of the frame. |
278 void StoreToParameterAt(int index) { | 278 void StoreToParameterAt(int index) { |
279 StoreToFrameSlotAt(param0_index() + index); | 279 StoreToFrameSlotAt(param0_index() + index); |
280 } | 280 } |
281 | 281 |
282 // The receiver frame slot. | 282 // The receiver frame slot. |
283 MemOperand Receiver() { return ParameterAt(-1); } | 283 MemOperand Receiver() { return ParameterAt(-1); } |
284 | 284 |
285 // Push a try-catch or try-finally handler on top of the virtual frame. | 285 // Push a try-catch or try-finally handler on top of the virtual frame. |
286 void PushTryHandler(HandlerType type); | 286 void PushTryHandler(HandlerType type); |
287 | 287 |
288 // Call stub given the number of arguments it expects on (and | 288 // Call stub given the number of arguments it expects on (and |
289 // removes from) the stack. | 289 // removes from) the stack. |
290 void CallStub(CodeStub* stub, int arg_count) { | 290 void CallStub(CodeStub* stub, int arg_count) { |
291 PrepareForCall(arg_count, arg_count); | 291 PrepareForCall(arg_count, arg_count); |
292 RawCallStub(stub); | 292 RawCallStub(stub); |
293 } | 293 } |
294 | 294 |
295 // Call stub that expects its argument in r0. The argument is given | |
296 // as a result which must be the register r0. | |
297 void CallStub(CodeStub* stub, Result* arg); | 295 void CallStub(CodeStub* stub, Result* arg); |
298 | 296 |
299 // Call stub that expects its arguments in r1 and r0. The arguments | |
300 // are given as results which must be the appropriate registers. | |
301 void CallStub(CodeStub* stub, Result* arg0, Result* arg1); | 297 void CallStub(CodeStub* stub, Result* arg0, Result* arg1); |
302 | 298 |
303 // Call runtime given the number of arguments expected on (and | 299 // Call runtime given the number of arguments expected on (and |
304 // removed from) the stack. | 300 // removed from) the stack. |
305 void CallRuntime(Runtime::Function* f, int arg_count); | 301 void CallRuntime(Runtime::Function* f, int arg_count); |
306 void CallRuntime(Runtime::FunctionId id, int arg_count); | 302 void CallRuntime(Runtime::FunctionId id, int arg_count); |
307 | 303 |
308 // Call runtime with sp aligned to 8 bytes. | 304 // Call runtime with sp aligned to 8 bytes. |
309 void CallAlignedRuntime(Runtime::Function* f, int arg_count); | 305 void CallAlignedRuntime(Runtime::Function* f, int arg_count); |
310 void CallAlignedRuntime(Runtime::FunctionId id, int arg_count); | 306 void CallAlignedRuntime(Runtime::FunctionId id, int arg_count); |
311 | 307 |
312 // Invoke builtin given the number of arguments it expects on (and | 308 // Invoke builtin given the number of arguments it expects on (and |
313 // removes from) the stack. | 309 // removes from) the stack. |
314 void InvokeBuiltin(Builtins::JavaScript id, | 310 void InvokeBuiltin(Builtins::JavaScript id, |
315 InvokeJSFlags flag, | 311 InvokeJSFlags flag, |
316 Result* arg_count_register, | 312 Result* arg_count_register, |
317 int arg_count); | 313 int arg_count); |
318 | 314 |
319 // Call into an IC stub given the number of arguments it removes | 315 // Call into an IC stub given the number of arguments it removes |
320 // from the stack. Register arguments are passed as results and | 316 // from the stack. Register arguments are passed as results and |
321 // consumed by the call. | 317 // consumed by the call. |
322 void CallCodeObject(Handle<Code> ic, | 318 void CallCodeObject(Handle<Code> ic, |
323 RelocInfo::Mode rmode, | 319 RelocInfo::Mode rmode, |
324 int dropped_args); | 320 int dropped_args); |
325 void CallCodeObject(Handle<Code> ic, | 321 void CallCodeObject(Handle<Code> ic, |
326 RelocInfo::Mode rmode, | 322 RelocInfo::Mode rmode, |
327 Result* arg, | 323 Result* arg, |
328 int dropped_args); | 324 int dropped_args); |
329 void CallCodeObject(Handle<Code> ic, | 325 void CallCodeObject(Handle<Code> ic, |
330 RelocInfo::Mode rmode, | 326 RelocInfo::Mode rmode, |
331 Result* arg0, | 327 Result* arg0, |
332 Result* arg1, | 328 Result* arg1, |
333 int dropped_args, | 329 int dropped_args, |
334 bool set_auto_args_slots = false); | 330 bool set_auto_args_slots = false); |
335 | 331 |
336 // Drop a number of elements from the top of the expression stack. May | 332 // Drop a number of elements from the top of the expression stack. May |
337 // emit code to affect the physical frame. Does not clobber any registers | 333 // emit code to affect the physical frame. Does not clobber any registers |
338 // excepting possibly the stack pointer. | 334 // excepting possibly the stack pointer. |
339 void Drop(int count); | 335 void Drop(int count); |
340 // Similar to VirtualFrame::Drop but we don't modify the actual stack. | 336 // Similar to VirtualFrame::Drop but we don't modify the actual stack. |
341 // This is because we need to manually restore sp to the correct position. | 337 // This is because we need to manually restore sp to the correct position. |
342 void DropFromVFrameOnly(int count); | 338 void DropFromVFrameOnly(int count); |
343 | 339 |
344 // Drop one element. | 340 // Drop one element. |
345 void Drop() { Drop(1); } | 341 void Drop() { Drop(1); } |
346 void DropFromVFrameOnly() { DropFromVFrameOnly(1); } | 342 void DropFromVFrameOnly() { DropFromVFrameOnly(1); } |
347 | 343 |
348 // Duplicate the top element of the frame. | 344 // Duplicate the top element of the frame. |
349 void Dup() { PushFrameSlotAt(element_count() - 1); } | 345 void Dup() { PushFrameSlotAt(element_count() - 1); } |
350 | 346 |
351 // Pop an element from the top of the expression stack. Returns a | 347 // Pop an element from the top of the expression stack. Returns a |
352 // Result, which may be a constant or a register. | 348 // Result, which may be a constant or a register. |
353 Result Pop(); | 349 Result Pop(); |
354 | 350 |
355 // Pop and save an element from the top of the expression stack and | 351 // Pop and save an element from the top of the expression stack and |
356 // emit a corresponding pop instruction. | 352 // emit a corresponding pop instruction. |
357 void EmitPop(Register reg); | 353 void EmitPop(Register reg); |
358 // Same but for multiple registers | 354 // Same but for multiple registers |
359 void EmitMultiPop(RegList regs); // higher indexed registers popped first | 355 void EmitMultiPop(RegList regs); |
360 void EmitMultiPopReversed(RegList regs); // lower first | 356 void EmitMultiPopReversed(RegList regs); |
361 | 357 |
362 // Push an element on top of the expression stack and emit a | 358 // Push an element on top of the expression stack and emit a |
363 // corresponding push instruction. | 359 // corresponding push instruction. |
364 void EmitPush(Register reg); | 360 void EmitPush(Register reg); |
365 // Same but for multiple registers. | 361 // Same but for multiple registers. |
366 void EmitMultiPush(RegList regs); // lower indexed registers are pushed first | 362 void EmitMultiPush(RegList regs); |
367 void EmitMultiPushReversed(RegList regs); // higher first | 363 void EmitMultiPushReversed(RegList regs); |
368 | 364 |
369 // Push an element on the virtual frame. | 365 // Push an element on the virtual frame. |
370 inline void Push(Register reg, NumberInfo info = NumberInfo::Unknown()); | 366 inline void Push(Register reg, NumberInfo info = NumberInfo::Unknown()); |
371 inline void Push(Handle<Object> value); | 367 inline void Push(Handle<Object> value); |
372 inline void Push(Smi* value); | 368 inline void Push(Smi* value); |
373 | 369 |
374 // Pushing a result invalidates it (its contents become owned by the frame). | 370 // Pushing a result invalidates it (its contents become owned by the frame). |
375 void Push(Result* result) { | 371 void Push(Result* result) { |
376 if (result->is_register()) { | 372 if (result->is_register()) { |
377 Push(result->reg()); | 373 Push(result->reg()); |
378 } else { | 374 } else { |
379 ASSERT(result->is_constant()); | 375 ASSERT(result->is_constant()); |
380 Push(result->handle()); | 376 Push(result->handle()); |
381 } | 377 } |
382 result->Unuse(); | 378 result->Unuse(); |
383 } | 379 } |
384 | 380 |
385 // Nip removes zero or more elements from immediately below the top | 381 // Nip removes zero or more elements from immediately below the top |
386 // of the frame, leaving the previous top-of-frame value on top of | 382 // of the frame, leaving the previous top-of-frame value on top of |
387 // the frame. Nip(k) is equivalent to x = Pop(), Drop(k), Push(x). | 383 // the frame. Nip(k) is equivalent to x = Pop(), Drop(k), Push(x). |
388 inline void Nip(int num_dropped); | 384 inline void Nip(int num_dropped); |
389 | 385 |
390 // This pushes 4 arguments slots on the stack and saves asked 'a' registers | 386 // This pushes 4 arguments slots on the stack and saves asked 'a' registers |
391 // 'a' registers are arguments register a0 to a3. | 387 // 'a' registers are arguments register a0 to a3. |
392 void EmitArgumentSlots(RegList reglist); | 388 void EmitArgumentSlots(RegList reglist); |
393 | 389 |
394 inline void SetTypeForLocalAt(int index, NumberInfo info); | 390 inline void SetTypeForLocalAt(int index, NumberInfo info); |
| 391 inline void SetTypeForParamAt(int index, NumberInfo info); |
395 | 392 |
396 private: | 393 private: |
397 static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset; | 394 static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset; |
398 static const int kFunctionOffset = JavaScriptFrameConstants::kFunctionOffset; | 395 static const int kFunctionOffset = JavaScriptFrameConstants::kFunctionOffset; |
399 static const int kContextOffset = StandardFrameConstants::kContextOffset; | 396 static const int kContextOffset = StandardFrameConstants::kContextOffset; |
400 | 397 |
401 static const int kHandlerSize = StackHandlerConstants::kSize / kPointerSize; | 398 static const int kHandlerSize = StackHandlerConstants::kSize / kPointerSize; |
402 static const int kPreallocatedElements = 5 + 8; // 8 expression stack slots. | 399 static const int kPreallocatedElements = 5 + 8; // 8 expression stack slots. |
403 | 400 |
404 ZoneList<FrameElement> elements_; | 401 ZoneList<FrameElement> elements_; |
405 | 402 |
406 // The index of the element that is at the processor's stack pointer | 403 // The index of the element that is at the processor's stack pointer |
407 // (the sp register). | 404 // (the sp register). |
408 int stack_pointer_; | 405 int stack_pointer_; |
409 | 406 |
410 // The index of the register frame element using each register, or | 407 // The index of the register frame element using each register, or |
411 // kIllegalIndex if a register is not on the frame. | 408 // kIllegalIndex if a register is not on the frame. |
412 int register_locations_[RegisterAllocator::kNumRegisters]; | 409 int register_locations_[RegisterAllocator::kNumRegisters]; |
413 | 410 |
414 // The number of frame-allocated locals and parameters respectively. | 411 // The number of frame-allocated locals and parameters respectively. |
415 int parameter_count() { return cgen()->scope()->num_parameters(); } | 412 int parameter_count() { return cgen()->scope()->num_parameters(); } |
416 int local_count() { return cgen()->scope()->num_stack_slots(); } | 413 int local_count() { return cgen()->scope()->num_stack_slots(); } |
417 | 414 |
418 // The index of the element that is at the processor's frame pointer | 415 // The index of the element that is at the processor's frame pointer |
419 // (the fp register). The parameters, receiver, function, and context | 416 // (the fp register). The parameters, receiver, function, and context |
420 // are below the frame pointer. | 417 // are below the frame pointer. |
421 int frame_pointer() { return parameter_count() + 3; } | 418 int frame_pointer() { return parameter_count() + 3; } |
422 | 419 |
423 // The index of the first parameter. The receiver lies below the first | 420 // The index of the first parameter. The receiver lies below the first |
424 // parameter. | 421 // parameter. |
425 int param0_index() { return 1; } | 422 int param0_index() { return 1; } |
426 | 423 |
427 // The index of the context slot in the frame. It is immediately | 424 // The index of the context slot in the frame. It is immediately |
428 // below the frame pointer. | 425 // below the frame pointer. |
429 int context_index() { return frame_pointer() - 1; } | 426 int context_index() { return frame_pointer() - 1; } |
430 | 427 |
431 // The index of the function slot in the frame. It is below the frame | 428 // The index of the function slot in the frame. It is below the frame |
432 // pointer and context slot. | 429 // pointer and context slot. |
433 int function_index() { return frame_pointer() - 2; } | 430 int function_index() { return frame_pointer() - 2; } |
434 | 431 |
435 // The index of the first local. Between the frame pointer and the | 432 // The index of the first local. Between the frame pointer and the |
436 // locals lies the return address. | 433 // locals lies the return address. |
437 int local0_index() { return frame_pointer() + 2; } | 434 int local0_index() { return frame_pointer() + 2; } |
438 | 435 |
439 // The index of the base of the expression stack. | 436 // The index of the base of the expression stack. |
440 int expression_base_index() { return local0_index() + local_count(); } | 437 int expression_base_index() { return local0_index() + local_count(); } |
441 | 438 |
442 // Convert a frame index into a frame pointer relative offset into the | 439 // Convert a frame index into a frame pointer relative offset into the |
443 // actual stack. | 440 // actual stack. |
444 int fp_relative(int index) { | 441 int fp_relative(int index) { |
445 ASSERT(index < element_count()); | 442 ASSERT(index < element_count()); |
446 ASSERT(frame_pointer() < element_count()); // FP is on the frame. | 443 ASSERT(frame_pointer() < element_count()); // FP is on the frame. |
447 return (frame_pointer() - index) * kPointerSize; | 444 return (frame_pointer() - index) * kPointerSize; |
448 } | 445 } |
449 | 446 |
450 // Record an occurrence of a register in the virtual frame. This has the | 447 // Record an occurrence of a register in the virtual frame. This has the |
451 // effect of incrementing the register's external reference count and | 448 // effect of incrementing the register's external reference count and |
452 // of updating the index of the register's location in the frame. | 449 // of updating the index of the register's location in the frame. |
453 void Use(Register reg, int index) { | 450 void Use(Register reg, int index) { |
454 ASSERT(!is_used(reg)); | 451 ASSERT(!is_used(reg)); |
455 set_register_location(reg, index); | 452 set_register_location(reg, index); |
456 cgen()->allocator()->Use(reg); | 453 cgen()->allocator()->Use(reg); |
457 } | 454 } |
458 | 455 |
459 // Record that a register reference has been dropped from the frame. This | 456 // Record that a register reference has been dropped from the frame. This |
460 // decrements the register's external reference count and invalidates the | 457 // decrements the register's external reference count and invalidates the |
461 // index of the register's location in the frame. | 458 // index of the register's location in the frame. |
462 void Unuse(Register reg) { | 459 void Unuse(Register reg) { |
463 ASSERT(is_used(reg)); | 460 ASSERT(is_used(reg)); |
464 set_register_location(reg, kIllegalIndex); | 461 set_register_location(reg, kIllegalIndex); |
465 cgen()->allocator()->Unuse(reg); | 462 cgen()->allocator()->Unuse(reg); |
466 } | 463 } |
467 | 464 |
468 // Spill the element at a particular index---write it to memory if | 465 // Spill the element at a particular index---write it to memory if |
469 // necessary, free any associated register, and forget its value if | 466 // necessary, free any associated register, and forget its value if |
470 // constant. | 467 // constant. |
471 void SpillElementAt(int index); | 468 void SpillElementAt(int index); |
472 | 469 |
473 // Sync the element at a particular index. If it is a register or | 470 // Sync the element at a particular index. If it is a register or |
474 // constant that disagrees with the value on the stack, write it to memory. | 471 // constant that disagrees with the value on the stack, write it to memory. |
475 // Keep the element type as register or constant, and clear the dirty bit. | 472 // Keep the element type as register or constant, and clear the dirty bit. |
476 void SyncElementAt(int index); | 473 void SyncElementAt(int index); |
477 | 474 |
478 // Sync the range of elements in [begin, end] with memory. | 475 // Sync the range of elements in [begin, end] with memory. |
479 void SyncRange(int begin, int end); | 476 void SyncRange(int begin, int end); |
480 | 477 |
481 // Sync a single unsynced element that lies beneath or at the stack pointer. | 478 // Sync a single unsynced element that lies beneath or at the stack pointer. |
482 void SyncElementBelowStackPointer(int index); | 479 void SyncElementBelowStackPointer(int index); |
483 | 480 |
484 // Sync a single unsynced element that lies just above the stack pointer. | 481 // Sync a single unsynced element that lies just above the stack pointer. |
485 void SyncElementByPushing(int index); | 482 void SyncElementByPushing(int index); |
486 | 483 |
487 // Push a copy of a frame slot (typically a local or parameter) on top of | 484 // Push a copy of a frame slot (typically a local or parameter) on top of |
488 // the frame. | 485 // the frame. |
489 inline void PushFrameSlotAt(int index); | 486 inline void PushFrameSlotAt(int index); |
490 | 487 |
491 // Push a the value of a frame slot (typically a local or parameter) on | 488 // Push a the value of a frame slot (typically a local or parameter) on |
492 // top of the frame and invalidate the slot. | 489 // top of the frame and invalidate the slot. |
493 void TakeFrameSlotAt(int index); | 490 void TakeFrameSlotAt(int index); |
494 | 491 |
495 // Store the value on top of the frame to a frame slot (typically a local | 492 // Store the value on top of the frame to a frame slot (typically a local |
496 // or parameter). | 493 // or parameter). |
497 void StoreToFrameSlotAt(int index); | 494 void StoreToFrameSlotAt(int index); |
498 | 495 |
499 // Spill all elements in registers. Spill the top spilled_args elements | 496 // Spill all elements in registers. Spill the top spilled_args elements |
500 // on the frame. Sync all other frame elements. | 497 // on the frame. Sync all other frame elements. |
501 // Then drop dropped_args elements from the virtual frame, to match | 498 // Then drop dropped_args elements from the virtual frame, to match |
502 // the effect of an upcoming call that will drop them from the stack. | 499 // the effect of an upcoming call that will drop them from the stack. |
503 void PrepareForCall(int spilled_args, int dropped_args); | 500 void PrepareForCall(int spilled_args, int dropped_args); |
504 | 501 |
505 // Move frame elements currently in registers or constants, that | 502 // Move frame elements currently in registers or constants, that |
506 // should be in memory in the expected frame, to memory. | 503 // should be in memory in the expected frame, to memory. |
507 void MergeMoveRegistersToMemory(VirtualFrame* expected); | 504 void MergeMoveRegistersToMemory(VirtualFrame* expected); |
508 | 505 |
509 // Make the register-to-register moves necessary to | 506 // Make the register-to-register moves necessary to |
510 // merge this frame with the expected frame. | 507 // merge this frame with the expected frame. |
511 // Register to memory moves must already have been made, | 508 // Register to memory moves must already have been made, |
512 // and memory to register moves must follow this call. | 509 // and memory to register moves must follow this call. |
513 // This is because some new memory-to-register moves are | 510 // This is because some new memory-to-register moves are |
514 // created in order to break cycles of register moves. | 511 // created in order to break cycles of register moves. |
515 // Used in the implementation of MergeTo(). | 512 // Used in the implementation of MergeTo(). |
516 void MergeMoveRegistersToRegisters(VirtualFrame* expected); | 513 void MergeMoveRegistersToRegisters(VirtualFrame* expected); |
517 | 514 |
518 // Make the memory-to-register and constant-to-register moves | 515 // Make the memory-to-register and constant-to-register moves |
519 // needed to make this frame equal the expected frame. | 516 // needed to make this frame equal the expected frame. |
520 // Called after all register-to-memory and register-to-register | 517 // Called after all register-to-memory and register-to-register |
521 // moves have been made. After this function returns, the frames | 518 // moves have been made. After this function returns, the frames |
522 // should be equal. | 519 // should be equal. |
523 void MergeMoveMemoryToRegisters(VirtualFrame* expected); | 520 void MergeMoveMemoryToRegisters(VirtualFrame* expected); |
524 | 521 |
525 // Invalidates a frame slot (puts an invalid frame element in it). | 522 // Invalidates a frame slot (puts an invalid frame element in it). |
526 // Copies on the frame are correctly handled, and if this slot was | 523 // Copies on the frame are correctly handled, and if this slot was |
527 // the backing store of copies, the index of the new backing store | 524 // the backing store of copies, the index of the new backing store |
528 // is returned. Otherwise, returns kIllegalIndex. | 525 // is returned. Otherwise, returns kIllegalIndex. |
529 // Register counts are correctly updated. | 526 // Register counts are correctly updated. |
530 int InvalidateFrameSlotAt(int index); | 527 int InvalidateFrameSlotAt(int index); |
531 | 528 |
532 // Call a code stub that has already been prepared for calling (via | 529 // Call a code stub that has already been prepared for calling (via |
533 // PrepareForCall). | 530 // PrepareForCall). |
534 void RawCallStub(CodeStub* stub); | 531 void RawCallStub(CodeStub* stub); |
535 | 532 |
536 // Calls a code object which has already been prepared for calling | 533 // Calls a code object which has already been prepared for calling |
537 // (via PrepareForCall). | 534 // (via PrepareForCall). |
538 void RawCallCodeObject(Handle<Code> code, RelocInfo::Mode rmode); | 535 void RawCallCodeObject(Handle<Code> code, RelocInfo::Mode rmode); |
539 | 536 |
540 inline bool Equals(VirtualFrame* other); | 537 inline bool Equals(VirtualFrame* other); |
541 | 538 |
542 // Classes that need raw access to the elements_ array. | 539 // Classes that need raw access to the elements_ array. |
543 friend class DeferredCode; | 540 friend class DeferredCode; |
544 friend class JumpTarget; | 541 friend class JumpTarget; |
545 }; | 542 }; |
546 | 543 |
547 | 544 |
548 } } // namespace v8::internal | 545 } } // namespace v8::internal |
549 | 546 |
550 #endif // V8_MIPS_VIRTUAL_FRAME_MIPS_H_ | 547 #endif // V8_MIPS_VIRTUAL_FRAME_MIPS_H_ |
551 | 548 |
OLD | NEW |