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 |