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 2089 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2100 bool has_unlinks = false; | 2100 bool has_unlinks = false; |
2101 for (int i = 0; i < shadows.length(); i++) { | 2101 for (int i = 0; i < shadows.length(); i++) { |
2102 shadows[i]->StopShadowing(); | 2102 shadows[i]->StopShadowing(); |
2103 has_unlinks = has_unlinks || shadows[i]->is_linked(); | 2103 has_unlinks = has_unlinks || shadows[i]->is_linked(); |
2104 } | 2104 } |
2105 function_return_is_shadowed_ = function_return_was_shadowed; | 2105 function_return_is_shadowed_ = function_return_was_shadowed; |
2106 | 2106 |
2107 // Get an external reference to the handler address. | 2107 // Get an external reference to the handler address. |
2108 ExternalReference handler_address(Top::k_handler_address); | 2108 ExternalReference handler_address(Top::k_handler_address); |
2109 | 2109 |
2110 // The next handler address is at kNextIndex in the stack. | |
2111 const int kNextIndex = StackHandlerConstants::kNextOffset / kPointerSize; | |
2112 // If we can fall off the end of the try block, unlink from try chain. | 2110 // If we can fall off the end of the try block, unlink from try chain. |
2113 if (has_valid_frame()) { | 2111 if (has_valid_frame()) { |
2114 __ ldr(r1, frame_->ElementAt(kNextIndex)); | 2112 // The next handler address is on top of the frame. Unlink from |
| 2113 // the handler list and drop the rest of this handler from the |
| 2114 // frame. |
| 2115 ASSERT(StackHandlerConstants::kNextOffset == 0); |
| 2116 frame_->EmitPop(r1); |
2115 __ mov(r3, Operand(handler_address)); | 2117 __ mov(r3, Operand(handler_address)); |
2116 __ str(r1, MemOperand(r3)); | 2118 __ str(r1, MemOperand(r3)); |
2117 frame_->Drop(StackHandlerConstants::kSize / kPointerSize); | 2119 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); |
2118 if (has_unlinks) { | 2120 if (has_unlinks) { |
2119 exit.Jump(); | 2121 exit.Jump(); |
2120 } | 2122 } |
2121 } | 2123 } |
2122 | 2124 |
2123 // Generate unlink code for the (formerly) shadowing labels that have been | 2125 // Generate unlink code for the (formerly) shadowing labels that have been |
2124 // jumped to. Deallocate each shadow target. | 2126 // jumped to. Deallocate each shadow target. |
2125 for (int i = 0; i < shadows.length(); i++) { | 2127 for (int i = 0; i < shadows.length(); i++) { |
2126 if (shadows[i]->is_linked()) { | 2128 if (shadows[i]->is_linked()) { |
2127 // Unlink from try chain; | 2129 // Unlink from try chain; |
2128 shadows[i]->Bind(); | 2130 shadows[i]->Bind(); |
2129 // Because we can be jumping here (to spilled code) from unspilled | 2131 // Because we can be jumping here (to spilled code) from unspilled |
2130 // code, we need to reestablish a spilled frame at this block. | 2132 // code, we need to reestablish a spilled frame at this block. |
2131 frame_->SpillAll(); | 2133 frame_->SpillAll(); |
2132 | 2134 |
2133 // Reload sp from the top handler, because some statements that we | 2135 // Reload sp from the top handler, because some statements that we |
2134 // break from (eg, for...in) may have left stuff on the stack. | 2136 // break from (eg, for...in) may have left stuff on the stack. |
2135 __ mov(r3, Operand(handler_address)); | 2137 __ mov(r3, Operand(handler_address)); |
2136 __ ldr(sp, MemOperand(r3)); | 2138 __ ldr(sp, MemOperand(r3)); |
2137 // The stack pointer was restored to just below the code slot | 2139 frame_->Forget(frame_->height() - handler_height); |
2138 // (the topmost slot) in the handler. | |
2139 frame_->Forget(frame_->height() - handler_height + 1); | |
2140 | 2140 |
2141 // kNextIndex is off by one because the code slot has already | 2141 ASSERT(StackHandlerConstants::kNextOffset == 0); |
2142 // been dropped. | 2142 frame_->EmitPop(r1); |
2143 __ ldr(r1, frame_->ElementAt(kNextIndex - 1)); | |
2144 __ str(r1, MemOperand(r3)); | 2143 __ str(r1, MemOperand(r3)); |
2145 // The code slot has already been dropped from the handler. | |
2146 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); | 2144 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); |
2147 | 2145 |
2148 if (!function_return_is_shadowed_ && i == kReturnShadowIndex) { | 2146 if (!function_return_is_shadowed_ && i == kReturnShadowIndex) { |
2149 frame_->PrepareForReturn(); | 2147 frame_->PrepareForReturn(); |
2150 } | 2148 } |
2151 shadows[i]->other_target()->Jump(); | 2149 shadows[i]->other_target()->Jump(); |
2152 } | 2150 } |
2153 } | 2151 } |
2154 | 2152 |
2155 exit.Bind(); | 2153 exit.Bind(); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2216 int nof_unlinks = 0; | 2214 int nof_unlinks = 0; |
2217 for (int i = 0; i < shadows.length(); i++) { | 2215 for (int i = 0; i < shadows.length(); i++) { |
2218 shadows[i]->StopShadowing(); | 2216 shadows[i]->StopShadowing(); |
2219 if (shadows[i]->is_linked()) nof_unlinks++; | 2217 if (shadows[i]->is_linked()) nof_unlinks++; |
2220 } | 2218 } |
2221 function_return_is_shadowed_ = function_return_was_shadowed; | 2219 function_return_is_shadowed_ = function_return_was_shadowed; |
2222 | 2220 |
2223 // Get an external reference to the handler address. | 2221 // Get an external reference to the handler address. |
2224 ExternalReference handler_address(Top::k_handler_address); | 2222 ExternalReference handler_address(Top::k_handler_address); |
2225 | 2223 |
2226 // The next handler address is at kNextIndex in the stack. | |
2227 const int kNextIndex = StackHandlerConstants::kNextOffset / kPointerSize; | |
2228 // If we can fall off the end of the try block, unlink from the try | 2224 // If we can fall off the end of the try block, unlink from the try |
2229 // chain and set the state on the frame to FALLING. | 2225 // chain and set the state on the frame to FALLING. |
2230 if (has_valid_frame()) { | 2226 if (has_valid_frame()) { |
2231 __ ldr(r1, frame_->ElementAt(kNextIndex)); | 2227 // The next handler address is on top of the frame. |
| 2228 ASSERT(StackHandlerConstants::kNextOffset == 0); |
| 2229 frame_->EmitPop(r1); |
2232 __ mov(r3, Operand(handler_address)); | 2230 __ mov(r3, Operand(handler_address)); |
2233 __ str(r1, MemOperand(r3)); | 2231 __ str(r1, MemOperand(r3)); |
2234 frame_->Drop(StackHandlerConstants::kSize / kPointerSize); | 2232 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); |
2235 | 2233 |
2236 // Fake a top of stack value (unneeded when FALLING) and set the | 2234 // Fake a top of stack value (unneeded when FALLING) and set the |
2237 // state in r2, then jump around the unlink blocks if any. | 2235 // state in r2, then jump around the unlink blocks if any. |
2238 __ mov(r0, Operand(Factory::undefined_value())); | 2236 __ mov(r0, Operand(Factory::undefined_value())); |
2239 frame_->EmitPush(r0); | 2237 frame_->EmitPush(r0); |
2240 __ mov(r2, Operand(Smi::FromInt(FALLING))); | 2238 __ mov(r2, Operand(Smi::FromInt(FALLING))); |
2241 if (nof_unlinks > 0) { | 2239 if (nof_unlinks > 0) { |
2242 finally_block.Jump(); | 2240 finally_block.Jump(); |
2243 } | 2241 } |
2244 } | 2242 } |
(...skipping 10 matching lines...) Expand all Loading... |
2255 // unspilled code, we need to reestablish a spilled frame at | 2253 // unspilled code, we need to reestablish a spilled frame at |
2256 // this block. | 2254 // this block. |
2257 shadows[i]->Bind(); | 2255 shadows[i]->Bind(); |
2258 frame_->SpillAll(); | 2256 frame_->SpillAll(); |
2259 | 2257 |
2260 // Reload sp from the top handler, because some statements that | 2258 // Reload sp from the top handler, because some statements that |
2261 // we break from (eg, for...in) may have left stuff on the | 2259 // we break from (eg, for...in) may have left stuff on the |
2262 // stack. | 2260 // stack. |
2263 __ mov(r3, Operand(handler_address)); | 2261 __ mov(r3, Operand(handler_address)); |
2264 __ ldr(sp, MemOperand(r3)); | 2262 __ ldr(sp, MemOperand(r3)); |
2265 // The stack pointer was restored to the address slot in the handler. | 2263 frame_->Forget(frame_->height() - handler_height); |
2266 ASSERT(StackHandlerConstants::kNextOffset == 1 * kPointerSize); | |
2267 frame_->Forget(frame_->height() - handler_height + 1); | |
2268 | 2264 |
2269 // Unlink this handler and drop it from the frame. The next | 2265 // Unlink this handler and drop it from the frame. The next |
2270 // handler address is now on top of the frame. | 2266 // handler address is currently on top of the frame. |
| 2267 ASSERT(StackHandlerConstants::kNextOffset == 0); |
2271 frame_->EmitPop(r1); | 2268 frame_->EmitPop(r1); |
2272 __ str(r1, MemOperand(r3)); | 2269 __ str(r1, MemOperand(r3)); |
2273 // The top (code) and the second (handler) slot have both been | 2270 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); |
2274 // dropped already. | |
2275 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 2); | |
2276 | 2271 |
2277 if (i == kReturnShadowIndex) { | 2272 if (i == kReturnShadowIndex) { |
2278 // If this label shadowed the function return, materialize the | 2273 // If this label shadowed the function return, materialize the |
2279 // return value on the stack. | 2274 // return value on the stack. |
2280 frame_->EmitPush(r0); | 2275 frame_->EmitPush(r0); |
2281 } else { | 2276 } else { |
2282 // Fake TOS for targets that shadowed breaks and continues. | 2277 // Fake TOS for targets that shadowed breaks and continues. |
2283 __ mov(r0, Operand(Factory::undefined_value())); | 2278 __ mov(r0, Operand(Factory::undefined_value())); |
2284 frame_->EmitPush(r0); | 2279 frame_->EmitPush(r0); |
2285 } | 2280 } |
(...skipping 2386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4672 __ push(r0); | 4667 __ push(r0); |
4673 __ mov(r0, Operand(0)); // set number of arguments | 4668 __ mov(r0, Operand(0)); // set number of arguments |
4674 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_JS); | 4669 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_JS); |
4675 | 4670 |
4676 __ bind(&done); | 4671 __ bind(&done); |
4677 __ StubReturn(1); | 4672 __ StubReturn(1); |
4678 } | 4673 } |
4679 | 4674 |
4680 | 4675 |
4681 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { | 4676 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { |
4682 // r0 holds exception | 4677 // r0 holds the exception. |
4683 ASSERT(StackHandlerConstants::kSize == 6 * kPointerSize); // adjust this code | 4678 |
| 4679 // Adjust this code if not the case. |
| 4680 ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); |
| 4681 |
| 4682 // Drop the sp to the top of the handler. |
4684 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); | 4683 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); |
4685 __ ldr(sp, MemOperand(r3)); | 4684 __ ldr(sp, MemOperand(r3)); |
4686 __ pop(r2); // pop next in chain | 4685 |
| 4686 // Restore the next handler and frame pointer, discard handler state. |
| 4687 ASSERT(StackHandlerConstants::kNextOffset == 0); |
| 4688 __ pop(r2); |
4687 __ str(r2, MemOperand(r3)); | 4689 __ str(r2, MemOperand(r3)); |
4688 // restore parameter- and frame-pointer and pop state. | 4690 ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); |
4689 __ ldm(ia_w, sp, r3.bit() | pp.bit() | fp.bit()); | 4691 __ ldm(ia_w, sp, r3.bit() | fp.bit()); // r3: discarded state. |
4690 // Before returning we restore the context from the frame pointer if not NULL. | 4692 |
4691 // The frame pointer is NULL in the exception handler of a JS entry frame. | 4693 // Before returning we restore the context from the frame pointer if |
| 4694 // not NULL. The frame pointer is NULL in the exception handler of a |
| 4695 // JS entry frame. |
4692 __ cmp(fp, Operand(0)); | 4696 __ cmp(fp, Operand(0)); |
4693 // Set cp to NULL if fp is NULL. | 4697 // Set cp to NULL if fp is NULL. |
4694 __ mov(cp, Operand(0), LeaveCC, eq); | 4698 __ mov(cp, Operand(0), LeaveCC, eq); |
4695 // Restore cp otherwise. | 4699 // Restore cp otherwise. |
4696 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne); | 4700 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne); |
4697 #ifdef DEBUG | 4701 #ifdef DEBUG |
4698 if (FLAG_debug_code) { | 4702 if (FLAG_debug_code) { |
4699 __ mov(lr, Operand(pc)); | 4703 __ mov(lr, Operand(pc)); |
4700 } | 4704 } |
4701 #endif | 4705 #endif |
| 4706 ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); |
4702 __ pop(pc); | 4707 __ pop(pc); |
4703 } | 4708 } |
4704 | 4709 |
4705 | 4710 |
4706 void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) { | 4711 void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) { |
4707 // Fetch top stack handler. | 4712 // Adjust this code if not the case. |
| 4713 ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); |
| 4714 |
| 4715 // Drop sp to the top stack handler. |
4708 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); | 4716 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); |
4709 __ ldr(r3, MemOperand(r3)); | 4717 __ ldr(sp, MemOperand(r3)); |
4710 | 4718 |
4711 // Unwind the handlers until the ENTRY handler is found. | 4719 // Unwind the handlers until the ENTRY handler is found. |
4712 Label loop, done; | 4720 Label loop, done; |
4713 __ bind(&loop); | 4721 __ bind(&loop); |
4714 // Load the type of the current stack handler. | 4722 // Load the type of the current stack handler. |
4715 const int kStateOffset = StackHandlerConstants::kAddressDisplacement + | 4723 const int kStateOffset = StackHandlerConstants::kStateOffset; |
4716 StackHandlerConstants::kStateOffset; | 4724 __ ldr(r2, MemOperand(sp, kStateOffset)); |
4717 __ ldr(r2, MemOperand(r3, kStateOffset)); | |
4718 __ cmp(r2, Operand(StackHandler::ENTRY)); | 4725 __ cmp(r2, Operand(StackHandler::ENTRY)); |
4719 __ b(eq, &done); | 4726 __ b(eq, &done); |
4720 // Fetch the next handler in the list. | 4727 // Fetch the next handler in the list. |
4721 const int kNextOffset = StackHandlerConstants::kAddressDisplacement + | 4728 const int kNextOffset = StackHandlerConstants::kNextOffset; |
4722 StackHandlerConstants::kNextOffset; | 4729 __ ldr(sp, MemOperand(sp, kNextOffset)); |
4723 __ ldr(r3, MemOperand(r3, kNextOffset)); | |
4724 __ jmp(&loop); | 4730 __ jmp(&loop); |
4725 __ bind(&done); | 4731 __ bind(&done); |
4726 | 4732 |
4727 // Set the top handler address to next handler past the current ENTRY handler. | 4733 // Set the top handler address to next handler past the current ENTRY handler. |
4728 __ ldr(r0, MemOperand(r3, kNextOffset)); | 4734 ASSERT(StackHandlerConstants::kNextOffset == 0); |
4729 __ mov(r2, Operand(ExternalReference(Top::k_handler_address))); | 4735 __ pop(r0); |
4730 __ str(r0, MemOperand(r2)); | 4736 __ str(r0, MemOperand(r3)); |
4731 | 4737 |
4732 // Set external caught exception to false. | 4738 // Set external caught exception to false. |
| 4739 ExternalReference external_caught(Top::k_external_caught_exception_address); |
4733 __ mov(r0, Operand(false)); | 4740 __ mov(r0, Operand(false)); |
4734 ExternalReference external_caught(Top::k_external_caught_exception_address); | |
4735 __ mov(r2, Operand(external_caught)); | 4741 __ mov(r2, Operand(external_caught)); |
4736 __ str(r0, MemOperand(r2)); | 4742 __ str(r0, MemOperand(r2)); |
4737 | 4743 |
4738 // Set pending exception and r0 to out of memory exception. | 4744 // Set pending exception and r0 to out of memory exception. |
4739 Failure* out_of_memory = Failure::OutOfMemoryException(); | 4745 Failure* out_of_memory = Failure::OutOfMemoryException(); |
4740 __ mov(r0, Operand(reinterpret_cast<int32_t>(out_of_memory))); | 4746 __ mov(r0, Operand(reinterpret_cast<int32_t>(out_of_memory))); |
4741 __ mov(r2, Operand(ExternalReference(Top::k_pending_exception_address))); | 4747 __ mov(r2, Operand(ExternalReference(Top::k_pending_exception_address))); |
4742 __ str(r0, MemOperand(r2)); | 4748 __ str(r0, MemOperand(r2)); |
4743 | 4749 |
4744 // Restore the stack to the address of the ENTRY handler | 4750 // Stack layout at this point. See also StackHandlerConstants. |
4745 __ mov(sp, Operand(r3)); | 4751 // sp -> state (ENTRY) |
| 4752 // fp |
| 4753 // lr |
4746 | 4754 |
4747 // Stack layout at this point. See also PushTryHandler | 4755 // Discard handler state (r2 is not used) and restore frame pointer. |
4748 // r3, sp -> next handler | 4756 ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); |
4749 // state (ENTRY) | 4757 __ ldm(ia_w, sp, r2.bit() | fp.bit()); // r2: discarded state. |
4750 // pp | 4758 // Before returning we restore the context from the frame pointer if |
4751 // fp | 4759 // not NULL. The frame pointer is NULL in the exception handler of a |
4752 // lr | 4760 // JS entry frame. |
4753 | |
4754 // Discard ENTRY state (r2 is not used), and restore parameter- | |
4755 // and frame-pointer and pop state. | |
4756 __ ldm(ia_w, sp, r2.bit() | r3.bit() | pp.bit() | fp.bit()); | |
4757 // Before returning we restore the context from the frame pointer if not NULL. | |
4758 // The frame pointer is NULL in the exception handler of a JS entry frame. | |
4759 __ cmp(fp, Operand(0)); | 4761 __ cmp(fp, Operand(0)); |
4760 // Set cp to NULL if fp is NULL. | 4762 // Set cp to NULL if fp is NULL. |
4761 __ mov(cp, Operand(0), LeaveCC, eq); | 4763 __ mov(cp, Operand(0), LeaveCC, eq); |
4762 // Restore cp otherwise. | 4764 // Restore cp otherwise. |
4763 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne); | 4765 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne); |
4764 #ifdef DEBUG | 4766 #ifdef DEBUG |
4765 if (FLAG_debug_code) { | 4767 if (FLAG_debug_code) { |
4766 __ mov(lr, Operand(pc)); | 4768 __ mov(lr, Operand(pc)); |
4767 } | 4769 } |
4768 #endif | 4770 #endif |
| 4771 ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); |
4769 __ pop(pc); | 4772 __ pop(pc); |
4770 } | 4773 } |
4771 | 4774 |
4772 | 4775 |
4773 void CEntryStub::GenerateCore(MacroAssembler* masm, | 4776 void CEntryStub::GenerateCore(MacroAssembler* masm, |
4774 Label* throw_normal_exception, | 4777 Label* throw_normal_exception, |
4775 Label* throw_out_of_memory_exception, | 4778 Label* throw_out_of_memory_exception, |
4776 StackFrame::Type frame_type, | 4779 StackFrame::Type frame_type, |
4777 bool do_gc, | 4780 bool do_gc, |
4778 bool always_allocate) { | 4781 bool always_allocate) { |
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5176 __ mov(r2, Operand(0)); | 5179 __ mov(r2, Operand(0)); |
5177 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); | 5180 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); |
5178 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)), | 5181 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)), |
5179 RelocInfo::CODE_TARGET); | 5182 RelocInfo::CODE_TARGET); |
5180 } | 5183 } |
5181 | 5184 |
5182 | 5185 |
5183 #undef __ | 5186 #undef __ |
5184 | 5187 |
5185 } } // namespace v8::internal | 5188 } } // namespace v8::internal |
OLD | NEW |