| 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 1571 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1582 Vector<JumpTarget*> case_targets, | 1582 Vector<JumpTarget*> case_targets, |
| 1583 Vector<JumpTarget> case_labels) { | 1583 Vector<JumpTarget> case_labels) { |
| 1584 // Notice: Internal references, used by both the jmp instruction and | 1584 // Notice: Internal references, used by both the jmp instruction and |
| 1585 // the table entries, need to be relocated if the buffer grows. This | 1585 // the table entries, need to be relocated if the buffer grows. This |
| 1586 // prevents the forward use of Labels, since a displacement cannot | 1586 // prevents the forward use of Labels, since a displacement cannot |
| 1587 // survive relocation, and it also cannot safely be distinguished | 1587 // survive relocation, and it also cannot safely be distinguished |
| 1588 // from a real address. Instead we put in zero-values as | 1588 // from a real address. Instead we put in zero-values as |
| 1589 // placeholders, and fill in the addresses after the labels have been | 1589 // placeholders, and fill in the addresses after the labels have been |
| 1590 // bound. | 1590 // bound. |
| 1591 | 1591 |
| 1592 frame_->Pop(eax); // supposed smi | 1592 frame_->Pop(eax); // supposed Smi |
| 1593 // check range of value, if outside [0..length-1] jump to default/end label. | 1593 // check range of value, if outside [0..length-1] jump to default/end label. |
| 1594 ASSERT(kSmiTagSize == 1 && kSmiTag == 0); | 1594 ASSERT(kSmiTagSize == 1 && kSmiTag == 0); |
| 1595 |
| 1596 // Test whether input is a HeapNumber that is really a Smi |
| 1597 JumpTarget is_smi(this); |
| 1598 __ test(eax, Immediate(kSmiTagMask)); |
| 1599 is_smi.Branch(equal); |
| 1600 // It's a heap object, not a Smi or a Failure |
| 1601 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 1602 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
| 1603 __ cmp(ebx, HEAP_NUMBER_TYPE); |
| 1604 fail_label->Branch(not_equal); |
| 1605 // eax points to a heap number. |
| 1606 __ push(eax); |
| 1607 __ CallRuntime(Runtime::kNumberToSmi, 1); |
| 1608 is_smi.Bind(); |
| 1609 |
| 1595 if (min_index != 0) { | 1610 if (min_index != 0) { |
| 1596 __ sub(Operand(eax), Immediate(min_index << kSmiTagSize)); | 1611 __ sub(Operand(eax), Immediate(min_index << kSmiTagSize)); |
| 1597 } | 1612 } |
| 1598 __ test(eax, Immediate(0x80000000 | kSmiTagMask)); // negative or not Smi | 1613 __ test(eax, Immediate(0x80000000 | kSmiTagMask)); // negative or not Smi |
| 1599 fail_label->Branch(not_equal, not_taken); | 1614 fail_label->Branch(not_equal, not_taken); |
| 1600 __ cmp(eax, range << kSmiTagSize); | 1615 __ cmp(eax, range << kSmiTagSize); |
| 1601 fail_label->Branch(greater_equal, not_taken); | 1616 fail_label->Branch(greater_equal, not_taken); |
| 1602 | 1617 |
| 1603 // 0 is placeholder. | 1618 // 0 is placeholder. |
| 1604 __ jmp(Operand(eax, times_2, 0x0, RelocInfo::INTERNAL_REFERENCE)); | 1619 __ jmp(Operand(eax, times_2, 0x0, RelocInfo::INTERNAL_REFERENCE)); |
| (...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2112 exit.Jump(); | 2127 exit.Jump(); |
| 2113 } | 2128 } |
| 2114 | 2129 |
| 2115 | 2130 |
| 2116 // --- Try block --- | 2131 // --- Try block --- |
| 2117 try_block.Bind(); | 2132 try_block.Bind(); |
| 2118 | 2133 |
| 2119 frame_->PushTryHandler(TRY_CATCH_HANDLER); | 2134 frame_->PushTryHandler(TRY_CATCH_HANDLER); |
| 2120 int handler_height = frame_->height(); | 2135 int handler_height = frame_->height(); |
| 2121 | 2136 |
| 2122 // Shadow the labels for all escapes from the try block, including | 2137 // Shadow the jump targets for all escapes from the try block, including |
| 2123 // returns. During shadowing, the original label is hidden as the | 2138 // returns. During shadowing, the original target is hidden as the |
| 2124 // LabelShadow and operations on the original actually affect the | 2139 // ShadowTarget and operations on the original actually affect the |
| 2125 // shadowing label. | 2140 // shadowing target. |
| 2126 // | 2141 // |
| 2127 // We should probably try to unify the escaping labels and the return | 2142 // We should probably try to unify the escaping targets and the return |
| 2128 // label. | 2143 // target. |
| 2129 int nof_escapes = node->escaping_targets()->length(); | 2144 int nof_escapes = node->escaping_targets()->length(); |
| 2130 List<ShadowTarget*> shadows(1 + nof_escapes); | 2145 List<ShadowTarget*> shadows(1 + nof_escapes); |
| 2131 shadows.Add(new ShadowTarget(&function_return_)); | 2146 shadows.Add(new ShadowTarget(&function_return_)); |
| 2132 for (int i = 0; i < nof_escapes; i++) { | 2147 for (int i = 0; i < nof_escapes; i++) { |
| 2133 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); | 2148 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); |
| 2134 } | 2149 } |
| 2135 bool function_return_was_shadowed = function_return_is_shadowed_; | 2150 bool function_return_was_shadowed = function_return_is_shadowed_; |
| 2136 function_return_is_shadowed_ = true; | 2151 function_return_is_shadowed_ = true; |
| 2137 | 2152 |
| 2138 // Generate code for the statements in the try block. | 2153 // Generate code for the statements in the try block. |
| 2139 bool was_inside_try = is_inside_try_; | 2154 bool was_inside_try = is_inside_try_; |
| 2140 is_inside_try_ = true; | 2155 is_inside_try_ = true; |
| 2141 VisitStatements(node->try_block()->statements()); | 2156 VisitStatements(node->try_block()->statements()); |
| 2142 is_inside_try_ = was_inside_try; | 2157 is_inside_try_ = was_inside_try; |
| 2143 | 2158 |
| 2144 // Stop the introduced shadowing and count the number of required unlinks. | 2159 // Stop the introduced shadowing and count the number of required unlinks. |
| 2145 // After shadowing stops, the original labels are unshadowed and the | 2160 // After shadowing stops, the original targets are unshadowed and the |
| 2146 // LabelShadows represent the formerly shadowing labels. | 2161 // ShadowTargets represent the formerly shadowing targets. |
| 2147 int nof_unlinks = 0; | 2162 int nof_unlinks = 0; |
| 2148 for (int i = 0; i <= nof_escapes; i++) { | 2163 for (int i = 0; i <= nof_escapes; i++) { |
| 2149 shadows[i]->StopShadowing(); | 2164 shadows[i]->StopShadowing(); |
| 2150 if (shadows[i]->is_linked()) nof_unlinks++; | 2165 if (shadows[i]->is_linked()) nof_unlinks++; |
| 2151 } | 2166 } |
| 2152 function_return_is_shadowed_ = function_return_was_shadowed; | 2167 function_return_is_shadowed_ = function_return_was_shadowed; |
| 2153 | 2168 |
| 2154 // Get an external reference to the handler address. | 2169 // Get an external reference to the handler address. |
| 2155 ExternalReference handler_address(Top::k_handler_address); | 2170 ExternalReference handler_address(Top::k_handler_address); |
| 2156 | 2171 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2167 if (frame_ != NULL) { | 2182 if (frame_ != NULL) { |
| 2168 frame_->Pop(eax); | 2183 frame_->Pop(eax); |
| 2169 __ mov(Operand::StaticVariable(handler_address), eax); // TOS == next_sp | 2184 __ mov(Operand::StaticVariable(handler_address), eax); // TOS == next_sp |
| 2170 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); | 2185 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); |
| 2171 // next_sp popped. | 2186 // next_sp popped. |
| 2172 if (nof_unlinks > 0) { | 2187 if (nof_unlinks > 0) { |
| 2173 exit.Jump(); | 2188 exit.Jump(); |
| 2174 } | 2189 } |
| 2175 } | 2190 } |
| 2176 | 2191 |
| 2177 // Generate unlink code for the (formerly) shadowing labels that have been | 2192 // Generate unlink code for the (formerly) shadowing targets that have been |
| 2178 // jumped to. | 2193 // jumped to. |
| 2179 for (int i = 0; i <= nof_escapes; i++) { | 2194 for (int i = 0; i <= nof_escapes; i++) { |
| 2180 if (shadows[i]->is_linked()) { | 2195 if (shadows[i]->is_linked()) { |
| 2181 // Unlink from try chain; be careful not to destroy the TOS. | 2196 // Unlink from try chain; be careful not to destroy the TOS. |
| 2182 shadows[i]->Bind(); | 2197 shadows[i]->Bind(); |
| 2183 | 2198 |
| 2184 // Reload sp from the top handler, because some statements that we | 2199 // Reload sp from the top handler, because some statements that we |
| 2185 // break from (eg, for...in) may have left stuff on the stack. | 2200 // break from (eg, for...in) may have left stuff on the stack. |
| 2186 __ mov(edx, Operand::StaticVariable(handler_address)); | 2201 __ mov(edx, Operand::StaticVariable(handler_address)); |
| 2187 const int kNextOffset = StackHandlerConstants::kNextOffset + | 2202 const int kNextOffset = StackHandlerConstants::kNextOffset + |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2221 __ Set(ecx, Immediate(Smi::FromInt(THROWING))); | 2236 __ Set(ecx, Immediate(Smi::FromInt(THROWING))); |
| 2222 finally_block.Jump(); | 2237 finally_block.Jump(); |
| 2223 | 2238 |
| 2224 | 2239 |
| 2225 // --- Try block --- | 2240 // --- Try block --- |
| 2226 try_block.Bind(); | 2241 try_block.Bind(); |
| 2227 | 2242 |
| 2228 frame_->PushTryHandler(TRY_FINALLY_HANDLER); | 2243 frame_->PushTryHandler(TRY_FINALLY_HANDLER); |
| 2229 int handler_height = frame_->height(); | 2244 int handler_height = frame_->height(); |
| 2230 | 2245 |
| 2231 // Shadow the labels for all escapes from the try block, including | 2246 // Shadow the jump targets for all escapes from the try block, including |
| 2232 // returns. During shadowing, the original label is hidden as the | 2247 // returns. During shadowing, the original target is hidden as the |
| 2233 // LabelShadow and operations on the original actually affect the | 2248 // ShadowTarget and operations on the original actually affect the |
| 2234 // shadowing label. | 2249 // shadowing target. |
| 2235 // | 2250 // |
| 2236 // We should probably try to unify the escaping labels and the return | 2251 // We should probably try to unify the escaping targets and the return |
| 2237 // label. | 2252 // target. |
| 2238 int nof_escapes = node->escaping_targets()->length(); | 2253 int nof_escapes = node->escaping_targets()->length(); |
| 2239 List<ShadowTarget*> shadows(1 + nof_escapes); | 2254 List<ShadowTarget*> shadows(1 + nof_escapes); |
| 2240 shadows.Add(new ShadowTarget(&function_return_)); | 2255 shadows.Add(new ShadowTarget(&function_return_)); |
| 2241 for (int i = 0; i < nof_escapes; i++) { | 2256 for (int i = 0; i < nof_escapes; i++) { |
| 2242 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); | 2257 shadows.Add(new ShadowTarget(node->escaping_targets()->at(i))); |
| 2243 } | 2258 } |
| 2244 bool function_return_was_shadowed = function_return_is_shadowed_; | 2259 bool function_return_was_shadowed = function_return_is_shadowed_; |
| 2245 function_return_is_shadowed_ = true; | 2260 function_return_is_shadowed_ = true; |
| 2246 | 2261 |
| 2247 // Generate code for the statements in the try block. | 2262 // Generate code for the statements in the try block. |
| 2248 bool was_inside_try = is_inside_try_; | 2263 bool was_inside_try = is_inside_try_; |
| 2249 is_inside_try_ = true; | 2264 is_inside_try_ = true; |
| 2250 VisitStatements(node->try_block()->statements()); | 2265 VisitStatements(node->try_block()->statements()); |
| 2251 is_inside_try_ = was_inside_try; | 2266 is_inside_try_ = was_inside_try; |
| 2252 | 2267 |
| 2253 // Stop the introduced shadowing and count the number of required unlinks. | 2268 // Stop the introduced shadowing and count the number of required unlinks. |
| 2254 // After shadowing stops, the original labels are unshadowed and the | 2269 // After shadowing stops, the original targets are unshadowed and the |
| 2255 // LabelShadows represent the formerly shadowing labels. | 2270 // ShadowTargets represent the formerly shadowing targets. |
| 2256 int nof_unlinks = 0; | 2271 int nof_unlinks = 0; |
| 2257 for (int i = 0; i <= nof_escapes; i++) { | 2272 for (int i = 0; i <= nof_escapes; i++) { |
| 2258 shadows[i]->StopShadowing(); | 2273 shadows[i]->StopShadowing(); |
| 2259 if (shadows[i]->is_linked()) nof_unlinks++; | 2274 if (shadows[i]->is_linked()) nof_unlinks++; |
| 2260 } | 2275 } |
| 2261 function_return_is_shadowed_ = function_return_was_shadowed; | 2276 function_return_is_shadowed_ = function_return_was_shadowed; |
| 2262 | 2277 |
| 2263 // If we can fall off the end of the try block, set the state on the stack | 2278 // If we can fall off the end of the try block, set the state on the stack |
| 2264 // to FALLING. | 2279 // to FALLING. |
| 2265 if (frame_ != NULL) { | 2280 if (frame_ != NULL) { |
| 2266 frame_->Push(Immediate(Factory::undefined_value())); // fake TOS | 2281 frame_->Push(Immediate(Factory::undefined_value())); // fake TOS |
| 2267 __ Set(ecx, Immediate(Smi::FromInt(FALLING))); | 2282 __ Set(ecx, Immediate(Smi::FromInt(FALLING))); |
| 2268 if (nof_unlinks > 0) { | 2283 if (nof_unlinks > 0) { |
| 2269 unlink.Jump(); | 2284 unlink.Jump(); |
| 2270 } | 2285 } |
| 2271 } | 2286 } |
| 2272 | 2287 |
| 2273 // Generate code to set the state for the (formerly) shadowing labels that | 2288 // Generate code to set the state for the (formerly) shadowing targets that |
| 2274 // have been jumped to. | 2289 // have been jumped to. |
| 2275 for (int i = 0; i <= nof_escapes; i++) { | 2290 for (int i = 0; i <= nof_escapes; i++) { |
| 2276 if (shadows[i]->is_linked()) { | 2291 if (shadows[i]->is_linked()) { |
| 2277 shadows[i]->Bind(); | 2292 shadows[i]->Bind(); |
| 2278 if (shadows[i]->original_target() == &function_return_) { | 2293 if (shadows[i]->original_target() == &function_return_) { |
| 2279 // If this label shadowed the function return, materialize the | 2294 // If this target shadowed the function return, materialize the |
| 2280 // return value on the stack. | 2295 // return value on the stack. |
| 2281 frame_->Push(eax); | 2296 frame_->Push(eax); |
| 2282 } else { | 2297 } else { |
| 2283 // Fake TOS for labels that shadowed breaks and continues. | 2298 // Fake TOS for targets that shadowed breaks and continues. |
| 2284 frame_->Push(Immediate(Factory::undefined_value())); | 2299 frame_->Push(Immediate(Factory::undefined_value())); |
| 2285 } | 2300 } |
| 2286 __ Set(ecx, Immediate(Smi::FromInt(JUMPING + i))); | 2301 __ Set(ecx, Immediate(Smi::FromInt(JUMPING + i))); |
| 2287 unlink.Jump(); | 2302 unlink.Jump(); |
| 2288 } | 2303 } |
| 2289 } | 2304 } |
| 2290 | 2305 |
| 2291 // Unlink from try chain; be careful not to destroy the TOS. | 2306 // Unlink from try chain; be careful not to destroy the TOS. |
| 2292 unlink.Bind(); | 2307 unlink.Bind(); |
| 2293 // Reload sp from the top handler, because some statements that we | 2308 // Reload sp from the top handler, because some statements that we |
| (...skipping 29 matching lines...) Expand all Loading... |
| 2323 // Generate code for the statements in the finally block. | 2338 // Generate code for the statements in the finally block. |
| 2324 VisitStatements(node->finally_block()->statements()); | 2339 VisitStatements(node->finally_block()->statements()); |
| 2325 | 2340 |
| 2326 break_stack_height_ -= kFinallyStackSize; | 2341 break_stack_height_ -= kFinallyStackSize; |
| 2327 if (frame_ != NULL) { | 2342 if (frame_ != NULL) { |
| 2328 // Restore state and return value or faked TOS. | 2343 // Restore state and return value or faked TOS. |
| 2329 frame_->Pop(ecx); | 2344 frame_->Pop(ecx); |
| 2330 frame_->Pop(eax); | 2345 frame_->Pop(eax); |
| 2331 | 2346 |
| 2332 // Generate code to jump to the right destination for all used | 2347 // Generate code to jump to the right destination for all used |
| 2333 // (formerly) shadowing labels. | 2348 // (formerly) shadowing targets. |
| 2334 for (int i = 0; i <= nof_escapes; i++) { | 2349 for (int i = 0; i <= nof_escapes; i++) { |
| 2335 if (shadows[i]->is_bound()) { | 2350 if (shadows[i]->is_bound()) { |
| 2336 __ cmp(Operand(ecx), Immediate(Smi::FromInt(JUMPING + i))); | 2351 __ cmp(Operand(ecx), Immediate(Smi::FromInt(JUMPING + i))); |
| 2337 shadows[i]->original_target()->Branch(equal); | 2352 shadows[i]->original_target()->Branch(equal); |
| 2338 } | 2353 } |
| 2339 } | 2354 } |
| 2340 | 2355 |
| 2341 // Check if we need to rethrow the exception. | 2356 // Check if we need to rethrow the exception. |
| 2342 __ cmp(Operand(ecx), Immediate(Smi::FromInt(THROWING))); | 2357 __ cmp(Operand(ecx), Immediate(Smi::FromInt(THROWING))); |
| 2343 exit.Branch(not_equal); | 2358 exit.Branch(not_equal); |
| (...skipping 2971 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5315 | 5330 |
| 5316 // Slow-case: Go through the JavaScript implementation. | 5331 // Slow-case: Go through the JavaScript implementation. |
| 5317 __ bind(&slow); | 5332 __ bind(&slow); |
| 5318 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 5333 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
| 5319 } | 5334 } |
| 5320 | 5335 |
| 5321 | 5336 |
| 5322 #undef __ | 5337 #undef __ |
| 5323 | 5338 |
| 5324 } } // namespace v8::internal | 5339 } } // namespace v8::internal |
| OLD | NEW |