Chromium Code Reviews| 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 count elements from the top of the frame all in-memory | 122 // Forget count elements from the top of the frame all in-memory |
| 109 // (including synced) and adjust the stack pointer downward, to | 123 // (including synced) and adjust the stack pointer downward, to |
| 110 // match an external frame effect (examples include a call removing | 124 // match an external frame effect (examples include a call removing |
| 111 // its arguments, and exiting a try/catch removing an exception | 125 // its arguments, and exiting a try/catch removing an exception |
| 112 // handler). No code will be emitted. | 126 // handler). No code will be emitted. |
| 113 void Forget(int count) { | 127 void Forget(int count) { |
| 114 ASSERT(count >= 0); | 128 ASSERT(count >= 0); |
| 115 ASSERT(stack_pointer_ == elements_.length() - 1); | 129 ASSERT(stack_pointer_ == element_count() - 1); |
| 116 stack_pointer_ -= count; | 130 stack_pointer_ -= count; |
| 117 ForgetElements(count); | 131 ForgetElements(count); |
| 118 } | 132 } |
| 119 | 133 |
| 120 // Forget count elements from the top of the frame without adjusting | 134 // Forget count elements from the top of the frame without adjusting |
| 121 // the stack pointer downward. This is used, for example, before | 135 // the stack pointer downward. This is used, for example, before |
| 122 // merging frames at break, continue, and return targets. | 136 // merging frames at break, continue, and return targets. |
| 123 void ForgetElements(int count); | 137 void ForgetElements(int count); |
| 124 | 138 |
| 125 // Spill all values from the frame to memory. | 139 // Spill all values from the frame to memory. |
| 126 void SpillAll(); | 140 void SpillAll(); |
| 127 | 141 |
| 128 // Spill all occurrences of a specific register from the frame. | 142 // Spill all occurrences of a specific register from the frame. |
| 129 void Spill(Register reg) { | 143 void Spill(Register reg) { |
| 130 if (is_used(reg)) SpillElementAt(register_index(reg)); | 144 if (is_used(reg)) SpillElementAt(register_location(reg)); |
| 131 } | 145 } |
| 132 | 146 |
| 133 // Spill all occurrences of an arbitrary register if possible. Return the | 147 // Spill all occurrences of an arbitrary register if possible. Return the |
| 134 // register spilled or no_reg if it was not possible to free any register | 148 // register spilled or no_reg if it was not possible to free any register |
| 135 // (ie, they all have frame-external references). | 149 // (ie, they all have frame-external references). |
| 136 Register SpillAnyRegister(); | 150 Register SpillAnyRegister(); |
| 137 | 151 |
| 152 // Sync the range of elements in [begin, end] with memory. | |
|
William Hesse
2009/05/26 13:33:32
I am surprised that there were no uses of this tha
Kevin Millikin (Chromium)
2009/05/27 07:43:07
The comment was incorrect. At some point we chang
| |
| 153 void SyncRange(int begin, int end); | |
| 154 | |
| 138 // Make this frame so that an arbitrary frame of the same height can | 155 // Make this frame so that an arbitrary frame of the same height can |
| 139 // be merged to it. Copies and constants are removed from the | 156 // be merged to it. Copies and constants are removed from the |
| 140 // topmost mergable_elements elements of the frame. A | 157 // topmost mergable_elements elements of the frame. A |
| 141 // mergable_elements of JumpTarget::kAllElements indicates constants | 158 // mergable_elements of JumpTarget::kAllElements indicates constants |
| 142 // and copies are should be removed from the entire frame. | 159 // and copies are should be removed from the entire frame. |
| 143 void MakeMergable(int mergable_elements); | 160 void MakeMergable(int mergable_elements); |
| 144 | 161 |
| 145 // Prepare this virtual frame for merging to an expected frame by | 162 // Prepare this virtual frame for merging to an expected frame by |
| 146 // performing some state changes that do not require generating | 163 // performing some state changes that do not require generating |
| 147 // code. It is guaranteed that no code will be generated. | 164 // code. It is guaranteed that no code will be generated. |
| 148 void PrepareMergeTo(VirtualFrame* expected); | 165 void PrepareMergeTo(VirtualFrame* expected); |
| 149 | 166 |
| 150 // Make this virtual frame have a state identical to an expected virtual | 167 // Make this virtual frame have a state identical to an expected virtual |
| 151 // frame. As a side effect, code may be emitted to make this frame match | 168 // frame. As a side effect, code may be emitted to make this frame match |
| 152 // the expected one. | 169 // the expected one. |
| 153 void MergeTo(VirtualFrame* expected); | 170 void MergeTo(VirtualFrame* expected); |
| 154 | 171 |
| 155 // Detach a frame from its code generator, perhaps temporarily. This | 172 // Detach a frame from its code generator, perhaps temporarily. This |
| 156 // tells the register allocator that it is free to use frame-internal | 173 // tells the register allocator that it is free to use frame-internal |
| 157 // registers. Used when the code generator's frame is switched from this | 174 // registers. Used when the code generator's frame is switched from this |
| 158 // one to NULL by an unconditional jump. | 175 // one to NULL by an unconditional jump. |
| 159 void DetachFromCodeGenerator() { | 176 void DetachFromCodeGenerator() { |
| 160 RegisterAllocator* cgen_allocator = cgen()->allocator(); | 177 RegisterAllocator* cgen_allocator = cgen()->allocator(); |
| 161 for (int i = 0; i < kNumRegisters; i++) { | 178 for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) { |
| 162 if (is_used(i)) { | 179 if (is_used(i)) cgen_allocator->Unuse(i); |
| 163 Register temp = { i }; | |
| 164 cgen_allocator->Unuse(temp); | |
| 165 } | |
| 166 } | 180 } |
| 167 } | 181 } |
| 168 | 182 |
| 169 // (Re)attach a frame to its code generator. This informs the register | 183 // (Re)attach a frame to its code generator. This informs the register |
| 170 // allocator that the frame-internal register references are active again. | 184 // allocator that the frame-internal register references are active again. |
| 171 // Used when a code generator's frame is switched from NULL to this one by | 185 // Used when a code generator's frame is switched from NULL to this one by |
| 172 // binding a label. | 186 // binding a label. |
| 173 void AttachToCodeGenerator() { | 187 void AttachToCodeGenerator() { |
| 174 RegisterAllocator* cgen_allocator = cgen()->allocator(); | 188 RegisterAllocator* cgen_allocator = cgen()->allocator(); |
| 175 for (int i = 0; i < kNumRegisters; i++) { | 189 for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) { |
| 176 if (is_used(i)) { | 190 if (is_used(i)) cgen_allocator->Use(i); |
| 177 Register temp = { i }; | |
| 178 cgen_allocator->Use(temp); | |
| 179 } | |
| 180 } | 191 } |
| 181 } | 192 } |
| 182 | 193 |
| 183 // Emit code for the physical JS entry and exit frame sequences. After | 194 // Emit code for the physical JS entry and exit frame sequences. After |
| 184 // calling Enter, the virtual frame is ready for use; and after calling | 195 // calling Enter, the virtual frame is ready for use; and after calling |
| 185 // Exit it should not be used. Note that Enter does not allocate space in | 196 // Exit it should not be used. Note that Enter does not allocate space in |
| 186 // the physical frame for storing frame-allocated locals. | 197 // the physical frame for storing frame-allocated locals. |
| 187 void Enter(); | 198 void Enter(); |
| 188 void Exit(); | 199 void Exit(); |
| 189 | 200 |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 204 // becomes owned by the frame and is invalidated. | 215 // becomes owned by the frame and is invalidated. |
| 205 void SetElementAt(int index, Result* value); | 216 void SetElementAt(int index, Result* value); |
| 206 | 217 |
| 207 // Set a frame element to a constant. The index is frame-top relative. | 218 // Set a frame element to a constant. The index is frame-top relative. |
| 208 void SetElementAt(int index, Handle<Object> value) { | 219 void SetElementAt(int index, Handle<Object> value) { |
| 209 Result temp(value); | 220 Result temp(value); |
| 210 SetElementAt(index, &temp); | 221 SetElementAt(index, &temp); |
| 211 } | 222 } |
| 212 | 223 |
| 213 void PushElementAt(int index) { | 224 void PushElementAt(int index) { |
| 214 PushFrameSlotAt(elements_.length() - index - 1); | 225 PushFrameSlotAt(element_count() - index - 1); |
| 215 } | 226 } |
| 216 | 227 |
| 217 void StoreToElementAt(int index) { | 228 void StoreToElementAt(int index) { |
| 218 StoreToFrameSlotAt(elements_.length() - index - 1); | 229 StoreToFrameSlotAt(element_count() - index - 1); |
| 219 } | 230 } |
| 220 | 231 |
| 221 // A frame-allocated local as an assembly operand. | 232 // A frame-allocated local as an assembly operand. |
| 222 Operand LocalAt(int index) { | 233 Operand LocalAt(int index) { |
| 223 ASSERT(0 <= index); | 234 ASSERT(0 <= index); |
| 224 ASSERT(index < local_count()); | 235 ASSERT(index < local_count()); |
| 225 return Operand(ebp, kLocal0Offset - index * kPointerSize); | 236 return Operand(ebp, kLocal0Offset - index * kPointerSize); |
| 226 } | 237 } |
| 227 | 238 |
| 228 // Push a copy of the value of a local frame slot on top of the frame. | 239 // Push a copy of the value of a local frame slot on top of the frame. |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 252 // Save the value of the esi register to the context frame slot. | 263 // Save the value of the esi register to the context frame slot. |
| 253 void SaveContextRegister(); | 264 void SaveContextRegister(); |
| 254 | 265 |
| 255 // Restore the esi register from the value of the context frame | 266 // Restore the esi register from the value of the context frame |
| 256 // slot. | 267 // slot. |
| 257 void RestoreContextRegister(); | 268 void RestoreContextRegister(); |
| 258 | 269 |
| 259 // A parameter as an assembly operand. | 270 // A parameter as an assembly operand. |
| 260 Operand ParameterAt(int index) { | 271 Operand ParameterAt(int index) { |
| 261 ASSERT(-1 <= index); // -1 is the receiver. | 272 ASSERT(-1 <= index); // -1 is the receiver. |
| 262 ASSERT(index <= parameter_count()); | 273 ASSERT(index < parameter_count()); |
| 263 return Operand(ebp, (1 + parameter_count() - index) * kPointerSize); | 274 return Operand(ebp, (1 + parameter_count() - index) * kPointerSize); |
| 264 } | 275 } |
| 265 | 276 |
| 266 // Push a copy of the value of a parameter frame slot on top of the frame. | 277 // Push a copy of the value of a parameter frame slot on top of the frame. |
| 267 void PushParameterAt(int index) { | 278 void PushParameterAt(int index) { |
| 268 PushFrameSlotAt(param0_index() + index); | 279 PushFrameSlotAt(param0_index() + index); |
| 269 } | 280 } |
| 270 | 281 |
| 271 // Push the value of a paramter frame slot on top of the frame and | 282 // Push the value of a paramter frame slot on top of the frame and |
| 272 // invalidate the parameter slot. The slot should be written to before | 283 // invalidate the parameter slot. The slot should be written to before |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 345 | 356 |
| 346 // Drop a number of elements from the top of the expression stack. May | 357 // Drop a number of elements from the top of the expression stack. May |
| 347 // emit code to affect the physical frame. Does not clobber any registers | 358 // emit code to affect the physical frame. Does not clobber any registers |
| 348 // excepting possibly the stack pointer. | 359 // excepting possibly the stack pointer. |
| 349 void Drop(int count); | 360 void Drop(int count); |
| 350 | 361 |
| 351 // Drop one element. | 362 // Drop one element. |
| 352 void Drop() { Drop(1); } | 363 void Drop() { Drop(1); } |
| 353 | 364 |
| 354 // Duplicate the top element of the frame. | 365 // Duplicate the top element of the frame. |
| 355 void Dup() { PushFrameSlotAt(elements_.length() - 1); } | 366 void Dup() { PushFrameSlotAt(element_count() - 1); } |
| 356 | 367 |
| 357 // Pop an element from the top of the expression stack. Returns a | 368 // Pop an element from the top of the expression stack. Returns a |
| 358 // Result, which may be a constant or a register. | 369 // Result, which may be a constant or a register. |
| 359 Result Pop(); | 370 Result Pop(); |
| 360 | 371 |
| 361 // Pop and save an element from the top of the expression stack and | 372 // Pop and save an element from the top of the expression stack and |
| 362 // emit a corresponding pop instruction. | 373 // emit a corresponding pop instruction. |
| 363 void EmitPop(Register reg); | 374 void EmitPop(Register reg); |
| 364 void EmitPop(Operand operand); | 375 void EmitPop(Operand operand); |
| 365 | 376 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 400 static const int kPreallocatedElements = 5 + 8; // 8 expression stack slots. | 411 static const int kPreallocatedElements = 5 + 8; // 8 expression stack slots. |
| 401 | 412 |
| 402 ZoneList<FrameElement> elements_; | 413 ZoneList<FrameElement> elements_; |
| 403 | 414 |
| 404 // The index of the element that is at the processor's stack pointer | 415 // The index of the element that is at the processor's stack pointer |
| 405 // (the esp register). | 416 // (the esp register). |
| 406 int stack_pointer_; | 417 int stack_pointer_; |
| 407 | 418 |
| 408 // The index of the register frame element using each register, or | 419 // The index of the register frame element using each register, or |
| 409 // kIllegalIndex if a register is not on the frame. | 420 // kIllegalIndex if a register is not on the frame. |
| 410 int register_locations_[kNumRegisters]; | 421 int register_locations_[RegisterAllocator::kNumRegisters]; |
| 411 | 422 |
| 412 // The number of frame-allocated locals and parameters respectively. | 423 // The number of frame-allocated locals and parameters respectively. |
| 413 int parameter_count() { return cgen()->scope()->num_parameters(); } | 424 int parameter_count() { return cgen()->scope()->num_parameters(); } |
| 414 int local_count() { return cgen()->scope()->num_stack_slots(); } | 425 int local_count() { return cgen()->scope()->num_stack_slots(); } |
| 415 | 426 |
| 416 // The index of the element that is at the processor's frame pointer | 427 // The index of the element that is at the processor's frame pointer |
| 417 // (the ebp register). The parameters, receiver, and return address | 428 // (the ebp register). The parameters, receiver, and return address |
| 418 // are below the frame pointer. | 429 // are below the frame pointer. |
| 419 int frame_pointer() { return parameter_count() + 2; } | 430 int frame_pointer() { return parameter_count() + 2; } |
| 420 | 431 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 433 // The index of the first local. Between the frame pointer and the | 444 // The index of the first local. Between the frame pointer and the |
| 434 // locals lie the context and the function. | 445 // locals lie the context and the function. |
| 435 int local0_index() { return frame_pointer() + 3; } | 446 int local0_index() { return frame_pointer() + 3; } |
| 436 | 447 |
| 437 // The index of the base of the expression stack. | 448 // The index of the base of the expression stack. |
| 438 int expression_base_index() { return local0_index() + local_count(); } | 449 int expression_base_index() { return local0_index() + local_count(); } |
| 439 | 450 |
| 440 // Convert a frame index into a frame pointer relative offset into the | 451 // Convert a frame index into a frame pointer relative offset into the |
| 441 // actual stack. | 452 // actual stack. |
| 442 int fp_relative(int index) { | 453 int fp_relative(int index) { |
| 443 ASSERT(index < elements_.length()); | 454 ASSERT(index < element_count()); |
| 444 ASSERT(frame_pointer() < elements_.length()); // FP is on the frame. | 455 ASSERT(frame_pointer() < element_count()); // FP is on the frame. |
| 445 return (frame_pointer() - index) * kPointerSize; | 456 return (frame_pointer() - index) * kPointerSize; |
| 446 } | 457 } |
| 447 | 458 |
| 448 // Record an occurrence of a register in the virtual frame. This has the | 459 // Record an occurrence of a register in the virtual frame. This has the |
| 449 // effect of incrementing the register's external reference count and | 460 // effect of incrementing the register's external reference count and |
| 450 // of updating the index of the register's location in the frame. | 461 // of updating the index of the register's location in the frame. |
| 451 void Use(Register reg, int index) { | 462 void Use(Register reg, int index) { |
| 452 ASSERT(!is_used(reg)); | 463 ASSERT(!is_used(reg)); |
| 453 register_locations_[reg.code()] = index; | 464 set_register_location(reg, index); |
| 454 cgen()->allocator()->Use(reg); | 465 cgen()->allocator()->Use(reg); |
| 455 } | 466 } |
| 456 | 467 |
| 457 // Record that a register reference has been dropped from the frame. This | 468 // Record that a register reference has been dropped from the frame. This |
| 458 // decrements the register's external reference count and invalidates the | 469 // decrements the register's external reference count and invalidates the |
| 459 // index of the register's location in the frame. | 470 // index of the register's location in the frame. |
| 460 void Unuse(Register reg) { | 471 void Unuse(Register reg) { |
| 461 ASSERT(register_locations_[reg.code()] != kIllegalIndex); | 472 ASSERT(is_used(reg)); |
| 462 register_locations_[reg.code()] = kIllegalIndex; | 473 set_register_location(reg, kIllegalIndex); |
| 463 cgen()->allocator()->Unuse(reg); | 474 cgen()->allocator()->Unuse(reg); |
| 464 } | 475 } |
| 465 | 476 |
| 466 // Spill the element at a particular index---write it to memory if | 477 // Spill the element at a particular index---write it to memory if |
| 467 // necessary, free any associated register, and forget its value if | 478 // necessary, free any associated register, and forget its value if |
| 468 // constant. | 479 // constant. |
| 469 void SpillElementAt(int index); | 480 void SpillElementAt(int index); |
| 470 | 481 |
| 471 // Sync the element at a particular index. If it is a register or | 482 // Sync the element at a particular index. If it is a register or |
| 472 // constant that disagrees with the value on the stack, write it to memory. | 483 // constant that disagrees with the value on the stack, write it to memory. |
| 473 // Keep the element type as register or constant, and clear the dirty bit. | 484 // Keep the element type as register or constant, and clear the dirty bit. |
| 474 void SyncElementAt(int index); | 485 void SyncElementAt(int index); |
| 475 | 486 |
| 476 // Sync the range of elements in [begin, end). | |
| 477 void SyncRange(int begin, int end); | |
| 478 | |
| 479 // Sync a single unsynced element that lies beneath or at the stack pointer. | 487 // Sync a single unsynced element that lies beneath or at the stack pointer. |
| 480 void SyncElementBelowStackPointer(int index); | 488 void SyncElementBelowStackPointer(int index); |
| 481 | 489 |
| 482 // Sync a single unsynced element that lies just above the stack pointer. | 490 // Sync a single unsynced element that lies just above the stack pointer. |
| 483 void SyncElementByPushing(int index); | 491 void SyncElementByPushing(int index); |
| 484 | 492 |
| 485 // Push a copy of a frame slot (typically a local or parameter) on top of | 493 // Push a copy of a frame slot (typically a local or parameter) on top of |
| 486 // the frame. | 494 // the frame. |
| 487 void PushFrameSlotAt(int index); | 495 void PushFrameSlotAt(int index); |
| 488 | 496 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 537 | 545 |
| 538 bool Equals(VirtualFrame* other); | 546 bool Equals(VirtualFrame* other); |
| 539 | 547 |
| 540 friend class JumpTarget; | 548 friend class JumpTarget; |
| 541 }; | 549 }; |
| 542 | 550 |
| 543 | 551 |
| 544 } } // namespace v8::internal | 552 } } // namespace v8::internal |
| 545 | 553 |
| 546 #endif // V8_IA32_VIRTUAL_FRAME_IA32_H_ | 554 #endif // V8_IA32_VIRTUAL_FRAME_IA32_H_ |
| OLD | NEW |