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

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

Issue 6759025: Version 3.2.6 (Closed) Base URL: https://v8.googlecode.com/svn/trunk
Patch Set: Created 9 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
« no previous file with comments | « src/mips/stub-cache-mips.cc ('k') | src/mips/virtual-frame-mips.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 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 12 matching lines...) Expand all
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 28
29 #ifndef V8_MIPS_VIRTUAL_FRAME_MIPS_H_ 29 #ifndef V8_MIPS_VIRTUAL_FRAME_MIPS_H_
30 #define V8_MIPS_VIRTUAL_FRAME_MIPS_H_ 30 #define V8_MIPS_VIRTUAL_FRAME_MIPS_H_
31 31
32 #include "register-allocator.h" 32 #include "register-allocator.h"
33 #include "scopes.h"
34 33
35 namespace v8 { 34 namespace v8 {
36 namespace internal { 35 namespace internal {
37 36
37 // This dummy class is only used to create invalid virtual frames.
38 extern class InvalidVirtualFrameInitializer {}* kInvalidVirtualFrameInitializer;
39
38 40
39 // ------------------------------------------------------------------------- 41 // -------------------------------------------------------------------------
40 // Virtual frames 42 // Virtual frames
41 // 43 //
42 // The virtual frame is an abstraction of the physical stack frame. It 44 // The virtual frame is an abstraction of the physical stack frame. It
43 // encapsulates the parameters, frame-allocated locals, and the expression 45 // encapsulates the parameters, frame-allocated locals, and the expression
44 // stack. It supports push/pop operations on the expression stack, as well 46 // stack. It supports push/pop operations on the expression stack, as well
45 // as random access to the expression stack elements, locals, and 47 // as random access to the expression stack elements, locals, and
46 // parameters. 48 // parameters.
47 49
48 class VirtualFrame : public ZoneObject { 50 class VirtualFrame : public ZoneObject {
49 public: 51 public:
52 class RegisterAllocationScope;
50 // A utility class to introduce a scope where the virtual frame is 53 // A utility class to introduce a scope where the virtual frame is
51 // expected to remain spilled. The constructor spills the code 54 // expected to remain spilled. The constructor spills the code
52 // generator's current frame, but no attempt is made to require it 55 // generator's current frame, and keeps it spilled.
53 // to stay spilled. It is intended as documentation while the code
54 // generator is being transformed.
55 class SpilledScope BASE_EMBEDDED { 56 class SpilledScope BASE_EMBEDDED {
56 public: 57 public:
58 explicit SpilledScope(VirtualFrame* frame)
59 : old_is_spilled_(
60 Isolate::Current()->is_virtual_frame_in_spilled_scope()) {
61 if (frame != NULL) {
62 if (!old_is_spilled_) {
63 frame->SpillAll();
64 } else {
65 frame->AssertIsSpilled();
66 }
67 }
68 Isolate::Current()->set_is_virtual_frame_in_spilled_scope(true);
69 }
70 ~SpilledScope() {
71 Isolate::Current()->set_is_virtual_frame_in_spilled_scope(
72 old_is_spilled_);
73 }
74 static bool is_spilled() {
75 return Isolate::Current()->is_virtual_frame_in_spilled_scope();
76 }
77
78 private:
79 int old_is_spilled_;
80
57 SpilledScope() {} 81 SpilledScope() {}
82
83 friend class RegisterAllocationScope;
84 };
85
86 class RegisterAllocationScope BASE_EMBEDDED {
87 public:
88 // A utility class to introduce a scope where the virtual frame
89 // is not spilled, ie. where register allocation occurs. Eventually
90 // when RegisterAllocationScope is ubiquitous it can be removed
91 // along with the (by then unused) SpilledScope class.
92 inline explicit RegisterAllocationScope(CodeGenerator* cgen);
93 inline ~RegisterAllocationScope();
94
95 private:
96 CodeGenerator* cgen_;
97 bool old_is_spilled_;
98
99 RegisterAllocationScope() {}
58 }; 100 };
59 101
60 // An illegal index into the virtual frame. 102 // An illegal index into the virtual frame.
61 static const int kIllegalIndex = -1; 103 static const int kIllegalIndex = -1;
62 104
63 // Construct an initial virtual frame on entry to a JS function. 105 // Construct an initial virtual frame on entry to a JS function.
64 inline VirtualFrame(); 106 inline VirtualFrame();
65 107
108 // Construct an invalid virtual frame, used by JumpTargets.
109 inline VirtualFrame(InvalidVirtualFrameInitializer* dummy);
110
66 // Construct a virtual frame as a clone of an existing one. 111 // Construct a virtual frame as a clone of an existing one.
67 explicit inline VirtualFrame(VirtualFrame* original); 112 explicit inline VirtualFrame(VirtualFrame* original);
68 113
69 CodeGenerator* cgen() { return CodeGeneratorScope::Current(); } 114 inline CodeGenerator* cgen() const;
70 MacroAssembler* masm() { return cgen()->masm(); } 115 inline MacroAssembler* masm();
71
72 // Create a duplicate of an existing valid frame element.
73 FrameElement CopyElementAt(int index,
74 NumberInfo info = NumberInfo::Unknown());
75 116
76 // The number of elements on the virtual frame. 117 // The number of elements on the virtual frame.
77 int element_count() { return elements_.length(); } 118 int element_count() const { return element_count_; }
78 119
79 // The height of the virtual expression stack. 120 // The height of the virtual expression stack.
80 int height() { 121 inline int height() const;
81 return element_count() - expression_base_index();
82 }
83
84 int register_location(int num) {
85 ASSERT(num >= 0 && num < RegisterAllocator::kNumRegisters);
86 return register_locations_[num];
87 }
88
89 int register_location(Register reg) {
90 return register_locations_[RegisterAllocator::ToNumber(reg)];
91 }
92
93 void set_register_location(Register reg, int index) {
94 register_locations_[RegisterAllocator::ToNumber(reg)] = index;
95 }
96 122
97 bool is_used(int num) { 123 bool is_used(int num) {
98 ASSERT(num >= 0 && num < RegisterAllocator::kNumRegisters); 124 switch (num) {
99 return register_locations_[num] != kIllegalIndex; 125 case 0: { // a0.
100 } 126 return kA0InUse[top_of_stack_state_];
101 127 }
102 bool is_used(Register reg) { 128 case 1: { // a1.
103 return register_locations_[RegisterAllocator::ToNumber(reg)] 129 return kA1InUse[top_of_stack_state_];
104 != kIllegalIndex; 130 }
131 case 2:
132 case 3:
133 case 4:
134 case 5:
135 case 6: { // a2 to a3, t0 to t2.
136 ASSERT(num - kFirstAllocatedRegister < kNumberOfAllocatedRegisters);
137 ASSERT(num >= kFirstAllocatedRegister);
138 if ((register_allocation_map_ &
139 (1 << (num - kFirstAllocatedRegister))) == 0) {
140 return false;
141 } else {
142 return true;
143 }
144 }
145 default: {
146 ASSERT(num < kFirstAllocatedRegister ||
147 num >= kFirstAllocatedRegister + kNumberOfAllocatedRegisters);
148 return false;
149 }
150 }
105 } 151 }
106 152
107 // Add extra in-memory elements to the top of the frame to match an actual 153 // 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 154 // frame (eg, the frame after an exception handler is pushed). No code is
109 // emitted. 155 // emitted.
110 void Adjust(int count); 156 void Adjust(int count);
111 157
112 // Forget elements from the top of the frame to match an actual frame (eg, 158 // 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. 159 // the frame after a runtime call). No code is emitted except to bring the
114 void Forget(int count) { 160 // frame to a spilled state.
115 ASSERT(count >= 0); 161 void Forget(int count);
116 ASSERT(stack_pointer_ == element_count() - 1);
117 stack_pointer_ -= count;
118 // On mips, all elements are in memory, so there is no extra bookkeeping
119 // (registers, copies, etc.) beyond dropping the elements.
120 elements_.Rewind(stack_pointer_ + 1);
121 }
122 162
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
125 // break, continue, and return targets.
126 void ForgetElements(int count);
127 163
128 // Spill all values from the frame to memory. 164 // Spill all values from the frame to memory.
129 void SpillAll(); 165 void SpillAll();
130 166
167 void AssertIsSpilled() const {
168 ASSERT(top_of_stack_state_ == NO_TOS_REGISTERS);
169 ASSERT(register_allocation_map_ == 0);
170 }
171
172 void AssertIsNotSpilled() {
173 ASSERT(!SpilledScope::is_spilled());
174 }
175
131 // Spill all occurrences of a specific register from the frame. 176 // Spill all occurrences of a specific register from the frame.
132 void Spill(Register reg) { 177 void Spill(Register reg) {
133 if (is_used(reg)) SpillElementAt(register_location(reg)); 178 UNIMPLEMENTED();
134 } 179 }
135 180
136 // Spill all occurrences of an arbitrary register if possible. Return the 181 // 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 182 // register spilled or no_reg if it was not possible to free any register
138 // (ie, they all have frame-external references). 183 // (ie, they all have frame-external references). Unimplemented.
139 Register SpillAnyRegister(); 184 Register SpillAnyRegister();
140 185
141 // Prepare this virtual frame for merging to an expected frame by
142 // performing some state changes that do not require generating
143 // code. It is guaranteed that no code will be generated.
144 void PrepareMergeTo(VirtualFrame* expected);
145
146 // Make this virtual frame have a state identical to an expected virtual 186 // 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 187 // frame. As a side effect, code may be emitted to make this frame match
148 // the expected one. 188 // the expected one.
149 void MergeTo(VirtualFrame* expected); 189 void MergeTo(const VirtualFrame* expected,
190 Condition cond = al,
191 Register r1 = no_reg,
192 const Operand& r2 = Operand(no_reg));
193
194 void MergeTo(VirtualFrame* expected,
195 Condition cond = al,
196 Register r1 = no_reg,
197 const Operand& r2 = Operand(no_reg));
198
199 // Checks whether this frame can be branched to by the other frame.
200 bool IsCompatibleWith(const VirtualFrame* other) const {
201 return (tos_known_smi_map_ & (~other->tos_known_smi_map_)) == 0;
202 }
203
204 inline void ForgetTypeInfo() {
205 tos_known_smi_map_ = 0;
206 }
150 207
151 // Detach a frame from its code generator, perhaps temporarily. This 208 // Detach a frame from its code generator, perhaps temporarily. This
152 // tells the register allocator that it is free to use frame-internal 209 // 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 210 // registers. Used when the code generator's frame is switched from this
154 // one to NULL by an unconditional jump. 211 // one to NULL by an unconditional jump.
155 void DetachFromCodeGenerator() { 212 void DetachFromCodeGenerator() {
156 RegisterAllocator* cgen_allocator = cgen()->allocator();
157 for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
158 if (is_used(i)) cgen_allocator->Unuse(i);
159 }
160 } 213 }
161 214
162 // (Re)attach a frame to its code generator. This informs the register 215 // (Re)attach a frame to its code generator. This informs the register
163 // allocator that the frame-internal register references are active again. 216 // 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 217 // Used when a code generator's frame is switched from NULL to this one by
165 // binding a label. 218 // binding a label.
166 void AttachToCodeGenerator() { 219 void AttachToCodeGenerator() {
167 RegisterAllocator* cgen_allocator = cgen()->allocator();
168 for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
169 if (is_used(i)) cgen_allocator->Unuse(i);
170 }
171 } 220 }
172 221
173 // Emit code for the physical JS entry and exit frame sequences. After 222 // 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 223 // 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 224 // Exit it should not be used. Note that Enter does not allocate space in
176 // the physical frame for storing frame-allocated locals. 225 // the physical frame for storing frame-allocated locals.
177 void Enter(); 226 void Enter();
178 void Exit(); 227 void Exit();
179 228
180 // Prepare for returning from the frame by spilling locals and 229 // Prepare for returning from the frame by elements in the virtual frame.
181 // dropping all non-locals elements in the virtual frame. This 230 // This avoids generating unnecessary merge code when jumping to the shared
182 // avoids generating unnecessary merge code when jumping to the 231 // return site. No spill code emitted. Value to return should be in v0.
183 // shared return site. Emits code for spills. 232 inline void PrepareForReturn();
184 void PrepareForReturn(); 233
234 // Number of local variables after when we use a loop for allocating.
235 static const int kLocalVarBound = 5;
185 236
186 // Allocate and initialize the frame-allocated locals. 237 // Allocate and initialize the frame-allocated locals.
187 void AllocateStackSlots(); 238 void AllocateStackSlots();
188 239
189 // The current top of the expression stack as an assembly operand. 240 // The current top of the expression stack as an assembly operand.
190 MemOperand Top() { return MemOperand(sp, 0); } 241 MemOperand Top() {
242 AssertIsSpilled();
243 return MemOperand(sp, 0);
244 }
191 245
192 // An element of the expression stack as an assembly operand. 246 // An element of the expression stack as an assembly operand.
193 MemOperand ElementAt(int index) { 247 MemOperand ElementAt(int index) {
194 return MemOperand(sp, index * kPointerSize); 248 int adjusted_index = index - kVirtualElements[top_of_stack_state_];
249 ASSERT(adjusted_index >= 0);
250 return MemOperand(sp, adjusted_index * kPointerSize);
195 } 251 }
196 252
197 // Random-access store to a frame-top relative frame element. The result 253 bool KnownSmiAt(int index) {
198 // becomes owned by the frame and is invalidated. 254 if (index >= kTOSKnownSmiMapSize) return false;
199 void SetElementAt(int index, Result* value); 255 return (tos_known_smi_map_ & (1 << index)) != 0;
200
201 // Set a frame element to a constant. The index is frame-top relative.
202 void SetElementAt(int index, Handle<Object> value) {
203 Result temp(value);
204 SetElementAt(index, &temp);
205 } 256 }
206
207 void PushElementAt(int index) {
208 PushFrameSlotAt(element_count() - index - 1);
209 }
210
211 // A frame-allocated local as an assembly operand. 257 // A frame-allocated local as an assembly operand.
212 MemOperand LocalAt(int index) { 258 inline MemOperand LocalAt(int index);
213 ASSERT(0 <= index);
214 ASSERT(index < local_count());
215 return MemOperand(s8_fp, kLocal0Offset - index * kPointerSize);
216 }
217
218 // Push a copy of the value of a local frame slot on top of the frame.
219 void PushLocalAt(int index) {
220 PushFrameSlotAt(local0_index() + index);
221 }
222
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
225 // from it again.
226 void TakeLocalAt(int index) {
227 TakeFrameSlotAt(local0_index() + index);
228 }
229
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.
232 void StoreToLocalAt(int index) {
233 StoreToFrameSlotAt(local0_index() + index);
234 }
235 259
236 // Push the address of the receiver slot on the frame. 260 // Push the address of the receiver slot on the frame.
237 void PushReceiverSlotAddress(); 261 void PushReceiverSlotAddress();
238 262
239 // The function frame slot. 263 // The function frame slot.
240 MemOperand Function() { return MemOperand(s8_fp, kFunctionOffset); } 264 MemOperand Function() { return MemOperand(fp, kFunctionOffset); }
241
242 // Push the function on top of the frame.
243 void PushFunction() { PushFrameSlotAt(function_index()); }
244 265
245 // The context frame slot. 266 // The context frame slot.
246 MemOperand Context() { return MemOperand(s8_fp, kContextOffset); } 267 MemOperand Context() { return MemOperand(fp, kContextOffset); }
247
248 // Save the value of the cp register to the context frame slot.
249 void SaveContextRegister();
250
251 // Restore the cp register from the value of the context frame
252 // slot.
253 void RestoreContextRegister();
254 268
255 // A parameter as an assembly operand. 269 // A parameter as an assembly operand.
256 MemOperand ParameterAt(int index) { 270 inline MemOperand ParameterAt(int index);
257 // Index -1 corresponds to the receiver.
258 ASSERT(-1 <= index); // -1 is the receiver.
259 ASSERT(index <= parameter_count());
260 uint16_t a = 0; // Number of argument slots.
261 return MemOperand(s8_fp, (1 + parameter_count() + a - index) *kPointerSize);
262 }
263
264 // Push a copy of the value of a parameter frame slot on top of the frame.
265 void PushParameterAt(int index) {
266 PushFrameSlotAt(param0_index() + index);
267 }
268
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
271 // trying to read from it again.
272 void TakeParameterAt(int index) {
273 TakeFrameSlotAt(param0_index() + index);
274 }
275
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.
278 void StoreToParameterAt(int index) {
279 StoreToFrameSlotAt(param0_index() + index);
280 }
281 271
282 // The receiver frame slot. 272 // The receiver frame slot.
283 MemOperand Receiver() { return ParameterAt(-1); } 273 inline MemOperand Receiver();
284 274
285 // Push a try-catch or try-finally handler on top of the virtual frame. 275 // Push a try-catch or try-finally handler on top of the virtual frame.
286 void PushTryHandler(HandlerType type); 276 void PushTryHandler(HandlerType type);
287 277
288 // Call stub given the number of arguments it expects on (and 278 // Call stub given the number of arguments it expects on (and
289 // removes from) the stack. 279 // removes from) the stack.
290 void CallStub(CodeStub* stub, int arg_count) { 280 inline void CallStub(CodeStub* stub, int arg_count);
291 PrepareForCall(arg_count, arg_count);
292 RawCallStub(stub);
293 }
294 281
295 void CallStub(CodeStub* stub, Result* arg); 282 // Call JS function from top of the stack with arguments
296 283 // taken from the stack.
297 void CallStub(CodeStub* stub, Result* arg0, Result* arg1); 284 void CallJSFunction(int arg_count);
298 285
299 // Call runtime given the number of arguments expected on (and 286 // Call runtime given the number of arguments expected on (and
300 // removed from) the stack. 287 // removed from) the stack.
301 void CallRuntime(Runtime::Function* f, int arg_count); 288 void CallRuntime(const Runtime::Function* f, int arg_count);
302 void CallRuntime(Runtime::FunctionId id, int arg_count); 289 void CallRuntime(Runtime::FunctionId id, int arg_count);
303 290
304 // Call runtime with sp aligned to 8 bytes. 291 #ifdef ENABLE_DEBUGGER_SUPPORT
305 void CallAlignedRuntime(Runtime::Function* f, int arg_count); 292 void DebugBreak();
306 void CallAlignedRuntime(Runtime::FunctionId id, int arg_count); 293 #endif
307 294
308 // Invoke builtin given the number of arguments it expects on (and 295 // Invoke builtin given the number of arguments it expects on (and
309 // removes from) the stack. 296 // removes from) the stack.
310 void InvokeBuiltin(Builtins::JavaScript id, 297 void InvokeBuiltin(Builtins::JavaScript id,
311 InvokeJSFlags flag, 298 InvokeJSFlags flag,
312 Result* arg_count_register,
313 int arg_count); 299 int arg_count);
314 300
301 // Call load IC. Receiver is on the stack and is consumed. Result is returned
302 // in v0.
303 void CallLoadIC(Handle<String> name, RelocInfo::Mode mode);
304
305 // Call store IC. If the load is contextual, value is found on top of the
306 // frame. If not, value and receiver are on the frame. Both are consumed.
307 // Result is returned in v0.
308 void CallStoreIC(Handle<String> name, bool is_contextual);
309
310 // Call keyed load IC. Key and receiver are on the stack. Both are consumed.
311 // Result is returned in v0.
312 void CallKeyedLoadIC();
313
314 // Call keyed store IC. Value, key and receiver are on the stack. All three
315 // are consumed. Result is returned in v0 (and a0).
316 void CallKeyedStoreIC();
317
315 // Call into an IC stub given the number of arguments it removes 318 // Call into an IC stub given the number of arguments it removes
316 // from the stack. Register arguments are passed as results and 319 // from the stack. Register arguments to the IC stub are implicit,
317 // consumed by the call. 320 // and depend on the type of IC stub.
318 void CallCodeObject(Handle<Code> ic, 321 void CallCodeObject(Handle<Code> ic,
319 RelocInfo::Mode rmode, 322 RelocInfo::Mode rmode,
320 int dropped_args); 323 int dropped_args);
321 void CallCodeObject(Handle<Code> ic,
322 RelocInfo::Mode rmode,
323 Result* arg,
324 int dropped_args);
325 void CallCodeObject(Handle<Code> ic,
326 RelocInfo::Mode rmode,
327 Result* arg0,
328 Result* arg1,
329 int dropped_args,
330 bool set_auto_args_slots = false);
331 324
332 // Drop a number of elements from the top of the expression stack. May 325 // Drop a number of elements from the top of the expression stack. May
333 // emit code to affect the physical frame. Does not clobber any registers 326 // emit code to affect the physical frame. Does not clobber any registers
334 // excepting possibly the stack pointer. 327 // excepting possibly the stack pointer.
335 void Drop(int count); 328 void Drop(int count);
336 // Similar to VirtualFrame::Drop but we don't modify the actual stack.
337 // This is because we need to manually restore sp to the correct position.
338 void DropFromVFrameOnly(int count);
339 329
340 // Drop one element. 330 // Drop one element.
341 void Drop() { Drop(1); } 331 void Drop() { Drop(1); }
342 void DropFromVFrameOnly() { DropFromVFrameOnly(1); }
343 332
344 // Duplicate the top element of the frame. 333 // Pop an element from the top of the expression stack. Discards
345 void Dup() { PushFrameSlotAt(element_count() - 1); } 334 // the result.
335 void Pop();
346 336
347 // Pop an element from the top of the expression stack. Returns a 337 // Pop an element from the top of the expression stack. The register
348 // Result, which may be a constant or a register. 338 // will be one normally used for the top of stack register allocation
349 Result Pop(); 339 // so you can't hold on to it if you push on the stack.
340 Register PopToRegister(Register but_not_to_this_one = no_reg);
341
342 // Look at the top of the stack. The register returned is aliased and
343 // must be copied to a scratch register before modification.
344 Register Peek();
345
346 // Look at the value beneath the top of the stack. The register returned is
347 // aliased and must be copied to a scratch register before modification.
348 Register Peek2();
349
350 // Duplicate the top of stack.
351 void Dup();
352
353 // Duplicate the two elements on top of stack.
354 void Dup2();
355
356 // Flushes all registers, but it puts a copy of the top-of-stack in a0.
357 void SpillAllButCopyTOSToA0();
358
359 // Flushes all registers, but it puts a copy of the top-of-stack in a1.
360 void SpillAllButCopyTOSToA1();
361
362 // Flushes all registers, but it puts a copy of the top-of-stack in a1
363 // and the next value on the stack in a0.
364 void SpillAllButCopyTOSToA1A0();
350 365
351 // Pop and save an element from the top of the expression stack and 366 // Pop and save an element from the top of the expression stack and
352 // emit a corresponding pop instruction. 367 // emit a corresponding pop instruction.
353 void EmitPop(Register reg); 368 void EmitPop(Register reg);
354 // Same but for multiple registers 369 // Same but for multiple registers
355 void EmitMultiPop(RegList regs); 370 void EmitMultiPop(RegList regs);
356 void EmitMultiPopReversed(RegList regs); 371 void EmitMultiPopReversed(RegList regs);
357 372
373
374 // Takes the top two elements and puts them in a0 (top element) and a1
375 // (second element).
376 void PopToA1A0();
377
378 // Takes the top element and puts it in a1.
379 void PopToA1();
380
381 // Takes the top element and puts it in a0.
382 void PopToA0();
383
358 // Push an element on top of the expression stack and emit a 384 // Push an element on top of the expression stack and emit a
359 // corresponding push instruction. 385 // corresponding push instruction.
360 void EmitPush(Register reg); 386 void EmitPush(Register reg, TypeInfo type_info = TypeInfo::Unknown());
387 void EmitPush(Operand operand, TypeInfo type_info = TypeInfo::Unknown());
388 void EmitPush(MemOperand operand, TypeInfo type_info = TypeInfo::Unknown());
389 void EmitPushRoot(Heap::RootListIndex index);
390
391 // Overwrite the nth thing on the stack. If the nth position is in a
392 // register then this turns into a Move, otherwise an sw. Afterwards
393 // you can still use the register even if it is a register that can be
394 // used for TOS (a0 or a1).
395 void SetElementAt(Register reg, int this_far_down);
396
397 // Get a register which is free and which must be immediately used to
398 // push on the top of the stack.
399 Register GetTOSRegister();
400
361 // Same but for multiple registers. 401 // Same but for multiple registers.
362 void EmitMultiPush(RegList regs); 402 void EmitMultiPush(RegList regs);
363 void EmitMultiPushReversed(RegList regs); 403 void EmitMultiPushReversed(RegList regs);
364 404
365 // Push an element on the virtual frame. 405 static Register scratch0() { return t4; }
366 inline void Push(Register reg, NumberInfo info = NumberInfo::Unknown()); 406 static Register scratch1() { return t5; }
367 inline void Push(Handle<Object> value); 407 static Register scratch2() { return t6; }
368 inline void Push(Smi* value);
369
370 // Pushing a result invalidates it (its contents become owned by the frame).
371 void Push(Result* result) {
372 if (result->is_register()) {
373 Push(result->reg());
374 } else {
375 ASSERT(result->is_constant());
376 Push(result->handle());
377 }
378 result->Unuse();
379 }
380
381 // Nip removes zero or more elements from immediately below the top
382 // of the frame, leaving the previous top-of-frame value on top of
383 // the frame. Nip(k) is equivalent to x = Pop(), Drop(k), Push(x).
384 inline void Nip(int num_dropped);
385
386 // This pushes 4 arguments slots on the stack and saves asked 'a' registers
387 // 'a' registers are arguments register a0 to a3.
388 void EmitArgumentSlots(RegList reglist);
389
390 inline void SetTypeForLocalAt(int index, NumberInfo info);
391 inline void SetTypeForParamAt(int index, NumberInfo info);
392 408
393 private: 409 private:
394 static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset; 410 static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset;
395 static const int kFunctionOffset = JavaScriptFrameConstants::kFunctionOffset; 411 static const int kFunctionOffset = JavaScriptFrameConstants::kFunctionOffset;
396 static const int kContextOffset = StandardFrameConstants::kContextOffset; 412 static const int kContextOffset = StandardFrameConstants::kContextOffset;
397 413
398 static const int kHandlerSize = StackHandlerConstants::kSize / kPointerSize; 414 static const int kHandlerSize = StackHandlerConstants::kSize / kPointerSize;
399 static const int kPreallocatedElements = 5 + 8; // 8 expression stack slots. 415 static const int kPreallocatedElements = 5 + 8; // 8 expression stack slots.
400 416
401 ZoneList<FrameElement> elements_; 417 // 5 states for the top of stack, which can be in memory or in a0 and a1.
418 enum TopOfStack { NO_TOS_REGISTERS, A0_TOS, A1_TOS, A1_A0_TOS, A0_A1_TOS,
419 TOS_STATES};
420 static const int kMaxTOSRegisters = 2;
421
422 static const bool kA0InUse[TOS_STATES];
423 static const bool kA1InUse[TOS_STATES];
424 static const int kVirtualElements[TOS_STATES];
425 static const TopOfStack kStateAfterPop[TOS_STATES];
426 static const TopOfStack kStateAfterPush[TOS_STATES];
427 static const Register kTopRegister[TOS_STATES];
428 static const Register kBottomRegister[TOS_STATES];
429
430 // We allocate up to 5 locals in registers.
431 static const int kNumberOfAllocatedRegisters = 5;
432 // r2 to r6 are allocated to locals.
433 static const int kFirstAllocatedRegister = 2;
434
435 static const Register kAllocatedRegisters[kNumberOfAllocatedRegisters];
436
437 static Register AllocatedRegister(int r) {
438 ASSERT(r >= 0 && r < kNumberOfAllocatedRegisters);
439 return kAllocatedRegisters[r];
440 }
441
442 // The number of elements on the stack frame.
443 int element_count_;
444 TopOfStack top_of_stack_state_:3;
445 int register_allocation_map_:kNumberOfAllocatedRegisters;
446 static const int kTOSKnownSmiMapSize = 4;
447 unsigned tos_known_smi_map_:kTOSKnownSmiMapSize;
402 448
403 // The index of the element that is at the processor's stack pointer 449 // The index of the element that is at the processor's stack pointer
404 // (the sp register). 450 // (the sp register). For now since everything is in memory it is given
405 int stack_pointer_; 451 // by the number of elements on the not-very-virtual stack frame.
406 452 int stack_pointer() { return element_count_ - 1; }
407 // The index of the register frame element using each register, or
408 // kIllegalIndex if a register is not on the frame.
409 int register_locations_[RegisterAllocator::kNumRegisters];
410 453
411 // The number of frame-allocated locals and parameters respectively. 454 // The number of frame-allocated locals and parameters respectively.
412 int parameter_count() { return cgen()->scope()->num_parameters(); } 455 inline int parameter_count() const;
413 int local_count() { return cgen()->scope()->num_stack_slots(); } 456 inline int local_count() const;
414 457
415 // The index of the element that is at the processor's frame pointer 458 // The index of the element that is at the processor's frame pointer
416 // (the fp register). The parameters, receiver, function, and context 459 // (the fp register). The parameters, receiver, function, and context
417 // are below the frame pointer. 460 // are below the frame pointer.
418 int frame_pointer() { return parameter_count() + 3; } 461 inline int frame_pointer() const;
419 462
420 // The index of the first parameter. The receiver lies below the first 463 // The index of the first parameter. The receiver lies below the first
421 // parameter. 464 // parameter.
422 int param0_index() { return 1; } 465 int param0_index() { return 1; }
423 466
424 // The index of the context slot in the frame. It is immediately 467 // The index of the context slot in the frame. It is immediately
425 // below the frame pointer. 468 // below the frame pointer.
426 int context_index() { return frame_pointer() - 1; } 469 inline int context_index();
427 470
428 // The index of the function slot in the frame. It is below the frame 471 // The index of the function slot in the frame. It is below the frame
429 // pointer and context slot. 472 // pointer and context slot.
430 int function_index() { return frame_pointer() - 2; } 473 inline int function_index();
431 474
432 // The index of the first local. Between the frame pointer and the 475 // The index of the first local. Between the frame pointer and the
433 // locals lies the return address. 476 // locals lies the return address.
434 int local0_index() { return frame_pointer() + 2; } 477 inline int local0_index() const;
435 478
436 // The index of the base of the expression stack. 479 // The index of the base of the expression stack.
437 int expression_base_index() { return local0_index() + local_count(); } 480 inline int expression_base_index() const;
438 481
439 // Convert a frame index into a frame pointer relative offset into the 482 // Convert a frame index into a frame pointer relative offset into the
440 // actual stack. 483 // actual stack.
441 int fp_relative(int index) { 484 inline int fp_relative(int index);
442 ASSERT(index < element_count());
443 ASSERT(frame_pointer() < element_count()); // FP is on the frame.
444 return (frame_pointer() - index) * kPointerSize;
445 }
446
447 // Record an occurrence of a register in the virtual frame. This has the
448 // effect of incrementing the register's external reference count and
449 // of updating the index of the register's location in the frame.
450 void Use(Register reg, int index) {
451 ASSERT(!is_used(reg));
452 set_register_location(reg, index);
453 cgen()->allocator()->Use(reg);
454 }
455
456 // Record that a register reference has been dropped from the frame. This
457 // decrements the register's external reference count and invalidates the
458 // index of the register's location in the frame.
459 void Unuse(Register reg) {
460 ASSERT(is_used(reg));
461 set_register_location(reg, kIllegalIndex);
462 cgen()->allocator()->Unuse(reg);
463 }
464
465 // Spill the element at a particular index---write it to memory if
466 // necessary, free any associated register, and forget its value if
467 // constant.
468 void SpillElementAt(int index);
469
470 // Sync the element at a particular index. If it is a register or
471 // constant that disagrees with the value on the stack, write it to memory.
472 // Keep the element type as register or constant, and clear the dirty bit.
473 void SyncElementAt(int index);
474
475 // Sync the range of elements in [begin, end] with memory.
476 void SyncRange(int begin, int end);
477
478 // Sync a single unsynced element that lies beneath or at the stack pointer.
479 void SyncElementBelowStackPointer(int index);
480
481 // Sync a single unsynced element that lies just above the stack pointer.
482 void SyncElementByPushing(int index);
483
484 // Push a copy of a frame slot (typically a local or parameter) on top of
485 // the frame.
486 inline void PushFrameSlotAt(int index);
487
488 // Push a the value of a frame slot (typically a local or parameter) on
489 // top of the frame and invalidate the slot.
490 void TakeFrameSlotAt(int index);
491
492 // Store the value on top of the frame to a frame slot (typically a local
493 // or parameter).
494 void StoreToFrameSlotAt(int index);
495 485
496 // Spill all elements in registers. Spill the top spilled_args elements 486 // Spill all elements in registers. Spill the top spilled_args elements
497 // on the frame. Sync all other frame elements. 487 // on the frame. Sync all other frame elements.
498 // Then drop dropped_args elements from the virtual frame, to match 488 // Then drop dropped_args elements from the virtual frame, to match
499 // the effect of an upcoming call that will drop them from the stack. 489 // the effect of an upcoming call that will drop them from the stack.
500 void PrepareForCall(int spilled_args, int dropped_args); 490 void PrepareForCall(int spilled_args, int dropped_args);
501 491
502 // Move frame elements currently in registers or constants, that 492 // If all top-of-stack registers are in use then the lowest one is pushed
503 // should be in memory in the expected frame, to memory. 493 // onto the physical stack and made free.
504 void MergeMoveRegistersToMemory(VirtualFrame* expected); 494 void EnsureOneFreeTOSRegister();
505 495
506 // Make the register-to-register moves necessary to 496 // Emit instructions to get the top of stack state from where we are to where
507 // merge this frame with the expected frame. 497 // we want to be.
508 // Register to memory moves must already have been made, 498 void MergeTOSTo(TopOfStack expected_state,
509 // and memory to register moves must follow this call. 499 Condition cond = al,
510 // This is because some new memory-to-register moves are 500 Register r1 = no_reg,
511 // created in order to break cycles of register moves. 501 const Operand& r2 = Operand(no_reg));
512 // Used in the implementation of MergeTo().
513 void MergeMoveRegistersToRegisters(VirtualFrame* expected);
514 502
515 // Make the memory-to-register and constant-to-register moves 503 inline bool Equals(const VirtualFrame* other);
516 // needed to make this frame equal the expected frame.
517 // Called after all register-to-memory and register-to-register
518 // moves have been made. After this function returns, the frames
519 // should be equal.
520 void MergeMoveMemoryToRegisters(VirtualFrame* expected);
521 504
522 // Invalidates a frame slot (puts an invalid frame element in it). 505 inline void LowerHeight(int count) {
523 // Copies on the frame are correctly handled, and if this slot was 506 element_count_ -= count;
524 // the backing store of copies, the index of the new backing store 507 if (count >= kTOSKnownSmiMapSize) {
525 // is returned. Otherwise, returns kIllegalIndex. 508 tos_known_smi_map_ = 0;
526 // Register counts are correctly updated. 509 } else {
527 int InvalidateFrameSlotAt(int index); 510 tos_known_smi_map_ >>= count;
511 }
512 }
528 513
529 // Call a code stub that has already been prepared for calling (via 514 inline void RaiseHeight(int count, unsigned known_smi_map = 0) {
530 // PrepareForCall). 515 ASSERT(known_smi_map < (1u << count));
531 void RawCallStub(CodeStub* stub); 516 element_count_ += count;
532 517 if (count >= kTOSKnownSmiMapSize) {
533 // Calls a code object which has already been prepared for calling 518 tos_known_smi_map_ = known_smi_map;
534 // (via PrepareForCall). 519 } else {
535 void RawCallCodeObject(Handle<Code> code, RelocInfo::Mode rmode); 520 tos_known_smi_map_ = ((tos_known_smi_map_ << count) | known_smi_map);
536 521 }
537 inline bool Equals(VirtualFrame* other); 522 }
538
539 // Classes that need raw access to the elements_ array.
540 friend class DeferredCode;
541 friend class JumpTarget; 523 friend class JumpTarget;
542 }; 524 };
543 525
544 526
545 } } // namespace v8::internal 527 } } // namespace v8::internal
546 528
547 #endif // V8_MIPS_VIRTUAL_FRAME_MIPS_H_ 529 #endif // V8_MIPS_VIRTUAL_FRAME_MIPS_H_
548 530
OLDNEW
« no previous file with comments | « src/mips/stub-cache-mips.cc ('k') | src/mips/virtual-frame-mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698