Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(91)

Side by Side Diff: src/codegen-arm.cc

Issue 28021: Experimental: cleanup the handling of try...catch and try...finally on... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: Created 11 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | src/codegen-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 2007 matching lines...) Expand 10 before | Expand all | Expand 10 after
2018 2018
2019 // Shadow the labels for all escapes from the try block, including 2019 // Shadow the labels for all escapes from the try block, including
2020 // returns. During shadowing, the original label is hidden as the 2020 // returns. During shadowing, the original label is hidden as the
2021 // LabelShadow and operations on the original actually affect the 2021 // LabelShadow and operations on the original actually affect the
2022 // shadowing label. 2022 // shadowing label.
2023 // 2023 //
2024 // We should probably try to unify the escaping labels and the return 2024 // We should probably try to unify the escaping labels and the return
2025 // label. 2025 // label.
2026 int nof_escapes = node->escaping_targets()->length(); 2026 int nof_escapes = node->escaping_targets()->length();
2027 List<ShadowTarget*> shadows(1 + nof_escapes); 2027 List<ShadowTarget*> shadows(1 + nof_escapes);
2028
2029 // Add the shadow target for the function return.
2030 static const int kReturnShadowIndex = 0;
2028 shadows.Add(new ShadowTarget(&function_return_)); 2031 shadows.Add(new ShadowTarget(&function_return_));
2032 bool function_return_was_shadowed = function_return_is_shadowed_;
2033 function_return_is_shadowed_ = true;
2034 ASSERT(shadows[kReturnShadowIndex]->other_target() == &function_return_);
2035
2036 // Add the remaining shadow targets.
2029 for (int i = 0; i < nof_escapes; i++) { 2037 for (int i = 0; i < nof_escapes; i++) {
2030 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); 2038 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i)));
2031 } 2039 }
2032 bool function_return_was_shadowed = function_return_is_shadowed_;
2033 function_return_is_shadowed_ = true;
2034 2040
2035 // Generate code for the statements in the try block. 2041 // Generate code for the statements in the try block.
2036 VisitStatementsAndSpill(node->try_block()->statements()); 2042 VisitStatementsAndSpill(node->try_block()->statements());
2037 if (frame_ != NULL) {
2038 frame_->Drop(); // Discard the result.
2039 }
2040 2043
2041 // Stop the introduced shadowing and count the number of required unlinks. 2044 // Stop the introduced shadowing and count the number of required unlinks.
2042 // After shadowing stops, the original labels are unshadowed and the 2045 // After shadowing stops, the original labels are unshadowed and the
2043 // LabelShadows represent the formerly shadowing labels. 2046 // LabelShadows represent the formerly shadowing labels.
2044 int nof_unlinks = 0; 2047 int nof_unlinks = 0;
2045 for (int i = 0; i <= nof_escapes; i++) { 2048 for (int i = 0; i <= nof_escapes; i++) {
2046 shadows[i]->StopShadowing(); 2049 shadows[i]->StopShadowing();
2047 if (shadows[i]->is_linked()) nof_unlinks++; 2050 if (shadows[i]->is_linked()) nof_unlinks++;
2048 } 2051 }
2049 function_return_is_shadowed_ = function_return_was_shadowed; 2052 function_return_is_shadowed_ = function_return_was_shadowed;
2050 2053
2051 const int kNextIndex = (StackHandlerConstants::kNextOffset 2054 const int kNextIndex = StackHandlerConstants::kNextOffset / kPointerSize;
2052 + StackHandlerConstants::kAddressDisplacement)
2053 / kPointerSize;
2054 // If we can fall off the end of the try block, unlink from try chain. 2055 // If we can fall off the end of the try block, unlink from try chain.
2055 if (frame_ != NULL) { 2056 if (has_valid_frame()) {
2056 __ ldr(r1, frame_->ElementAt(kNextIndex)); // read next_sp 2057 // The next handler address is at kNextIndex in the stack.
2058 __ ldr(r1, frame_->ElementAt(kNextIndex));
2057 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); 2059 __ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
2058 __ str(r1, MemOperand(r3)); 2060 __ str(r1, MemOperand(r3));
2059 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code 2061 frame_->Drop(StackHandlerConstants::kSize / kPointerSize);
2060 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
2061 // Code slot popped.
2062 if (nof_unlinks > 0) { 2062 if (nof_unlinks > 0) {
2063 exit.Jump(); 2063 exit.Jump();
2064 } 2064 }
2065 } 2065 }
2066 2066
2067 // Generate unlink code for the (formerly) shadowing labels that have been 2067 // Generate unlink code for the (formerly) shadowing labels that have been
2068 // jumped to. 2068 // jumped to.
2069 for (int i = 0; i <= nof_escapes; i++) { 2069 for (int i = 0; i <= nof_escapes; i++) {
2070 if (shadows[i]->is_linked()) { 2070 if (shadows[i]->is_linked()) {
2071 // Unlink from try chain; 2071 // Unlink from try chain;
2072 shadows[i]->Bind(); 2072 shadows[i]->Bind();
2073 // Because we can be jumping here (to spilled code) from unspilled
2074 // code, we need to reestablish a spilled frame at this block.
2075 frame_->SpillAll();
2073 2076
2074 // Reload sp from the top handler, because some statements that we 2077 // Reload sp from the top handler, because some statements that we
2075 // break from (eg, for...in) may have left stuff on the stack. 2078 // break from (eg, for...in) may have left stuff on the stack.
2076 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); 2079 __ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
2077 __ ldr(sp, MemOperand(r3)); 2080 __ ldr(sp, MemOperand(r3));
2078 frame_->Forget(frame_->height() - handler_height); 2081 // The stack pointer was restored to just below the code slot
2082 // (the topmost slot) in the handler.
2083 frame_->Forget(frame_->height() - handler_height + 1);
2079 2084
2080 __ ldr(r1, frame_->ElementAt(kNextIndex)); 2085 // kNextIndex is off by one because the code slot has already
2086 // been dropped.
2087 __ ldr(r1, frame_->ElementAt(kNextIndex - 1));
2081 __ str(r1, MemOperand(r3)); 2088 __ str(r1, MemOperand(r3));
2082 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code
2083 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); 2089 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
2084 // Code slot popped. 2090
2085 frame_->Forget(1); 2091 if (!function_return_is_shadowed_ && i == kReturnShadowIndex) {
2092 frame_->PrepareForReturn();
2093 }
2086 shadows[i]->other_target()->Jump(); 2094 shadows[i]->other_target()->Jump();
2087 } 2095 }
2088 } 2096 }
2089 2097
2090 exit.Bind(); 2098 exit.Bind();
2091 ASSERT(!has_valid_frame() || frame_->height() == original_height); 2099 ASSERT(!has_valid_frame() || frame_->height() == original_height);
2092 } 2100 }
2093 2101
2094 2102
2095 void CodeGenerator::VisitTryFinally(TryFinally* node) { 2103 void CodeGenerator::VisitTryFinally(TryFinally* node) {
(...skipping 13 matching lines...) Expand all
2109 JumpTarget try_block(this); 2117 JumpTarget try_block(this);
2110 JumpTarget finally_block(this); 2118 JumpTarget finally_block(this);
2111 2119
2112 try_block.Call(); 2120 try_block.Call();
2113 2121
2114 frame_->EmitPush(r0); // save exception object on the stack 2122 frame_->EmitPush(r0); // save exception object on the stack
2115 // In case of thrown exceptions, this is where we continue. 2123 // In case of thrown exceptions, this is where we continue.
2116 __ mov(r2, Operand(Smi::FromInt(THROWING))); 2124 __ mov(r2, Operand(Smi::FromInt(THROWING)));
2117 finally_block.Jump(); 2125 finally_block.Jump();
2118 2126
2119
2120 // --- Try block --- 2127 // --- Try block ---
2121 try_block.Bind(); 2128 try_block.Bind();
2122 2129
2123 frame_->PushTryHandler(TRY_FINALLY_HANDLER); 2130 frame_->PushTryHandler(TRY_FINALLY_HANDLER);
2124 int handler_height = frame_->height(); 2131 int handler_height = frame_->height();
2125 2132
2126 // Shadow the labels for all escapes from the try block, including 2133 // Shadow the labels for all escapes from the try block, including
2127 // returns. Shadowing hides the original label as the LabelShadow and 2134 // returns. Shadowing hides the original label as the LabelShadow and
2128 // operations on the original actually affect the shadowing label. 2135 // operations on the original actually affect the shadowing label.
2129 // 2136 //
2130 // We should probably try to unify the escaping labels and the return 2137 // We should probably try to unify the escaping labels and the return
2131 // label. 2138 // label.
2132 int nof_escapes = node->escaping_targets()->length(); 2139 int nof_escapes = node->escaping_targets()->length();
2133 List<ShadowTarget*> shadows(1 + nof_escapes); 2140 List<ShadowTarget*> shadows(1 + nof_escapes);
2141
2142 // Add the shadow target for the function return.
2143 static const int kReturnShadowIndex = 0;
2134 shadows.Add(new ShadowTarget(&function_return_)); 2144 shadows.Add(new ShadowTarget(&function_return_));
2145 bool function_return_was_shadowed = function_return_is_shadowed_;
2146 function_return_is_shadowed_ = true;
2147 ASSERT(shadows[kReturnShadowIndex]->other_target() == &function_return_);
2148
2149 // Add the remaining shadow targets.
2135 for (int i = 0; i < nof_escapes; i++) { 2150 for (int i = 0; i < nof_escapes; i++) {
2136 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); 2151 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i)));
2137 } 2152 }
2138 bool function_return_was_shadowed = function_return_is_shadowed_;
2139 function_return_is_shadowed_ = true;
2140 2153
2141 // Generate code for the statements in the try block. 2154 // Generate code for the statements in the try block.
2142 VisitStatementsAndSpill(node->try_block()->statements()); 2155 VisitStatementsAndSpill(node->try_block()->statements());
2143 2156
2144 // Stop the introduced shadowing and count the number of required unlinks. 2157 // Stop the introduced shadowing and count the number of required unlinks.
2145 // After shadowing stops, the original labels are unshadowed and the 2158 // After shadowing stops, the original labels are unshadowed and the
2146 // LabelShadows represent the formerly shadowing labels. 2159 // LabelShadows represent the formerly shadowing labels.
2147 int nof_unlinks = 0; 2160 int nof_unlinks = 0;
2148 for (int i = 0; i <= nof_escapes; i++) { 2161 for (int i = 0; i <= nof_escapes; i++) {
2149 shadows[i]->StopShadowing(); 2162 shadows[i]->StopShadowing();
2150 if (shadows[i]->is_linked()) nof_unlinks++; 2163 if (shadows[i]->is_linked()) nof_unlinks++;
2151 } 2164 }
2152 function_return_is_shadowed_ = function_return_was_shadowed; 2165 function_return_is_shadowed_ = function_return_was_shadowed;
2153 2166
2154 // If we can fall off the end of the try block, set the state on the stack 2167 // If we can fall off the end of the try block, set the state on the stack
2155 // to FALLING. 2168 // to FALLING.
2156 if (frame_ != NULL) { 2169 if (has_valid_frame()) {
2157 __ mov(r0, Operand(Factory::undefined_value())); // fake TOS 2170 __ mov(r0, Operand(Factory::undefined_value())); // fake TOS
2158 frame_->EmitPush(r0); 2171 frame_->EmitPush(r0);
2159 __ mov(r2, Operand(Smi::FromInt(FALLING))); 2172 __ mov(r2, Operand(Smi::FromInt(FALLING)));
2160 if (nof_unlinks > 0) { 2173 if (nof_unlinks > 0) {
2161 unlink.Jump(); 2174 unlink.Jump();
2162 } 2175 }
2163 } 2176 }
2164 2177
2165 // Generate code to set the state for the (formerly) shadowing labels that 2178 // Generate code to set the state for the (formerly) shadowing labels that
2166 // have been jumped to. 2179 // have been jumped to.
2167 for (int i = 0; i <= nof_escapes; i++) { 2180 for (int i = 0; i <= nof_escapes; i++) {
2168 if (shadows[i]->is_linked()) { 2181 if (shadows[i]->is_linked()) {
2182 // Because we can be jumping here (to spilled code) from
2183 // unspilled code, we need to reestablish a spilled frame at
2184 // this block.
2169 shadows[i]->Bind(); 2185 shadows[i]->Bind();
2170 if (shadows[i]->other_target() == &function_return_) { 2186 frame_->SpillAll();
2187 if (i == kReturnShadowIndex) {
2171 // If this label shadowed the function return, materialize the 2188 // If this label shadowed the function return, materialize the
2172 // return value on the stack. 2189 // return value on the stack.
2173 frame_->EmitPush(r0); 2190 frame_->EmitPush(r0);
2174 } else { 2191 } else {
2175 // Fake TOS for labels that shadowed breaks and continues. 2192 // Fake TOS for targets that shadowed breaks and continues.
2176 __ mov(r0, Operand(Factory::undefined_value())); 2193 __ mov(r0, Operand(Factory::undefined_value()));
2177 frame_->EmitPush(r0); 2194 frame_->EmitPush(r0);
2178 } 2195 }
2179 __ mov(r2, Operand(Smi::FromInt(JUMPING + i))); 2196 __ mov(r2, Operand(Smi::FromInt(JUMPING + i)));
2180 unlink.Jump(); 2197 unlink.Jump();
2181 } 2198 }
2182 } 2199 }
2183 2200
2184 // Unlink from try chain; 2201 // Unlink from try chain;
2185 unlink.Bind(); 2202 unlink.Bind();
2186 2203
2187 frame_->EmitPop(r0); // Store TOS in r0 across stack manipulation 2204 // Preserve TOS result in r0 across stack manipulation.
2205 frame_->EmitPop(r0);
2188 // Reload sp from the top handler, because some statements that we 2206 // Reload sp from the top handler, because some statements that we
2189 // break from (eg, for...in) may have left stuff on the stack. 2207 // break from (eg, for...in) may have left stuff on the stack.
2190 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); 2208 __ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
2191 __ ldr(sp, MemOperand(r3)); 2209 __ ldr(sp, MemOperand(r3));
2192 frame_->Forget(frame_->height() - handler_height); 2210 // The stack pointer was restored to just below the code slot
2211 // (the topmost slot) in the handler.
2212 frame_->Forget(frame_->height() - handler_height + 1);
2193 const int kNextIndex = (StackHandlerConstants::kNextOffset 2213 const int kNextIndex = (StackHandlerConstants::kNextOffset
2194 + StackHandlerConstants::kAddressDisplacement) 2214 + StackHandlerConstants::kAddressDisplacement)
2195 / kPointerSize; 2215 / kPointerSize;
2196 __ ldr(r1, frame_->ElementAt(kNextIndex)); 2216 __ ldr(r1, frame_->ElementAt(kNextIndex));
2197 __ str(r1, MemOperand(r3)); 2217 __ str(r1, MemOperand(r3));
2198 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code 2218 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code
2219 // Drop the rest of the handler (not including the already dropped
2220 // code slot).
2199 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); 2221 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
2200 // Code slot popped. 2222 // Restore the result to TOS.
2201 frame_->Forget(1);
2202 frame_->EmitPush(r0); 2223 frame_->EmitPush(r0);
2203 2224
2204 // --- Finally block --- 2225 // --- Finally block ---
2205 finally_block.Bind(); 2226 finally_block.Bind();
2206 2227
2207 // Push the state on the stack. 2228 // Push the state on the stack.
2208 frame_->EmitPush(r2); 2229 frame_->EmitPush(r2);
2209 2230
2210 // We keep two elements on the stack - the (possibly faked) result 2231 // We keep two elements on the stack - the (possibly faked) result
2211 // and the state - while evaluating the finally block. Record it, so 2232 // and the state - while evaluating the finally block. Record it, so
2212 // that a break/continue crossing this statement can restore the 2233 // that a break/continue crossing this statement can restore the
2213 // stack. 2234 // stack.
2214 const int kFinallyStackSize = 2 * kPointerSize; 2235 const int kFinallyStackSize = 2 * kPointerSize;
2215 break_stack_height_ += kFinallyStackSize; 2236 break_stack_height_ += kFinallyStackSize;
2216 2237
2217 // Generate code for the statements in the finally block. 2238 // Generate code for the statements in the finally block.
2218 VisitStatementsAndSpill(node->finally_block()->statements()); 2239 VisitStatementsAndSpill(node->finally_block()->statements());
2219 2240
2220 break_stack_height_ -= kFinallyStackSize; 2241 break_stack_height_ -= kFinallyStackSize;
2221 if (frame_ != NULL) { 2242 if (has_valid_frame()) {
2222 JumpTarget exit(this); 2243 JumpTarget exit(this);
2223 // Restore state and return value or faked TOS. 2244 // Restore state and return value or faked TOS.
2224 frame_->EmitPop(r2); 2245 frame_->EmitPop(r2);
2225 frame_->EmitPop(r0); 2246 frame_->EmitPop(r0);
2226 2247
2227 // Generate code to jump to the right destination for all used (formerly) 2248 // Generate code to jump to the right destination for all used (formerly)
2228 // shadowing labels. 2249 // shadowing labels.
2229 for (int i = 0; i <= nof_escapes; i++) { 2250 for (int i = 0; i <= nof_escapes; i++) {
2230 if (shadows[i]->is_bound()) { 2251 if (shadows[i]->is_bound()) {
2252 JumpTarget* original = shadows[i]->other_target();
2231 __ cmp(r2, Operand(Smi::FromInt(JUMPING + i))); 2253 __ cmp(r2, Operand(Smi::FromInt(JUMPING + i)));
2232 if (shadows[i]->other_target() != &function_return_) { 2254 if (!function_return_is_shadowed_ && i == kReturnShadowIndex) {
2233 JumpTarget next(this); 2255 JumpTarget skip(this);
2234 next.Branch(ne); 2256 skip.Branch(ne);
2235 shadows[i]->other_target()->Jump(); 2257 frame_->PrepareForReturn();
2236 next.Bind(); 2258 original->Jump();
2259 skip.Bind();
2237 } else { 2260 } else {
2238 shadows[i]->other_target()->Branch(eq); 2261 original->Branch(eq);
2239 } 2262 }
2240 } 2263 }
2241 } 2264 }
2242 2265
2243 // Check if we need to rethrow the exception. 2266 // Check if we need to rethrow the exception.
2244 __ cmp(r2, Operand(Smi::FromInt(THROWING))); 2267 __ cmp(r2, Operand(Smi::FromInt(THROWING)));
2245 exit.Branch(ne); 2268 exit.Branch(ne);
2246 2269
2247 // Rethrow exception. 2270 // Rethrow exception.
2248 frame_->EmitPush(r0); 2271 frame_->EmitPush(r0);
(...skipping 2766 matching lines...) Expand 10 before | Expand all | Expand 10 after
5015 __ mov(r2, Operand(0)); 5038 __ mov(r2, Operand(0));
5016 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); 5039 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
5017 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)), 5040 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)),
5018 RelocInfo::CODE_TARGET); 5041 RelocInfo::CODE_TARGET);
5019 } 5042 }
5020 5043
5021 5044
5022 #undef __ 5045 #undef __
5023 5046
5024 } } // namespace v8::internal 5047 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698