| OLD | NEW |
| 1 // Copyright 2008 the V8 project authors. All rights reserved. | 1 // Copyright 2008 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 11 matching lines...) Expand all Loading... |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #ifndef V8_VIRTUAL_FRAME_IA32_H_ | 28 #ifndef V8_VIRTUAL_FRAME_IA32_H_ |
| 29 #define V8_VIRTUAL_FRAME_IA32_H_ | 29 #define V8_VIRTUAL_FRAME_IA32_H_ |
| 30 | 30 |
| 31 #include "macro-assembler.h" | 31 #include "macro-assembler.h" |
| 32 #include "register-allocator.h" |
| 32 | 33 |
| 33 namespace v8 { namespace internal { | 34 namespace v8 { namespace internal { |
| 34 | 35 |
| 35 // ------------------------------------------------------------------------- | 36 // ------------------------------------------------------------------------- |
| 36 // Virtual frame elements | 37 // Virtual frame elements |
| 37 // | 38 // |
| 38 // The internal elements of the virtual frames. Elements are (currently) of | 39 // The internal elements of the virtual frames. There are several kinds of |
| 39 // only one kind, in-memory. Their actual location is given by their | 40 // elements: |
| 40 // position in the virtual frame. | 41 // * Memory: an element that resides in the actual frame. Its address is |
| 42 // given by its position in the virtual frame. |
| 43 // * Register: an element that resides in a register. |
| 44 // * Constant: an element whose value is known at compile time. |
| 41 | 45 |
| 42 class FrameElement BASE_EMBEDDED { | 46 class FrameElement BASE_EMBEDDED { |
| 43 public: | 47 public: |
| 48 enum SyncFlag { SYNCED, NOT_SYNCED }; |
| 49 |
| 50 // Construct an in-memory frame element. |
| 44 FrameElement() { | 51 FrameElement() { |
| 45 type_ = TypeField::encode(MEMORY) | DirtyField::encode(false); | 52 type_ = TypeField::encode(MEMORY) | SyncField::encode(SYNCED); |
| 46 // Memory elements have no useful data. | 53 // In-memory elements have no useful data. |
| 47 data_.reg_ = no_reg; | 54 data_.reg_ = no_reg; |
| 48 } | 55 } |
| 49 | 56 |
| 50 explicit FrameElement(Register reg) { | 57 // Construct an in-register frame element. |
| 51 type_ = TypeField::encode(REGISTER) | DirtyField::encode(true); | 58 FrameElement(Register reg, SyncFlag is_synced) { |
| 59 type_ = TypeField::encode(REGISTER) | SyncField::encode(is_synced); |
| 52 data_.reg_ = reg; | 60 data_.reg_ = reg; |
| 53 } | 61 } |
| 54 | 62 |
| 55 explicit FrameElement(Handle<Object> value) { | 63 // Construct a frame element whose value is known at compile time. |
| 56 type_ = TypeField::encode(CONSTANT) | DirtyField::encode(true); | 64 FrameElement(Handle<Object> value, SyncFlag is_synced) { |
| 65 type_ = TypeField::encode(CONSTANT) | SyncField::encode(is_synced); |
| 57 data_.handle_ = value.location(); | 66 data_.handle_ = value.location(); |
| 58 } | 67 } |
| 59 | 68 |
| 60 bool is_dirty() const { return DirtyField::decode(type_); } | 69 bool is_synced() const { return SyncField::decode(type_) == SYNCED; } |
| 61 | 70 |
| 62 void set_dirty() { | 71 void set_sync() { |
| 63 ASSERT(type() != MEMORY); | 72 ASSERT(type() != MEMORY); |
| 64 type_ = type_ | DirtyField::encode(true); | 73 type_ = type_ | SyncField::encode(SYNCED); |
| 65 } | 74 } |
| 66 | 75 |
| 67 void clear_dirty() { | 76 void clear_sync() { |
| 68 ASSERT(type() != MEMORY); | 77 ASSERT(type() != MEMORY); |
| 69 type_ = type_ & ~DirtyField::mask(); | 78 type_ = type_ & ~SyncField::mask(); |
| 70 } | 79 } |
| 71 | 80 |
| 72 bool is_register() const { return type() == REGISTER; } | 81 bool is_register() const { return type() == REGISTER; } |
| 73 bool is_constant() const { return type() == CONSTANT; } | 82 bool is_constant() const { return type() == CONSTANT; } |
| 74 | 83 |
| 75 Register reg() const { | 84 Register reg() const { |
| 76 ASSERT(type() == REGISTER); | 85 ASSERT(type() == REGISTER); |
| 77 return data_.reg_; | 86 return data_.reg_; |
| 78 } | 87 } |
| 79 | 88 |
| 80 Handle<Object> handle() const { | 89 Handle<Object> handle() const { |
| 81 ASSERT(type() == CONSTANT); | 90 ASSERT(type() == CONSTANT); |
| 82 return Handle<Object>(data_.handle_); | 91 return Handle<Object>(data_.handle_); |
| 83 } | 92 } |
| 84 | 93 |
| 85 private: | 94 private: |
| 86 enum Type { MEMORY, REGISTER, CONSTANT }; | 95 enum Type { MEMORY, REGISTER, CONSTANT }; |
| 87 | 96 |
| 88 // BitField is <type, shift, size>. | 97 // BitField is <type, shift, size>. |
| 89 class DirtyField : public BitField<bool, 0, 1> {}; | 98 class SyncField : public BitField<SyncFlag, 0, 1> {}; |
| 90 class TypeField : public BitField<Type, 1, 32 - 1> {}; | 99 class TypeField : public BitField<Type, 1, 32 - 1> {}; |
| 91 | 100 |
| 92 Type type() const { return TypeField::decode(type_); } | 101 Type type() const { return TypeField::decode(type_); } |
| 93 | 102 |
| 94 // The element's type and a dirty bit. The dirty bit can be cleared | 103 // The element's type and a dirty bit. The dirty bit can be cleared |
| 95 // for non-memory elements to indicate that the element agrees with | 104 // for non-memory elements to indicate that the element agrees with |
| 96 // the value in memory in the actual frame. | 105 // the value in memory in the actual frame. |
| 97 int type_; | 106 int type_; |
| 98 | 107 |
| 99 union { | 108 union { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 130 // emitted. | 139 // emitted. |
| 131 void Adjust(int count); | 140 void Adjust(int count); |
| 132 | 141 |
| 133 // Forget elements from the top of the frame to match an actual frame (eg, | 142 // Forget elements from the top of the frame to match an actual frame (eg, |
| 134 // the frame after a runtime call). No code is emitted. | 143 // the frame after a runtime call). No code is emitted. |
| 135 void Forget(int count); | 144 void Forget(int count); |
| 136 | 145 |
| 137 // Spill all values from the frame to memory. | 146 // Spill all values from the frame to memory. |
| 138 void SpillAll(); | 147 void SpillAll(); |
| 139 | 148 |
| 149 // Spill a register if possible. Return the register spilled or no_reg if |
| 150 // it was not possible to spill one. |
| 151 Register SpillAnyRegister(); |
| 152 |
| 140 // Ensure that this frame is in a state where an arbitrary frame of the | 153 // Ensure that this frame is in a state where an arbitrary frame of the |
| 141 // right size could be merged to it. May emit code. | 154 // right size could be merged to it. May emit code. |
| 142 void EnsureMergable(); | 155 void EnsureMergable(); |
| 143 | 156 |
| 144 // Make this virtual frame have a state identical to an expected virtual | 157 // Make this virtual frame have a state identical to an expected virtual |
| 145 // frame. As a side effect, code may be emitted to make this frame match | 158 // frame. As a side effect, code may be emitted to make this frame match |
| 146 // the expected one. | 159 // the expected one. |
| 147 void MergeTo(VirtualFrame* expected); | 160 void MergeTo(VirtualFrame* expected); |
| 148 | 161 |
| 149 // Emit code for the physical JS entry and exit frame sequences. After | 162 // Emit code for the physical JS entry and exit frame sequences. After |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 224 // corresponding pop instruction. | 237 // corresponding pop instruction. |
| 225 void EmitPop(Register reg); | 238 void EmitPop(Register reg); |
| 226 void EmitPop(Operand operand); | 239 void EmitPop(Operand operand); |
| 227 | 240 |
| 228 // Push an element on top of the expression stack and emit a corresponding | 241 // Push an element on top of the expression stack and emit a corresponding |
| 229 // push instruction. | 242 // push instruction. |
| 230 void EmitPush(Register reg); | 243 void EmitPush(Register reg); |
| 231 void EmitPush(Operand operand); | 244 void EmitPush(Operand operand); |
| 232 void EmitPush(Immediate immediate); | 245 void EmitPush(Immediate immediate); |
| 233 | 246 |
| 247 // Push an element on the virtual frame. |
| 248 void Push(Register reg); |
| 249 void Push(Handle<Object> value); |
| 250 |
| 234 private: | 251 private: |
| 235 // An illegal index into the virtual frame. | 252 // An illegal index into the virtual frame. |
| 236 static const int kIllegalIndex = -1; | 253 static const int kIllegalIndex = -1; |
| 237 | 254 |
| 238 static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset; | 255 static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset; |
| 239 static const int kFunctionOffset = JavaScriptFrameConstants::kFunctionOffset; | 256 static const int kFunctionOffset = JavaScriptFrameConstants::kFunctionOffset; |
| 240 static const int kContextOffset = StandardFrameConstants::kContextOffset; | 257 static const int kContextOffset = StandardFrameConstants::kContextOffset; |
| 241 | 258 |
| 242 static const int kHandlerSize = StackHandlerConstants::kSize / kPointerSize; | 259 static const int kHandlerSize = StackHandlerConstants::kSize / kPointerSize; |
| 243 | 260 |
| 261 CodeGenerator* cgen_; |
| 244 MacroAssembler* masm_; | 262 MacroAssembler* masm_; |
| 245 | 263 |
| 246 List<FrameElement> elements_; | 264 List<FrameElement> elements_; |
| 247 | 265 |
| 248 int parameter_count_; | 266 int parameter_count_; |
| 249 int local_count_; | 267 int local_count_; |
| 250 | 268 |
| 251 // The index of the element that is at the processor's stack pointer | 269 // The index of the element that is at the processor's stack pointer |
| 252 // (the esp register). | 270 // (the esp register). |
| 253 int stack_pointer_; | 271 int stack_pointer_; |
| 254 | 272 |
| 255 // The index of the element that is at the processor's frame pointer | 273 // The index of the element that is at the processor's frame pointer |
| 256 // (the ebp register). | 274 // (the ebp register). |
| 257 int frame_pointer_; | 275 int frame_pointer_; |
| 258 | 276 |
| 277 // The frame has an embedded register file that it uses to track registers |
| 278 // used in the frame. |
| 279 RegisterFile frame_registers_; |
| 280 |
| 259 // The index of the first parameter. The receiver lies below the first | 281 // The index of the first parameter. The receiver lies below the first |
| 260 // parameter. | 282 // parameter. |
| 261 int param0_index() const { return 1; } | 283 int param0_index() const { return 1; } |
| 262 | 284 |
| 285 // The index of the context slot in the frame. |
| 286 int context_index() const { |
| 287 ASSERT(frame_pointer_ != kIllegalIndex); |
| 288 return frame_pointer_ + 1; |
| 289 } |
| 290 |
| 291 // The index of the function slot in the frame. It lies above the context |
| 292 // slot. |
| 293 int function_index() const { |
| 294 ASSERT(frame_pointer_ != kIllegalIndex); |
| 295 return frame_pointer_ + 2; |
| 296 } |
| 297 |
| 263 // The index of the first local. Between the parameters and the locals | 298 // The index of the first local. Between the parameters and the locals |
| 264 // lie the return address, the saved frame pointer, the context, and the | 299 // lie the return address, the saved frame pointer, the context, and the |
| 265 // function. | 300 // function. |
| 266 int local0_index() const { return param0_index() + parameter_count_ + 4; } | 301 int local0_index() const { |
| 302 ASSERT(frame_pointer_ != kIllegalIndex); |
| 303 return frame_pointer_ + 3; |
| 304 } |
| 267 | 305 |
| 268 // The index of the base of the expression stack. | 306 // The index of the base of the expression stack. |
| 269 int expression_base_index() const { return local0_index() + local_count_; } | 307 int expression_base_index() const { return local0_index() + local_count_; } |
| 270 | 308 |
| 271 // Convert a frame index into a frame pointer relative offset into the | 309 // Convert a frame index into a frame pointer relative offset into the |
| 272 // actual stack. | 310 // actual stack. |
| 273 int fp_relative(int index) const { | 311 int fp_relative(int index) const { |
| 274 return (frame_pointer_ - index) * kPointerSize; | 312 return (frame_pointer_ - index) * kPointerSize; |
| 275 } | 313 } |
| 276 | 314 |
| 315 // Record an occurrence of a register in the virtual frame. This has the |
| 316 // effect of incrementing both the register's frame-internal reference |
| 317 // count and its external reference count. |
| 318 void Use(Register reg); |
| 319 |
| 320 // Record that a register reference has been dropped from the frame. This |
| 321 // decrements both the register's internal and external reference counts. |
| 322 void Unuse(Register reg); |
| 323 |
| 277 // Sync the element at a particular index---write it to memory if | 324 // Sync the element at a particular index---write it to memory if |
| 278 // necessary, but do not free any associated register or forget its value | 325 // necessary, but do not free any associated register or forget its value |
| 279 // if constant. Space should have already been allocated in the actual | 326 // if constant. Space should have already been allocated in the actual |
| 280 // frame for all the elements below this one (at least). | 327 // frame for all the elements below this one (at least). |
| 281 void SyncElementAt(int index); | 328 void SyncElementAt(int index); |
| 282 | 329 |
| 283 // Spill the element at a particular index---write it to memory if | 330 // Spill the element at a particular index---write it to memory if |
| 284 // necessary, free any associated register, and forget its value if | 331 // necessary, free any associated register, and forget its value if |
| 285 // constant. Space should have already been allocated in the actual frame | 332 // constant. Space should have already been allocated in the actual frame |
| 286 // for all the elements below this one (at least). | 333 // for all the elements below this one (at least). |
| 287 void SpillElementAt(int index); | 334 void SpillElementAt(int index); |
| 288 | 335 |
| 336 // Sync all elements in the frame. |
| 337 void SyncAll(); |
| 338 |
| 289 // Spill the topmost elements of the frame to memory (eg, they are the | 339 // Spill the topmost elements of the frame to memory (eg, they are the |
| 290 // arguments to a call) and all registers. | 340 // arguments to a call) and all registers. |
| 291 void PrepareForCall(int count); | 341 void PrepareForCall(int count); |
| 292 }; | 342 }; |
| 293 | 343 |
| 294 | 344 |
| 295 } } // namespace v8::internal | 345 } } // namespace v8::internal |
| 296 | 346 |
| 297 #endif // V8_VIRTUAL_FRAME_IA32_H_ | 347 #endif // V8_VIRTUAL_FRAME_IA32_H_ |
| OLD | NEW |