| 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 |