Chromium Code Reviews| 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 2231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2242 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); | 2242 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); |
| 2243 } | 2243 } |
| 2244 if (node->break_target()->is_linked()) { | 2244 if (node->break_target()->is_linked()) { |
| 2245 node->break_target()->Bind(); | 2245 node->break_target()->Bind(); |
| 2246 } | 2246 } |
| 2247 } | 2247 } |
| 2248 break; | 2248 break; |
| 2249 } | 2249 } |
| 2250 | 2250 |
| 2251 case LoopStatement::WHILE_LOOP: { | 2251 case LoopStatement::WHILE_LOOP: { |
| 2252 JumpTarget body(this, JumpTarget::BIDIRECTIONAL); | |
| 2252 IncrementLoopNesting(); | 2253 IncrementLoopNesting(); |
| 2253 | 2254 |
| 2254 // If the test is never true and has no side effects there is no need | 2255 // Based on the condition analysis, compile the test if |
| 2255 // to compile the test or body. | 2256 // necessary and label the body if necessary. |
| 2256 if (info == ALWAYS_FALSE) break; | 2257 if (info == ALWAYS_TRUE) { |
| 2258 // We will not compile the test expression. Label the top of | |
| 2259 // the loop with the continue target. | |
| 2260 node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL); | |
| 2261 node->continue_target()->Bind(); | |
| 2262 } else if (info == ALWAYS_FALSE) { | |
|
Kasper Lund
2009/02/24 08:52:55
I actually preferred to have this as a separate ch
Kevin Millikin (Chromium)
2009/02/24 08:56:32
Easily done.
| |
| 2263 // We will not compile the test or the body. Nothing is | |
| 2264 // labeled. | |
| 2265 break; | |
| 2266 } else { | |
| 2267 ASSERT(info == DONT_KNOW); | |
| 2268 node->continue_target()->Initialize(this); | |
| 2269 // Compile the test with the body as the true target and | |
| 2270 // preferred fall-through and with the break target as the | |
| 2271 // false target. | |
| 2272 ControlDestination dest(&body, node->break_target(), true); | |
| 2273 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); | |
| 2257 | 2274 |
| 2258 // Label the top of the loop with the continue target for the backward | 2275 if (dest.false_was_fall_through()) { |
| 2259 // CFG edge. | 2276 // If we don't have dangling jumps to the body, the test is |
| 2260 node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL); | 2277 // unconditionally false and we do not need to compile the |
| 2261 node->continue_target()->Bind(); | 2278 // body. |
| 2279 if (!body.is_linked()) break; | |
| 2262 | 2280 |
| 2263 // If the test is always true and has no side effects there is no need | 2281 // Otherwise, jump around the body on the fall through and |
| 2264 // to compile it. We only compile the test when we do not know its | 2282 // then bind the body target. |
| 2265 // outcome or it may have side effects. | 2283 node->break_target()->Unuse(); |
| 2266 JumpTarget body(this); | 2284 node->break_target()->Jump(); |
| 2267 ControlDestination dest(&body, node->break_target(), true); | 2285 body.Bind(); |
| 2268 if (info == DONT_KNOW) { | 2286 } |
| 2269 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); | |
| 2270 } | 2287 } |
| 2271 | 2288 |
| 2272 if (dest.false_was_fall_through()) { | 2289 // The (stack check at the start of the) body was labeled. |
| 2273 // The break target was bound. We may have dangling jumps to | 2290 // Compile it. |
| 2274 // the body. | |
| 2275 if (!body.is_linked()) break; | |
| 2276 | |
| 2277 // We have dangling jumps to the body target. | |
| 2278 node->break_target()->Unuse(); | |
| 2279 node->break_target()->Jump(); | |
| 2280 body.Bind(); | |
| 2281 } | |
| 2282 | |
| 2283 // The body target has just been bound or else we didn't compile | |
| 2284 // the test. | |
| 2285 CheckStack(); // TODO(1222600): ignore if body contains calls. | 2291 CheckStack(); // TODO(1222600): ignore if body contains calls. |
| 2286 Visit(node->body()); | 2292 Visit(node->body()); |
| 2287 | 2293 |
| 2288 // If control flow can fall out of the body, jump back to the top. | 2294 // Compile the test if necessary and jump back. |
| 2289 if (has_valid_frame()) { | 2295 if (info == ALWAYS_TRUE) { |
| 2290 node->continue_target()->Jump(); | 2296 // The body has been labeled with the continue target. |
| 2297 if (has_valid_frame()) { | |
| 2298 node->continue_target()->Jump(); | |
| 2299 } | |
| 2300 } else { | |
| 2301 ASSERT(info == DONT_KNOW); // ALWAYS_FALSE cannot reach here. | |
| 2302 if (node->continue_target()->is_linked()) { | |
| 2303 node->continue_target()->Bind(); | |
| 2304 } | |
| 2305 | |
| 2306 // If control can reach the bottom by falling off the body or | |
| 2307 // a continue in the body, (re)compile the test at the bottom. | |
| 2308 if (has_valid_frame()) { | |
| 2309 // The break target is the fall-through (body is a backward | |
| 2310 // jump from here). | |
| 2311 ControlDestination dest(&body, node->break_target(), false); | |
| 2312 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); | |
| 2313 } | |
| 2291 } | 2314 } |
| 2315 | |
| 2316 // The break target may be already bound (by the condition), or | |
| 2317 // there may not be a valid frame. Bind it only if needed. | |
| 2292 if (node->break_target()->is_linked()) { | 2318 if (node->break_target()->is_linked()) { |
| 2293 node->break_target()->Bind(); | 2319 node->break_target()->Bind(); |
| 2294 } | 2320 } |
| 2295 break; | 2321 break; |
| 2296 } | 2322 } |
| 2297 | 2323 |
| 2298 case LoopStatement::FOR_LOOP: { | 2324 case LoopStatement::FOR_LOOP: { |
| 2299 JumpTarget loop(this, JumpTarget::BIDIRECTIONAL); | 2325 JumpTarget body(this, JumpTarget::BIDIRECTIONAL); |
| 2326 | |
| 2327 // Compile the init expression if present. | |
| 2300 if (node->init() != NULL) { | 2328 if (node->init() != NULL) { |
| 2301 Visit(node->init()); | 2329 Visit(node->init()); |
| 2302 } | 2330 } |
| 2303 | 2331 |
| 2304 IncrementLoopNesting(); | 2332 IncrementLoopNesting(); |
| 2305 // If the test is never true and has no side effects there is no need | |
| 2306 // to compile the test or body. | |
| 2307 if (info == ALWAYS_FALSE) break; | |
| 2308 | 2333 |
| 2309 // Label the top of the loop for the backward CFG edge. If there is | 2334 // Based on the condition analysis, compile the test if |
| 2310 // no update expression we can use the continue target. | 2335 // necessary and label the body if necessary. |
| 2311 if (node->next() == NULL) { | 2336 if (info == ALWAYS_TRUE) { |
| 2312 node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL); | 2337 // We will not compile the test expression. Label the top of |
| 2313 node->continue_target()->Bind(); | 2338 // the loop with the continue target if there is no update |
| 2339 // expression, otherwise with the body target. | |
| 2340 if (node->next() == NULL) { | |
| 2341 node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL); | |
| 2342 node->continue_target()->Bind(); | |
| 2343 } else { | |
| 2344 node->continue_target()->Initialize(this); | |
| 2345 body.Bind(); | |
| 2346 } | |
| 2347 } else if (info == ALWAYS_FALSE) { | |
| 2348 // We will not compile the test, the body, or the update | |
| 2349 // expression. Nothing is labeled. | |
| 2350 break; | |
|
Kasper Lund
2009/02/24 08:52:55
Same here. Move ALWAYS_FALSE check to beginning of
| |
| 2314 } else { | 2351 } else { |
| 2352 ASSERT(info == DONT_KNOW); | |
| 2315 node->continue_target()->Initialize(this); | 2353 node->continue_target()->Initialize(this); |
| 2316 loop.Bind(); | 2354 // Compile the test with the body as the true target and |
| 2355 // preferred fall-through and with the break target as the | |
| 2356 // false target. | |
| 2357 ControlDestination dest(&body, node->break_target(), true); | |
| 2358 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); | |
| 2359 | |
| 2360 if (dest.false_was_fall_through()) { | |
| 2361 // If we don't have dangling jumps to the body, the test is | |
| 2362 // unconditionally false and we do not need to compile the | |
| 2363 // body. | |
| 2364 if (!body.is_linked()) break; | |
| 2365 | |
| 2366 // Otherwise, jump around the body on the fall through and | |
| 2367 // then bind the body target. | |
| 2368 node->break_target()->Unuse(); | |
| 2369 node->break_target()->Jump(); | |
| 2370 body.Bind(); | |
| 2371 } | |
| 2317 } | 2372 } |
| 2318 | 2373 |
| 2319 // If the test is always true and has no side effects there is no need | 2374 // The (stack check at the start of the) body was labeled. |
| 2320 // to compile it. We only compile the test when we do not know its | 2375 // Compile it. |
| 2321 // outcome or it has side effects. | |
| 2322 JumpTarget body(this); | |
| 2323 ControlDestination dest(&body, node->break_target(), true); | |
| 2324 if (info == DONT_KNOW) { | |
| 2325 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); | |
| 2326 } | |
| 2327 | |
| 2328 if (dest.false_was_fall_through()) { | |
| 2329 // The break target was bound. We may have dangling jumps to | |
| 2330 // the body. | |
| 2331 if (!body.is_linked()) break; | |
| 2332 | |
| 2333 node->break_target()->Unuse(); | |
| 2334 node->break_target()->Jump(); | |
| 2335 body.Bind(); | |
| 2336 } | |
| 2337 | |
| 2338 // The body target has just been bound or else we didn't compile | |
| 2339 // the test. | |
| 2340 CheckStack(); // TODO(1222600): ignore if body contains calls. | 2376 CheckStack(); // TODO(1222600): ignore if body contains calls. |
| 2341 Visit(node->body()); | 2377 Visit(node->body()); |
| 2342 | 2378 |
| 2343 if (node->next() == NULL) { | 2379 // If there is an update expression, compile it if necessary. |
| 2344 // If there is no update statement and control flow can fall out | 2380 if (node->next() != NULL) { |
| 2345 // of the loop, jump to the continue label. | 2381 // We did not use the continue target for the body. |
| 2346 if (has_valid_frame()) { | |
| 2347 node->continue_target()->Jump(); | |
| 2348 } | |
| 2349 if (node->break_target()->is_linked()) { | |
| 2350 node->break_target()->Bind(); | |
| 2351 } | |
| 2352 | |
| 2353 } else { | |
| 2354 // If there is an update statement and control flow can reach it | |
| 2355 // via falling out of the body of the loop or continuing, we | |
| 2356 // compile the update statement. | |
| 2357 if (node->continue_target()->is_linked()) { | 2382 if (node->continue_target()->is_linked()) { |
| 2358 node->continue_target()->Bind(); | 2383 node->continue_target()->Bind(); |
| 2359 } | 2384 } |
| 2385 | |
| 2386 // Control can reach the update by falling out of the body or | |
| 2387 // by a continue in the body. | |
| 2360 if (has_valid_frame()) { | 2388 if (has_valid_frame()) { |
| 2361 // Record source position of the statement as this code which is | 2389 // Record the source position of the statement as this code |
| 2362 // after the code for the body actually belongs to the loop | 2390 // which is after the code for the body actually belongs to |
| 2363 // statement and not the body. | 2391 // the loop statement and not the body. |
| 2364 CodeForStatementPosition(node); | 2392 CodeForStatementPosition(node); |
| 2365 Visit(node->next()); | 2393 Visit(node->next()); |
| 2366 loop.Jump(); | |
| 2367 } | |
| 2368 if (node->break_target()->is_linked()) { | |
| 2369 node->break_target()->Bind(); | |
| 2370 } | 2394 } |
| 2371 } | 2395 } |
| 2372 | 2396 |
| 2397 // Compile the test if necessary and jump back. | |
| 2398 if (info == ALWAYS_TRUE) { | |
| 2399 if (has_valid_frame()) { | |
| 2400 if (node->next() == NULL) { | |
| 2401 node->continue_target()->Jump(); | |
| 2402 } else { | |
| 2403 body.Jump(); | |
| 2404 } | |
| 2405 } | |
| 2406 } else { | |
| 2407 ASSERT(info == DONT_KNOW); // ALWAYS_FALSE cannot reach here. | |
| 2408 if (node->continue_target()->is_linked()) { | |
| 2409 // We can have dangling jumps to the continue target if | |
| 2410 // there was no update expression. | |
| 2411 node->continue_target()->Bind(); | |
| 2412 } | |
| 2413 | |
| 2414 // Control can reach the test at the bottom by falling out of | |
| 2415 // the body, by a continue in the body, or from the update | |
| 2416 // expression. | |
| 2417 if (has_valid_frame()) { | |
| 2418 // The break target is the fall-through (body is a backward | |
| 2419 // jump from here). | |
| 2420 ControlDestination dest(&body, node->break_target(), false); | |
| 2421 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); | |
| 2422 } | |
| 2423 } | |
| 2424 | |
| 2425 // The break target may be already bound (by the condition), or | |
| 2426 // there may not be a valid frame. Bind it only if needed. | |
| 2427 if (node->break_target()->is_linked()) { | |
| 2428 node->break_target()->Bind(); | |
| 2429 } | |
| 2373 break; | 2430 break; |
| 2374 } | 2431 } |
| 2375 } | 2432 } |
| 2376 | 2433 |
| 2377 DecrementLoopNesting(); | 2434 DecrementLoopNesting(); |
| 2378 } | 2435 } |
| 2379 | 2436 |
| 2380 | 2437 |
| 2381 void CodeGenerator::VisitForInStatement(ForInStatement* node) { | 2438 void CodeGenerator::VisitForInStatement(ForInStatement* node) { |
| 2382 ASSERT(!in_spilled_code()); | 2439 ASSERT(!in_spilled_code()); |
| (...skipping 4284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6667 | 6724 |
| 6668 // Slow-case: Go through the JavaScript implementation. | 6725 // Slow-case: Go through the JavaScript implementation. |
| 6669 __ bind(&slow); | 6726 __ bind(&slow); |
| 6670 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 6727 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
| 6671 } | 6728 } |
| 6672 | 6729 |
| 6673 | 6730 |
| 6674 #undef __ | 6731 #undef __ |
| 6675 | 6732 |
| 6676 } } // namespace v8::internal | 6733 } } // namespace v8::internal |
| OLD | NEW |