| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 426 (saved_registers.Count() * kXRegSizeInBytes) + | 426 (saved_registers.Count() * kXRegSizeInBytes) + |
| 427 (saved_fp_registers.Count() * kDRegSizeInBytes); | 427 (saved_fp_registers.Count() * kDRegSizeInBytes); |
| 428 | 428 |
| 429 // Floating point registers are saved on the stack above core registers. | 429 // Floating point registers are saved on the stack above core registers. |
| 430 const int kFPRegistersOffset = saved_registers.Count() * kXRegSizeInBytes; | 430 const int kFPRegistersOffset = saved_registers.Count() * kXRegSizeInBytes; |
| 431 | 431 |
| 432 // Get the bailout id from the stack. | 432 // Get the bailout id from the stack. |
| 433 Register bailout_id = x2; | 433 Register bailout_id = x2; |
| 434 __ Peek(bailout_id, kSavedRegistersAreaSize); | 434 __ Peek(bailout_id, kSavedRegistersAreaSize); |
| 435 | 435 |
| 436 // Get the address of the location in the code object if possible | |
| 437 // and compute the fp-to-sp delta. | |
| 438 Register code_object = x3; | 436 Register code_object = x3; |
| 439 Register fp_to_sp = x4; | 437 Register fp_to_sp = x4; |
| 440 if ((type() == EAGER) || (type() == SOFT)) { | 438 // Get the address of the location in the code object. This is the return |
| 441 __ Mov(code_object, 0); | 439 // address for lazy deoptimization. |
| 442 // Correct one word for bailout id. | 440 __ Mov(code_object, lr); |
| 443 __ Add(fp_to_sp, | 441 // Compute the fp-to-sp delta, and correct one word for bailout id. |
| 444 masm()->StackPointer(), | 442 __ Add(fp_to_sp, masm()->StackPointer(), |
| 445 kSavedRegistersAreaSize + (1 * kPointerSize)); | 443 kSavedRegistersAreaSize + (1 * kPointerSize)); |
| 446 } else if (type() == OSR) { | |
| 447 __ Mov(code_object, lr); | |
| 448 // Correct one word for bailout id. | |
| 449 __ Add(fp_to_sp, | |
| 450 masm()->StackPointer(), | |
| 451 kSavedRegistersAreaSize + (1 * kPointerSize)); | |
| 452 } else { | |
| 453 __ Mov(code_object, lr); | |
| 454 // Correct two words for bailout id and return address. | |
| 455 __ Add(fp_to_sp, | |
| 456 masm()->StackPointer(), | |
| 457 kSavedRegistersAreaSize + (2 * kPointerSize)); | |
| 458 } | |
| 459 __ Sub(fp_to_sp, fp, fp_to_sp); | 444 __ Sub(fp_to_sp, fp, fp_to_sp); |
| 460 | 445 |
| 461 // Allocate a new deoptimizer object. | 446 // Allocate a new deoptimizer object. |
| 462 __ Ldr(x0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 447 __ Ldr(x0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 463 __ Mov(x1, type()); | 448 __ Mov(x1, type()); |
| 464 // Following arguments are already loaded: | 449 // Following arguments are already loaded: |
| 465 // - x2: bailout id | 450 // - x2: bailout id |
| 466 // - x3: code object address | 451 // - x3: code object address |
| 467 // - x4: fp-to-sp delta | 452 // - x4: fp-to-sp delta |
| 468 __ Mov(x5, Operand(ExternalReference::isolate_address(isolate()))); | 453 __ Mov(x5, Operand(ExternalReference::isolate_address(isolate()))); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 493 // Copy FP registers to the input frame. | 478 // Copy FP registers to the input frame. |
| 494 for (int i = 0; i < saved_fp_registers.Count(); i++) { | 479 for (int i = 0; i < saved_fp_registers.Count(); i++) { |
| 495 // TODO(all): Look for opportunities to optimize this by using ldp/stp. | 480 // TODO(all): Look for opportunities to optimize this by using ldp/stp. |
| 496 int dst_offset = FrameDescription::double_registers_offset() + | 481 int dst_offset = FrameDescription::double_registers_offset() + |
| 497 (i * kDoubleSize); | 482 (i * kDoubleSize); |
| 498 int src_offset = kFPRegistersOffset + (i * kDoubleSize); | 483 int src_offset = kFPRegistersOffset + (i * kDoubleSize); |
| 499 __ Peek(x2, src_offset); | 484 __ Peek(x2, src_offset); |
| 500 __ Str(x2, MemOperand(x1, dst_offset)); | 485 __ Str(x2, MemOperand(x1, dst_offset)); |
| 501 } | 486 } |
| 502 | 487 |
| 503 // Remove the bailout id, eventually return address, and the saved registers | 488 // Remove the bailout id and the saved registers from the stack. |
| 504 // from the stack. | 489 __ Drop(1 + (kSavedRegistersAreaSize / kXRegSizeInBytes)); |
| 505 if ((type() == EAGER) || (type() == SOFT) || (type() == OSR)) { | |
| 506 __ Drop(1 + (kSavedRegistersAreaSize / kXRegSizeInBytes)); | |
| 507 } else { | |
| 508 // Also remove return address for lazy deopt. | |
| 509 __ Drop(2 + (kSavedRegistersAreaSize / kXRegSizeInBytes)); | |
| 510 } | |
| 511 | 490 |
| 512 // Compute a pointer to the unwinding limit in register x2; that is | 491 // Compute a pointer to the unwinding limit in register x2; that is |
| 513 // the first stack slot not part of the input frame. | 492 // the first stack slot not part of the input frame. |
| 514 Register unwind_limit = x2; | 493 Register unwind_limit = x2; |
| 515 __ Ldr(unwind_limit, MemOperand(x1, FrameDescription::frame_size_offset())); | 494 __ Ldr(unwind_limit, MemOperand(x1, FrameDescription::frame_size_offset())); |
| 516 __ Add(unwind_limit, unwind_limit, __ StackPointer()); | 495 __ Add(unwind_limit, unwind_limit, __ StackPointer()); |
| 517 | 496 |
| 518 // Unwind the stack down to - but not including - the unwinding | 497 // Unwind the stack down to - but not including - the unwinding |
| 519 // limit and copy the contents of the activation frame to the input | 498 // limit and copy the contents of the activation frame to the input |
| 520 // frame description. | 499 // frame description. |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 604 __ Ldr(continuation, MemOperand(last_output_frame, | 583 __ Ldr(continuation, MemOperand(last_output_frame, |
| 605 FrameDescription::continuation_offset())); | 584 FrameDescription::continuation_offset())); |
| 606 __ Ldr(lr, MemOperand(last_output_frame, FrameDescription::pc_offset())); | 585 __ Ldr(lr, MemOperand(last_output_frame, FrameDescription::pc_offset())); |
| 607 __ InitializeRootRegister(); | 586 __ InitializeRootRegister(); |
| 608 __ Br(continuation); | 587 __ Br(continuation); |
| 609 } | 588 } |
| 610 | 589 |
| 611 | 590 |
| 612 // Size of an entry of the second level deopt table. | 591 // Size of an entry of the second level deopt table. |
| 613 // This is the code size generated by GeneratePrologue for one entry. | 592 // This is the code size generated by GeneratePrologue for one entry. |
| 614 const int Deoptimizer::table_entry_size_ = 4 * kInstructionSize; | 593 const int Deoptimizer::table_entry_size_ = 2 * kInstructionSize; |
| 615 | 594 |
| 616 | 595 |
| 617 void Deoptimizer::TableEntryGenerator::GeneratePrologue() { | 596 void Deoptimizer::TableEntryGenerator::GeneratePrologue() { |
| 618 // Create a sequence of deoptimization entries. | 597 // Create a sequence of deoptimization entries. |
| 619 // Note that any registers may be still live. | 598 // Note that registers are still live when jumping to an entry. |
| 620 Label done; | 599 Label done; |
| 621 { | 600 { |
| 622 InstructionAccurateScope scope(masm()); | 601 InstructionAccurateScope scope(masm()); |
| 623 | 602 |
| 624 // The number of entry will never exceed kMaxNumberOfEntries. | 603 // The number of entry will never exceed kMaxNumberOfEntries. |
| 625 // As long as kMaxNumberOfEntries is a valid 16 bits immediate you can use | 604 // As long as kMaxNumberOfEntries is a valid 16 bits immediate you can use |
| 626 // a movz instruction to load the entry id. | 605 // a movz instruction to load the entry id. |
| 627 ASSERT(is_uint16(Deoptimizer::kMaxNumberOfEntries)); | 606 ASSERT(is_uint16(Deoptimizer::kMaxNumberOfEntries)); |
| 628 | 607 |
| 629 for (int i = 0; i < count(); i++) { | 608 for (int i = 0; i < count(); i++) { |
| 630 int start = masm()->pc_offset(); | 609 int start = masm()->pc_offset(); |
| 631 USE(start); | 610 USE(start); |
| 632 if ((type() == EAGER) || (type() == SOFT)) { | |
| 633 // These nops are fillers; all entries must be the same size. | |
| 634 __ nop(); | |
| 635 __ nop(); | |
| 636 } else { | |
| 637 // Push lr on the stack. | |
| 638 // We cannot use Push from the MacroAssembler here since we are in an | |
| 639 // instruction accurate scope. | |
| 640 __ sub(csp, jssp, kPointerSize); | |
| 641 __ str(lr, MemOperand(jssp, -kPointerSize, PreIndex)); | |
| 642 } | |
| 643 | |
| 644 __ movz(masm()->Tmp0(), i); | 611 __ movz(masm()->Tmp0(), i); |
| 645 __ b(&done); | 612 __ b(&done); |
| 646 ASSERT(masm()->pc_offset() - start == table_entry_size_); | 613 ASSERT(masm()->pc_offset() - start == table_entry_size_); |
| 647 } | 614 } |
| 648 } | 615 } |
| 649 __ Bind(&done); | 616 __ Bind(&done); |
| 650 // TODO(all): We need to add some kind of assertion to verify that Tmp0() | 617 // TODO(all): We need to add some kind of assertion to verify that Tmp0() |
| 651 // is not clobbered by Push. | 618 // is not clobbered by Push. |
| 652 __ Push(masm()->Tmp0()); | 619 __ Push(masm()->Tmp0()); |
| 653 } | 620 } |
| 654 | 621 |
| 655 #undef __ | 622 #undef __ |
| 656 | 623 |
| 657 } } // namespace v8::internal | 624 } } // namespace v8::internal |
| OLD | NEW |