| 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); | 
| 395 | 391 | 
| 396  private: | 392  private: | 
| 397   static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset; | 393   static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset; | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
| 409 | 405 | 
| 410   // The index of the register frame element using each register, or | 406   // The index of the register frame element using each register, or | 
| 411   // kIllegalIndex if a register is not on the frame. | 407   // kIllegalIndex if a register is not on the frame. | 
| 412   int register_locations_[RegisterAllocator::kNumRegisters]; | 408   int register_locations_[RegisterAllocator::kNumRegisters]; | 
| 413 | 409 | 
| 414   // The number of frame-allocated locals and parameters respectively. | 410   // The number of frame-allocated locals and parameters respectively. | 
| 415   int parameter_count() { return cgen()->scope()->num_parameters(); } | 411   int parameter_count() { return cgen()->scope()->num_parameters(); } | 
| 416   int local_count() { return cgen()->scope()->num_stack_slots(); } | 412   int local_count() { return cgen()->scope()->num_stack_slots(); } | 
| 417 | 413 | 
| 418   // The index of the element that is at the processor's frame pointer | 414   // The index of the element that is at the processor's frame pointer | 
| 419   // (the fp register).  The parameters, receiver, function, and context | 415   // (the fp register). The parameters, receiver, function, and context | 
| 420   // are below the frame pointer. | 416   // are below the frame pointer. | 
| 421   int frame_pointer() { return parameter_count() + 3; } | 417   int frame_pointer() { return parameter_count() + 3; } | 
| 422 | 418 | 
| 423   // The index of the first parameter.  The receiver lies below the first | 419   // The index of the first parameter. The receiver lies below the first | 
| 424   // parameter. | 420   // parameter. | 
| 425   int param0_index() { return 1; } | 421   int param0_index() { return 1; } | 
| 426 | 422 | 
| 427   // The index of the context slot in the frame.  It is immediately | 423   // The index of the context slot in the frame. It is immediately | 
| 428   // below the frame pointer. | 424   // below the frame pointer. | 
| 429   int context_index() { return frame_pointer() - 1; } | 425   int context_index() { return frame_pointer() - 1; } | 
| 430 | 426 | 
| 431   // The index of the function slot in the frame.  It is below the frame | 427   // The index of the function slot in the frame. It is below the frame | 
| 432   // pointer and context slot. | 428   // pointer and context slot. | 
| 433   int function_index() { return frame_pointer() - 2; } | 429   int function_index() { return frame_pointer() - 2; } | 
| 434 | 430 | 
| 435   // The index of the first local.  Between the frame pointer and the | 431   // The index of the first local. Between the frame pointer and the | 
| 436   // locals lies the return address. | 432   // locals lies the return address. | 
| 437   int local0_index() { return frame_pointer() + 2; } | 433   int local0_index() { return frame_pointer() + 2; } | 
| 438 | 434 | 
| 439   // The index of the base of the expression stack. | 435   // The index of the base of the expression stack. | 
| 440   int expression_base_index() { return local0_index() + local_count(); } | 436   int expression_base_index() { return local0_index() + local_count(); } | 
| 441 | 437 | 
| 442   // Convert a frame index into a frame pointer relative offset into the | 438   // Convert a frame index into a frame pointer relative offset into the | 
| 443   // actual stack. | 439   // actual stack. | 
| 444   int fp_relative(int index) { | 440   int fp_relative(int index) { | 
| 445     ASSERT(index < element_count()); | 441     ASSERT(index < element_count()); | 
| 446     ASSERT(frame_pointer() < element_count());  // FP is on the frame. | 442     ASSERT(frame_pointer() < element_count());  // FP is on the frame. | 
| 447     return (frame_pointer() - index) * kPointerSize; | 443     return (frame_pointer() - index) * kPointerSize; | 
| 448   } | 444   } | 
| 449 | 445 | 
| 450   // Record an occurrence of a register in the virtual frame.  This has the | 446   // Record an occurrence of a register in the virtual frame. This has the | 
| 451   // effect of incrementing the register's external reference count and | 447   // effect of incrementing the register's external reference count and | 
| 452   // of updating the index of the register's location in the frame. | 448   // of updating the index of the register's location in the frame. | 
| 453   void Use(Register reg, int index) { | 449   void Use(Register reg, int index) { | 
| 454     ASSERT(!is_used(reg)); | 450     ASSERT(!is_used(reg)); | 
| 455     set_register_location(reg, index); | 451     set_register_location(reg, index); | 
| 456     cgen()->allocator()->Use(reg); | 452     cgen()->allocator()->Use(reg); | 
| 457   } | 453   } | 
| 458 | 454 | 
| 459   // Record that a register reference has been dropped from the frame.  This | 455   // Record that a register reference has been dropped from the frame. This | 
| 460   // decrements the register's external reference count and invalidates the | 456   // decrements the register's external reference count and invalidates the | 
| 461   // index of the register's location in the frame. | 457   // index of the register's location in the frame. | 
| 462   void Unuse(Register reg) { | 458   void Unuse(Register reg) { | 
| 463     ASSERT(is_used(reg)); | 459     ASSERT(is_used(reg)); | 
| 464     set_register_location(reg, kIllegalIndex); | 460     set_register_location(reg, kIllegalIndex); | 
| 465     cgen()->allocator()->Unuse(reg); | 461     cgen()->allocator()->Unuse(reg); | 
| 466   } | 462   } | 
| 467 | 463 | 
| 468   // Spill the element at a particular index---write it to memory if | 464   // Spill the element at a particular index---write it to memory if | 
| 469   // necessary, free any associated register, and forget its value if | 465   // necessary, free any associated register, and forget its value if | 
| 470   // constant. | 466   // constant. | 
| 471   void SpillElementAt(int index); | 467   void SpillElementAt(int index); | 
| 472 | 468 | 
| 473   // Sync the element at a particular index.  If it is a register or | 469   // 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. | 470   // 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. | 471   // Keep the element type as register or constant, and clear the dirty bit. | 
| 476   void SyncElementAt(int index); | 472   void SyncElementAt(int index); | 
| 477 | 473 | 
| 478   // Sync the range of elements in [begin, end] with memory. | 474   // Sync the range of elements in [begin, end] with memory. | 
| 479   void SyncRange(int begin, int end); | 475   void SyncRange(int begin, int end); | 
| 480 | 476 | 
| 481   // Sync a single unsynced element that lies beneath or at the stack pointer. | 477   // Sync a single unsynced element that lies beneath or at the stack pointer. | 
| 482   void SyncElementBelowStackPointer(int index); | 478   void SyncElementBelowStackPointer(int index); | 
| 483 | 479 | 
| 484   // Sync a single unsynced element that lies just above the stack pointer. | 480   // Sync a single unsynced element that lies just above the stack pointer. | 
| 485   void SyncElementByPushing(int index); | 481   void SyncElementByPushing(int index); | 
| 486 | 482 | 
| 487   // Push a copy of a frame slot (typically a local or parameter) on top of | 483   // Push a copy of a frame slot (typically a local or parameter) on top of | 
| 488   // the frame. | 484   // the frame. | 
| 489   inline void PushFrameSlotAt(int index); | 485   inline void PushFrameSlotAt(int index); | 
| 490 | 486 | 
| 491   // Push a the value of a frame slot (typically a local or parameter) on | 487   // Push a the value of a frame slot (typically a local or parameter) on | 
| 492   // top of the frame and invalidate the slot. | 488   // top of the frame and invalidate the slot. | 
| 493   void TakeFrameSlotAt(int index); | 489   void TakeFrameSlotAt(int index); | 
| 494 | 490 | 
| 495   // Store the value on top of the frame to a frame slot (typically a local | 491   // Store the value on top of the frame to a frame slot (typically a local | 
| 496   // or parameter). | 492   // or parameter). | 
| 497   void StoreToFrameSlotAt(int index); | 493   void StoreToFrameSlotAt(int index); | 
| 498 | 494 | 
| 499   // Spill all elements in registers. Spill the top spilled_args elements | 495   // Spill all elements in registers. Spill the top spilled_args elements | 
| 500   // on the frame.  Sync all other frame elements. | 496   // on the frame. Sync all other frame elements. | 
| 501   // Then drop dropped_args elements from the virtual frame, to match | 497   // 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. | 498   // the effect of an upcoming call that will drop them from the stack. | 
| 503   void PrepareForCall(int spilled_args, int dropped_args); | 499   void PrepareForCall(int spilled_args, int dropped_args); | 
| 504 | 500 | 
| 505   // Move frame elements currently in registers or constants, that | 501   // Move frame elements currently in registers or constants, that | 
| 506   // should be in memory in the expected frame, to memory. | 502   // should be in memory in the expected frame, to memory. | 
| 507   void MergeMoveRegistersToMemory(VirtualFrame* expected); | 503   void MergeMoveRegistersToMemory(VirtualFrame* expected); | 
| 508 | 504 | 
| 509   // Make the register-to-register moves necessary to | 505   // Make the register-to-register moves necessary to | 
| 510   // merge this frame with the expected frame. | 506   // merge this frame with the expected frame. | 
| 511   // Register to memory moves must already have been made, | 507   // Register to memory moves must already have been made, | 
| 512   // and memory to register moves must follow this call. | 508   // and memory to register moves must follow this call. | 
| 513   // This is because some new memory-to-register moves are | 509   // This is because some new memory-to-register moves are | 
| 514   // created in order to break cycles of register moves. | 510   // created in order to break cycles of register moves. | 
| 515   // Used in the implementation of MergeTo(). | 511   // Used in the implementation of MergeTo(). | 
| 516   void MergeMoveRegistersToRegisters(VirtualFrame* expected); | 512   void MergeMoveRegistersToRegisters(VirtualFrame* expected); | 
| 517 | 513 | 
| 518   // Make the memory-to-register and constant-to-register moves | 514   // Make the memory-to-register and constant-to-register moves | 
| 519   // needed to make this frame equal the expected frame. | 515   // needed to make this frame equal the expected frame. | 
| 520   // Called after all register-to-memory and register-to-register | 516   // Called after all register-to-memory and register-to-register | 
| 521   // moves have been made.  After this function returns, the frames | 517   // moves have been made. After this function returns, the frames | 
| 522   // should be equal. | 518   // should be equal. | 
| 523   void MergeMoveMemoryToRegisters(VirtualFrame* expected); | 519   void MergeMoveMemoryToRegisters(VirtualFrame* expected); | 
| 524 | 520 | 
| 525   // Invalidates a frame slot (puts an invalid frame element in it). | 521   // Invalidates a frame slot (puts an invalid frame element in it). | 
| 526   // Copies on the frame are correctly handled, and if this slot was | 522   // 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 | 523   // the backing store of copies, the index of the new backing store | 
| 528   // is returned.  Otherwise, returns kIllegalIndex. | 524   // is returned. Otherwise, returns kIllegalIndex. | 
| 529   // Register counts are correctly updated. | 525   // Register counts are correctly updated. | 
| 530   int InvalidateFrameSlotAt(int index); | 526   int InvalidateFrameSlotAt(int index); | 
| 531 | 527 | 
| 532   // Call a code stub that has already been prepared for calling (via | 528   // Call a code stub that has already been prepared for calling (via | 
| 533   // PrepareForCall). | 529   // PrepareForCall). | 
| 534   void RawCallStub(CodeStub* stub); | 530   void RawCallStub(CodeStub* stub); | 
| 535 | 531 | 
| 536   // Calls a code object which has already been prepared for calling | 532   // Calls a code object which has already been prepared for calling | 
| 537   // (via PrepareForCall). | 533   // (via PrepareForCall). | 
| 538   void RawCallCodeObject(Handle<Code> code, RelocInfo::Mode rmode); | 534   void RawCallCodeObject(Handle<Code> code, RelocInfo::Mode rmode); | 
| 539 | 535 | 
| 540   inline bool Equals(VirtualFrame* other); | 536   inline bool Equals(VirtualFrame* other); | 
| 541 | 537 | 
| 542   // Classes that need raw access to the elements_ array. | 538   // Classes that need raw access to the elements_ array. | 
| 543   friend class DeferredCode; | 539   friend class DeferredCode; | 
| 544   friend class JumpTarget; | 540   friend class JumpTarget; | 
| 545 }; | 541 }; | 
| 546 | 542 | 
| 547 | 543 | 
| 548 } }  // namespace v8::internal | 544 } }  // namespace v8::internal | 
| 549 | 545 | 
| 550 #endif  // V8_MIPS_VIRTUAL_FRAME_MIPS_H_ | 546 #endif  // V8_MIPS_VIRTUAL_FRAME_MIPS_H_ | 
| 551 | 547 | 
| OLD | NEW | 
|---|