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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 | 43 |
44 class VirtualFrame : public ZoneObject { | 44 class VirtualFrame : public ZoneObject { |
45 public: | 45 public: |
46 // A utility class to introduce a scope where the virtual frame is | 46 // A utility class to introduce a scope where the virtual frame is |
47 // expected to remain spilled. The constructor spills the code | 47 // expected to remain spilled. The constructor spills the code |
48 // generator's current frame, but no attempt is made to require it | 48 // generator's current frame, but no attempt is made to require it |
49 // to stay spilled. It is intended as documentation while the code | 49 // to stay spilled. It is intended as documentation while the code |
50 // generator is being transformed. | 50 // generator is being transformed. |
51 class SpilledScope BASE_EMBEDDED { | 51 class SpilledScope BASE_EMBEDDED { |
52 public: | 52 public: |
53 explicit SpilledScope(CodeGenerator* cgen); | 53 explicit SpilledScope(CodeGenerator* cgen) |
| 54 : cgen_(cgen), |
| 55 previous_state_(cgen->in_spilled_code()) { |
| 56 ASSERT(cgen->has_valid_frame()); |
| 57 cgen->frame()->SpillAll(); |
| 58 cgen->set_in_spilled_code(true); |
| 59 } |
54 | 60 |
55 ~SpilledScope(); | 61 ~SpilledScope() { |
| 62 cgen_->set_in_spilled_code(previous_state_); |
| 63 } |
56 | 64 |
57 private: | 65 private: |
58 CodeGenerator* cgen_; | 66 CodeGenerator* cgen_; |
59 bool previous_state_; | 67 bool previous_state_; |
60 }; | 68 }; |
61 | 69 |
62 // An illegal index into the virtual frame. | 70 // An illegal index into the virtual frame. |
63 static const int kIllegalIndex = -1; | 71 static const int kIllegalIndex = -1; |
64 | 72 |
65 // Construct an initial virtual frame on entry to a JS function. | 73 // Construct an initial virtual frame on entry to a JS function. |
(...skipping 22 matching lines...) Expand all Loading... |
88 return is_used(reg.code()); | 96 return is_used(reg.code()); |
89 } | 97 } |
90 | 98 |
91 // Add extra in-memory elements to the top of the frame to match an actual | 99 // Add extra in-memory elements to the top of the frame to match an actual |
92 // frame (eg, the frame after an exception handler is pushed). No code is | 100 // frame (eg, the frame after an exception handler is pushed). No code is |
93 // emitted. | 101 // emitted. |
94 void Adjust(int count); | 102 void Adjust(int count); |
95 | 103 |
96 // Forget elements from the top of the frame to match an actual frame (eg, | 104 // Forget elements from the top of the frame to match an actual frame (eg, |
97 // the frame after a runtime call). No code is emitted. | 105 // the frame after a runtime call). No code is emitted. |
98 void Forget(int count); | 106 void Forget(int count) { |
| 107 ASSERT(count >= 0); |
| 108 ASSERT(stack_pointer_ == elements_.length() - 1); |
| 109 stack_pointer_ -= count; |
| 110 ForgetElements(count); |
| 111 } |
99 | 112 |
100 // Forget count elements from the top of the frame without adjusting | 113 // Forget count elements from the top of the frame without adjusting |
101 // the stack pointer downward. This is used, for example, before | 114 // the stack pointer downward. This is used, for example, before |
102 // merging frames at break, continue, and return targets. | 115 // merging frames at break, continue, and return targets. |
103 void ForgetElements(int count); | 116 void ForgetElements(int count); |
104 | 117 |
105 // Spill all values from the frame to memory. | 118 // Spill all values from the frame to memory. |
106 void SpillAll(); | 119 void SpillAll(); |
107 | 120 |
108 // Spill all occurrences of a specific register from the frame. | 121 // Spill all occurrences of a specific register from the frame. |
109 void Spill(Register reg); | 122 void Spill(Register reg) { |
| 123 if (is_used(reg)) SpillElementAt(register_index(reg)); |
| 124 } |
110 | 125 |
111 // Spill all occurrences of an arbitrary register if possible. Return the | 126 // Spill all occurrences of an arbitrary register if possible. Return the |
112 // register spilled or no_reg if it was not possible to free any register | 127 // register spilled or no_reg if it was not possible to free any register |
113 // (ie, they all have frame-external references). | 128 // (ie, they all have frame-external references). |
114 Register SpillAnyRegister(); | 129 Register SpillAnyRegister(); |
115 | 130 |
116 // Prepare this virtual frame for merging to an expected frame by | 131 // Prepare this virtual frame for merging to an expected frame by |
117 // performing some state changes that do not require generating | 132 // performing some state changes that do not require generating |
118 // code. It is guaranteed that no code will be generated. | 133 // code. It is guaranteed that no code will be generated. |
119 void PrepareMergeTo(VirtualFrame* expected); | 134 void PrepareMergeTo(VirtualFrame* expected); |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 } | 274 } |
260 | 275 |
261 // The receiver frame slot. | 276 // The receiver frame slot. |
262 MemOperand Receiver() const { return ParameterAt(-1); } | 277 MemOperand Receiver() const { return ParameterAt(-1); } |
263 | 278 |
264 // Push a try-catch or try-finally handler on top of the virtual frame. | 279 // Push a try-catch or try-finally handler on top of the virtual frame. |
265 void PushTryHandler(HandlerType type); | 280 void PushTryHandler(HandlerType type); |
266 | 281 |
267 // Call stub given the number of arguments it expects on (and | 282 // Call stub given the number of arguments it expects on (and |
268 // removes from) the stack. | 283 // removes from) the stack. |
269 Result CallStub(CodeStub* stub, int arg_count); | 284 Result CallStub(CodeStub* stub, int arg_count) { |
| 285 PrepareForCall(arg_count, arg_count); |
| 286 return RawCallStub(stub); |
| 287 } |
270 | 288 |
271 // Call stub that expects its argument in r0. The argument is given | 289 // Call stub that expects its argument in r0. The argument is given |
272 // as a result which must be the register r0. | 290 // as a result which must be the register r0. |
273 Result CallStub(CodeStub* stub, Result* arg); | 291 Result CallStub(CodeStub* stub, Result* arg); |
274 | 292 |
275 // Call stub that expects its arguments in r1 and r0. The arguments | 293 // Call stub that expects its arguments in r1 and r0. The arguments |
276 // are given as results which must be the appropriate registers. | 294 // are given as results which must be the appropriate registers. |
277 Result CallStub(CodeStub* stub, Result* arg0, Result* arg1); | 295 Result CallStub(CodeStub* stub, Result* arg0, Result* arg1); |
278 | 296 |
279 // Call runtime given the number of arguments expected on (and | 297 // Call runtime given the number of arguments expected on (and |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
326 // Push an element on top of the expression stack and emit a | 344 // Push an element on top of the expression stack and emit a |
327 // corresponding push instruction. | 345 // corresponding push instruction. |
328 void EmitPush(Register reg); | 346 void EmitPush(Register reg); |
329 | 347 |
330 // Push an element on the virtual frame. | 348 // Push an element on the virtual frame. |
331 void Push(Register reg, StaticType static_type = StaticType()); | 349 void Push(Register reg, StaticType static_type = StaticType()); |
332 void Push(Handle<Object> value); | 350 void Push(Handle<Object> value); |
333 void Push(Smi* value) { Push(Handle<Object>(value)); } | 351 void Push(Smi* value) { Push(Handle<Object>(value)); } |
334 | 352 |
335 // Pushing a result invalidates it (its contents become owned by the frame). | 353 // Pushing a result invalidates it (its contents become owned by the frame). |
336 void Push(Result* result); | 354 void Push(Result* result) { |
| 355 if (result->is_register()) { |
| 356 Push(result->reg(), result->static_type()); |
| 357 } else { |
| 358 ASSERT(result->is_constant()); |
| 359 Push(result->handle()); |
| 360 } |
| 361 result->Unuse(); |
| 362 } |
337 | 363 |
338 // Nip removes zero or more elements from immediately below the top | 364 // Nip removes zero or more elements from immediately below the top |
339 // of the frame, leaving the previous top-of-frame value on top of | 365 // of the frame, leaving the previous top-of-frame value on top of |
340 // the frame. Nip(k) is equivalent to x = Pop(), Drop(k), Push(x). | 366 // the frame. Nip(k) is equivalent to x = Pop(), Drop(k), Push(x). |
341 void Nip(int num_dropped); | 367 void Nip(int num_dropped); |
342 | 368 |
343 private: | 369 private: |
344 static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset; | 370 static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset; |
345 static const int kFunctionOffset = JavaScriptFrameConstants::kFunctionOffset; | 371 static const int kFunctionOffset = JavaScriptFrameConstants::kFunctionOffset; |
346 static const int kContextOffset = StandardFrameConstants::kContextOffset; | 372 static const int kContextOffset = StandardFrameConstants::kContextOffset; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 | 425 |
400 // Convert a frame index into a frame pointer relative offset into the | 426 // Convert a frame index into a frame pointer relative offset into the |
401 // actual stack. | 427 // actual stack. |
402 int fp_relative(int index) const { | 428 int fp_relative(int index) const { |
403 return (frame_pointer_ - index) * kPointerSize; | 429 return (frame_pointer_ - index) * kPointerSize; |
404 } | 430 } |
405 | 431 |
406 // Record an occurrence of a register in the virtual frame. This has the | 432 // Record an occurrence of a register in the virtual frame. This has the |
407 // effect of incrementing the register's external reference count and | 433 // effect of incrementing the register's external reference count and |
408 // of updating the index of the register's location in the frame. | 434 // of updating the index of the register's location in the frame. |
409 void Use(Register reg, int index); | 435 void Use(Register reg, int index) { |
| 436 ASSERT(!is_used(reg)); |
| 437 register_locations_[reg.code()] = index; |
| 438 cgen_->allocator()->Use(reg); |
| 439 } |
410 | 440 |
411 // Record that a register reference has been dropped from the frame. This | 441 // Record that a register reference has been dropped from the frame. This |
412 // decrements the register's external reference count and invalidates the | 442 // decrements the register's external reference count and invalidates the |
413 // index of the register's location in the frame. | 443 // index of the register's location in the frame. |
414 void Unuse(Register reg); | 444 void Unuse(Register reg) { |
| 445 ASSERT(register_locations_[reg.code()] != kIllegalIndex); |
| 446 register_locations_[reg.code()] = kIllegalIndex; |
| 447 cgen_->allocator()->Unuse(reg); |
| 448 } |
415 | 449 |
416 // Spill the element at a particular index---write it to memory if | 450 // Spill the element at a particular index---write it to memory if |
417 // necessary, free any associated register, and forget its value if | 451 // necessary, free any associated register, and forget its value if |
418 // constant. | 452 // constant. |
419 void SpillElementAt(int index); | 453 void SpillElementAt(int index); |
420 | 454 |
421 // Sync the element at a particular index. If it is a register or | 455 // Sync the element at a particular index. If it is a register or |
422 // constant that disagrees with the value on the stack, write it to memory. | 456 // constant that disagrees with the value on the stack, write it to memory. |
423 // Keep the element type as register or constant, and clear the dirty bit. | 457 // Keep the element type as register or constant, and clear the dirty bit. |
424 void SyncElementAt(int index); | 458 void SyncElementAt(int index); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
487 | 521 |
488 bool Equals(VirtualFrame* other); | 522 bool Equals(VirtualFrame* other); |
489 | 523 |
490 friend class JumpTarget; | 524 friend class JumpTarget; |
491 }; | 525 }; |
492 | 526 |
493 | 527 |
494 } } // namespace v8::internal | 528 } } // namespace v8::internal |
495 | 529 |
496 #endif // V8_ARM_VIRTUAL_FRAME_ARM_H_ | 530 #endif // V8_ARM_VIRTUAL_FRAME_ARM_H_ |
OLD | NEW |