| 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 596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 607 // r1: preserved | 607 // r1: preserved |
| 608 // r2: preserved | 608 // r2: preserved |
| 609 | 609 |
| 610 // Drop the execution stack down to the frame pointer and restore | 610 // Drop the execution stack down to the frame pointer and restore |
| 611 // the caller frame pointer and return address. | 611 // the caller frame pointer and return address. |
| 612 mov(sp, fp); | 612 mov(sp, fp); |
| 613 ldm(ia_w, sp, fp.bit() | lr.bit()); | 613 ldm(ia_w, sp, fp.bit() | lr.bit()); |
| 614 } | 614 } |
| 615 | 615 |
| 616 | 616 |
| 617 void MacroAssembler::EnterExitFrame(bool save_doubles) { | 617 void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space) { |
| 618 // Compute the argv pointer in a callee-saved register. | |
| 619 add(r6, sp, Operand(r0, LSL, kPointerSizeLog2)); | |
| 620 sub(r6, r6, Operand(kPointerSize)); | |
| 621 | |
| 622 // Setup the frame structure on the stack. | 618 // Setup the frame structure on the stack. |
| 623 ASSERT_EQ(2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement); | 619 ASSERT_EQ(2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement); |
| 624 ASSERT_EQ(1 * kPointerSize, ExitFrameConstants::kCallerPCOffset); | 620 ASSERT_EQ(1 * kPointerSize, ExitFrameConstants::kCallerPCOffset); |
| 625 ASSERT_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset); | 621 ASSERT_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset); |
| 626 Push(lr, fp); | 622 Push(lr, fp); |
| 627 mov(fp, Operand(sp)); // Setup new frame pointer. | 623 mov(fp, Operand(sp)); // Setup new frame pointer. |
| 628 // Reserve room for saved entry sp and code object. | 624 // Reserve room for saved entry sp and code object. |
| 629 sub(sp, sp, Operand(2 * kPointerSize)); | 625 sub(sp, sp, Operand(2 * kPointerSize)); |
| 630 if (FLAG_debug_code) { | 626 if (FLAG_debug_code) { |
| 631 mov(ip, Operand(0)); | 627 mov(ip, Operand(0)); |
| 632 str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset)); | 628 str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset)); |
| 633 } | 629 } |
| 634 mov(ip, Operand(CodeObject())); | 630 mov(ip, Operand(CodeObject())); |
| 635 str(ip, MemOperand(fp, ExitFrameConstants::kCodeOffset)); | 631 str(ip, MemOperand(fp, ExitFrameConstants::kCodeOffset)); |
| 636 | 632 |
| 637 // Save the frame pointer and the context in top. | 633 // Save the frame pointer and the context in top. |
| 638 mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address))); | 634 mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address))); |
| 639 str(fp, MemOperand(ip)); | 635 str(fp, MemOperand(ip)); |
| 640 mov(ip, Operand(ExternalReference(Top::k_context_address))); | 636 mov(ip, Operand(ExternalReference(Top::k_context_address))); |
| 641 str(cp, MemOperand(ip)); | 637 str(cp, MemOperand(ip)); |
| 642 | 638 |
| 643 // Setup argc and the builtin function in callee-saved registers. | |
| 644 mov(r4, Operand(r0)); | |
| 645 mov(r5, Operand(r1)); | |
| 646 | |
| 647 // Optionally save all double registers. | 639 // Optionally save all double registers. |
| 648 if (save_doubles) { | 640 if (save_doubles) { |
| 649 sub(sp, sp, Operand(DwVfpRegister::kNumRegisters * kDoubleSize)); | 641 sub(sp, sp, Operand(DwVfpRegister::kNumRegisters * kDoubleSize)); |
| 650 const int offset = -2 * kPointerSize; | 642 const int offset = -2 * kPointerSize; |
| 651 for (int i = 0; i < DwVfpRegister::kNumRegisters; i++) { | 643 for (int i = 0; i < DwVfpRegister::kNumRegisters; i++) { |
| 652 DwVfpRegister reg = DwVfpRegister::from_code(i); | 644 DwVfpRegister reg = DwVfpRegister::from_code(i); |
| 653 vstr(reg, fp, offset - ((i + 1) * kDoubleSize)); | 645 vstr(reg, fp, offset - ((i + 1) * kDoubleSize)); |
| 654 } | 646 } |
| 655 // Note that d0 will be accessible at | 647 // Note that d0 will be accessible at |
| 656 // fp - 2 * kPointerSize - DwVfpRegister::kNumRegisters * kDoubleSize, | 648 // fp - 2 * kPointerSize - DwVfpRegister::kNumRegisters * kDoubleSize, |
| 657 // since the sp slot and code slot were pushed after the fp. | 649 // since the sp slot and code slot were pushed after the fp. |
| 658 } | 650 } |
| 659 | 651 |
| 660 // Reserve place for the return address and align the frame preparing for | 652 // Reserve place for the return address and stack space and align the frame |
| 661 // calling the runtime function. | 653 // preparing for calling the runtime function. |
| 662 const int frame_alignment = MacroAssembler::ActivationFrameAlignment(); | 654 const int frame_alignment = MacroAssembler::ActivationFrameAlignment(); |
| 663 sub(sp, sp, Operand(kPointerSize)); | 655 sub(sp, sp, Operand((stack_space + 1) * kPointerSize)); |
| 664 if (frame_alignment > 0) { | 656 if (frame_alignment > 0) { |
| 665 ASSERT(IsPowerOf2(frame_alignment)); | 657 ASSERT(IsPowerOf2(frame_alignment)); |
| 666 and_(sp, sp, Operand(-frame_alignment)); | 658 and_(sp, sp, Operand(-frame_alignment)); |
| 667 } | 659 } |
| 668 | 660 |
| 669 // Set the exit frame sp value to point just before the return address | 661 // Set the exit frame sp value to point just before the return address |
| 670 // location. | 662 // location. |
| 671 add(ip, sp, Operand(kPointerSize)); | 663 add(ip, sp, Operand(kPointerSize)); |
| 672 str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset)); | 664 str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset)); |
| 673 } | 665 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 697 #else // defined(V8_HOST_ARCH_ARM) | 689 #else // defined(V8_HOST_ARCH_ARM) |
| 698 // If we are using the simulator then we should always align to the expected | 690 // If we are using the simulator then we should always align to the expected |
| 699 // alignment. As the simulator is used to generate snapshots we do not know | 691 // alignment. As the simulator is used to generate snapshots we do not know |
| 700 // if the target platform will need alignment, so this is controlled from a | 692 // if the target platform will need alignment, so this is controlled from a |
| 701 // flag. | 693 // flag. |
| 702 return FLAG_sim_stack_alignment; | 694 return FLAG_sim_stack_alignment; |
| 703 #endif // defined(V8_HOST_ARCH_ARM) | 695 #endif // defined(V8_HOST_ARCH_ARM) |
| 704 } | 696 } |
| 705 | 697 |
| 706 | 698 |
| 707 void MacroAssembler::LeaveExitFrame(bool save_doubles) { | 699 void MacroAssembler::LeaveExitFrame(bool save_doubles, |
| 700 Register argument_count) { |
| 708 // Optionally restore all double registers. | 701 // Optionally restore all double registers. |
| 709 if (save_doubles) { | 702 if (save_doubles) { |
| 710 for (int i = 0; i < DwVfpRegister::kNumRegisters; i++) { | 703 for (int i = 0; i < DwVfpRegister::kNumRegisters; i++) { |
| 711 DwVfpRegister reg = DwVfpRegister::from_code(i); | 704 DwVfpRegister reg = DwVfpRegister::from_code(i); |
| 712 const int offset = -2 * kPointerSize; | 705 const int offset = -2 * kPointerSize; |
| 713 vldr(reg, fp, offset - ((i + 1) * kDoubleSize)); | 706 vldr(reg, fp, offset - ((i + 1) * kDoubleSize)); |
| 714 } | 707 } |
| 715 } | 708 } |
| 716 | 709 |
| 717 // Clear top frame. | 710 // Clear top frame. |
| 718 mov(r3, Operand(0, RelocInfo::NONE)); | 711 mov(r3, Operand(0, RelocInfo::NONE)); |
| 719 mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address))); | 712 mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address))); |
| 720 str(r3, MemOperand(ip)); | 713 str(r3, MemOperand(ip)); |
| 721 | 714 |
| 722 // Restore current context from top and clear it in debug mode. | 715 // Restore current context from top and clear it in debug mode. |
| 723 mov(ip, Operand(ExternalReference(Top::k_context_address))); | 716 mov(ip, Operand(ExternalReference(Top::k_context_address))); |
| 724 ldr(cp, MemOperand(ip)); | 717 ldr(cp, MemOperand(ip)); |
| 725 #ifdef DEBUG | 718 #ifdef DEBUG |
| 726 str(r3, MemOperand(ip)); | 719 str(r3, MemOperand(ip)); |
| 727 #endif | 720 #endif |
| 728 | 721 |
| 729 // Tear down the exit frame, pop the arguments, and return. Callee-saved | 722 // Tear down the exit frame, pop the arguments, and return. |
| 730 // register r4 still holds argc. | |
| 731 mov(sp, Operand(fp)); | 723 mov(sp, Operand(fp)); |
| 732 ldm(ia_w, sp, fp.bit() | lr.bit()); | 724 ldm(ia_w, sp, fp.bit() | lr.bit()); |
| 733 add(sp, sp, Operand(r4, LSL, kPointerSizeLog2)); | 725 if (argument_count.is_valid()) { |
| 734 mov(pc, lr); | 726 add(sp, sp, Operand(argument_count, LSL, kPointerSizeLog2)); |
| 727 } |
| 735 } | 728 } |
| 736 | 729 |
| 737 | 730 |
| 738 void MacroAssembler::InvokePrologue(const ParameterCount& expected, | 731 void MacroAssembler::InvokePrologue(const ParameterCount& expected, |
| 739 const ParameterCount& actual, | 732 const ParameterCount& actual, |
| 740 Handle<Code> code_constant, | 733 Handle<Code> code_constant, |
| 741 Register code_reg, | 734 Register code_reg, |
| 742 Label* done, | 735 Label* done, |
| 743 InvokeFlag flag, | 736 InvokeFlag flag, |
| 744 PostCallGenerator* post_call_generator) { | 737 PostCallGenerator* post_call_generator) { |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 988 | 981 |
| 989 void MacroAssembler::PopTryHandler() { | 982 void MacroAssembler::PopTryHandler() { |
| 990 ASSERT_EQ(0, StackHandlerConstants::kNextOffset); | 983 ASSERT_EQ(0, StackHandlerConstants::kNextOffset); |
| 991 pop(r1); | 984 pop(r1); |
| 992 mov(ip, Operand(ExternalReference(Top::k_handler_address))); | 985 mov(ip, Operand(ExternalReference(Top::k_handler_address))); |
| 993 add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); | 986 add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); |
| 994 str(r1, MemOperand(ip)); | 987 str(r1, MemOperand(ip)); |
| 995 } | 988 } |
| 996 | 989 |
| 997 | 990 |
| 991 void MacroAssembler::Throw(Register value) { |
| 992 // r0 is expected to hold the exception. |
| 993 if (!value.is(r0)) { |
| 994 mov(r0, value); |
| 995 } |
| 996 |
| 997 // Adjust this code if not the case. |
| 998 STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); |
| 999 |
| 1000 // Drop the sp to the top of the handler. |
| 1001 mov(r3, Operand(ExternalReference(Top::k_handler_address))); |
| 1002 ldr(sp, MemOperand(r3)); |
| 1003 |
| 1004 // Restore the next handler and frame pointer, discard handler state. |
| 1005 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
| 1006 pop(r2); |
| 1007 str(r2, MemOperand(r3)); |
| 1008 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); |
| 1009 ldm(ia_w, sp, r3.bit() | fp.bit()); // r3: discarded state. |
| 1010 |
| 1011 // Before returning we restore the context from the frame pointer if |
| 1012 // not NULL. The frame pointer is NULL in the exception handler of a |
| 1013 // JS entry frame. |
| 1014 cmp(fp, Operand(0, RelocInfo::NONE)); |
| 1015 // Set cp to NULL if fp is NULL. |
| 1016 mov(cp, Operand(0, RelocInfo::NONE), LeaveCC, eq); |
| 1017 // Restore cp otherwise. |
| 1018 ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne); |
| 1019 #ifdef DEBUG |
| 1020 if (FLAG_debug_code) { |
| 1021 mov(lr, Operand(pc)); |
| 1022 } |
| 1023 #endif |
| 1024 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); |
| 1025 pop(pc); |
| 1026 } |
| 1027 |
| 1028 |
| 1029 void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, |
| 1030 Register value) { |
| 1031 // Adjust this code if not the case. |
| 1032 STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); |
| 1033 |
| 1034 // r0 is expected to hold the exception. |
| 1035 if (!value.is(r0)) { |
| 1036 mov(r0, value); |
| 1037 } |
| 1038 |
| 1039 // Drop sp to the top stack handler. |
| 1040 mov(r3, Operand(ExternalReference(Top::k_handler_address))); |
| 1041 ldr(sp, MemOperand(r3)); |
| 1042 |
| 1043 // Unwind the handlers until the ENTRY handler is found. |
| 1044 Label loop, done; |
| 1045 bind(&loop); |
| 1046 // Load the type of the current stack handler. |
| 1047 const int kStateOffset = StackHandlerConstants::kStateOffset; |
| 1048 ldr(r2, MemOperand(sp, kStateOffset)); |
| 1049 cmp(r2, Operand(StackHandler::ENTRY)); |
| 1050 b(eq, &done); |
| 1051 // Fetch the next handler in the list. |
| 1052 const int kNextOffset = StackHandlerConstants::kNextOffset; |
| 1053 ldr(sp, MemOperand(sp, kNextOffset)); |
| 1054 jmp(&loop); |
| 1055 bind(&done); |
| 1056 |
| 1057 // Set the top handler address to next handler past the current ENTRY handler. |
| 1058 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
| 1059 pop(r2); |
| 1060 str(r2, MemOperand(r3)); |
| 1061 |
| 1062 if (type == OUT_OF_MEMORY) { |
| 1063 // Set external caught exception to false. |
| 1064 ExternalReference external_caught(Top::k_external_caught_exception_address); |
| 1065 mov(r0, Operand(false, RelocInfo::NONE)); |
| 1066 mov(r2, Operand(external_caught)); |
| 1067 str(r0, MemOperand(r2)); |
| 1068 |
| 1069 // Set pending exception and r0 to out of memory exception. |
| 1070 Failure* out_of_memory = Failure::OutOfMemoryException(); |
| 1071 mov(r0, Operand(reinterpret_cast<int32_t>(out_of_memory))); |
| 1072 mov(r2, Operand(ExternalReference(Top::k_pending_exception_address))); |
| 1073 str(r0, MemOperand(r2)); |
| 1074 } |
| 1075 |
| 1076 // Stack layout at this point. See also StackHandlerConstants. |
| 1077 // sp -> state (ENTRY) |
| 1078 // fp |
| 1079 // lr |
| 1080 |
| 1081 // Discard handler state (r2 is not used) and restore frame pointer. |
| 1082 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); |
| 1083 ldm(ia_w, sp, r2.bit() | fp.bit()); // r2: discarded state. |
| 1084 // Before returning we restore the context from the frame pointer if |
| 1085 // not NULL. The frame pointer is NULL in the exception handler of a |
| 1086 // JS entry frame. |
| 1087 cmp(fp, Operand(0, RelocInfo::NONE)); |
| 1088 // Set cp to NULL if fp is NULL. |
| 1089 mov(cp, Operand(0, RelocInfo::NONE), LeaveCC, eq); |
| 1090 // Restore cp otherwise. |
| 1091 ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne); |
| 1092 #ifdef DEBUG |
| 1093 if (FLAG_debug_code) { |
| 1094 mov(lr, Operand(pc)); |
| 1095 } |
| 1096 #endif |
| 1097 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); |
| 1098 pop(pc); |
| 1099 } |
| 1100 |
| 1101 |
| 998 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, | 1102 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, |
| 999 Register scratch, | 1103 Register scratch, |
| 1000 Label* miss) { | 1104 Label* miss) { |
| 1001 Label same_contexts; | 1105 Label same_contexts; |
| 1002 | 1106 |
| 1003 ASSERT(!holder_reg.is(scratch)); | 1107 ASSERT(!holder_reg.is(scratch)); |
| 1004 ASSERT(!holder_reg.is(ip)); | 1108 ASSERT(!holder_reg.is(ip)); |
| 1005 ASSERT(!scratch.is(ip)); | 1109 ASSERT(!scratch.is(ip)); |
| 1006 | 1110 |
| 1007 // Load current lexical context from the stack frame. | 1111 // Load current lexical context from the stack frame. |
| (...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1452 // in initial map. | 1556 // in initial map. |
| 1453 bind(&non_instance); | 1557 bind(&non_instance); |
| 1454 ldr(result, FieldMemOperand(result, Map::kConstructorOffset)); | 1558 ldr(result, FieldMemOperand(result, Map::kConstructorOffset)); |
| 1455 | 1559 |
| 1456 // All done. | 1560 // All done. |
| 1457 bind(&done); | 1561 bind(&done); |
| 1458 } | 1562 } |
| 1459 | 1563 |
| 1460 | 1564 |
| 1461 void MacroAssembler::CallStub(CodeStub* stub, Condition cond) { | 1565 void MacroAssembler::CallStub(CodeStub* stub, Condition cond) { |
| 1462 ASSERT(allow_stub_calls()); // stub calls are not allowed in some stubs | 1566 ASSERT(allow_stub_calls()); // Stub calls are not allowed in some stubs. |
| 1463 Call(stub->GetCode(), RelocInfo::CODE_TARGET, cond); | 1567 Call(stub->GetCode(), RelocInfo::CODE_TARGET, cond); |
| 1464 } | 1568 } |
| 1465 | 1569 |
| 1466 | 1570 |
| 1467 void MacroAssembler::TailCallStub(CodeStub* stub, Condition cond) { | 1571 void MacroAssembler::TailCallStub(CodeStub* stub, Condition cond) { |
| 1468 ASSERT(allow_stub_calls()); // stub calls are not allowed in some stubs | 1572 ASSERT(allow_stub_calls()); // Stub calls are not allowed in some stubs. |
| 1469 Jump(stub->GetCode(), RelocInfo::CODE_TARGET, cond); | 1573 Jump(stub->GetCode(), RelocInfo::CODE_TARGET, cond); |
| 1470 } | 1574 } |
| 1471 | 1575 |
| 1472 | 1576 |
| 1577 MaybeObject* MacroAssembler::TryTailCallStub(CodeStub* stub, Condition cond) { |
| 1578 ASSERT(allow_stub_calls()); // Stub calls are not allowed in some stubs. |
| 1579 Object* result; |
| 1580 { MaybeObject* maybe_result = stub->TryGetCode(); |
| 1581 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 1582 } |
| 1583 Jump(stub->GetCode(), RelocInfo::CODE_TARGET, cond); |
| 1584 return result; |
| 1585 } |
| 1586 |
| 1587 |
| 1588 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { |
| 1589 return ref0.address() - ref1.address(); |
| 1590 } |
| 1591 |
| 1592 |
| 1593 MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn( |
| 1594 ApiFunction* function, int stack_space) { |
| 1595 ExternalReference next_address = |
| 1596 ExternalReference::handle_scope_next_address(); |
| 1597 const int kNextOffset = 0; |
| 1598 const int kLimitOffset = AddressOffset( |
| 1599 ExternalReference::handle_scope_limit_address(), |
| 1600 next_address); |
| 1601 const int kLevelOffset = AddressOffset( |
| 1602 ExternalReference::handle_scope_level_address(), |
| 1603 next_address); |
| 1604 |
| 1605 // Allocate HandleScope in callee-save registers. |
| 1606 mov(r7, Operand(next_address)); |
| 1607 ldr(r4, MemOperand(r7, kNextOffset)); |
| 1608 ldr(r5, MemOperand(r7, kLimitOffset)); |
| 1609 ldr(r6, MemOperand(r7, kLevelOffset)); |
| 1610 add(r6, r6, Operand(1)); |
| 1611 str(r6, MemOperand(r7, kLevelOffset)); |
| 1612 |
| 1613 // Native call returns to the DirectCEntry stub which redirects to the |
| 1614 // return address pushed on stack (could have moved after GC). |
| 1615 // DirectCEntry stub itself is generated early and never moves. |
| 1616 DirectCEntryStub stub; |
| 1617 stub.GenerateCall(this, function); |
| 1618 |
| 1619 Label promote_scheduled_exception; |
| 1620 Label delete_allocated_handles; |
| 1621 Label leave_exit_frame; |
| 1622 |
| 1623 // If result is non-zero, dereference to get the result value |
| 1624 // otherwise set it to undefined. |
| 1625 cmp(r0, Operand(0)); |
| 1626 LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); |
| 1627 ldr(r0, MemOperand(r0), ne); |
| 1628 |
| 1629 // No more valid handles (the result handle was the last one). Restore |
| 1630 // previous handle scope. |
| 1631 str(r4, MemOperand(r7, kNextOffset)); |
| 1632 if (FLAG_debug_code) { |
| 1633 ldr(r1, MemOperand(r7, kLevelOffset)); |
| 1634 cmp(r1, r6); |
| 1635 Check(eq, "Unexpected level after return from api call"); |
| 1636 } |
| 1637 sub(r6, r6, Operand(1)); |
| 1638 str(r6, MemOperand(r7, kLevelOffset)); |
| 1639 ldr(ip, MemOperand(r7, kLimitOffset)); |
| 1640 cmp(r5, ip); |
| 1641 b(ne, &delete_allocated_handles); |
| 1642 |
| 1643 // Check if the function scheduled an exception. |
| 1644 bind(&leave_exit_frame); |
| 1645 LoadRoot(r4, Heap::kTheHoleValueRootIndex); |
| 1646 mov(ip, Operand(ExternalReference::scheduled_exception_address())); |
| 1647 ldr(r5, MemOperand(ip)); |
| 1648 cmp(r4, r5); |
| 1649 b(ne, &promote_scheduled_exception); |
| 1650 |
| 1651 // LeaveExitFrame expects unwind space to be in a register. |
| 1652 mov(r4, Operand(stack_space)); |
| 1653 LeaveExitFrame(false, r4); |
| 1654 mov(pc, lr); |
| 1655 |
| 1656 bind(&promote_scheduled_exception); |
| 1657 MaybeObject* result = TryTailCallExternalReference( |
| 1658 ExternalReference(Runtime::kPromoteScheduledException), 0, 1); |
| 1659 if (result->IsFailure()) { |
| 1660 return result; |
| 1661 } |
| 1662 |
| 1663 // HandleScope limit has changed. Delete allocated extensions. |
| 1664 bind(&delete_allocated_handles); |
| 1665 str(r5, MemOperand(r7, kLimitOffset)); |
| 1666 mov(r4, r0); |
| 1667 PrepareCallCFunction(0, r5); |
| 1668 CallCFunction(ExternalReference::delete_handle_scope_extensions(), 0); |
| 1669 mov(r0, r4); |
| 1670 jmp(&leave_exit_frame); |
| 1671 |
| 1672 return result; |
| 1673 } |
| 1674 |
| 1675 |
| 1473 void MacroAssembler::IllegalOperation(int num_arguments) { | 1676 void MacroAssembler::IllegalOperation(int num_arguments) { |
| 1474 if (num_arguments > 0) { | 1677 if (num_arguments > 0) { |
| 1475 add(sp, sp, Operand(num_arguments * kPointerSize)); | 1678 add(sp, sp, Operand(num_arguments * kPointerSize)); |
| 1476 } | 1679 } |
| 1477 LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 1680 LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
| 1478 } | 1681 } |
| 1479 | 1682 |
| 1480 | 1683 |
| 1481 void MacroAssembler::IndexFromHash(Register hash, Register index) { | 1684 void MacroAssembler::IndexFromHash(Register hash, Register index) { |
| 1482 // If the hash field contains an array index pick it out. The assert checks | 1685 // If the hash field contains an array index pick it out. The assert checks |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1716 int result_size) { | 1919 int result_size) { |
| 1717 // TODO(1236192): Most runtime routines don't need the number of | 1920 // TODO(1236192): Most runtime routines don't need the number of |
| 1718 // arguments passed in because it is constant. At some point we | 1921 // arguments passed in because it is constant. At some point we |
| 1719 // should remove this need and make the runtime routine entry code | 1922 // should remove this need and make the runtime routine entry code |
| 1720 // smarter. | 1923 // smarter. |
| 1721 mov(r0, Operand(num_arguments)); | 1924 mov(r0, Operand(num_arguments)); |
| 1722 JumpToExternalReference(ext); | 1925 JumpToExternalReference(ext); |
| 1723 } | 1926 } |
| 1724 | 1927 |
| 1725 | 1928 |
| 1929 MaybeObject* MacroAssembler::TryTailCallExternalReference( |
| 1930 const ExternalReference& ext, int num_arguments, int result_size) { |
| 1931 // TODO(1236192): Most runtime routines don't need the number of |
| 1932 // arguments passed in because it is constant. At some point we |
| 1933 // should remove this need and make the runtime routine entry code |
| 1934 // smarter. |
| 1935 mov(r0, Operand(num_arguments)); |
| 1936 return TryJumpToExternalReference(ext); |
| 1937 } |
| 1938 |
| 1939 |
| 1726 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid, | 1940 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid, |
| 1727 int num_arguments, | 1941 int num_arguments, |
| 1728 int result_size) { | 1942 int result_size) { |
| 1729 TailCallExternalReference(ExternalReference(fid), num_arguments, result_size); | 1943 TailCallExternalReference(ExternalReference(fid), num_arguments, result_size); |
| 1730 } | 1944 } |
| 1731 | 1945 |
| 1732 | 1946 |
| 1733 void MacroAssembler::JumpToExternalReference(const ExternalReference& builtin) { | 1947 void MacroAssembler::JumpToExternalReference(const ExternalReference& builtin) { |
| 1734 #if defined(__thumb__) | 1948 #if defined(__thumb__) |
| 1735 // Thumb mode builtin. | 1949 // Thumb mode builtin. |
| 1736 ASSERT((reinterpret_cast<intptr_t>(builtin.address()) & 1) == 1); | 1950 ASSERT((reinterpret_cast<intptr_t>(builtin.address()) & 1) == 1); |
| 1737 #endif | 1951 #endif |
| 1738 mov(r1, Operand(builtin)); | 1952 mov(r1, Operand(builtin)); |
| 1739 CEntryStub stub(1); | 1953 CEntryStub stub(1); |
| 1740 Jump(stub.GetCode(), RelocInfo::CODE_TARGET); | 1954 Jump(stub.GetCode(), RelocInfo::CODE_TARGET); |
| 1741 } | 1955 } |
| 1742 | 1956 |
| 1743 | 1957 |
| 1958 MaybeObject* MacroAssembler::TryJumpToExternalReference( |
| 1959 const ExternalReference& builtin) { |
| 1960 #if defined(__thumb__) |
| 1961 // Thumb mode builtin. |
| 1962 ASSERT((reinterpret_cast<intptr_t>(builtin.address()) & 1) == 1); |
| 1963 #endif |
| 1964 mov(r1, Operand(builtin)); |
| 1965 CEntryStub stub(1); |
| 1966 return TryTailCallStub(&stub); |
| 1967 } |
| 1968 |
| 1969 |
| 1744 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, | 1970 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, |
| 1745 InvokeJSFlags flags, | 1971 InvokeJSFlags flags, |
| 1746 PostCallGenerator* post_call_generator) { | 1972 PostCallGenerator* post_call_generator) { |
| 1747 GetBuiltinEntry(r2, id); | 1973 GetBuiltinEntry(r2, id); |
| 1748 if (flags == CALL_JS) { | 1974 if (flags == CALL_JS) { |
| 1749 Call(r2); | 1975 Call(r2); |
| 1750 if (post_call_generator != NULL) post_call_generator->Generate(); | 1976 if (post_call_generator != NULL) post_call_generator->Generate(); |
| 1751 } else { | 1977 } else { |
| 1752 ASSERT(flags == JUMP_JS); | 1978 ASSERT(flags == JUMP_JS); |
| 1753 Jump(r2); | 1979 Jump(r2); |
| (...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2258 | 2484 |
| 2259 void CodePatcher::Emit(Address addr) { | 2485 void CodePatcher::Emit(Address addr) { |
| 2260 masm()->emit(reinterpret_cast<Instr>(addr)); | 2486 masm()->emit(reinterpret_cast<Instr>(addr)); |
| 2261 } | 2487 } |
| 2262 #endif // ENABLE_DEBUGGER_SUPPORT | 2488 #endif // ENABLE_DEBUGGER_SUPPORT |
| 2263 | 2489 |
| 2264 | 2490 |
| 2265 } } // namespace v8::internal | 2491 } } // namespace v8::internal |
| 2266 | 2492 |
| 2267 #endif // V8_TARGET_ARCH_ARM | 2493 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |