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 1982 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1993 __ jmp(&exit); | 1993 __ jmp(&exit); |
1994 | 1994 |
1995 | 1995 |
1996 // --- Try block --- | 1996 // --- Try block --- |
1997 __ bind(&try_block); | 1997 __ bind(&try_block); |
1998 | 1998 |
1999 __ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER); | 1999 __ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER); |
2000 // TODO(1222589): remove the reliance of PushTryHandler on a cached TOS | 2000 // TODO(1222589): remove the reliance of PushTryHandler on a cached TOS |
2001 frame_->Push(eax); // | 2001 frame_->Push(eax); // |
2002 | 2002 |
2003 // Introduce shadow labels for all escapes from the try block, | 2003 // Shadow the labels for all escapes from the try block, including |
2004 // including returns. We should probably try to unify the escaping | 2004 // returns. During shadowing, the original label is hidden as the |
2005 // labels and the return label. | 2005 // LabelShadow and operations on the original actually affect the |
| 2006 // shadowing label. |
| 2007 // |
| 2008 // We should probably try to unify the escaping labels and the return |
| 2009 // label. |
2006 int nof_escapes = node->escaping_labels()->length(); | 2010 int nof_escapes = node->escaping_labels()->length(); |
2007 List<LabelShadow*> shadows(1 + nof_escapes); | 2011 List<LabelShadow*> shadows(1 + nof_escapes); |
2008 shadows.Add(new LabelShadow(&function_return_)); | 2012 shadows.Add(new LabelShadow(&function_return_)); |
2009 for (int i = 0; i < nof_escapes; i++) { | 2013 for (int i = 0; i < nof_escapes; i++) { |
2010 shadows.Add(new LabelShadow(node->escaping_labels()->at(i))); | 2014 shadows.Add(new LabelShadow(node->escaping_labels()->at(i))); |
2011 } | 2015 } |
2012 | 2016 |
2013 // Generate code for the statements in the try block. | 2017 // Generate code for the statements in the try block. |
2014 bool was_inside_try = is_inside_try_; | 2018 bool was_inside_try = is_inside_try_; |
2015 is_inside_try_ = true; | 2019 is_inside_try_ = true; |
2016 VisitStatements(node->try_block()->statements()); | 2020 VisitStatements(node->try_block()->statements()); |
2017 is_inside_try_ = was_inside_try; | 2021 is_inside_try_ = was_inside_try; |
2018 | 2022 |
2019 // Stop the introduced shadowing and count the number of required unlinks. | 2023 // Stop the introduced shadowing and count the number of required unlinks. |
| 2024 // After shadowing stops, the original labels are unshadowed and the |
| 2025 // LabelShadows represent the formerly shadowing labels. |
2020 int nof_unlinks = 0; | 2026 int nof_unlinks = 0; |
2021 for (int i = 0; i <= nof_escapes; i++) { | 2027 for (int i = 0; i <= nof_escapes; i++) { |
2022 shadows[i]->StopShadowing(); | 2028 shadows[i]->StopShadowing(); |
2023 if (shadows[i]->is_linked()) nof_unlinks++; | 2029 if (shadows[i]->is_linked()) nof_unlinks++; |
2024 } | 2030 } |
2025 | 2031 |
2026 // Get an external reference to the handler address. | 2032 // Get an external reference to the handler address. |
2027 ExternalReference handler_address(Top::k_handler_address); | 2033 ExternalReference handler_address(Top::k_handler_address); |
2028 | 2034 |
2029 // Make sure that there's nothing left on the stack above the | 2035 // Make sure that there's nothing left on the stack above the |
2030 // handler structure. | 2036 // handler structure. |
2031 if (FLAG_debug_code) { | 2037 if (FLAG_debug_code) { |
2032 __ mov(eax, Operand::StaticVariable(handler_address)); | 2038 __ mov(eax, Operand::StaticVariable(handler_address)); |
2033 __ lea(eax, Operand(eax, StackHandlerConstants::kAddressDisplacement)); | 2039 __ lea(eax, Operand(eax, StackHandlerConstants::kAddressDisplacement)); |
2034 __ cmp(esp, Operand(eax)); | 2040 __ cmp(esp, Operand(eax)); |
2035 __ Assert(equal, "stack pointer should point to top handler"); | 2041 __ Assert(equal, "stack pointer should point to top handler"); |
2036 } | 2042 } |
2037 | 2043 |
2038 // Unlink from try chain. | 2044 // Unlink from try chain. |
2039 frame_->Pop(eax); | 2045 frame_->Pop(eax); |
2040 __ mov(Operand::StaticVariable(handler_address), eax); // TOS == next_sp | 2046 __ mov(Operand::StaticVariable(handler_address), eax); // TOS == next_sp |
2041 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); | 2047 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); |
2042 // next_sp popped. | 2048 // next_sp popped. |
2043 if (nof_unlinks > 0) __ jmp(&exit); | 2049 if (nof_unlinks > 0) __ jmp(&exit); |
2044 | 2050 |
2045 // Generate unlink code for all used shadow labels. | 2051 // Generate unlink code for the (formerly) shadowing labels that have been |
| 2052 // jumped to. |
2046 for (int i = 0; i <= nof_escapes; i++) { | 2053 for (int i = 0; i <= nof_escapes; i++) { |
2047 if (shadows[i]->is_linked()) { | 2054 if (shadows[i]->is_linked()) { |
2048 // Unlink from try chain; be careful not to destroy the TOS. | 2055 // Unlink from try chain; be careful not to destroy the TOS. |
2049 __ bind(shadows[i]); | 2056 __ bind(shadows[i]); |
2050 | 2057 |
2051 // Reload sp from the top handler, because some statements that we | 2058 // Reload sp from the top handler, because some statements that we |
2052 // break from (eg, for...in) may have left stuff on the stack. | 2059 // break from (eg, for...in) may have left stuff on the stack. |
2053 __ mov(edx, Operand::StaticVariable(handler_address)); | 2060 __ mov(edx, Operand::StaticVariable(handler_address)); |
2054 const int kNextOffset = StackHandlerConstants::kNextOffset + | 2061 const int kNextOffset = StackHandlerConstants::kNextOffset + |
2055 StackHandlerConstants::kAddressDisplacement; | 2062 StackHandlerConstants::kAddressDisplacement; |
2056 __ lea(esp, Operand(edx, kNextOffset)); | 2063 __ lea(esp, Operand(edx, kNextOffset)); |
2057 | 2064 |
2058 frame_->Pop(Operand::StaticVariable(handler_address)); | 2065 frame_->Pop(Operand::StaticVariable(handler_address)); |
2059 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); | 2066 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); |
2060 // next_sp popped. | 2067 // next_sp popped. |
2061 __ jmp(shadows[i]->shadowed()); | 2068 __ jmp(shadows[i]->original_label()); |
2062 } | 2069 } |
2063 } | 2070 } |
2064 | 2071 |
2065 __ bind(&exit); | 2072 __ bind(&exit); |
2066 } | 2073 } |
2067 | 2074 |
2068 | 2075 |
2069 void CodeGenerator::VisitTryFinally(TryFinally* node) { | 2076 void CodeGenerator::VisitTryFinally(TryFinally* node) { |
2070 Comment cmnt(masm_, "[ TryFinally"); | 2077 Comment cmnt(masm_, "[ TryFinally"); |
2071 | 2078 |
(...skipping 12 matching lines...) Expand all Loading... |
2084 __ jmp(&finally_block); | 2091 __ jmp(&finally_block); |
2085 | 2092 |
2086 | 2093 |
2087 // --- Try block --- | 2094 // --- Try block --- |
2088 __ bind(&try_block); | 2095 __ bind(&try_block); |
2089 | 2096 |
2090 __ PushTryHandler(IN_JAVASCRIPT, TRY_FINALLY_HANDLER); | 2097 __ PushTryHandler(IN_JAVASCRIPT, TRY_FINALLY_HANDLER); |
2091 // TODO(1222589): remove the reliance of PushTryHandler on a cached TOS | 2098 // TODO(1222589): remove the reliance of PushTryHandler on a cached TOS |
2092 frame_->Push(eax); | 2099 frame_->Push(eax); |
2093 | 2100 |
2094 // Introduce shadow labels for all escapes from the try block, | 2101 // Shadow the labels for all escapes from the try block, including |
2095 // including returns. We should probably try to unify the escaping | 2102 // returns. Shadowing hides the original label as the LabelShadow and |
2096 // labels and the return label. | 2103 // operations on the original actually affect the shadowing label. |
| 2104 // |
| 2105 // We should probably try to unify the escaping labels and the return |
| 2106 // label. |
2097 int nof_escapes = node->escaping_labels()->length(); | 2107 int nof_escapes = node->escaping_labels()->length(); |
2098 List<LabelShadow*> shadows(1 + nof_escapes); | 2108 List<LabelShadow*> shadows(1 + nof_escapes); |
2099 shadows.Add(new LabelShadow(&function_return_)); | 2109 shadows.Add(new LabelShadow(&function_return_)); |
2100 for (int i = 0; i < nof_escapes; i++) { | 2110 for (int i = 0; i < nof_escapes; i++) { |
2101 shadows.Add(new LabelShadow(node->escaping_labels()->at(i))); | 2111 shadows.Add(new LabelShadow(node->escaping_labels()->at(i))); |
2102 } | 2112 } |
2103 | 2113 |
2104 // Generate code for the statements in the try block. | 2114 // Generate code for the statements in the try block. |
2105 bool was_inside_try = is_inside_try_; | 2115 bool was_inside_try = is_inside_try_; |
2106 is_inside_try_ = true; | 2116 is_inside_try_ = true; |
2107 VisitStatements(node->try_block()->statements()); | 2117 VisitStatements(node->try_block()->statements()); |
2108 is_inside_try_ = was_inside_try; | 2118 is_inside_try_ = was_inside_try; |
2109 | 2119 |
2110 // Stop the introduced shadowing and count the number of required | 2120 // Stop the introduced shadowing and count the number of required unlinks. |
2111 // unlinks. | 2121 // After shadowing stops, the original labels are unshadowed and the |
| 2122 // LabelShadows represent the formerly shadowing labels. |
2112 int nof_unlinks = 0; | 2123 int nof_unlinks = 0; |
2113 for (int i = 0; i <= nof_escapes; i++) { | 2124 for (int i = 0; i <= nof_escapes; i++) { |
2114 shadows[i]->StopShadowing(); | 2125 shadows[i]->StopShadowing(); |
2115 if (shadows[i]->is_linked()) nof_unlinks++; | 2126 if (shadows[i]->is_linked()) nof_unlinks++; |
2116 } | 2127 } |
2117 | 2128 |
2118 // Set the state on the stack to FALLING. | 2129 // Set the state on the stack to FALLING. |
2119 frame_->Push(Immediate(Factory::undefined_value())); // fake TOS | 2130 frame_->Push(Immediate(Factory::undefined_value())); // fake TOS |
2120 __ Set(ecx, Immediate(Smi::FromInt(FALLING))); | 2131 __ Set(ecx, Immediate(Smi::FromInt(FALLING))); |
2121 if (nof_unlinks > 0) __ jmp(&unlink); | 2132 if (nof_unlinks > 0) __ jmp(&unlink); |
2122 | 2133 |
2123 // Generate code that sets the state for all used shadow labels. | 2134 // Generate code to set the state for the (formerly) shadowing labels that |
| 2135 // have been jumped to. |
2124 for (int i = 0; i <= nof_escapes; i++) { | 2136 for (int i = 0; i <= nof_escapes; i++) { |
2125 if (shadows[i]->is_linked()) { | 2137 if (shadows[i]->is_linked()) { |
2126 __ bind(shadows[i]); | 2138 __ bind(shadows[i]); |
2127 if (shadows[i]->shadowed() == &function_return_) { | 2139 if (shadows[i]->original_label() == &function_return_) { |
2128 // Materialize the return value on the stack. | 2140 // If this label shadowed the function return, materialize the |
| 2141 // return value on the stack. |
2129 frame_->Push(eax); | 2142 frame_->Push(eax); |
2130 } else { | 2143 } else { |
2131 // Fake TOS for break and continue. | 2144 // Fake TOS for labels that shadowed breaks and continues. |
2132 frame_->Push(Immediate(Factory::undefined_value())); | 2145 frame_->Push(Immediate(Factory::undefined_value())); |
2133 } | 2146 } |
2134 __ Set(ecx, Immediate(Smi::FromInt(JUMPING + i))); | 2147 __ Set(ecx, Immediate(Smi::FromInt(JUMPING + i))); |
2135 __ jmp(&unlink); | 2148 __ jmp(&unlink); |
2136 } | 2149 } |
2137 } | 2150 } |
2138 | 2151 |
2139 // Unlink from try chain; be careful not to destroy the TOS. | 2152 // Unlink from try chain; be careful not to destroy the TOS. |
2140 __ bind(&unlink); | 2153 __ bind(&unlink); |
2141 // Reload sp from the top handler, because some statements that we | 2154 // Reload sp from the top handler, because some statements that we |
(...skipping 26 matching lines...) Expand all Loading... |
2168 break_stack_height_ += kFinallyStackSize; | 2181 break_stack_height_ += kFinallyStackSize; |
2169 | 2182 |
2170 // Generate code for the statements in the finally block. | 2183 // Generate code for the statements in the finally block. |
2171 VisitStatements(node->finally_block()->statements()); | 2184 VisitStatements(node->finally_block()->statements()); |
2172 | 2185 |
2173 // Restore state and return value or faked TOS. | 2186 // Restore state and return value or faked TOS. |
2174 frame_->Pop(ecx); | 2187 frame_->Pop(ecx); |
2175 frame_->Pop(eax); | 2188 frame_->Pop(eax); |
2176 break_stack_height_ -= kFinallyStackSize; | 2189 break_stack_height_ -= kFinallyStackSize; |
2177 | 2190 |
2178 // Generate code that jumps to the right destination for all used | 2191 // Generate code to jump to the right destination for all used (formerly) |
2179 // shadow labels. | 2192 // shadowing labels. |
2180 for (int i = 0; i <= nof_escapes; i++) { | 2193 for (int i = 0; i <= nof_escapes; i++) { |
2181 if (shadows[i]->is_bound()) { | 2194 if (shadows[i]->is_bound()) { |
2182 __ cmp(Operand(ecx), Immediate(Smi::FromInt(JUMPING + i))); | 2195 __ cmp(Operand(ecx), Immediate(Smi::FromInt(JUMPING + i))); |
2183 __ j(equal, shadows[i]->shadowed()); | 2196 __ j(equal, shadows[i]->original_label()); |
2184 } | 2197 } |
2185 } | 2198 } |
2186 | 2199 |
2187 // Check if we need to rethrow the exception. | 2200 // Check if we need to rethrow the exception. |
2188 __ cmp(Operand(ecx), Immediate(Smi::FromInt(THROWING))); | 2201 __ cmp(Operand(ecx), Immediate(Smi::FromInt(THROWING))); |
2189 __ j(not_equal, &exit); | 2202 __ j(not_equal, &exit); |
2190 | 2203 |
2191 // Rethrow exception. | 2204 // Rethrow exception. |
2192 frame_->Push(eax); // undo pop from above | 2205 frame_->Push(eax); // undo pop from above |
2193 __ CallRuntime(Runtime::kReThrow, 1); | 2206 __ CallRuntime(Runtime::kReThrow, 1); |
(...skipping 2903 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5097 | 5110 |
5098 // Slow-case: Go through the JavaScript implementation. | 5111 // Slow-case: Go through the JavaScript implementation. |
5099 __ bind(&slow); | 5112 __ bind(&slow); |
5100 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 5113 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
5101 } | 5114 } |
5102 | 5115 |
5103 | 5116 |
5104 #undef __ | 5117 #undef __ |
5105 | 5118 |
5106 } } // namespace v8::internal | 5119 } } // namespace v8::internal |
OLD | NEW |