OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 5683 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5694 #ifdef DEBUG | 5694 #ifdef DEBUG |
5695 if (FLAG_debug_code) { | 5695 if (FLAG_debug_code) { |
5696 __ mov(lr, Operand(pc)); | 5696 __ mov(lr, Operand(pc)); |
5697 } | 5697 } |
5698 #endif | 5698 #endif |
5699 ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); | 5699 ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); |
5700 __ pop(pc); | 5700 __ pop(pc); |
5701 } | 5701 } |
5702 | 5702 |
5703 | 5703 |
5704 void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) { | 5704 void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm, |
| 5705 UncatchableExceptionType type) { |
5705 // Adjust this code if not the case. | 5706 // Adjust this code if not the case. |
5706 ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); | 5707 ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); |
5707 | 5708 |
5708 // Drop sp to the top stack handler. | 5709 // Drop sp to the top stack handler. |
5709 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); | 5710 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); |
5710 __ ldr(sp, MemOperand(r3)); | 5711 __ ldr(sp, MemOperand(r3)); |
5711 | 5712 |
5712 // Unwind the handlers until the ENTRY handler is found. | 5713 // Unwind the handlers until the ENTRY handler is found. |
5713 Label loop, done; | 5714 Label loop, done; |
5714 __ bind(&loop); | 5715 __ bind(&loop); |
5715 // Load the type of the current stack handler. | 5716 // Load the type of the current stack handler. |
5716 const int kStateOffset = StackHandlerConstants::kStateOffset; | 5717 const int kStateOffset = StackHandlerConstants::kStateOffset; |
5717 __ ldr(r2, MemOperand(sp, kStateOffset)); | 5718 __ ldr(r2, MemOperand(sp, kStateOffset)); |
5718 __ cmp(r2, Operand(StackHandler::ENTRY)); | 5719 __ cmp(r2, Operand(StackHandler::ENTRY)); |
5719 __ b(eq, &done); | 5720 __ b(eq, &done); |
5720 // Fetch the next handler in the list. | 5721 // Fetch the next handler in the list. |
5721 const int kNextOffset = StackHandlerConstants::kNextOffset; | 5722 const int kNextOffset = StackHandlerConstants::kNextOffset; |
5722 __ ldr(sp, MemOperand(sp, kNextOffset)); | 5723 __ ldr(sp, MemOperand(sp, kNextOffset)); |
5723 __ jmp(&loop); | 5724 __ jmp(&loop); |
5724 __ bind(&done); | 5725 __ bind(&done); |
5725 | 5726 |
5726 // Set the top handler address to next handler past the current ENTRY handler. | 5727 // Set the top handler address to next handler past the current ENTRY handler. |
5727 ASSERT(StackHandlerConstants::kNextOffset == 0); | 5728 ASSERT(StackHandlerConstants::kNextOffset == 0); |
5728 __ pop(r0); | 5729 __ pop(r2); |
5729 __ str(r0, MemOperand(r3)); | 5730 __ str(r2, MemOperand(r3)); |
5730 | 5731 |
5731 // Set external caught exception to false. | 5732 if (type == OUT_OF_MEMORY) { |
5732 ExternalReference external_caught(Top::k_external_caught_exception_address); | 5733 // Set external caught exception to false. |
5733 __ mov(r0, Operand(false)); | 5734 ExternalReference external_caught(Top::k_external_caught_exception_address); |
5734 __ mov(r2, Operand(external_caught)); | 5735 __ mov(r0, Operand(false)); |
5735 __ str(r0, MemOperand(r2)); | 5736 __ mov(r2, Operand(external_caught)); |
| 5737 __ str(r0, MemOperand(r2)); |
5736 | 5738 |
5737 // Set pending exception and r0 to out of memory exception. | 5739 // Set pending exception and r0 to out of memory exception. |
5738 Failure* out_of_memory = Failure::OutOfMemoryException(); | 5740 Failure* out_of_memory = Failure::OutOfMemoryException(); |
5739 __ mov(r0, Operand(reinterpret_cast<int32_t>(out_of_memory))); | 5741 __ mov(r0, Operand(reinterpret_cast<int32_t>(out_of_memory))); |
5740 __ mov(r2, Operand(ExternalReference(Top::k_pending_exception_address))); | 5742 __ mov(r2, Operand(ExternalReference(Top::k_pending_exception_address))); |
5741 __ str(r0, MemOperand(r2)); | 5743 __ str(r0, MemOperand(r2)); |
| 5744 } |
5742 | 5745 |
5743 // Stack layout at this point. See also StackHandlerConstants. | 5746 // Stack layout at this point. See also StackHandlerConstants. |
5744 // sp -> state (ENTRY) | 5747 // sp -> state (ENTRY) |
5745 // fp | 5748 // fp |
5746 // lr | 5749 // lr |
5747 | 5750 |
5748 // Discard handler state (r2 is not used) and restore frame pointer. | 5751 // Discard handler state (r2 is not used) and restore frame pointer. |
5749 ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); | 5752 ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); |
5750 __ ldm(ia_w, sp, r2.bit() | fp.bit()); // r2: discarded state. | 5753 __ ldm(ia_w, sp, r2.bit() | fp.bit()); // r2: discarded state. |
5751 // Before returning we restore the context from the frame pointer if | 5754 // Before returning we restore the context from the frame pointer if |
5752 // not NULL. The frame pointer is NULL in the exception handler of a | 5755 // not NULL. The frame pointer is NULL in the exception handler of a |
5753 // JS entry frame. | 5756 // JS entry frame. |
5754 __ cmp(fp, Operand(0)); | 5757 __ cmp(fp, Operand(0)); |
5755 // Set cp to NULL if fp is NULL. | 5758 // Set cp to NULL if fp is NULL. |
5756 __ mov(cp, Operand(0), LeaveCC, eq); | 5759 __ mov(cp, Operand(0), LeaveCC, eq); |
5757 // Restore cp otherwise. | 5760 // Restore cp otherwise. |
5758 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne); | 5761 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne); |
5759 #ifdef DEBUG | 5762 #ifdef DEBUG |
5760 if (FLAG_debug_code) { | 5763 if (FLAG_debug_code) { |
5761 __ mov(lr, Operand(pc)); | 5764 __ mov(lr, Operand(pc)); |
5762 } | 5765 } |
5763 #endif | 5766 #endif |
5764 ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); | 5767 ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); |
5765 __ pop(pc); | 5768 __ pop(pc); |
5766 } | 5769 } |
5767 | 5770 |
5768 | 5771 |
5769 void CEntryStub::GenerateCore(MacroAssembler* masm, | 5772 void CEntryStub::GenerateCore(MacroAssembler* masm, |
5770 Label* throw_normal_exception, | 5773 Label* throw_normal_exception, |
| 5774 Label* throw_termination_exception, |
5771 Label* throw_out_of_memory_exception, | 5775 Label* throw_out_of_memory_exception, |
5772 StackFrame::Type frame_type, | 5776 StackFrame::Type frame_type, |
5773 bool do_gc, | 5777 bool do_gc, |
5774 bool always_allocate) { | 5778 bool always_allocate) { |
5775 // r0: result parameter for PerformGC, if any | 5779 // r0: result parameter for PerformGC, if any |
5776 // r4: number of arguments including receiver (C callee-saved) | 5780 // r4: number of arguments including receiver (C callee-saved) |
5777 // r5: pointer to builtin function (C callee-saved) | 5781 // r5: pointer to builtin function (C callee-saved) |
5778 // r6: pointer to the first argument (C callee-saved) | 5782 // r6: pointer to the first argument (C callee-saved) |
5779 | 5783 |
5780 if (do_gc) { | 5784 if (do_gc) { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5831 // fp: frame pointer | 5835 // fp: frame pointer |
5832 __ LeaveExitFrame(frame_type); | 5836 __ LeaveExitFrame(frame_type); |
5833 | 5837 |
5834 // check if we should retry or throw exception | 5838 // check if we should retry or throw exception |
5835 Label retry; | 5839 Label retry; |
5836 __ bind(&failure_returned); | 5840 __ bind(&failure_returned); |
5837 ASSERT(Failure::RETRY_AFTER_GC == 0); | 5841 ASSERT(Failure::RETRY_AFTER_GC == 0); |
5838 __ tst(r0, Operand(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize)); | 5842 __ tst(r0, Operand(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize)); |
5839 __ b(eq, &retry); | 5843 __ b(eq, &retry); |
5840 | 5844 |
5841 Label continue_exception; | 5845 // Special handling of out of memory exceptions. |
5842 // If the returned failure is EXCEPTION then promote Top::pending_exception(). | 5846 Failure* out_of_memory = Failure::OutOfMemoryException(); |
5843 __ cmp(r0, Operand(reinterpret_cast<int32_t>(Failure::Exception()))); | 5847 __ cmp(r0, Operand(reinterpret_cast<int32_t>(out_of_memory))); |
5844 __ b(ne, &continue_exception); | 5848 __ b(eq, throw_out_of_memory_exception); |
5845 | 5849 |
5846 // Retrieve the pending exception and clear the variable. | 5850 // Retrieve the pending exception and clear the variable. |
5847 __ mov(ip, Operand(ExternalReference::the_hole_value_location())); | 5851 __ mov(ip, Operand(ExternalReference::the_hole_value_location())); |
5848 __ ldr(r3, MemOperand(ip)); | 5852 __ ldr(r3, MemOperand(ip)); |
5849 __ mov(ip, Operand(ExternalReference(Top::k_pending_exception_address))); | 5853 __ mov(ip, Operand(ExternalReference(Top::k_pending_exception_address))); |
5850 __ ldr(r0, MemOperand(ip)); | 5854 __ ldr(r0, MemOperand(ip)); |
5851 __ str(r3, MemOperand(ip)); | 5855 __ str(r3, MemOperand(ip)); |
5852 | 5856 |
5853 __ bind(&continue_exception); | 5857 // Special handling of termination exceptions which are uncatchable |
5854 // Special handling of out of memory exception. | 5858 // by javascript code. |
5855 Failure* out_of_memory = Failure::OutOfMemoryException(); | 5859 __ cmp(r0, Operand(Factory::termination_exception())); |
5856 __ cmp(r0, Operand(reinterpret_cast<int32_t>(out_of_memory))); | 5860 __ b(eq, throw_termination_exception); |
5857 __ b(eq, throw_out_of_memory_exception); | |
5858 | 5861 |
5859 // Handle normal exception. | 5862 // Handle normal exception. |
5860 __ jmp(throw_normal_exception); | 5863 __ jmp(throw_normal_exception); |
5861 | 5864 |
5862 __ bind(&retry); // pass last failure (r0) as parameter (r0) when retrying | 5865 __ bind(&retry); // pass last failure (r0) as parameter (r0) when retrying |
5863 } | 5866 } |
5864 | 5867 |
5865 | 5868 |
5866 void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) { | 5869 void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) { |
5867 // Called from JavaScript; parameters are on stack as if calling JS function | 5870 // Called from JavaScript; parameters are on stack as if calling JS function |
(...skipping 12 matching lines...) Expand all Loading... |
5880 ? StackFrame::EXIT_DEBUG | 5883 ? StackFrame::EXIT_DEBUG |
5881 : StackFrame::EXIT; | 5884 : StackFrame::EXIT; |
5882 | 5885 |
5883 // Enter the exit frame that transitions from JavaScript to C++. | 5886 // Enter the exit frame that transitions from JavaScript to C++. |
5884 __ EnterExitFrame(frame_type); | 5887 __ EnterExitFrame(frame_type); |
5885 | 5888 |
5886 // r4: number of arguments (C callee-saved) | 5889 // r4: number of arguments (C callee-saved) |
5887 // r5: pointer to builtin function (C callee-saved) | 5890 // r5: pointer to builtin function (C callee-saved) |
5888 // r6: pointer to first argument (C callee-saved) | 5891 // r6: pointer to first argument (C callee-saved) |
5889 | 5892 |
| 5893 Label throw_normal_exception; |
| 5894 Label throw_termination_exception; |
5890 Label throw_out_of_memory_exception; | 5895 Label throw_out_of_memory_exception; |
5891 Label throw_normal_exception; | |
5892 | 5896 |
5893 // Call into the runtime system. | 5897 // Call into the runtime system. |
5894 GenerateCore(masm, &throw_normal_exception, | 5898 GenerateCore(masm, |
| 5899 &throw_normal_exception, |
| 5900 &throw_termination_exception, |
5895 &throw_out_of_memory_exception, | 5901 &throw_out_of_memory_exception, |
5896 frame_type, | 5902 frame_type, |
5897 false, | 5903 false, |
5898 false); | 5904 false); |
5899 | 5905 |
5900 // Do space-specific GC and retry runtime call. | 5906 // Do space-specific GC and retry runtime call. |
5901 GenerateCore(masm, | 5907 GenerateCore(masm, |
5902 &throw_normal_exception, | 5908 &throw_normal_exception, |
| 5909 &throw_termination_exception, |
5903 &throw_out_of_memory_exception, | 5910 &throw_out_of_memory_exception, |
5904 frame_type, | 5911 frame_type, |
5905 true, | 5912 true, |
5906 false); | 5913 false); |
5907 | 5914 |
5908 // Do full GC and retry runtime call one final time. | 5915 // Do full GC and retry runtime call one final time. |
5909 Failure* failure = Failure::InternalError(); | 5916 Failure* failure = Failure::InternalError(); |
5910 __ mov(r0, Operand(reinterpret_cast<int32_t>(failure))); | 5917 __ mov(r0, Operand(reinterpret_cast<int32_t>(failure))); |
5911 GenerateCore(masm, | 5918 GenerateCore(masm, |
5912 &throw_normal_exception, | 5919 &throw_normal_exception, |
| 5920 &throw_termination_exception, |
5913 &throw_out_of_memory_exception, | 5921 &throw_out_of_memory_exception, |
5914 frame_type, | 5922 frame_type, |
5915 true, | 5923 true, |
5916 true); | 5924 true); |
5917 | 5925 |
5918 __ bind(&throw_out_of_memory_exception); | 5926 __ bind(&throw_out_of_memory_exception); |
5919 GenerateThrowOutOfMemory(masm); | 5927 GenerateThrowUncatchable(masm, OUT_OF_MEMORY); |
5920 // control flow for generated will not return. | 5928 |
| 5929 __ bind(&throw_termination_exception); |
| 5930 GenerateThrowUncatchable(masm, TERMINATION); |
5921 | 5931 |
5922 __ bind(&throw_normal_exception); | 5932 __ bind(&throw_normal_exception); |
5923 GenerateThrowTOS(masm); | 5933 GenerateThrowTOS(masm); |
5924 } | 5934 } |
5925 | 5935 |
5926 | 5936 |
5927 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { | 5937 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { |
5928 // r0: code entry | 5938 // r0: code entry |
5929 // r1: function | 5939 // r1: function |
5930 // r2: receiver | 5940 // r2: receiver |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6228 int CompareStub::MinorKey() { | 6238 int CompareStub::MinorKey() { |
6229 // Encode the two parameters in a unique 16 bit value. | 6239 // Encode the two parameters in a unique 16 bit value. |
6230 ASSERT(static_cast<unsigned>(cc_) >> 28 < (1 << 15)); | 6240 ASSERT(static_cast<unsigned>(cc_) >> 28 < (1 << 15)); |
6231 return (static_cast<unsigned>(cc_) >> 27) | (strict_ ? 1 : 0); | 6241 return (static_cast<unsigned>(cc_) >> 27) | (strict_ ? 1 : 0); |
6232 } | 6242 } |
6233 | 6243 |
6234 | 6244 |
6235 #undef __ | 6245 #undef __ |
6236 | 6246 |
6237 } } // namespace v8::internal | 6247 } } // namespace v8::internal |
OLD | NEW |