| 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 2035 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2046 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); | 2046 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); |
| 2047 } | 2047 } |
| 2048 | 2048 |
| 2049 // Generate code for the statements in the try block. | 2049 // Generate code for the statements in the try block. |
| 2050 VisitStatementsAndSpill(node->try_block()->statements()); | 2050 VisitStatementsAndSpill(node->try_block()->statements()); |
| 2051 | 2051 |
| 2052 // Stop the introduced shadowing and count the number of required unlinks. | 2052 // Stop the introduced shadowing and count the number of required unlinks. |
| 2053 // After shadowing stops, the original labels are unshadowed and the | 2053 // After shadowing stops, the original labels are unshadowed and the |
| 2054 // LabelShadows represent the formerly shadowing labels. | 2054 // LabelShadows represent the formerly shadowing labels. |
| 2055 bool has_unlinks = false; | 2055 bool has_unlinks = false; |
| 2056 for (int i = 0; i <= nof_escapes; i++) { | 2056 for (int i = 0; i < shadows.length(); i++) { |
| 2057 shadows[i]->StopShadowing(); | 2057 shadows[i]->StopShadowing(); |
| 2058 has_unlinks = has_unlinks || shadows[i]->is_linked(); | 2058 has_unlinks = has_unlinks || shadows[i]->is_linked(); |
| 2059 } | 2059 } |
| 2060 function_return_is_shadowed_ = function_return_was_shadowed; | 2060 function_return_is_shadowed_ = function_return_was_shadowed; |
| 2061 | 2061 |
| 2062 // Get an external reference to the handler address. | 2062 // Get an external reference to the handler address. |
| 2063 ExternalReference handler_address(Top::k_handler_address); | 2063 ExternalReference handler_address(Top::k_handler_address); |
| 2064 | 2064 |
| 2065 // The next handler address is at kNextIndex in the stack. | 2065 // The next handler address is at kNextIndex in the stack. |
| 2066 const int kNextIndex = StackHandlerConstants::kNextOffset / kPointerSize; | 2066 const int kNextIndex = StackHandlerConstants::kNextOffset / kPointerSize; |
| 2067 // If we can fall off the end of the try block, unlink from try chain. | 2067 // If we can fall off the end of the try block, unlink from try chain. |
| 2068 if (has_valid_frame()) { | 2068 if (has_valid_frame()) { |
| 2069 __ ldr(r1, frame_->ElementAt(kNextIndex)); | 2069 __ ldr(r1, frame_->ElementAt(kNextIndex)); |
| 2070 __ mov(r3, Operand(handler_address)); | 2070 __ mov(r3, Operand(handler_address)); |
| 2071 __ str(r1, MemOperand(r3)); | 2071 __ str(r1, MemOperand(r3)); |
| 2072 frame_->Drop(StackHandlerConstants::kSize / kPointerSize); | 2072 frame_->Drop(StackHandlerConstants::kSize / kPointerSize); |
| 2073 if (has_unlinks) { | 2073 if (has_unlinks) { |
| 2074 exit.Jump(); | 2074 exit.Jump(); |
| 2075 } | 2075 } |
| 2076 } | 2076 } |
| 2077 | 2077 |
| 2078 // Generate unlink code for the (formerly) shadowing labels that have been | 2078 // Generate unlink code for the (formerly) shadowing labels that have been |
| 2079 // jumped to. | 2079 // jumped to. Deallocate each shadow target. |
| 2080 for (int i = 0; i <= nof_escapes; i++) { | 2080 for (int i = 0; i < shadows.length(); i++) { |
| 2081 if (shadows[i]->is_linked()) { | 2081 if (shadows[i]->is_linked()) { |
| 2082 // Unlink from try chain; | 2082 // Unlink from try chain; |
| 2083 shadows[i]->Bind(); | 2083 shadows[i]->Bind(); |
| 2084 // Because we can be jumping here (to spilled code) from unspilled | 2084 // Because we can be jumping here (to spilled code) from unspilled |
| 2085 // code, we need to reestablish a spilled frame at this block. | 2085 // code, we need to reestablish a spilled frame at this block. |
| 2086 frame_->SpillAll(); | 2086 frame_->SpillAll(); |
| 2087 | 2087 |
| 2088 // Reload sp from the top handler, because some statements that we | 2088 // Reload sp from the top handler, because some statements that we |
| 2089 // break from (eg, for...in) may have left stuff on the stack. | 2089 // break from (eg, for...in) may have left stuff on the stack. |
| 2090 __ mov(r3, Operand(handler_address)); | 2090 __ mov(r3, Operand(handler_address)); |
| 2091 __ ldr(sp, MemOperand(r3)); | 2091 __ ldr(sp, MemOperand(r3)); |
| 2092 // The stack pointer was restored to just below the code slot | 2092 // The stack pointer was restored to just below the code slot |
| 2093 // (the topmost slot) in the handler. | 2093 // (the topmost slot) in the handler. |
| 2094 frame_->Forget(frame_->height() - handler_height + 1); | 2094 frame_->Forget(frame_->height() - handler_height + 1); |
| 2095 | 2095 |
| 2096 // kNextIndex is off by one because the code slot has already | 2096 // kNextIndex is off by one because the code slot has already |
| 2097 // been dropped. | 2097 // been dropped. |
| 2098 __ ldr(r1, frame_->ElementAt(kNextIndex - 1)); | 2098 __ ldr(r1, frame_->ElementAt(kNextIndex - 1)); |
| 2099 __ str(r1, MemOperand(r3)); | 2099 __ str(r1, MemOperand(r3)); |
| 2100 // The code slot has already been dropped from the handler. | 2100 // The code slot has already been dropped from the handler. |
| 2101 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); | 2101 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); |
| 2102 | 2102 |
| 2103 if (!function_return_is_shadowed_ && i == kReturnShadowIndex) { | 2103 if (!function_return_is_shadowed_ && i == kReturnShadowIndex) { |
| 2104 frame_->PrepareForReturn(); | 2104 frame_->PrepareForReturn(); |
| 2105 } | 2105 } |
| 2106 shadows[i]->other_target()->Jump(); | 2106 shadows[i]->other_target()->Jump(); |
| 2107 } | 2107 } |
| 2108 delete shadows[i]; |
| 2108 } | 2109 } |
| 2109 | 2110 |
| 2110 exit.Bind(); | 2111 exit.Bind(); |
| 2111 ASSERT(!has_valid_frame() || frame_->height() == original_height); | 2112 ASSERT(!has_valid_frame() || frame_->height() == original_height); |
| 2112 } | 2113 } |
| 2113 | 2114 |
| 2114 | 2115 |
| 2115 void CodeGenerator::VisitTryFinally(TryFinally* node) { | 2116 void CodeGenerator::VisitTryFinally(TryFinally* node) { |
| 2116 #ifdef DEBUG | 2117 #ifdef DEBUG |
| 2117 int original_height = frame_->height(); | 2118 int original_height = frame_->height(); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2162 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); | 2163 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); |
| 2163 } | 2164 } |
| 2164 | 2165 |
| 2165 // Generate code for the statements in the try block. | 2166 // Generate code for the statements in the try block. |
| 2166 VisitStatementsAndSpill(node->try_block()->statements()); | 2167 VisitStatementsAndSpill(node->try_block()->statements()); |
| 2167 | 2168 |
| 2168 // Stop the introduced shadowing and count the number of required unlinks. | 2169 // Stop the introduced shadowing and count the number of required unlinks. |
| 2169 // After shadowing stops, the original labels are unshadowed and the | 2170 // After shadowing stops, the original labels are unshadowed and the |
| 2170 // LabelShadows represent the formerly shadowing labels. | 2171 // LabelShadows represent the formerly shadowing labels. |
| 2171 int nof_unlinks = 0; | 2172 int nof_unlinks = 0; |
| 2172 for (int i = 0; i <= nof_escapes; i++) { | 2173 for (int i = 0; i < shadows.length(); i++) { |
| 2173 shadows[i]->StopShadowing(); | 2174 shadows[i]->StopShadowing(); |
| 2174 if (shadows[i]->is_linked()) nof_unlinks++; | 2175 if (shadows[i]->is_linked()) nof_unlinks++; |
| 2175 } | 2176 } |
| 2176 function_return_is_shadowed_ = function_return_was_shadowed; | 2177 function_return_is_shadowed_ = function_return_was_shadowed; |
| 2177 | 2178 |
| 2178 // Get an external reference to the handler address. | 2179 // Get an external reference to the handler address. |
| 2179 ExternalReference handler_address(Top::k_handler_address); | 2180 ExternalReference handler_address(Top::k_handler_address); |
| 2180 | 2181 |
| 2181 // The next handler address is at kNextIndex in the stack. | 2182 // The next handler address is at kNextIndex in the stack. |
| 2182 const int kNextIndex = StackHandlerConstants::kNextOffset / kPointerSize; | 2183 const int kNextIndex = StackHandlerConstants::kNextOffset / kPointerSize; |
| 2183 // If we can fall off the end of the try block, unlink from the try | 2184 // If we can fall off the end of the try block, unlink from the try |
| 2184 // chain and set the state on the frame to FALLING. | 2185 // chain and set the state on the frame to FALLING. |
| 2185 if (has_valid_frame()) { | 2186 if (has_valid_frame()) { |
| 2186 __ ldr(r1, frame_->ElementAt(kNextIndex)); | 2187 __ ldr(r1, frame_->ElementAt(kNextIndex)); |
| 2187 __ mov(r3, Operand(handler_address)); | 2188 __ mov(r3, Operand(handler_address)); |
| 2188 __ str(r1, MemOperand(r3)); | 2189 __ str(r1, MemOperand(r3)); |
| 2189 frame_->Drop(StackHandlerConstants::kSize / kPointerSize); | 2190 frame_->Drop(StackHandlerConstants::kSize / kPointerSize); |
| 2190 | 2191 |
| 2191 // Fake a top of stack value (unneeded when FALLING) and set the | 2192 // Fake a top of stack value (unneeded when FALLING) and set the |
| 2192 // state in r2, then jump around the unlink blocks if any. | 2193 // state in r2, then jump around the unlink blocks if any. |
| 2193 __ mov(r0, Operand(Factory::undefined_value())); | 2194 __ mov(r0, Operand(Factory::undefined_value())); |
| 2194 frame_->EmitPush(r0); | 2195 frame_->EmitPush(r0); |
| 2195 __ mov(r2, Operand(Smi::FromInt(FALLING))); | 2196 __ mov(r2, Operand(Smi::FromInt(FALLING))); |
| 2196 if (nof_unlinks > 0) { | 2197 if (nof_unlinks > 0) { |
| 2197 finally_block.Jump(); | 2198 finally_block.Jump(); |
| 2198 } | 2199 } |
| 2199 } | 2200 } |
| 2200 | 2201 |
| 2201 // Generate code to unlink and set the state for the (formerly) | 2202 // Generate code to unlink and set the state for the (formerly) |
| 2202 // shadowing labels that have been jumped to. | 2203 // shadowing targets that have been jumped to. |
| 2203 for (int i = 0; i <= nof_escapes; i++) { | 2204 for (int i = 0; i < shadows.length(); i++) { |
| 2204 if (shadows[i]->is_linked()) { | 2205 if (shadows[i]->is_linked()) { |
| 2205 // If we have come from the shadowed return, the return value is | 2206 // If we have come from the shadowed return, the return value is |
| 2206 // in (a non-refcounted reference to) r0. We must preserve it | 2207 // in (a non-refcounted reference to) r0. We must preserve it |
| 2207 // until it is pushed. | 2208 // until it is pushed. |
| 2208 // | 2209 // |
| 2209 // Because we can be jumping here (to spilled code) from | 2210 // Because we can be jumping here (to spilled code) from |
| 2210 // unspilled code, we need to reestablish a spilled frame at | 2211 // unspilled code, we need to reestablish a spilled frame at |
| 2211 // this block. | 2212 // this block. |
| 2212 shadows[i]->Bind(); | 2213 shadows[i]->Bind(); |
| 2213 frame_->SpillAll(); | 2214 frame_->SpillAll(); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2257 // | 2258 // |
| 2258 // Generate code for the statements in the finally block. | 2259 // Generate code for the statements in the finally block. |
| 2259 VisitStatementsAndSpill(node->finally_block()->statements()); | 2260 VisitStatementsAndSpill(node->finally_block()->statements()); |
| 2260 | 2261 |
| 2261 if (has_valid_frame()) { | 2262 if (has_valid_frame()) { |
| 2262 JumpTarget exit(this); | 2263 JumpTarget exit(this); |
| 2263 // Restore state and return value or faked TOS. | 2264 // Restore state and return value or faked TOS. |
| 2264 frame_->EmitPop(r2); | 2265 frame_->EmitPop(r2); |
| 2265 frame_->EmitPop(r0); | 2266 frame_->EmitPop(r0); |
| 2266 | 2267 |
| 2267 // Generate code to jump to the right destination for all used (formerly) | 2268 // Generate code to jump to the right destination for all used |
| 2268 // shadowing labels. | 2269 // formerly shadowing targets. Deallocate each shadow target. |
| 2269 for (int i = 0; i <= nof_escapes; i++) { | 2270 for (int i = 0; i < shadows.length(); i++) { |
| 2270 if (shadows[i]->is_bound()) { | 2271 if (shadows[i]->is_bound()) { |
| 2271 JumpTarget* original = shadows[i]->other_target(); | 2272 JumpTarget* original = shadows[i]->other_target(); |
| 2272 __ cmp(r2, Operand(Smi::FromInt(JUMPING + i))); | 2273 __ cmp(r2, Operand(Smi::FromInt(JUMPING + i))); |
| 2273 if (!function_return_is_shadowed_ && i == kReturnShadowIndex) { | 2274 if (!function_return_is_shadowed_ && i == kReturnShadowIndex) { |
| 2274 JumpTarget skip(this); | 2275 JumpTarget skip(this); |
| 2275 skip.Branch(ne); | 2276 skip.Branch(ne); |
| 2276 frame_->PrepareForReturn(); | 2277 frame_->PrepareForReturn(); |
| 2277 original->Jump(); | 2278 original->Jump(); |
| 2278 skip.Bind(); | 2279 skip.Bind(); |
| 2279 } else { | 2280 } else { |
| 2280 original->Branch(eq); | 2281 original->Branch(eq); |
| 2281 } | 2282 } |
| 2282 } | 2283 } |
| 2284 delete shadows[i]; |
| 2283 } | 2285 } |
| 2284 | 2286 |
| 2285 // Check if we need to rethrow the exception. | 2287 // Check if we need to rethrow the exception. |
| 2286 __ cmp(r2, Operand(Smi::FromInt(THROWING))); | 2288 __ cmp(r2, Operand(Smi::FromInt(THROWING))); |
| 2287 exit.Branch(ne); | 2289 exit.Branch(ne); |
| 2288 | 2290 |
| 2289 // Rethrow exception. | 2291 // Rethrow exception. |
| 2290 frame_->EmitPush(r0); | 2292 frame_->EmitPush(r0); |
| 2291 frame_->CallRuntime(Runtime::kReThrow, 1); | 2293 frame_->CallRuntime(Runtime::kReThrow, 1); |
| 2292 | 2294 |
| (...skipping 2853 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5146 __ mov(r2, Operand(0)); | 5148 __ mov(r2, Operand(0)); |
| 5147 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); | 5149 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); |
| 5148 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)), | 5150 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)), |
| 5149 RelocInfo::CODE_TARGET); | 5151 RelocInfo::CODE_TARGET); |
| 5150 } | 5152 } |
| 5151 | 5153 |
| 5152 | 5154 |
| 5153 #undef __ | 5155 #undef __ |
| 5154 | 5156 |
| 5155 } } // namespace v8::internal | 5157 } } // namespace v8::internal |
| OLD | NEW |