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

Side by Side Diff: src/arm/code-stubs-arm.cc

Issue 240053010: Return Object* instead of MaybeObject* from runtime calls. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: cmpp Created 6 years, 8 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
« no previous file with comments | « src/arguments.h ('k') | src/arm/regexp-macro-assembler-arm.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 1484 matching lines...) Expand 10 before | Expand all | Expand 10 after
1495 isolate->set_fp_stubs_generated(true); 1495 isolate->set_fp_stubs_generated(true);
1496 } 1496 }
1497 1497
1498 1498
1499 void CEntryStub::GenerateAheadOfTime(Isolate* isolate) { 1499 void CEntryStub::GenerateAheadOfTime(Isolate* isolate) {
1500 CEntryStub stub(1, kDontSaveFPRegs); 1500 CEntryStub stub(1, kDontSaveFPRegs);
1501 stub.GetCode(isolate); 1501 stub.GetCode(isolate);
1502 } 1502 }
1503 1503
1504 1504
1505 void CEntryStub::GenerateCore(MacroAssembler* masm, 1505 void CEntryStub::Generate(MacroAssembler* masm) {
1506 Label* throw_normal_exception, 1506 // Called from JavaScript; parameters are on stack as if calling JS function.
1507 Label* throw_termination_exception, 1507 // r0: number of arguments including receiver
1508 bool do_gc, 1508 // r1: pointer to builtin function
1509 bool always_allocate) { 1509 // fp: frame pointer (restored after C call)
1510 // r0: result parameter for PerformGC, if any 1510 // sp: stack pointer (restored as callee's sp after C call)
1511 // r4: number of arguments including receiver (C callee-saved) 1511 // cp: current context (C callee-saved)
1512
1513 ProfileEntryHookStub::MaybeCallEntryHook(masm);
1514
1515 __ mov(r5, Operand(r1));
1516
1517 // Compute the argv pointer in a callee-saved register.
1518 __ add(r1, sp, Operand(r0, LSL, kPointerSizeLog2));
1519 __ sub(r1, r1, Operand(kPointerSize));
1520
1521 // Enter the exit frame that transitions from JavaScript to C++.
1522 FrameScope scope(masm, StackFrame::MANUAL);
1523 __ EnterExitFrame(save_doubles_);
1524
1525 // Store a copy of argc in callee-saved registers for later.
1526 __ mov(r4, Operand(r0));
1527
1528 // r0, r4: number of arguments including receiver (C callee-saved)
1529 // r1: pointer to the first argument (C callee-saved)
1512 // r5: pointer to builtin function (C callee-saved) 1530 // r5: pointer to builtin function (C callee-saved)
1513 // r6: pointer to the first argument (C callee-saved) 1531
1532 // Result returned in r0 or r0+r1 by default.
1533
1514 Isolate* isolate = masm->isolate(); 1534 Isolate* isolate = masm->isolate();
1515 1535
1516 if (do_gc) {
1517 // Passing r0.
1518 __ PrepareCallCFunction(2, 0, r1);
1519 __ mov(r1, Operand(ExternalReference::isolate_address(masm->isolate())));
1520 __ CallCFunction(ExternalReference::perform_gc_function(isolate),
1521 2, 0);
1522 }
1523
1524 ExternalReference scope_depth =
1525 ExternalReference::heap_always_allocate_scope_depth(isolate);
1526 if (always_allocate) {
1527 __ mov(r0, Operand(scope_depth));
1528 __ ldr(r1, MemOperand(r0));
1529 __ add(r1, r1, Operand(1));
1530 __ str(r1, MemOperand(r0));
1531 }
1532
1533 // Call C built-in.
1534 // r0 = argc, r1 = argv
1535 __ mov(r0, Operand(r4));
1536 __ mov(r1, Operand(r6));
1537
1538 #if V8_HOST_ARCH_ARM 1536 #if V8_HOST_ARCH_ARM
1539 int frame_alignment = MacroAssembler::ActivationFrameAlignment(); 1537 int frame_alignment = MacroAssembler::ActivationFrameAlignment();
1540 int frame_alignment_mask = frame_alignment - 1; 1538 int frame_alignment_mask = frame_alignment - 1;
1541 if (FLAG_debug_code) { 1539 if (FLAG_debug_code) {
1542 if (frame_alignment > kPointerSize) { 1540 if (frame_alignment > kPointerSize) {
1543 Label alignment_as_expected; 1541 Label alignment_as_expected;
1544 ASSERT(IsPowerOf2(frame_alignment)); 1542 ASSERT(IsPowerOf2(frame_alignment));
1545 __ tst(sp, Operand(frame_alignment_mask)); 1543 __ tst(sp, Operand(frame_alignment_mask));
1546 __ b(eq, &alignment_as_expected); 1544 __ b(eq, &alignment_as_expected);
1547 // Don't use Check here, as it will call Runtime_Abort re-entering here. 1545 // Don't use Check here, as it will call Runtime_Abort re-entering here.
1548 __ stop("Unexpected alignment"); 1546 __ stop("Unexpected alignment");
1549 __ bind(&alignment_as_expected); 1547 __ bind(&alignment_as_expected);
1550 } 1548 }
1551 } 1549 }
1552 #endif 1550 #endif
1553 1551
1552 // Call C built-in.
1553 // r0 = argc, r1 = argv
1554 __ mov(r2, Operand(ExternalReference::isolate_address(isolate))); 1554 __ mov(r2, Operand(ExternalReference::isolate_address(isolate)));
1555 1555
1556 // To let the GC traverse the return address of the exit frames, we need to 1556 // To let the GC traverse the return address of the exit frames, we need to
1557 // know where the return address is. The CEntryStub is unmovable, so 1557 // know where the return address is. The CEntryStub is unmovable, so
1558 // we can store the address on the stack to be able to find it again and 1558 // we can store the address on the stack to be able to find it again and
1559 // we never have to restore it, because it will not change. 1559 // we never have to restore it, because it will not change.
1560 // Compute the return address in lr to return to after the jump below. Pc is 1560 // Compute the return address in lr to return to after the jump below. Pc is
1561 // already at '+ 8' from the current instruction but return is after three 1561 // already at '+ 8' from the current instruction but return is after three
1562 // instructions so add another 4 to pc to get the return address. 1562 // instructions so add another 4 to pc to get the return address.
1563 { 1563 {
1564 // Prevent literal pool emission before return address. 1564 // Prevent literal pool emission before return address.
1565 Assembler::BlockConstPoolScope block_const_pool(masm); 1565 Assembler::BlockConstPoolScope block_const_pool(masm);
1566 __ add(lr, pc, Operand(4)); 1566 __ add(lr, pc, Operand(4));
1567 __ str(lr, MemOperand(sp, 0)); 1567 __ str(lr, MemOperand(sp, 0));
1568 __ Call(r5); 1568 __ Call(r5);
1569 } 1569 }
1570 1570
1571 __ VFPEnsureFPSCRState(r2); 1571 __ VFPEnsureFPSCRState(r2);
1572 1572
1573 if (always_allocate) { 1573 // Runtime functions should not return 'the hole'. Allowing it to escape may
1574 // It's okay to clobber r2 and r3 here. Don't mess with r0 and r1 1574 // lead to crashes in the IC code later.
1575 // though (contain the result). 1575 if (FLAG_debug_code) {
1576 __ mov(r2, Operand(scope_depth)); 1576 Label okay;
1577 __ ldr(r3, MemOperand(r2)); 1577 __ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
1578 __ sub(r3, r3, Operand(1)); 1578 __ b(ne, &okay);
1579 __ str(r3, MemOperand(r2)); 1579 __ stop("The hole escaped");
1580 __ bind(&okay);
1580 } 1581 }
1581 1582
1582 // check for failure result 1583 // Check result for exception sentinel.
1583 Label failure_returned; 1584 Label exception_returned;
1584 STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); 1585 __ CompareRoot(r0, Heap::kExceptionRootIndex);
1585 // Lower 2 bits of r2 are 0 iff r0 has failure tag. 1586 __ b(eq, &exception_returned);
1586 __ add(r2, r0, Operand(1)); 1587
1587 __ tst(r2, Operand(kFailureTagMask)); 1588 ExternalReference pending_exception_address(
1588 __ b(eq, &failure_returned); 1589 Isolate::kPendingExceptionAddress, isolate);
1590
1591 // Check that there is no pending exception, otherwise we
1592 // should have returned the exception sentinel.
1593 if (FLAG_debug_code) {
1594 Label okay;
1595 __ mov(r2, Operand(pending_exception_address));
1596 __ ldr(r2, MemOperand(r2));
1597 __ CompareRoot(r2, Heap::kTheHoleValueRootIndex);
1598 // Cannot use check here as it attempts to generate call into runtime.
1599 __ b(eq, &okay);
1600 __ stop("Unexpected pending exception");
1601 __ bind(&okay);
1602 }
1589 1603
1590 // Exit C frame and return. 1604 // Exit C frame and return.
1591 // r0:r1: result 1605 // r0:r1: result
1592 // sp: stack pointer 1606 // sp: stack pointer
1593 // fp: frame pointer 1607 // fp: frame pointer
1594 // Callee-saved register r4 still holds argc. 1608 // Callee-saved register r4 still holds argc.
1595 __ LeaveExitFrame(save_doubles_, r4, true); 1609 __ LeaveExitFrame(save_doubles_, r4, true);
1596 __ mov(pc, lr); 1610 __ mov(pc, lr);
1597 1611
1598 // check if we should retry or throw exception 1612 // Handling of exception.
1599 Label retry; 1613 __ bind(&exception_returned);
1600 __ bind(&failure_returned);
1601 STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0);
1602 __ tst(r0, Operand(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize));
1603 __ b(eq, &retry);
1604 1614
1605 // Retrieve the pending exception. 1615 // Retrieve the pending exception.
1606 __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress, 1616 __ mov(r2, Operand(pending_exception_address));
1607 isolate))); 1617 __ ldr(r0, MemOperand(r2));
1608 __ ldr(r0, MemOperand(ip));
1609 1618
1610 // Clear the pending exception. 1619 // Clear the pending exception.
1611 __ LoadRoot(r3, Heap::kTheHoleValueRootIndex); 1620 __ LoadRoot(r3, Heap::kTheHoleValueRootIndex);
1612 __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress, 1621 __ str(r3, MemOperand(r2));
1613 isolate)));
1614 __ str(r3, MemOperand(ip));
1615 1622
1616 // Special handling of termination exceptions which are uncatchable 1623 // Special handling of termination exceptions which are uncatchable
1617 // by javascript code. 1624 // by javascript code.
1618 __ LoadRoot(r3, Heap::kTerminationExceptionRootIndex); 1625 Label throw_termination_exception;
1619 __ cmp(r0, r3); 1626 __ CompareRoot(r0, Heap::kTerminationExceptionRootIndex);
1620 __ b(eq, throw_termination_exception); 1627 __ b(eq, &throw_termination_exception);
1621 1628
1622 // Handle normal exception. 1629 // Handle normal exception.
1623 __ jmp(throw_normal_exception); 1630 __ Throw(r0);
1624 1631
1625 __ bind(&retry); // pass last failure (r0) as parameter (r0) when retrying 1632 __ bind(&throw_termination_exception);
1633 __ ThrowUncatchable(r0);
1626 } 1634 }
1627 1635
1628 1636
1629 void CEntryStub::Generate(MacroAssembler* masm) {
1630 // Called from JavaScript; parameters are on stack as if calling JS function
1631 // r0: number of arguments including receiver
1632 // r1: pointer to builtin function
1633 // fp: frame pointer (restored after C call)
1634 // sp: stack pointer (restored as callee's sp after C call)
1635 // cp: current context (C callee-saved)
1636
1637 ProfileEntryHookStub::MaybeCallEntryHook(masm);
1638
1639 // Result returned in r0 or r0+r1 by default.
1640
1641 // NOTE: Invocations of builtins may return failure objects
1642 // instead of a proper result. The builtin entry handles
1643 // this by performing a garbage collection and retrying the
1644 // builtin once.
1645
1646 // Compute the argv pointer in a callee-saved register.
1647 __ add(r6, sp, Operand(r0, LSL, kPointerSizeLog2));
1648 __ sub(r6, r6, Operand(kPointerSize));
1649
1650 // Enter the exit frame that transitions from JavaScript to C++.
1651 FrameScope scope(masm, StackFrame::MANUAL);
1652 __ EnterExitFrame(save_doubles_);
1653
1654 // Set up argc and the builtin function in callee-saved registers.
1655 __ mov(r4, Operand(r0));
1656 __ mov(r5, Operand(r1));
1657
1658 // r4: number of arguments (C callee-saved)
1659 // r5: pointer to builtin function (C callee-saved)
1660 // r6: pointer to first argument (C callee-saved)
1661
1662 Label throw_normal_exception;
1663 Label throw_termination_exception;
1664
1665 // Call into the runtime system.
1666 GenerateCore(masm,
1667 &throw_normal_exception,
1668 &throw_termination_exception,
1669 false,
1670 false);
1671
1672 // Do space-specific GC and retry runtime call.
1673 GenerateCore(masm,
1674 &throw_normal_exception,
1675 &throw_termination_exception,
1676 true,
1677 false);
1678
1679 // Do full GC and retry runtime call one final time.
1680 Failure* failure = Failure::InternalError();
1681 __ mov(r0, Operand(reinterpret_cast<int32_t>(failure)));
1682 GenerateCore(masm,
1683 &throw_normal_exception,
1684 &throw_termination_exception,
1685 true,
1686 true);
1687
1688 { FrameScope scope(masm, StackFrame::MANUAL);
1689 __ PrepareCallCFunction(0, r0);
1690 __ CallCFunction(
1691 ExternalReference::out_of_memory_function(masm->isolate()), 0, 0);
1692 }
1693
1694 __ bind(&throw_termination_exception);
1695 __ ThrowUncatchable(r0);
1696
1697 __ bind(&throw_normal_exception);
1698 __ Throw(r0);
1699 }
1700
1701
1702 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { 1637 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
1703 // r0: code entry 1638 // r0: code entry
1704 // r1: function 1639 // r1: function
1705 // r2: receiver 1640 // r2: receiver
1706 // r3: argc 1641 // r3: argc
1707 // [sp+0]: argv 1642 // [sp+0]: argv
1708 1643
1709 Label invoke, handler_entry, exit; 1644 Label invoke, handler_entry, exit;
1710 1645
1711 ProfileEntryHookStub::MaybeCallEntryHook(masm); 1646 ProfileEntryHookStub::MaybeCallEntryHook(masm);
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1784 __ bind(&handler_entry); 1719 __ bind(&handler_entry);
1785 handler_offset_ = handler_entry.pos(); 1720 handler_offset_ = handler_entry.pos();
1786 // Caught exception: Store result (exception) in the pending exception 1721 // Caught exception: Store result (exception) in the pending exception
1787 // field in the JSEnv and return a failure sentinel. Coming in here the 1722 // field in the JSEnv and return a failure sentinel. Coming in here the
1788 // fp will be invalid because the PushTryHandler below sets it to 0 to 1723 // fp will be invalid because the PushTryHandler below sets it to 0 to
1789 // signal the existence of the JSEntry frame. 1724 // signal the existence of the JSEntry frame.
1790 __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress, 1725 __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
1791 isolate))); 1726 isolate)));
1792 } 1727 }
1793 __ str(r0, MemOperand(ip)); 1728 __ str(r0, MemOperand(ip));
1794 __ mov(r0, Operand(reinterpret_cast<int32_t>(Failure::Exception()))); 1729 __ LoadRoot(r0, Heap::kExceptionRootIndex);
1795 __ b(&exit); 1730 __ b(&exit);
1796 1731
1797 // Invoke: Link this frame into the handler chain. There's only one 1732 // Invoke: Link this frame into the handler chain. There's only one
1798 // handler block in this code object, so its index is 0. 1733 // handler block in this code object, so its index is 0.
1799 __ bind(&invoke); 1734 __ bind(&invoke);
1800 // Must preserve r0-r4, r5-r6 are available. 1735 // Must preserve r0-r4, r5-r6 are available.
1801 __ PushTryHandler(StackHandler::JS_ENTRY, 0); 1736 __ PushTryHandler(StackHandler::JS_ENTRY, 0);
1802 // If an exception not caught by another handler occurs, this handler 1737 // If an exception not caught by another handler occurs, this handler
1803 // returns control to the code after the bl(&invoke) above, which 1738 // returns control to the code after the bl(&invoke) above, which
1804 // restores all kCalleeSaved registers (including cp and fp) to their 1739 // restores all kCalleeSaved registers (including cp and fp) to their
(...skipping 3450 matching lines...) Expand 10 before | Expand all | Expand 10 after
5255 MemOperand(fp, 6 * kPointerSize), 5190 MemOperand(fp, 6 * kPointerSize),
5256 NULL); 5191 NULL);
5257 } 5192 }
5258 5193
5259 5194
5260 #undef __ 5195 #undef __
5261 5196
5262 } } // namespace v8::internal 5197 } } // namespace v8::internal
5263 5198
5264 #endif // V8_TARGET_ARCH_ARM 5199 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arguments.h ('k') | src/arm/regexp-macro-assembler-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698