Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: src/arm/macro-assembler-arm.cc

Issue 6170001: Direct call api functions (arm implementation) (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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);
(...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after
2274 2383
2275 void CodePatcher::Emit(Address addr) { 2384 void CodePatcher::Emit(Address addr) {
2276 masm()->emit(reinterpret_cast<Instr>(addr)); 2385 masm()->emit(reinterpret_cast<Instr>(addr));
2277 } 2386 }
2278 #endif // ENABLE_DEBUGGER_SUPPORT 2387 #endif // ENABLE_DEBUGGER_SUPPORT
2279 2388
2280 2389
2281 } } // namespace v8::internal 2390 } } // namespace v8::internal
2282 2391
2283 #endif // V8_TARGET_ARCH_ARM 2392 #endif // V8_TARGET_ARCH_ARM
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698