OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 2040 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2051 for (int i = 0; i < nof_escapes; i++) { | 2051 for (int i = 0; i < nof_escapes; i++) { |
2052 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); | 2052 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); |
2053 } | 2053 } |
2054 | 2054 |
2055 // Generate code for the statements in the try block. | 2055 // Generate code for the statements in the try block. |
2056 VisitStatementsAndSpill(node->try_block()->statements()); | 2056 VisitStatementsAndSpill(node->try_block()->statements()); |
2057 | 2057 |
2058 // Stop the introduced shadowing and count the number of required unlinks. | 2058 // Stop the introduced shadowing and count the number of required unlinks. |
2059 // After shadowing stops, the original labels are unshadowed and the | 2059 // After shadowing stops, the original labels are unshadowed and the |
2060 // LabelShadows represent the formerly shadowing labels. | 2060 // LabelShadows represent the formerly shadowing labels. |
2061 int nof_unlinks = 0; | 2061 bool has_unlinks = false; |
2062 for (int i = 0; i <= nof_escapes; i++) { | 2062 for (int i = 0; i <= nof_escapes; i++) { |
2063 shadows[i]->StopShadowing(); | 2063 shadows[i]->StopShadowing(); |
2064 if (shadows[i]->is_linked()) nof_unlinks++; | 2064 has_unlinks = has_unlinks || shadows[i]->is_linked(); |
2065 } | 2065 } |
2066 function_return_is_shadowed_ = function_return_was_shadowed; | 2066 function_return_is_shadowed_ = function_return_was_shadowed; |
2067 | 2067 |
| 2068 // Get an external reference to the handler address. |
| 2069 ExternalReference handler_address(Top::k_handler_address); |
| 2070 |
| 2071 // The next handler address is at kNextIndex in the stack. |
2068 const int kNextIndex = StackHandlerConstants::kNextOffset / kPointerSize; | 2072 const int kNextIndex = StackHandlerConstants::kNextOffset / kPointerSize; |
2069 // If we can fall off the end of the try block, unlink from try chain. | 2073 // If we can fall off the end of the try block, unlink from try chain. |
2070 if (has_valid_frame()) { | 2074 if (has_valid_frame()) { |
2071 // The next handler address is at kNextIndex in the stack. | |
2072 __ ldr(r1, frame_->ElementAt(kNextIndex)); | 2075 __ ldr(r1, frame_->ElementAt(kNextIndex)); |
2073 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); | 2076 __ mov(r3, Operand(handler_address)); |
2074 __ str(r1, MemOperand(r3)); | 2077 __ str(r1, MemOperand(r3)); |
2075 frame_->Drop(StackHandlerConstants::kSize / kPointerSize); | 2078 frame_->Drop(StackHandlerConstants::kSize / kPointerSize); |
2076 if (nof_unlinks > 0) { | 2079 if (has_unlinks) { |
2077 exit.Jump(); | 2080 exit.Jump(); |
2078 } | 2081 } |
2079 } | 2082 } |
2080 | 2083 |
2081 // Generate unlink code for the (formerly) shadowing labels that have been | 2084 // Generate unlink code for the (formerly) shadowing labels that have been |
2082 // jumped to. | 2085 // jumped to. |
2083 for (int i = 0; i <= nof_escapes; i++) { | 2086 for (int i = 0; i <= nof_escapes; i++) { |
2084 if (shadows[i]->is_linked()) { | 2087 if (shadows[i]->is_linked()) { |
2085 // Unlink from try chain; | 2088 // Unlink from try chain; |
2086 shadows[i]->Bind(); | 2089 shadows[i]->Bind(); |
2087 // Because we can be jumping here (to spilled code) from unspilled | 2090 // Because we can be jumping here (to spilled code) from unspilled |
2088 // code, we need to reestablish a spilled frame at this block. | 2091 // code, we need to reestablish a spilled frame at this block. |
2089 frame_->SpillAll(); | 2092 frame_->SpillAll(); |
2090 | 2093 |
2091 // Reload sp from the top handler, because some statements that we | 2094 // Reload sp from the top handler, because some statements that we |
2092 // break from (eg, for...in) may have left stuff on the stack. | 2095 // break from (eg, for...in) may have left stuff on the stack. |
2093 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); | 2096 __ mov(r3, Operand(handler_address)); |
2094 __ ldr(sp, MemOperand(r3)); | 2097 __ ldr(sp, MemOperand(r3)); |
2095 // The stack pointer was restored to just below the code slot | 2098 // The stack pointer was restored to just below the code slot |
2096 // (the topmost slot) in the handler. | 2099 // (the topmost slot) in the handler. |
2097 frame_->Forget(frame_->height() - handler_height + 1); | 2100 frame_->Forget(frame_->height() - handler_height + 1); |
2098 | 2101 |
2099 // kNextIndex is off by one because the code slot has already | 2102 // kNextIndex is off by one because the code slot has already |
2100 // been dropped. | 2103 // been dropped. |
2101 __ ldr(r1, frame_->ElementAt(kNextIndex - 1)); | 2104 __ ldr(r1, frame_->ElementAt(kNextIndex - 1)); |
2102 __ str(r1, MemOperand(r3)); | 2105 __ str(r1, MemOperand(r3)); |
2103 // The code slot has already been dropped from the handler. | 2106 // The code slot has already been dropped from the handler. |
(...skipping 17 matching lines...) Expand all Loading... |
2121 #endif | 2124 #endif |
2122 VirtualFrame::SpilledScope spilled_scope(this); | 2125 VirtualFrame::SpilledScope spilled_scope(this); |
2123 Comment cmnt(masm_, "[ TryFinally"); | 2126 Comment cmnt(masm_, "[ TryFinally"); |
2124 CodeForStatementPosition(node); | 2127 CodeForStatementPosition(node); |
2125 | 2128 |
2126 // State: Used to keep track of reason for entering the finally | 2129 // State: Used to keep track of reason for entering the finally |
2127 // block. Should probably be extended to hold information for | 2130 // block. Should probably be extended to hold information for |
2128 // break/continue from within the try block. | 2131 // break/continue from within the try block. |
2129 enum { FALLING, THROWING, JUMPING }; | 2132 enum { FALLING, THROWING, JUMPING }; |
2130 | 2133 |
2131 JumpTarget unlink(this); | |
2132 JumpTarget try_block(this); | 2134 JumpTarget try_block(this); |
2133 JumpTarget finally_block(this); | 2135 JumpTarget finally_block(this); |
2134 | 2136 |
2135 try_block.Call(); | 2137 try_block.Call(); |
2136 | 2138 |
2137 frame_->EmitPush(r0); // save exception object on the stack | 2139 frame_->EmitPush(r0); // save exception object on the stack |
2138 // In case of thrown exceptions, this is where we continue. | 2140 // In case of thrown exceptions, this is where we continue. |
2139 __ mov(r2, Operand(Smi::FromInt(THROWING))); | 2141 __ mov(r2, Operand(Smi::FromInt(THROWING))); |
2140 finally_block.Jump(); | 2142 finally_block.Jump(); |
2141 | 2143 |
(...skipping 30 matching lines...) Expand all Loading... |
2172 // Stop the introduced shadowing and count the number of required unlinks. | 2174 // Stop the introduced shadowing and count the number of required unlinks. |
2173 // After shadowing stops, the original labels are unshadowed and the | 2175 // After shadowing stops, the original labels are unshadowed and the |
2174 // LabelShadows represent the formerly shadowing labels. | 2176 // LabelShadows represent the formerly shadowing labels. |
2175 int nof_unlinks = 0; | 2177 int nof_unlinks = 0; |
2176 for (int i = 0; i <= nof_escapes; i++) { | 2178 for (int i = 0; i <= nof_escapes; i++) { |
2177 shadows[i]->StopShadowing(); | 2179 shadows[i]->StopShadowing(); |
2178 if (shadows[i]->is_linked()) nof_unlinks++; | 2180 if (shadows[i]->is_linked()) nof_unlinks++; |
2179 } | 2181 } |
2180 function_return_is_shadowed_ = function_return_was_shadowed; | 2182 function_return_is_shadowed_ = function_return_was_shadowed; |
2181 | 2183 |
2182 // If we can fall off the end of the try block, set the state on the stack | 2184 // Get an external reference to the handler address. |
2183 // to FALLING. | 2185 ExternalReference handler_address(Top::k_handler_address); |
| 2186 |
| 2187 // The next handler address is at kNextIndex in the stack. |
| 2188 const int kNextIndex = StackHandlerConstants::kNextOffset / kPointerSize; |
| 2189 // If we can fall off the end of the try block, unlink from the try |
| 2190 // chain and set the state on the frame to FALLING. |
2184 if (has_valid_frame()) { | 2191 if (has_valid_frame()) { |
2185 __ mov(r0, Operand(Factory::undefined_value())); // fake TOS | 2192 __ ldr(r1, frame_->ElementAt(kNextIndex)); |
| 2193 __ mov(r3, Operand(handler_address)); |
| 2194 __ str(r1, MemOperand(r3)); |
| 2195 frame_->Drop(StackHandlerConstants::kSize / kPointerSize); |
| 2196 |
| 2197 // Fake a top of stack value (unneeded when FALLING) and set the |
| 2198 // state in r2, then jump around the unlink blocks if any. |
| 2199 __ mov(r0, Operand(Factory::undefined_value())); |
2186 frame_->EmitPush(r0); | 2200 frame_->EmitPush(r0); |
2187 __ mov(r2, Operand(Smi::FromInt(FALLING))); | 2201 __ mov(r2, Operand(Smi::FromInt(FALLING))); |
2188 if (nof_unlinks > 0) { | 2202 if (nof_unlinks > 0) { |
2189 unlink.Jump(); | 2203 finally_block.Jump(); |
2190 } | 2204 } |
2191 } | 2205 } |
2192 | 2206 |
2193 // Generate code to set the state for the (formerly) shadowing labels that | 2207 // Generate code to unlink and set the state for the (formerly) |
2194 // have been jumped to. | 2208 // shadowing labels that have been jumped to. |
2195 for (int i = 0; i <= nof_escapes; i++) { | 2209 for (int i = 0; i <= nof_escapes; i++) { |
2196 if (shadows[i]->is_linked()) { | 2210 if (shadows[i]->is_linked()) { |
| 2211 // If we have come from the shadowed return, the return value is |
| 2212 // in (a non-refcounted reference to) r0. We must preserve it |
| 2213 // until it is pushed. |
| 2214 // |
2197 // Because we can be jumping here (to spilled code) from | 2215 // Because we can be jumping here (to spilled code) from |
2198 // unspilled code, we need to reestablish a spilled frame at | 2216 // unspilled code, we need to reestablish a spilled frame at |
2199 // this block. | 2217 // this block. |
2200 shadows[i]->Bind(); | 2218 shadows[i]->Bind(); |
2201 frame_->SpillAll(); | 2219 frame_->SpillAll(); |
| 2220 |
| 2221 // Reload sp from the top handler, because some statements that |
| 2222 // we break from (eg, for...in) may have left stuff on the |
| 2223 // stack. |
| 2224 __ mov(r3, Operand(handler_address)); |
| 2225 __ ldr(sp, MemOperand(r3)); |
| 2226 // The stack pointer was restored to the address slot in the handler. |
| 2227 ASSERT(StackHandlerConstants::kNextOffset == 1 * kPointerSize); |
| 2228 frame_->Forget(frame_->height() - handler_height + 1); |
| 2229 |
| 2230 // Unlink this handler and drop it from the frame. The next |
| 2231 // handler address is now on top of the frame. |
| 2232 frame_->EmitPop(r1); |
| 2233 __ str(r1, MemOperand(r3)); |
| 2234 // The top (code) and the second (handler) slot have both been |
| 2235 // dropped already. |
| 2236 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 2); |
| 2237 |
2202 if (i == kReturnShadowIndex) { | 2238 if (i == kReturnShadowIndex) { |
2203 // If this label shadowed the function return, materialize the | 2239 // If this label shadowed the function return, materialize the |
2204 // return value on the stack. | 2240 // return value on the stack. |
2205 frame_->EmitPush(r0); | 2241 frame_->EmitPush(r0); |
2206 } else { | 2242 } else { |
2207 // Fake TOS for targets that shadowed breaks and continues. | 2243 // Fake TOS for targets that shadowed breaks and continues. |
2208 __ mov(r0, Operand(Factory::undefined_value())); | 2244 __ mov(r0, Operand(Factory::undefined_value())); |
2209 frame_->EmitPush(r0); | 2245 frame_->EmitPush(r0); |
2210 } | 2246 } |
2211 __ mov(r2, Operand(Smi::FromInt(JUMPING + i))); | 2247 __ mov(r2, Operand(Smi::FromInt(JUMPING + i))); |
2212 unlink.Jump(); | 2248 if (--nof_unlinks > 0) { |
| 2249 // If this is not the last unlink block, jump around the next. |
| 2250 finally_block.Jump(); |
| 2251 } |
2213 } | 2252 } |
2214 } | 2253 } |
2215 | 2254 |
2216 // Unlink from try chain; | |
2217 if (unlink.is_linked()) { | |
2218 unlink.Bind(); | |
2219 } | |
2220 | |
2221 // Control can reach here via a jump to unlink or by falling off the | |
2222 // end of the try block (with no unlinks). | |
2223 if (has_valid_frame()) { | |
2224 // Preserve TOS result in r0 across stack manipulation. | |
2225 frame_->EmitPop(r0); | |
2226 // Reload sp from the top handler, because some statements that we | |
2227 // break from (eg, for...in) may have left stuff on the stack. | |
2228 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); | |
2229 __ ldr(sp, MemOperand(r3)); | |
2230 // The stack pointer was restored to just below the code slot (the | |
2231 // topmost slot) in the handler. | |
2232 frame_->Forget(frame_->height() - handler_height + 1); | |
2233 const int kNextIndex = (StackHandlerConstants::kNextOffset | |
2234 + StackHandlerConstants::kAddressDisplacement) | |
2235 / kPointerSize; | |
2236 __ ldr(r1, frame_->ElementAt(kNextIndex)); | |
2237 __ str(r1, MemOperand(r3)); | |
2238 ASSERT(StackHandlerConstants::kCodeOffset == 0); | |
2239 // Drop the rest of the handler (not including the already dropped | |
2240 // code slot). | |
2241 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); | |
2242 // Restore the result to TOS. | |
2243 frame_->EmitPush(r0); | |
2244 } | |
2245 | |
2246 // --- Finally block --- | 2255 // --- Finally block --- |
2247 finally_block.Bind(); | 2256 finally_block.Bind(); |
2248 | 2257 |
2249 // Push the state on the stack. | 2258 // Push the state on the stack. |
2250 frame_->EmitPush(r2); | 2259 frame_->EmitPush(r2); |
2251 | 2260 |
2252 // We keep two elements on the stack - the (possibly faked) result | 2261 // We keep two elements on the stack - the (possibly faked) result |
2253 // and the state - while evaluating the finally block. Record it, so | 2262 // and the state - while evaluating the finally block. Record it, so |
2254 // that a break/continue crossing this statement can restore the | 2263 // that a break/continue crossing this statement can restore the |
2255 // stack. | 2264 // stack. |
(...skipping 2830 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5086 __ mov(r2, Operand(0)); | 5095 __ mov(r2, Operand(0)); |
5087 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); | 5096 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); |
5088 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)), | 5097 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)), |
5089 RelocInfo::CODE_TARGET); | 5098 RelocInfo::CODE_TARGET); |
5090 } | 5099 } |
5091 | 5100 |
5092 | 5101 |
5093 #undef __ | 5102 #undef __ |
5094 | 5103 |
5095 } } // namespace v8::internal | 5104 } } // namespace v8::internal |
OLD | NEW |