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 696 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
707 #else // defined(V8_HOST_ARCH_ARM) | 707 #else // defined(V8_HOST_ARCH_ARM) |
708 // If we are using the simulator then we should always align to the expected | 708 // If we are using the simulator then we should always align to the expected |
709 // alignment. As the simulator is used to generate snapshots we do not know | 709 // alignment. As the simulator is used to generate snapshots we do not know |
710 // if the target platform will need alignment, so this is controlled from a | 710 // if the target platform will need alignment, so this is controlled from a |
711 // flag. | 711 // flag. |
712 return FLAG_sim_stack_alignment; | 712 return FLAG_sim_stack_alignment; |
713 #endif // defined(V8_HOST_ARCH_ARM) | 713 #endif // defined(V8_HOST_ARCH_ARM) |
714 } | 714 } |
715 | 715 |
716 | 716 |
717 void MacroAssembler::LeaveExitFrame(bool save_doubles) { | 717 void MacroAssembler::LeaveExitFrame(bool save_doubles, |
| 718 Register argument_count) { |
718 // Optionally restore all double registers. | 719 // Optionally restore all double registers. |
719 if (save_doubles) { | 720 if (save_doubles) { |
720 for (int i = 0; i < DwVfpRegister::kNumRegisters; i++) { | 721 for (int i = 0; i < DwVfpRegister::kNumRegisters; i++) { |
721 DwVfpRegister reg = DwVfpRegister::from_code(i); | 722 DwVfpRegister reg = DwVfpRegister::from_code(i); |
722 const int offset = -2 * kPointerSize; | 723 const int offset = -2 * kPointerSize; |
723 vldr(reg, fp, offset - ((i + 1) * kDoubleSize)); | 724 vldr(reg, fp, offset - ((i + 1) * kDoubleSize)); |
724 } | 725 } |
725 } | 726 } |
726 | 727 |
727 // Clear top frame. | 728 // Clear top frame. |
728 mov(r3, Operand(0, RelocInfo::NONE)); | 729 mov(r3, Operand(0, RelocInfo::NONE)); |
729 mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address))); | 730 mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address))); |
730 str(r3, MemOperand(ip)); | 731 str(r3, MemOperand(ip)); |
731 | 732 |
732 // Restore current context from top and clear it in debug mode. | 733 // Restore current context from top and clear it in debug mode. |
733 mov(ip, Operand(ExternalReference(Top::k_context_address))); | 734 mov(ip, Operand(ExternalReference(Top::k_context_address))); |
734 ldr(cp, MemOperand(ip)); | 735 ldr(cp, MemOperand(ip)); |
735 #ifdef DEBUG | 736 #ifdef DEBUG |
736 str(r3, MemOperand(ip)); | 737 str(r3, MemOperand(ip)); |
737 #endif | 738 #endif |
738 | 739 |
739 // Tear down the exit frame, pop the arguments, and return. Callee-saved | 740 // Tear down the exit frame, pop the arguments, and return. |
740 // register r4 still holds argc. | |
741 mov(sp, Operand(fp)); | 741 mov(sp, Operand(fp)); |
742 ldm(ia_w, sp, fp.bit() | lr.bit()); | 742 ldm(ia_w, sp, fp.bit() | lr.bit()); |
743 add(sp, sp, Operand(r4, LSL, kPointerSizeLog2)); | 743 if (argument_count.is_valid()) { |
744 mov(pc, lr); | 744 add(sp, sp, Operand(argument_count, LSL, kPointerSizeLog2)); |
| 745 } |
745 } | 746 } |
746 | 747 |
747 | 748 |
748 void MacroAssembler::InvokePrologue(const ParameterCount& expected, | 749 void MacroAssembler::InvokePrologue(const ParameterCount& expected, |
749 const ParameterCount& actual, | 750 const ParameterCount& actual, |
750 Handle<Code> code_constant, | 751 Handle<Code> code_constant, |
751 Register code_reg, | 752 Register code_reg, |
752 Label* done, | 753 Label* done, |
753 InvokeFlag flag, | 754 InvokeFlag flag, |
754 PostCallGenerator* post_call_generator) { | 755 PostCallGenerator* post_call_generator) { |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
998 | 999 |
999 void MacroAssembler::PopTryHandler() { | 1000 void MacroAssembler::PopTryHandler() { |
1000 ASSERT_EQ(0, StackHandlerConstants::kNextOffset); | 1001 ASSERT_EQ(0, StackHandlerConstants::kNextOffset); |
1001 pop(r1); | 1002 pop(r1); |
1002 mov(ip, Operand(ExternalReference(Top::k_handler_address))); | 1003 mov(ip, Operand(ExternalReference(Top::k_handler_address))); |
1003 add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); | 1004 add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); |
1004 str(r1, MemOperand(ip)); | 1005 str(r1, MemOperand(ip)); |
1005 } | 1006 } |
1006 | 1007 |
1007 | 1008 |
| 1009 void MacroAssembler::Throw(Register value) { |
| 1010 // r0 is expected to hold the exception. |
| 1011 if (!value.is(r0)) { |
| 1012 mov(r0, value); |
| 1013 } |
| 1014 |
| 1015 // Adjust this code if not the case. |
| 1016 STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); |
| 1017 |
| 1018 // Drop the sp to the top of the handler. |
| 1019 mov(r3, Operand(ExternalReference(Top::k_handler_address))); |
| 1020 ldr(sp, MemOperand(r3)); |
| 1021 |
| 1022 // Restore the next handler and frame pointer, discard handler state. |
| 1023 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
| 1024 pop(r2); |
| 1025 str(r2, MemOperand(r3)); |
| 1026 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); |
| 1027 ldm(ia_w, sp, r3.bit() | fp.bit()); // r3: discarded state. |
| 1028 |
| 1029 // Before returning we restore the context from the frame pointer if |
| 1030 // not NULL. The frame pointer is NULL in the exception handler of a |
| 1031 // JS entry frame. |
| 1032 cmp(fp, Operand(0, RelocInfo::NONE)); |
| 1033 // Set cp to NULL if fp is NULL. |
| 1034 mov(cp, Operand(0, RelocInfo::NONE), LeaveCC, eq); |
| 1035 // Restore cp otherwise. |
| 1036 ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne); |
| 1037 #ifdef DEBUG |
| 1038 if (FLAG_debug_code) { |
| 1039 mov(lr, Operand(pc)); |
| 1040 } |
| 1041 #endif |
| 1042 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); |
| 1043 pop(pc); |
| 1044 } |
| 1045 |
| 1046 |
| 1047 void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, |
| 1048 Register value) { |
| 1049 // Adjust this code if not the case. |
| 1050 STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); |
| 1051 |
| 1052 // r0 is expected to hold the exception. |
| 1053 if (!value.is(r0)) { |
| 1054 mov(r0, value); |
| 1055 } |
| 1056 |
| 1057 // Drop sp to the top stack handler. |
| 1058 mov(r3, Operand(ExternalReference(Top::k_handler_address))); |
| 1059 ldr(sp, MemOperand(r3)); |
| 1060 |
| 1061 // Unwind the handlers until the ENTRY handler is found. |
| 1062 Label loop, done; |
| 1063 bind(&loop); |
| 1064 // Load the type of the current stack handler. |
| 1065 const int kStateOffset = StackHandlerConstants::kStateOffset; |
| 1066 ldr(r2, MemOperand(sp, kStateOffset)); |
| 1067 cmp(r2, Operand(StackHandler::ENTRY)); |
| 1068 b(eq, &done); |
| 1069 // Fetch the next handler in the list. |
| 1070 const int kNextOffset = StackHandlerConstants::kNextOffset; |
| 1071 ldr(sp, MemOperand(sp, kNextOffset)); |
| 1072 jmp(&loop); |
| 1073 bind(&done); |
| 1074 |
| 1075 // Set the top handler address to next handler past the current ENTRY handler. |
| 1076 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
| 1077 pop(r2); |
| 1078 str(r2, MemOperand(r3)); |
| 1079 |
| 1080 if (type == OUT_OF_MEMORY) { |
| 1081 // Set external caught exception to false. |
| 1082 ExternalReference external_caught(Top::k_external_caught_exception_address); |
| 1083 mov(r0, Operand(false, RelocInfo::NONE)); |
| 1084 mov(r2, Operand(external_caught)); |
| 1085 str(r0, MemOperand(r2)); |
| 1086 |
| 1087 // Set pending exception and r0 to out of memory exception. |
| 1088 Failure* out_of_memory = Failure::OutOfMemoryException(); |
| 1089 mov(r0, Operand(reinterpret_cast<int32_t>(out_of_memory))); |
| 1090 mov(r2, Operand(ExternalReference(Top::k_pending_exception_address))); |
| 1091 str(r0, MemOperand(r2)); |
| 1092 } |
| 1093 |
| 1094 // Stack layout at this point. See also StackHandlerConstants. |
| 1095 // sp -> state (ENTRY) |
| 1096 // fp |
| 1097 // lr |
| 1098 |
| 1099 // Discard handler state (r2 is not used) and restore frame pointer. |
| 1100 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); |
| 1101 ldm(ia_w, sp, r2.bit() | fp.bit()); // r2: discarded state. |
| 1102 // Before returning we restore the context from the frame pointer if |
| 1103 // not NULL. The frame pointer is NULL in the exception handler of a |
| 1104 // JS entry frame. |
| 1105 cmp(fp, Operand(0, RelocInfo::NONE)); |
| 1106 // Set cp to NULL if fp is NULL. |
| 1107 mov(cp, Operand(0, RelocInfo::NONE), LeaveCC, eq); |
| 1108 // Restore cp otherwise. |
| 1109 ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne); |
| 1110 #ifdef DEBUG |
| 1111 if (FLAG_debug_code) { |
| 1112 mov(lr, Operand(pc)); |
| 1113 } |
| 1114 #endif |
| 1115 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); |
| 1116 pop(pc); |
| 1117 } |
| 1118 |
| 1119 |
1008 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, | 1120 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, |
1009 Register scratch, | 1121 Register scratch, |
1010 Label* miss) { | 1122 Label* miss) { |
1011 Label same_contexts; | 1123 Label same_contexts; |
1012 | 1124 |
1013 ASSERT(!holder_reg.is(scratch)); | 1125 ASSERT(!holder_reg.is(scratch)); |
1014 ASSERT(!holder_reg.is(ip)); | 1126 ASSERT(!holder_reg.is(ip)); |
1015 ASSERT(!scratch.is(ip)); | 1127 ASSERT(!scratch.is(ip)); |
1016 | 1128 |
1017 // Load current lexical context from the stack frame. | 1129 // Load current lexical context from the stack frame. |
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1547 b(ne, &delete_allocated_handles); | 1659 b(ne, &delete_allocated_handles); |
1548 | 1660 |
1549 // Check if the function scheduled an exception. | 1661 // Check if the function scheduled an exception. |
1550 bind(&leave_exit_frame); | 1662 bind(&leave_exit_frame); |
1551 LoadRoot(r4, Heap::kTheHoleValueRootIndex); | 1663 LoadRoot(r4, Heap::kTheHoleValueRootIndex); |
1552 mov(ip, Operand(ExternalReference::scheduled_exception_address())); | 1664 mov(ip, Operand(ExternalReference::scheduled_exception_address())); |
1553 ldr(r5, MemOperand(ip)); | 1665 ldr(r5, MemOperand(ip)); |
1554 cmp(r4, r5); | 1666 cmp(r4, r5); |
1555 b(ne, &promote_scheduled_exception); | 1667 b(ne, &promote_scheduled_exception); |
1556 | 1668 |
1557 // LeaveExitFrame expects unwind space to be in r4. | 1669 // LeaveExitFrame expects unwind space to be in a register. |
1558 mov(r4, Operand(stack_space)); | 1670 mov(r4, Operand(stack_space)); |
1559 LeaveExitFrame(false); | 1671 LeaveExitFrame(false, r4); |
| 1672 mov(pc, lr); |
1560 | 1673 |
1561 bind(&promote_scheduled_exception); | 1674 bind(&promote_scheduled_exception); |
1562 MaybeObject* result = TryTailCallExternalReference( | 1675 MaybeObject* result = TryTailCallExternalReference( |
1563 ExternalReference(Runtime::kPromoteScheduledException), 0, 1); | 1676 ExternalReference(Runtime::kPromoteScheduledException), 0, 1); |
1564 if (result->IsFailure()) { | 1677 if (result->IsFailure()) { |
1565 return result; | 1678 return result; |
1566 } | 1679 } |
1567 | 1680 |
1568 // HandleScope limit has changed. Delete allocated extensions. | 1681 // HandleScope limit has changed. Delete allocated extensions. |
1569 bind(&delete_allocated_handles); | 1682 bind(&delete_allocated_handles); |
(...skipping 853 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2423 void CodePatcher::EmitCondition(Condition cond) { | 2536 void CodePatcher::EmitCondition(Condition cond) { |
2424 Instr instr = Assembler::instr_at(masm_.pc_); | 2537 Instr instr = Assembler::instr_at(masm_.pc_); |
2425 instr = (instr & ~kCondMask) | cond; | 2538 instr = (instr & ~kCondMask) | cond; |
2426 masm_.emit(instr); | 2539 masm_.emit(instr); |
2427 } | 2540 } |
2428 | 2541 |
2429 | 2542 |
2430 } } // namespace v8::internal | 2543 } } // namespace v8::internal |
2431 | 2544 |
2432 #endif // V8_TARGET_ARCH_ARM | 2545 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |