| 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 |