OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 614 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
625 // r1: preserved | 625 // r1: preserved |
626 // r2: preserved | 626 // r2: preserved |
627 | 627 |
628 // Drop the execution stack down to the frame pointer and restore | 628 // Drop the execution stack down to the frame pointer and restore |
629 // the caller frame pointer and return address. | 629 // the caller frame pointer and return address. |
630 mov(sp, fp); | 630 mov(sp, fp); |
631 ldm(ia_w, sp, fp.bit() | lr.bit()); | 631 ldm(ia_w, sp, fp.bit() | lr.bit()); |
632 } | 632 } |
633 | 633 |
634 | 634 |
635 void MacroAssembler::EnterExitFrame(bool save_doubles) { | 635 void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space) { |
636 // Compute the argv pointer in a callee-saved register. | |
637 add(r6, sp, Operand(r0, LSL, kPointerSizeLog2)); | |
638 sub(r6, r6, Operand(kPointerSize)); | |
639 | |
640 // Setup the frame structure on the stack. | 636 // Setup the frame structure on the stack. |
641 ASSERT_EQ(2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement); | 637 ASSERT_EQ(2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement); |
642 ASSERT_EQ(1 * kPointerSize, ExitFrameConstants::kCallerPCOffset); | 638 ASSERT_EQ(1 * kPointerSize, ExitFrameConstants::kCallerPCOffset); |
643 ASSERT_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset); | 639 ASSERT_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset); |
644 Push(lr, fp); | 640 Push(lr, fp); |
645 mov(fp, Operand(sp)); // Setup new frame pointer. | 641 mov(fp, Operand(sp)); // Setup new frame pointer. |
646 // Reserve room for saved entry sp and code object. | 642 // Reserve room for saved entry sp and code object. |
647 sub(sp, sp, Operand(2 * kPointerSize)); | 643 sub(sp, sp, Operand(2 * kPointerSize)); |
648 if (FLAG_debug_code) { | 644 if (FLAG_debug_code) { |
649 mov(ip, Operand(0)); | 645 mov(ip, Operand(0)); |
650 str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset)); | 646 str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset)); |
651 } | 647 } |
652 mov(ip, Operand(CodeObject())); | 648 mov(ip, Operand(CodeObject())); |
653 str(ip, MemOperand(fp, ExitFrameConstants::kCodeOffset)); | 649 str(ip, MemOperand(fp, ExitFrameConstants::kCodeOffset)); |
654 | 650 |
655 // Save the frame pointer and the context in top. | 651 // Save the frame pointer and the context in top. |
656 mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address))); | 652 mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address))); |
657 str(fp, MemOperand(ip)); | 653 str(fp, MemOperand(ip)); |
658 mov(ip, Operand(ExternalReference(Top::k_context_address))); | 654 mov(ip, Operand(ExternalReference(Top::k_context_address))); |
659 str(cp, MemOperand(ip)); | 655 str(cp, MemOperand(ip)); |
660 | 656 |
661 // Setup argc and the builtin function in callee-saved registers. | |
662 mov(r4, Operand(r0)); | |
663 mov(r5, Operand(r1)); | |
664 | |
665 // Optionally save all double registers. | 657 // Optionally save all double registers. |
666 if (save_doubles) { | 658 if (save_doubles) { |
667 sub(sp, sp, Operand(DwVfpRegister::kNumRegisters * kDoubleSize)); | 659 sub(sp, sp, Operand(DwVfpRegister::kNumRegisters * kDoubleSize)); |
668 const int offset = -2 * kPointerSize; | 660 const int offset = -2 * kPointerSize; |
669 for (int i = 0; i < DwVfpRegister::kNumRegisters; i++) { | 661 for (int i = 0; i < DwVfpRegister::kNumRegisters; i++) { |
670 DwVfpRegister reg = DwVfpRegister::from_code(i); | 662 DwVfpRegister reg = DwVfpRegister::from_code(i); |
671 vstr(reg, fp, offset - ((i + 1) * kDoubleSize)); | 663 vstr(reg, fp, offset - ((i + 1) * kDoubleSize)); |
672 } | 664 } |
673 // Note that d0 will be accessible at | 665 // Note that d0 will be accessible at |
674 // fp - 2 * kPointerSize - DwVfpRegister::kNumRegisters * kDoubleSize, | 666 // fp - 2 * kPointerSize - DwVfpRegister::kNumRegisters * kDoubleSize, |
675 // since the sp slot and code slot were pushed after the fp. | 667 // since the sp slot and code slot were pushed after the fp. |
676 } | 668 } |
677 | 669 |
678 // Reserve place for the return address and align the frame preparing for | 670 // Reserve place for the return address and stack space and align the frame |
679 // calling the runtime function. | 671 // preparing for calling the runtime function. |
680 const int frame_alignment = MacroAssembler::ActivationFrameAlignment(); | 672 const int frame_alignment = MacroAssembler::ActivationFrameAlignment(); |
681 sub(sp, sp, Operand(kPointerSize)); | 673 sub(sp, sp, Operand((stack_space + 1) * kPointerSize)); |
682 if (frame_alignment > 0) { | 674 if (frame_alignment > 0) { |
683 ASSERT(IsPowerOf2(frame_alignment)); | 675 ASSERT(IsPowerOf2(frame_alignment)); |
684 and_(sp, sp, Operand(-frame_alignment)); | 676 and_(sp, sp, Operand(-frame_alignment)); |
685 } | 677 } |
686 | 678 |
687 // Set the exit frame sp value to point just before the return address | 679 // Set the exit frame sp value to point just before the return address |
688 // location. | 680 // location. |
689 add(ip, sp, Operand(kPointerSize)); | 681 add(ip, sp, Operand(kPointerSize)); |
690 str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset)); | 682 str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset)); |
691 } | 683 } |
(...skipping 776 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1468 // in initial map. | 1460 // in initial map. |
1469 bind(&non_instance); | 1461 bind(&non_instance); |
1470 ldr(result, FieldMemOperand(result, Map::kConstructorOffset)); | 1462 ldr(result, FieldMemOperand(result, Map::kConstructorOffset)); |
1471 | 1463 |
1472 // All done. | 1464 // All done. |
1473 bind(&done); | 1465 bind(&done); |
1474 } | 1466 } |
1475 | 1467 |
1476 | 1468 |
1477 void MacroAssembler::CallStub(CodeStub* stub, Condition cond) { | 1469 void MacroAssembler::CallStub(CodeStub* stub, Condition cond) { |
1478 ASSERT(allow_stub_calls()); // stub calls are not allowed in some stubs | 1470 ASSERT(allow_stub_calls()); // Stub calls are not allowed in some stubs. |
1479 Call(stub->GetCode(), RelocInfo::CODE_TARGET, cond); | 1471 Call(stub->GetCode(), RelocInfo::CODE_TARGET, cond); |
1480 } | 1472 } |
1481 | 1473 |
1482 | 1474 |
1483 void MacroAssembler::TailCallStub(CodeStub* stub, Condition cond) { | 1475 void MacroAssembler::TailCallStub(CodeStub* stub, Condition cond) { |
1484 ASSERT(allow_stub_calls()); // stub calls are not allowed in some stubs | 1476 ASSERT(allow_stub_calls()); // Stub calls are not allowed in some stubs. |
1485 Jump(stub->GetCode(), RelocInfo::CODE_TARGET, cond); | 1477 Jump(stub->GetCode(), RelocInfo::CODE_TARGET, cond); |
1486 } | 1478 } |
1487 | 1479 |
1488 | 1480 |
1481 MaybeObject* MacroAssembler::TryTailCallStub(CodeStub* stub, Condition cond) { | |
1482 ASSERT(allow_stub_calls()); // Stub calls are not allowed in some stubs. | |
1483 Object* result; | |
1484 { MaybeObject* maybe_result = stub->TryGetCode(); | |
1485 if (!maybe_result->ToObject(&result)) return maybe_result; | |
1486 } | |
1487 Jump(stub->GetCode(), RelocInfo::CODE_TARGET, cond); | |
1488 return result; | |
1489 } | |
1490 | |
1491 | |
1492 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { | |
1493 return ref0.address() - ref1.address(); | |
1494 } | |
1495 | |
1496 | |
1497 MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn( | |
1498 ApiFunction* function, int stack_space) { | |
1499 ExternalReference next_address = | |
1500 ExternalReference::handle_scope_next_address(); | |
1501 const int kNextOffset = 0; | |
1502 const int kLimitOffset = AddressOffset( | |
1503 ExternalReference::handle_scope_limit_address(), | |
1504 next_address); | |
1505 const int kLevelOffset = AddressOffset( | |
1506 ExternalReference::handle_scope_level_address(), | |
1507 next_address); | |
1508 | |
1509 // Allocate HandleScope in callee-save registers. | |
1510 mov(r7, Operand(next_address)); | |
1511 ldr(r4, MemOperand(r7, kNextOffset)); | |
1512 ldr(r5, MemOperand(r7, kLimitOffset)); | |
1513 ldr(r6, MemOperand(r7, kLevelOffset)); | |
1514 add(r6, r6, Operand(1)); | |
1515 str(r6, MemOperand(r7, kLevelOffset)); | |
1516 | |
1517 // Native call returns to the DirectCEntry stub which redirects to the | |
1518 // return address pushed on stack (could have moved after GC). | |
1519 // DirectCEntry stub itself is generated early and never moves. | |
1520 DirectCEntryStub stub; | |
1521 stub.GenerateCall(this, function); | |
1522 | |
1523 Label promote_scheduled_exception; | |
1524 Label delete_allocated_handles; | |
1525 Label leave_exit_frame; | |
1526 | |
1527 // If result is non-zero, dereference to get the result value | |
1528 // otherwise set it to undefined. | |
1529 cmp(r0, Operand(0)); | |
1530 LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); | |
1531 ldr(r0, MemOperand(r0), ne); | |
1532 | |
1533 // No more valid handles (the result handle was the last one). Restore | |
1534 // previous handle scope. | |
1535 str(r4, MemOperand(r7, kNextOffset)); | |
1536 if (FLAG_debug_code) { | |
1537 ldr(r1, MemOperand(r7, kLevelOffset)); | |
1538 cmp(r1, r6); | |
1539 Check(eq, "Unexpected level after return from api call"); | |
1540 } | |
1541 sub(r6, r6, Operand(1)); | |
1542 str(r6, MemOperand(r7, kLevelOffset)); | |
1543 ldr(ip, MemOperand(r7, kLimitOffset)); | |
1544 cmp(r5, ip); | |
1545 b(ne, &delete_allocated_handles); | |
1546 | |
1547 // Check if the function scheduled an exception. | |
1548 bind(&leave_exit_frame); | |
1549 LoadRoot(r4, Heap::kTheHoleValueRootIndex); | |
1550 mov(ip, Operand(ExternalReference::scheduled_exception_address())); | |
1551 ldr(r5, MemOperand(ip)); | |
1552 cmp(r4, r5); | |
1553 b(ne, &promote_scheduled_exception); | |
1554 | |
1555 // LeaveExitFrame expects unwind space to be in r4. | |
1556 mov(r4, Operand(stack_space)); | |
1557 LeaveExitFrame(false); | |
1558 | |
1559 bind(&promote_scheduled_exception); | |
1560 MaybeObject* result = TryTailCallExternalReference( | |
1561 ExternalReference(Runtime::kPromoteScheduledException), 0, 1); | |
1562 if (result->IsFailure()) { | |
1563 return result; | |
1564 } | |
1565 | |
1566 // HandleScope limit has changed. Delete allocated extensions. | |
1567 bind(&delete_allocated_handles); | |
1568 str(r5, MemOperand(r7, kLimitOffset)); | |
1569 mov(r4, r0); | |
1570 PrepareCallCFunction(0, r5); | |
1571 CallCFunction(ExternalReference::delete_handle_scope_extensions(), 0); | |
1572 mov(r0, r4); | |
1573 jmp(&leave_exit_frame); | |
1574 | |
1575 return result; | |
1576 } | |
1577 | |
1578 | |
1489 void MacroAssembler::IllegalOperation(int num_arguments) { | 1579 void MacroAssembler::IllegalOperation(int num_arguments) { |
1490 if (num_arguments > 0) { | 1580 if (num_arguments > 0) { |
1491 add(sp, sp, Operand(num_arguments * kPointerSize)); | 1581 add(sp, sp, Operand(num_arguments * kPointerSize)); |
1492 } | 1582 } |
1493 LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 1583 LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
1494 } | 1584 } |
1495 | 1585 |
1496 | 1586 |
1497 void MacroAssembler::IndexFromHash(Register hash, Register index) { | 1587 void MacroAssembler::IndexFromHash(Register hash, Register index) { |
1498 // If the hash field contains an array index pick it out. The assert checks | 1588 // If the hash field contains an array index pick it out. The assert checks |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1730 void MacroAssembler::TailCallExternalReference(const ExternalReference& ext, | 1820 void MacroAssembler::TailCallExternalReference(const ExternalReference& ext, |
1731 int num_arguments, | 1821 int num_arguments, |
1732 int result_size) { | 1822 int result_size) { |
1733 // TODO(1236192): Most runtime routines don't need the number of | 1823 // TODO(1236192): Most runtime routines don't need the number of |
1734 // arguments passed in because it is constant. At some point we | 1824 // arguments passed in because it is constant. At some point we |
1735 // should remove this need and make the runtime routine entry code | 1825 // should remove this need and make the runtime routine entry code |
1736 // smarter. | 1826 // smarter. |
1737 mov(r0, Operand(num_arguments)); | 1827 mov(r0, Operand(num_arguments)); |
1738 JumpToExternalReference(ext); | 1828 JumpToExternalReference(ext); |
1739 } | 1829 } |
1740 | 1830 |
Erik Corry
2011/02/04 09:55:55
Blank line
antonm
2011/02/04 12:59:45
Done.
| |
1831 MaybeObject* MacroAssembler::TryTailCallExternalReference( | |
1832 const ExternalReference& ext, int num_arguments, int result_size) { | |
1833 // TODO(1236192): Most runtime routines don't need the number of | |
1834 // arguments passed in because it is constant. At some point we | |
1835 // should remove this need and make the runtime routine entry code | |
1836 // smarter. | |
1837 mov(r0, Operand(num_arguments)); | |
1838 return TryJumpToExternalReference(ext); | |
1839 } | |
1741 | 1840 |
Erik Corry
2011/02/04 09:55:55
Blank line
antonm
2011/02/04 12:59:45
Done.
| |
1742 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid, | 1841 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid, |
1743 int num_arguments, | 1842 int num_arguments, |
1744 int result_size) { | 1843 int result_size) { |
1745 TailCallExternalReference(ExternalReference(fid), num_arguments, result_size); | 1844 TailCallExternalReference(ExternalReference(fid), num_arguments, result_size); |
1746 } | 1845 } |
1747 | 1846 |
1748 | 1847 |
1749 void MacroAssembler::JumpToExternalReference(const ExternalReference& builtin) { | 1848 void MacroAssembler::JumpToExternalReference(const ExternalReference& builtin) { |
1750 #if defined(__thumb__) | 1849 #if defined(__thumb__) |
1751 // Thumb mode builtin. | 1850 // Thumb mode builtin. |
1752 ASSERT((reinterpret_cast<intptr_t>(builtin.address()) & 1) == 1); | 1851 ASSERT((reinterpret_cast<intptr_t>(builtin.address()) & 1) == 1); |
1753 #endif | 1852 #endif |
1754 mov(r1, Operand(builtin)); | 1853 mov(r1, Operand(builtin)); |
1755 CEntryStub stub(1); | 1854 CEntryStub stub(1); |
1756 Jump(stub.GetCode(), RelocInfo::CODE_TARGET); | 1855 Jump(stub.GetCode(), RelocInfo::CODE_TARGET); |
1757 } | 1856 } |
1758 | 1857 |
Erik Corry
2011/02/04 09:55:55
Blank line
antonm
2011/02/04 12:59:45
Done.
| |
1858 MaybeObject* MacroAssembler::TryJumpToExternalReference( | |
1859 const ExternalReference& builtin) { | |
1860 #if defined(__thumb__) | |
1861 // Thumb mode builtin. | |
1862 ASSERT((reinterpret_cast<intptr_t>(builtin.address()) & 1) == 1); | |
1863 #endif | |
1864 mov(r1, Operand(builtin)); | |
1865 CEntryStub stub(1); | |
1866 return TryTailCallStub(&stub); | |
1867 } | |
1759 | 1868 |
Erik Corry
2011/02/04 09:55:55
Blank line
antonm
2011/02/04 12:59:45
Done.
| |
1760 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, | 1869 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, |
1761 InvokeJSFlags flags, | 1870 InvokeJSFlags flags, |
1762 PostCallGenerator* post_call_generator) { | 1871 PostCallGenerator* post_call_generator) { |
1763 GetBuiltinEntry(r2, id); | 1872 GetBuiltinEntry(r2, id); |
1764 if (flags == CALL_JS) { | 1873 if (flags == CALL_JS) { |
1765 Call(r2); | 1874 Call(r2); |
1766 if (post_call_generator != NULL) post_call_generator->Generate(); | 1875 if (post_call_generator != NULL) post_call_generator->Generate(); |
1767 } else { | 1876 } else { |
1768 ASSERT(flags == JUMP_JS); | 1877 ASSERT(flags == JUMP_JS); |
1769 Jump(r2); | 1878 Jump(r2); |
(...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2285 | 2394 |
2286 void CodePatcher::Emit(Address addr) { | 2395 void CodePatcher::Emit(Address addr) { |
2287 masm()->emit(reinterpret_cast<Instr>(addr)); | 2396 masm()->emit(reinterpret_cast<Instr>(addr)); |
2288 } | 2397 } |
2289 #endif // ENABLE_DEBUGGER_SUPPORT | 2398 #endif // ENABLE_DEBUGGER_SUPPORT |
2290 | 2399 |
2291 | 2400 |
2292 } } // namespace v8::internal | 2401 } } // namespace v8::internal |
2293 | 2402 |
2294 #endif // V8_TARGET_ARCH_ARM | 2403 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |