| OLD | NEW |
| 1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 | 76 |
| 77 // Construct a virtual frame as a clone of an existing one. | 77 // Construct a virtual frame as a clone of an existing one. |
| 78 explicit VirtualFrame(VirtualFrame* original); | 78 explicit VirtualFrame(VirtualFrame* original); |
| 79 | 79 |
| 80 CodeGenerator* cgen() { return CodeGeneratorScope::Current(); } | 80 CodeGenerator* cgen() { return CodeGeneratorScope::Current(); } |
| 81 MacroAssembler* masm() { return cgen()->masm(); } | 81 MacroAssembler* masm() { return cgen()->masm(); } |
| 82 | 82 |
| 83 // Create a duplicate of an existing valid frame element. | 83 // Create a duplicate of an existing valid frame element. |
| 84 FrameElement CopyElementAt(int index); | 84 FrameElement CopyElementAt(int index); |
| 85 | 85 |
| 86 // The number of elements on the virtual frame. |
| 87 int element_count() { return elements_.length(); } |
| 88 |
| 86 // The height of the virtual expression stack. | 89 // The height of the virtual expression stack. |
| 87 int height() { | 90 int height() { |
| 88 return elements_.length() - expression_base_index(); | 91 return element_count() - expression_base_index(); |
| 89 } | 92 } |
| 90 | 93 |
| 91 int register_index(Register reg) { | 94 int register_location(int num) { |
| 92 return register_locations_[reg.code()]; | 95 ASSERT(num >= 0 && num < RegisterAllocator::kNumRegisters); |
| 96 return register_locations_[num]; |
| 93 } | 97 } |
| 94 | 98 |
| 95 bool is_used(int reg_code) { | 99 int register_location(Register reg) { |
| 96 return register_locations_[reg_code] != kIllegalIndex; | 100 return register_locations_[RegisterAllocator::ToNumber(reg)]; |
| 101 } |
| 102 |
| 103 void set_register_location(Register reg, int index) { |
| 104 register_locations_[RegisterAllocator::ToNumber(reg)] = index; |
| 105 } |
| 106 |
| 107 bool is_used(int num) { |
| 108 ASSERT(num >= 0 && num < RegisterAllocator::kNumRegisters); |
| 109 return register_locations_[num] != kIllegalIndex; |
| 97 } | 110 } |
| 98 | 111 |
| 99 bool is_used(Register reg) { | 112 bool is_used(Register reg) { |
| 100 return is_used(reg.code()); | 113 return register_locations_[RegisterAllocator::ToNumber(reg)] |
| 114 != kIllegalIndex; |
| 101 } | 115 } |
| 102 | 116 |
| 103 // Add extra in-memory elements to the top of the frame to match an actual | 117 // Add extra in-memory elements to the top of the frame to match an actual |
| 104 // frame (eg, the frame after an exception handler is pushed). No code is | 118 // frame (eg, the frame after an exception handler is pushed). No code is |
| 105 // emitted. | 119 // emitted. |
| 106 void Adjust(int count); | 120 void Adjust(int count); |
| 107 | 121 |
| 108 // Forget elements from the top of the frame to match an actual frame (eg, | 122 // Forget elements from the top of the frame to match an actual frame (eg, |
| 109 // the frame after a runtime call). No code is emitted. | 123 // the frame after a runtime call). No code is emitted. |
| 110 void Forget(int count) { | 124 void Forget(int count) { |
| 111 ASSERT(count >= 0); | 125 ASSERT(count >= 0); |
| 112 ASSERT(stack_pointer_ == elements_.length() - 1); | 126 ASSERT(stack_pointer_ == element_count() - 1); |
| 113 stack_pointer_ -= count; | 127 stack_pointer_ -= count; |
| 114 ForgetElements(count); | 128 ForgetElements(count); |
| 115 } | 129 } |
| 116 | 130 |
| 117 // Forget count elements from the top of the frame without adjusting | 131 // Forget count elements from the top of the frame without adjusting |
| 118 // the stack pointer downward. This is used, for example, before | 132 // the stack pointer downward. This is used, for example, before |
| 119 // merging frames at break, continue, and return targets. | 133 // merging frames at break, continue, and return targets. |
| 120 void ForgetElements(int count); | 134 void ForgetElements(int count); |
| 121 | 135 |
| 122 // Spill all values from the frame to memory. | 136 // Spill all values from the frame to memory. |
| 123 void SpillAll(); | 137 void SpillAll(); |
| 124 | 138 |
| 125 // Spill all occurrences of a specific register from the frame. | 139 // Spill all occurrences of a specific register from the frame. |
| 126 void Spill(Register reg) { | 140 void Spill(Register reg) { |
| 127 if (is_used(reg)) SpillElementAt(register_index(reg)); | 141 if (is_used(reg)) SpillElementAt(register_location(reg)); |
| 128 } | 142 } |
| 129 | 143 |
| 130 // Spill all occurrences of an arbitrary register if possible. Return the | 144 // Spill all occurrences of an arbitrary register if possible. Return the |
| 131 // register spilled or no_reg if it was not possible to free any register | 145 // register spilled or no_reg if it was not possible to free any register |
| 132 // (ie, they all have frame-external references). | 146 // (ie, they all have frame-external references). |
| 133 Register SpillAnyRegister(); | 147 Register SpillAnyRegister(); |
| 134 | 148 |
| 135 // Prepare this virtual frame for merging to an expected frame by | 149 // Prepare this virtual frame for merging to an expected frame by |
| 136 // performing some state changes that do not require generating | 150 // performing some state changes that do not require generating |
| 137 // code. It is guaranteed that no code will be generated. | 151 // code. It is guaranteed that no code will be generated. |
| 138 void PrepareMergeTo(VirtualFrame* expected); | 152 void PrepareMergeTo(VirtualFrame* expected); |
| 139 | 153 |
| 140 // Make this virtual frame have a state identical to an expected virtual | 154 // Make this virtual frame have a state identical to an expected virtual |
| 141 // frame. As a side effect, code may be emitted to make this frame match | 155 // frame. As a side effect, code may be emitted to make this frame match |
| 142 // the expected one. | 156 // the expected one. |
| 143 void MergeTo(VirtualFrame* expected); | 157 void MergeTo(VirtualFrame* expected); |
| 144 | 158 |
| 145 // Detach a frame from its code generator, perhaps temporarily. This | 159 // Detach a frame from its code generator, perhaps temporarily. This |
| 146 // tells the register allocator that it is free to use frame-internal | 160 // tells the register allocator that it is free to use frame-internal |
| 147 // registers. Used when the code generator's frame is switched from this | 161 // registers. Used when the code generator's frame is switched from this |
| 148 // one to NULL by an unconditional jump. | 162 // one to NULL by an unconditional jump. |
| 149 void DetachFromCodeGenerator() { | 163 void DetachFromCodeGenerator() { |
| 150 RegisterAllocator* cgen_allocator = cgen()->allocator(); | 164 RegisterAllocator* cgen_allocator = cgen()->allocator(); |
| 151 for (int i = 0; i < kNumRegisters; i++) { | 165 for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) { |
| 152 if (is_used(i)) { | 166 if (is_used(i)) cgen_allocator->Unuse(i); |
| 153 Register temp = { i }; | |
| 154 cgen_allocator->Unuse(temp); | |
| 155 } | |
| 156 } | 167 } |
| 157 } | 168 } |
| 158 | 169 |
| 159 // (Re)attach a frame to its code generator. This informs the register | 170 // (Re)attach a frame to its code generator. This informs the register |
| 160 // allocator that the frame-internal register references are active again. | 171 // allocator that the frame-internal register references are active again. |
| 161 // Used when a code generator's frame is switched from NULL to this one by | 172 // Used when a code generator's frame is switched from NULL to this one by |
| 162 // binding a label. | 173 // binding a label. |
| 163 void AttachToCodeGenerator() { | 174 void AttachToCodeGenerator() { |
| 164 RegisterAllocator* cgen_allocator = cgen()->allocator(); | 175 RegisterAllocator* cgen_allocator = cgen()->allocator(); |
| 165 for (int i = 0; i < kNumRegisters; i++) { | 176 for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) { |
| 166 if (is_used(i)) { | 177 if (is_used(i)) cgen_allocator->Unuse(i); |
| 167 Register temp = { i }; | |
| 168 cgen_allocator->Use(temp); | |
| 169 } | |
| 170 } | 178 } |
| 171 } | 179 } |
| 172 | 180 |
| 173 // Emit code for the physical JS entry and exit frame sequences. After | 181 // 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 | 182 // 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 | 183 // Exit it should not be used. Note that Enter does not allocate space in |
| 176 // the physical frame for storing frame-allocated locals. | 184 // the physical frame for storing frame-allocated locals. |
| 177 void Enter(); | 185 void Enter(); |
| 178 void Exit(); | 186 void Exit(); |
| 179 | 187 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 198 // becomes owned by the frame and is invalidated. | 206 // becomes owned by the frame and is invalidated. |
| 199 void SetElementAt(int index, Result* value); | 207 void SetElementAt(int index, Result* value); |
| 200 | 208 |
| 201 // Set a frame element to a constant. The index is frame-top relative. | 209 // Set a frame element to a constant. The index is frame-top relative. |
| 202 void SetElementAt(int index, Handle<Object> value) { | 210 void SetElementAt(int index, Handle<Object> value) { |
| 203 Result temp(value); | 211 Result temp(value); |
| 204 SetElementAt(index, &temp); | 212 SetElementAt(index, &temp); |
| 205 } | 213 } |
| 206 | 214 |
| 207 void PushElementAt(int index) { | 215 void PushElementAt(int index) { |
| 208 PushFrameSlotAt(elements_.length() - index - 1); | 216 PushFrameSlotAt(element_count() - index - 1); |
| 209 } | 217 } |
| 210 | 218 |
| 211 // A frame-allocated local as an assembly operand. | 219 // A frame-allocated local as an assembly operand. |
| 212 MemOperand LocalAt(int index) { | 220 MemOperand LocalAt(int index) { |
| 213 ASSERT(0 <= index); | 221 ASSERT(0 <= index); |
| 214 ASSERT(index < local_count()); | 222 ASSERT(index < local_count()); |
| 215 return MemOperand(fp, kLocal0Offset - index * kPointerSize); | 223 return MemOperand(fp, kLocal0Offset - index * kPointerSize); |
| 216 } | 224 } |
| 217 | 225 |
| 218 // Push a copy of the value of a local frame slot on top of the frame. | 226 // Push a copy of the value of a local frame slot on top of the frame. |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 329 | 337 |
| 330 // Drop a number of elements from the top of the expression stack. May | 338 // Drop a number of elements from the top of the expression stack. May |
| 331 // emit code to affect the physical frame. Does not clobber any registers | 339 // emit code to affect the physical frame. Does not clobber any registers |
| 332 // excepting possibly the stack pointer. | 340 // excepting possibly the stack pointer. |
| 333 void Drop(int count); | 341 void Drop(int count); |
| 334 | 342 |
| 335 // Drop one element. | 343 // Drop one element. |
| 336 void Drop() { Drop(1); } | 344 void Drop() { Drop(1); } |
| 337 | 345 |
| 338 // Duplicate the top element of the frame. | 346 // Duplicate the top element of the frame. |
| 339 void Dup() { PushFrameSlotAt(elements_.length() - 1); } | 347 void Dup() { PushFrameSlotAt(element_count() - 1); } |
| 340 | 348 |
| 341 // Pop an element from the top of the expression stack. Returns a | 349 // Pop an element from the top of the expression stack. Returns a |
| 342 // Result, which may be a constant or a register. | 350 // Result, which may be a constant or a register. |
| 343 Result Pop(); | 351 Result Pop(); |
| 344 | 352 |
| 345 // Pop and save an element from the top of the expression stack and | 353 // Pop and save an element from the top of the expression stack and |
| 346 // emit a corresponding pop instruction. | 354 // emit a corresponding pop instruction. |
| 347 void EmitPop(Register reg); | 355 void EmitPop(Register reg); |
| 348 | 356 |
| 349 // Push an element on top of the expression stack and emit a | 357 // Push an element on top of the expression stack and emit a |
| (...skipping 30 matching lines...) Expand all Loading... |
| 380 static const int kPreallocatedElements = 5 + 8; // 8 expression stack slots. | 388 static const int kPreallocatedElements = 5 + 8; // 8 expression stack slots. |
| 381 | 389 |
| 382 ZoneList<FrameElement> elements_; | 390 ZoneList<FrameElement> elements_; |
| 383 | 391 |
| 384 // The index of the element that is at the processor's stack pointer | 392 // The index of the element that is at the processor's stack pointer |
| 385 // (the sp register). | 393 // (the sp register). |
| 386 int stack_pointer_; | 394 int stack_pointer_; |
| 387 | 395 |
| 388 // The index of the register frame element using each register, or | 396 // The index of the register frame element using each register, or |
| 389 // kIllegalIndex if a register is not on the frame. | 397 // kIllegalIndex if a register is not on the frame. |
| 390 int register_locations_[kNumRegisters]; | 398 int register_locations_[RegisterAllocator::kNumRegisters]; |
| 391 | 399 |
| 392 // The number of frame-allocated locals and parameters respectively. | 400 // The number of frame-allocated locals and parameters respectively. |
| 393 int parameter_count() { return cgen()->scope()->num_parameters(); } | 401 int parameter_count() { return cgen()->scope()->num_parameters(); } |
| 394 int local_count() { return cgen()->scope()->num_stack_slots(); } | 402 int local_count() { return cgen()->scope()->num_stack_slots(); } |
| 395 | 403 |
| 396 // The index of the element that is at the processor's frame pointer | 404 // The index of the element that is at the processor's frame pointer |
| 397 // (the fp register). The parameters, receiver, function, and context | 405 // (the fp register). The parameters, receiver, function, and context |
| 398 // are below the frame pointer. | 406 // are below the frame pointer. |
| 399 int frame_pointer() { return parameter_count() + 3; } | 407 int frame_pointer() { return parameter_count() + 3; } |
| 400 | 408 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 413 // The index of the first local. Between the frame pointer and the | 421 // The index of the first local. Between the frame pointer and the |
| 414 // locals lies the return address. | 422 // locals lies the return address. |
| 415 int local0_index() { return frame_pointer() + 2; } | 423 int local0_index() { return frame_pointer() + 2; } |
| 416 | 424 |
| 417 // The index of the base of the expression stack. | 425 // The index of the base of the expression stack. |
| 418 int expression_base_index() { return local0_index() + local_count(); } | 426 int expression_base_index() { return local0_index() + local_count(); } |
| 419 | 427 |
| 420 // Convert a frame index into a frame pointer relative offset into the | 428 // Convert a frame index into a frame pointer relative offset into the |
| 421 // actual stack. | 429 // actual stack. |
| 422 int fp_relative(int index) { | 430 int fp_relative(int index) { |
| 423 ASSERT(index < elements_.length()); | 431 ASSERT(index < element_count()); |
| 424 ASSERT(frame_pointer() < elements_.length()); // FP is on the frame. | 432 ASSERT(frame_pointer() < element_count()); // FP is on the frame. |
| 425 return (frame_pointer() - index) * kPointerSize; | 433 return (frame_pointer() - index) * kPointerSize; |
| 426 } | 434 } |
| 427 | 435 |
| 428 // Record an occurrence of a register in the virtual frame. This has the | 436 // Record an occurrence of a register in the virtual frame. This has the |
| 429 // effect of incrementing the register's external reference count and | 437 // effect of incrementing the register's external reference count and |
| 430 // of updating the index of the register's location in the frame. | 438 // of updating the index of the register's location in the frame. |
| 431 void Use(Register reg, int index) { | 439 void Use(Register reg, int index) { |
| 432 ASSERT(!is_used(reg)); | 440 ASSERT(!is_used(reg)); |
| 433 register_locations_[reg.code()] = index; | 441 set_register_location(reg, index); |
| 434 cgen()->allocator()->Use(reg); | 442 cgen()->allocator()->Use(reg); |
| 435 } | 443 } |
| 436 | 444 |
| 437 // Record that a register reference has been dropped from the frame. This | 445 // Record that a register reference has been dropped from the frame. This |
| 438 // decrements the register's external reference count and invalidates the | 446 // decrements the register's external reference count and invalidates the |
| 439 // index of the register's location in the frame. | 447 // index of the register's location in the frame. |
| 440 void Unuse(Register reg) { | 448 void Unuse(Register reg) { |
| 441 ASSERT(register_locations_[reg.code()] != kIllegalIndex); | 449 ASSERT(is_used(reg)); |
| 442 register_locations_[reg.code()] = kIllegalIndex; | 450 set_register_location(reg, kIllegalIndex); |
| 443 cgen()->allocator()->Unuse(reg); | 451 cgen()->allocator()->Unuse(reg); |
| 444 } | 452 } |
| 445 | 453 |
| 446 // Spill the element at a particular index---write it to memory if | 454 // Spill the element at a particular index---write it to memory if |
| 447 // necessary, free any associated register, and forget its value if | 455 // necessary, free any associated register, and forget its value if |
| 448 // constant. | 456 // constant. |
| 449 void SpillElementAt(int index); | 457 void SpillElementAt(int index); |
| 450 | 458 |
| 451 // Sync the element at a particular index. If it is a register or | 459 // Sync the element at a particular index. If it is a register or |
| 452 // constant that disagrees with the value on the stack, write it to memory. | 460 // constant that disagrees with the value on the stack, write it to memory. |
| 453 // Keep the element type as register or constant, and clear the dirty bit. | 461 // Keep the element type as register or constant, and clear the dirty bit. |
| 454 void SyncElementAt(int index); | 462 void SyncElementAt(int index); |
| 455 | 463 |
| 456 // Sync the range of elements in [begin, end). | 464 // Sync the range of elements in [begin, end] with memory. |
| 457 void SyncRange(int begin, int end); | 465 void SyncRange(int begin, int end); |
| 458 | 466 |
| 459 // Sync a single unsynced element that lies beneath or at the stack pointer. | 467 // Sync a single unsynced element that lies beneath or at the stack pointer. |
| 460 void SyncElementBelowStackPointer(int index); | 468 void SyncElementBelowStackPointer(int index); |
| 461 | 469 |
| 462 // Sync a single unsynced element that lies just above the stack pointer. | 470 // Sync a single unsynced element that lies just above the stack pointer. |
| 463 void SyncElementByPushing(int index); | 471 void SyncElementByPushing(int index); |
| 464 | 472 |
| 465 // Push a copy of a frame slot (typically a local or parameter) on top of | 473 // Push a copy of a frame slot (typically a local or parameter) on top of |
| 466 // the frame. | 474 // the frame. |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 517 | 525 |
| 518 bool Equals(VirtualFrame* other); | 526 bool Equals(VirtualFrame* other); |
| 519 | 527 |
| 520 friend class JumpTarget; | 528 friend class JumpTarget; |
| 521 }; | 529 }; |
| 522 | 530 |
| 523 | 531 |
| 524 } } // namespace v8::internal | 532 } } // namespace v8::internal |
| 525 | 533 |
| 526 #endif // V8_ARM_VIRTUAL_FRAME_ARM_H_ | 534 #endif // V8_ARM_VIRTUAL_FRAME_ARM_H_ |
| OLD | NEW |