| 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 |