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. |
| 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(rbp, kLocal0Offset - index * kPointerSize); | 236 return Operand(rbp, 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 116 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 |
421 // The index of the first parameter. The receiver lies below the first | 432 // The index of the first parameter. The receiver lies below the first |
422 // parameter. | 433 // parameter. |
423 int param0_index() const { return 1; } | 434 int param0_index() { return 1; } |
424 | 435 |
425 // The index of the context slot in the frame. It is immediately | 436 // The index of the context slot in the frame. It is immediately |
426 // above the frame pointer. | 437 // above the frame pointer. |
427 int context_index() { return frame_pointer() + 1; } | 438 int context_index() { return frame_pointer() + 1; } |
428 | 439 |
429 // The index of the function slot in the frame. It is above the frame | 440 // The index of the function slot in the frame. It is above the frame |
430 // pointer and the context slot. | 441 // pointer and the context slot. |
431 int function_index() { return frame_pointer() + 2; } | 442 int function_index() { return frame_pointer() + 2; } |
432 | 443 |
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_X64_VIRTUAL_FRAME_X64_H_ | 554 #endif // V8_X64_VIRTUAL_FRAME_X64_H_ |
OLD | NEW |