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

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

Issue 40294: Work around issue 260 for now by disabling duplication of the loop... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 9 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 | test/mjsunit/regress/regress-260.js » ('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 2156 matching lines...) Expand 10 before | Expand all | Expand 10 after
2167 info = ALWAYS_FALSE; 2167 info = ALWAYS_FALSE;
2168 } 2168 }
2169 } 2169 }
2170 } 2170 }
2171 2171
2172 switch (node->type()) { 2172 switch (node->type()) {
2173 case LoopStatement::DO_LOOP: { 2173 case LoopStatement::DO_LOOP: {
2174 JumpTarget body(this, JumpTarget::BIDIRECTIONAL); 2174 JumpTarget body(this, JumpTarget::BIDIRECTIONAL);
2175 IncrementLoopNesting(); 2175 IncrementLoopNesting();
2176 2176
2177 // Label the top of the loop for the backward CFG edge. If the test 2177 // Label the top of the loop for the backward jump if necessary.
2178 // is always true we can use the continue target, and if the test is
2179 // always false there is no need.
2180 if (info == ALWAYS_TRUE) { 2178 if (info == ALWAYS_TRUE) {
2179 // Use the continue target.
2181 node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL); 2180 node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL);
2182 node->continue_target()->Bind(); 2181 node->continue_target()->Bind();
2183 } else if (info == ALWAYS_FALSE) { 2182 } else if (info == ALWAYS_FALSE) {
2183 // No need to label it.
2184 node->continue_target()->Initialize(this); 2184 node->continue_target()->Initialize(this);
2185 } else { 2185 } else {
2186 // Continue is the test, so use the backward body target.
2186 ASSERT(info == DONT_KNOW); 2187 ASSERT(info == DONT_KNOW);
2187 node->continue_target()->Initialize(this); 2188 node->continue_target()->Initialize(this);
2188 body.Bind(); 2189 body.Bind();
2189 } 2190 }
2190 2191
2191 CheckStack(); // TODO(1222600): ignore if body contains calls. 2192 CheckStack(); // TODO(1222600): ignore if body contains calls.
2192 Visit(node->body()); 2193 Visit(node->body());
2193 2194
2194 // Compile the test. 2195 // Compile the test.
2195 if (info == ALWAYS_TRUE) { 2196 if (info == ALWAYS_TRUE) {
2196 // If control flow can fall off the end of the body, jump back to 2197 // If control flow can fall off the end of the body, jump back
2197 // the top and bind the break target as the exit. 2198 // to the top and bind the break target at the exit.
2198 if (has_valid_frame()) { 2199 if (has_valid_frame()) {
2199 node->continue_target()->Jump(); 2200 node->continue_target()->Jump();
2200 } 2201 }
2201 if (node->break_target()->is_linked()) { 2202 if (node->break_target()->is_linked()) {
2202 node->break_target()->Bind(); 2203 node->break_target()->Bind();
2203 } 2204 }
2204 2205
2205 } else if (info == ALWAYS_FALSE) { 2206 } else if (info == ALWAYS_FALSE) {
2206 // We may have had continues or breaks in the body. 2207 // We may have had continues or breaks in the body.
2207 if (node->continue_target()->is_linked()) { 2208 if (node->continue_target()->is_linked()) {
(...skipping 15 matching lines...) Expand all
2223 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); 2224 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
2224 } 2225 }
2225 if (node->break_target()->is_linked()) { 2226 if (node->break_target()->is_linked()) {
2226 node->break_target()->Bind(); 2227 node->break_target()->Bind();
2227 } 2228 }
2228 } 2229 }
2229 break; 2230 break;
2230 } 2231 }
2231 2232
2232 case LoopStatement::WHILE_LOOP: { 2233 case LoopStatement::WHILE_LOOP: {
2233 JumpTarget body(this, JumpTarget::BIDIRECTIONAL); 2234 // TODO(260): This flag controls whether to duplicate the test
2235 // at the bottom of the loop. Replace it with a better
2236 // indication of when it is safe to do so.
2237 static const bool test_at_bottom = false;
2238
2239 JumpTarget body; // Uninitialized.
2234 IncrementLoopNesting(); 2240 IncrementLoopNesting();
2235 2241
2236 // If the condition is always false and has no side effects, we 2242 // If the condition is always false and has no side effects, we
2237 // do not need to compile anything. 2243 // do not need to compile anything.
2238 if (info == ALWAYS_FALSE) break; 2244 if (info == ALWAYS_FALSE) break;
2239 2245
2240 // Based on the condition analysis, compile the test if 2246 // Based on the condition analysis, compile the test as necessary.
2241 // necessary and label the body if necessary.
2242 if (info == ALWAYS_TRUE) { 2247 if (info == ALWAYS_TRUE) {
2243 // We will not compile the test expression. Label the top of 2248 // We will not compile the test expression. Label the top of
2244 // the loop with the continue target. 2249 // the loop with the continue target.
2245 node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL); 2250 node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL);
2246 node->continue_target()->Bind(); 2251 node->continue_target()->Bind();
2247 } else { 2252 } else {
2248 ASSERT(info == DONT_KNOW); // ALWAYS_FALSE cannot reach here. 2253 ASSERT(info == DONT_KNOW); // ALWAYS_FALSE cannot reach here.
2249 node->continue_target()->Initialize(this); 2254 if (test_at_bottom) {
2255 // Continue is the test at the bottom, no need to label the
2256 // test at the top. The body is a backward target.
2257 node->continue_target()->Initialize(this);
2258 body.Initialize(this, JumpTarget::BIDIRECTIONAL);
2259 } else {
2260 // Label the test at the top as the continue target. The
2261 // body is a forward-only target.
2262 node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL);
2263 node->continue_target()->Bind();
2264 body.Initialize(this);
2265 }
2250 // Compile the test with the body as the true target and 2266 // Compile the test with the body as the true target and
2251 // preferred fall-through and with the break target as the 2267 // preferred fall-through and with the break target as the
2252 // false target. 2268 // false target.
2253 ControlDestination dest(&body, node->break_target(), true); 2269 ControlDestination dest(&body, node->break_target(), true);
2254 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); 2270 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
2255 2271
2256 if (dest.false_was_fall_through()) { 2272 if (dest.false_was_fall_through()) {
2257 // If we don't have dangling jumps to the body, the test is 2273 // If we got the break target as fall-through, the test may
2258 // unconditionally false and we do not need to compile the 2274 // have been unconditionally false (if there are no jumps to
2259 // body. 2275 // the body).
2260 if (!body.is_linked()) break; 2276 if (!body.is_linked()) break;
2261 2277
2262 // Otherwise, jump around the body on the fall through and 2278 // Otherwise, jump around the body on the fall through and
2263 // then bind the body target. 2279 // then bind the body target.
2264 node->break_target()->Unuse(); 2280 node->break_target()->Unuse();
2265 node->break_target()->Jump(); 2281 node->break_target()->Jump();
2266 body.Bind(); 2282 body.Bind();
2267 } 2283 }
2268 } 2284 }
2269 2285
2270 // The (stack check at the start of the) body was labeled.
2271 // Compile it.
2272 CheckStack(); // TODO(1222600): ignore if body contains calls. 2286 CheckStack(); // TODO(1222600): ignore if body contains calls.
2273 Visit(node->body()); 2287 Visit(node->body());
2274 2288
2275 // Compile the test if necessary and jump back. 2289 // Based on the condition analysis, compile the backward jump as
2290 // necessary.
2276 if (info == ALWAYS_TRUE) { 2291 if (info == ALWAYS_TRUE) {
2277 // The body has been labeled with the continue target. 2292 // The loop body has been labeled with the continue target.
2278 if (has_valid_frame()) { 2293 if (has_valid_frame()) {
2279 node->continue_target()->Jump(); 2294 node->continue_target()->Jump();
2280 } 2295 }
2281 } else { 2296 } else {
2282 ASSERT(info == DONT_KNOW); // ALWAYS_FALSE cannot reach here. 2297 ASSERT(info == DONT_KNOW); // ALWAYS_FALSE cannot reach here.
2283 if (node->continue_target()->is_linked()) { 2298 if (test_at_bottom) {
2284 node->continue_target()->Bind(); 2299 // If we have chosen to recompile the test at the bottom,
2285 } 2300 // then it is the continue target.
2286 2301 if (node->continue_target()->is_linked()) {
2287 // If control can reach the bottom by falling off the body or 2302 node->continue_target()->Bind();
2288 // a continue in the body, (re)compile the test at the bottom. 2303 }
2289 if (has_valid_frame()) { 2304 if (has_valid_frame()) {
2290 // The break target is the fall-through (body is a backward 2305 // The break target is the fall-through (body is a backward
2291 // jump from here). 2306 // jump from here and thus an invalid fall-through).
2292 ControlDestination dest(&body, node->break_target(), false); 2307 ControlDestination dest(&body, node->break_target(), false);
2293 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); 2308 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
2309 }
2310 } else {
2311 // If we have chosen not to recompile the test at the
2312 // bottom, jump back to the one at the top.
2313 if (has_valid_frame()) {
2314 node->continue_target()->Jump();
2315 }
2294 } 2316 }
2295 } 2317 }
2296 2318
2297 // The break target may be already bound (by the condition), or 2319 // The break target may be already bound (by the condition), or
2298 // there may not be a valid frame. Bind it only if needed. 2320 // there may not be a valid frame. Bind it only if needed.
2299 if (node->break_target()->is_linked()) { 2321 if (node->break_target()->is_linked()) {
2300 node->break_target()->Bind(); 2322 node->break_target()->Bind();
2301 } 2323 }
2302 break; 2324 break;
2303 } 2325 }
2304 2326
2305 case LoopStatement::FOR_LOOP: { 2327 case LoopStatement::FOR_LOOP: {
2306 JumpTarget body(this, JumpTarget::BIDIRECTIONAL); 2328 // TODO(260): This flag controls whether to duplicate the test
2329 // at the bottom of the loop. Replace it with a better
2330 // indication of when it is safe to do so.
2331 static const bool test_at_bottom = false;
2332
2333 JumpTarget loop(this, JumpTarget::BIDIRECTIONAL);
2334 JumpTarget body(this);
2307 2335
2308 // Compile the init expression if present. 2336 // Compile the init expression if present.
2309 if (node->init() != NULL) { 2337 if (node->init() != NULL) {
2310 Visit(node->init()); 2338 Visit(node->init());
2311 } 2339 }
2312 2340
2313 IncrementLoopNesting(); 2341 IncrementLoopNesting();
2314 2342
2315 // If the condition is always false and has no side effects, we 2343 // If the condition is always false and has no side effects, we
2316 // do not need to compile anything else. 2344 // do not need to compile anything else.
2317 if (info == ALWAYS_FALSE) break; 2345 if (info == ALWAYS_FALSE) break;
2318 2346
2319 // Based on the condition analysis, compile the test if 2347 // Based on the condition analysis, compile the test as necessary.
2320 // necessary and label the body if necessary.
2321 if (info == ALWAYS_TRUE) { 2348 if (info == ALWAYS_TRUE) {
2322 // We will not compile the test expression. Label the top of 2349 // We will not compile the test expression. Label the top of
2323 // the loop with the continue target if there is no update 2350 // the loop.
2324 // expression, otherwise with the body target.
2325 if (node->next() == NULL) { 2351 if (node->next() == NULL) {
2352 // Use the continue target if there is no update expression.
2326 node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL); 2353 node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL);
2327 node->continue_target()->Bind(); 2354 node->continue_target()->Bind();
2328 } else { 2355 } else {
2356 // Otherwise use the backward loop target.
2329 node->continue_target()->Initialize(this); 2357 node->continue_target()->Initialize(this);
2330 body.Bind(); 2358 loop.Bind();
2331 } 2359 }
2332 } else { 2360 } else {
2333 ASSERT(info == DONT_KNOW); 2361 ASSERT(info == DONT_KNOW);
2334 node->continue_target()->Initialize(this); 2362 if (test_at_bottom) {
2363 // Continue is either the update expression or the test at
2364 // the bottom, no need to label the test at the top.
2365 node->continue_target()->Initialize(this);
2366 } else if (node->next() == NULL) {
2367 // We are not recompiling the test at the bottom and there
2368 // is no update expression.
2369 node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL);
2370 node->continue_target()->Bind();
2371 } else {
2372 // We are not recompiling the test at the bottom and there
2373 // is an update expression.
2374 node->continue_target()->Initialize(this);
2375 loop.Bind();
2376 }
2377
2335 // Compile the test with the body as the true target and 2378 // Compile the test with the body as the true target and
2336 // preferred fall-through and with the break target as the 2379 // preferred fall-through and with the break target as the
2337 // false target. 2380 // false target.
2338 ControlDestination dest(&body, node->break_target(), true); 2381 ControlDestination dest(&body, node->break_target(), true);
2339 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); 2382 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
2340 2383
2341 if (dest.false_was_fall_through()) { 2384 if (dest.false_was_fall_through()) {
2342 // If we don't have dangling jumps to the body, the test is 2385 // If we got the break target as fall-through, the test may
2343 // unconditionally false and we do not need to compile the 2386 // have been unconditionally false (if there are no jumps to
2344 // body. 2387 // the body).
2345 if (!body.is_linked()) break; 2388 if (!body.is_linked()) break;
2346 2389
2347 // Otherwise, jump around the body on the fall through and 2390 // Otherwise, jump around the body on the fall through and
2348 // then bind the body target. 2391 // then bind the body target.
2349 node->break_target()->Unuse(); 2392 node->break_target()->Unuse();
2350 node->break_target()->Jump(); 2393 node->break_target()->Jump();
2351 body.Bind(); 2394 body.Bind();
2352 } 2395 }
2353 } 2396 }
2354 2397
2355 // The (stack check at the start of the) body was labeled.
2356 // Compile it.
2357 CheckStack(); // TODO(1222600): ignore if body contains calls. 2398 CheckStack(); // TODO(1222600): ignore if body contains calls.
2358 Visit(node->body()); 2399 Visit(node->body());
2359 2400
2360 // If there is an update expression, compile it if necessary. 2401 // If there is an update expression, compile it if necessary.
2361 if (node->next() != NULL) { 2402 if (node->next() != NULL) {
2362 // We did not use the continue target for the body.
2363 if (node->continue_target()->is_linked()) { 2403 if (node->continue_target()->is_linked()) {
2364 node->continue_target()->Bind(); 2404 node->continue_target()->Bind();
2365 } 2405 }
2366 2406
2367 // Control can reach the update by falling out of the body or 2407 // Control can reach the update by falling out of the body or
2368 // by a continue in the body. 2408 // by a continue.
2369 if (has_valid_frame()) { 2409 if (has_valid_frame()) {
2370 // Record the source position of the statement as this code 2410 // Record the source position of the statement as this code
2371 // which is after the code for the body actually belongs to 2411 // which is after the code for the body actually belongs to
2372 // the loop statement and not the body. 2412 // the loop statement and not the body.
2373 CodeForStatementPosition(node); 2413 CodeForStatementPosition(node);
2374 Visit(node->next()); 2414 Visit(node->next());
2375 } 2415 }
2376 } 2416 }
2377 2417
2378 // Compile the test if necessary and jump back. 2418 // Based on the condition analysis, compile the backward jump as
2419 // necessary.
2379 if (info == ALWAYS_TRUE) { 2420 if (info == ALWAYS_TRUE) {
2380 if (has_valid_frame()) { 2421 if (has_valid_frame()) {
2381 if (node->next() == NULL) { 2422 if (node->next() == NULL) {
2382 node->continue_target()->Jump(); 2423 node->continue_target()->Jump();
2383 } else { 2424 } else {
2384 body.Jump(); 2425 loop.Jump();
2385 } 2426 }
2386 } 2427 }
2387 } else { 2428 } else {
2388 ASSERT(info == DONT_KNOW); // ALWAYS_FALSE cannot reach here. 2429 ASSERT(info == DONT_KNOW); // ALWAYS_FALSE cannot reach here.
2389 if (node->continue_target()->is_linked()) { 2430 if (test_at_bottom) {
2390 // We can have dangling jumps to the continue target if 2431 if (node->continue_target()->is_linked()) {
2391 // there was no update expression. 2432 // We can have dangling jumps to the continue target if
2392 node->continue_target()->Bind(); 2433 // there was no update expression.
2393 } 2434 node->continue_target()->Bind();
2394 2435 }
2395 // Control can reach the test at the bottom by falling out of 2436 // Control can reach the test at the bottom by falling out
2396 // the body, by a continue in the body, or from the update 2437 // of the body, by a continue in the body, or from the
2397 // expression. 2438 // update expression.
2398 if (has_valid_frame()) { 2439 if (has_valid_frame()) {
2399 // The break target is the fall-through (body is a backward 2440 // The break target is the fall-through (body is a
2400 // jump from here). 2441 // backward jump from here).
2401 ControlDestination dest(&body, node->break_target(), false); 2442 ControlDestination dest(&body, node->break_target(), false);
2402 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); 2443 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
2444 }
2445 } else {
2446 // Otherwise, jump back to the test at the top.
2447 if (has_valid_frame()) {
2448 if (node->next() == NULL) {
2449 node->continue_target()->Jump();
2450 } else {
2451 loop.Jump();
2452 }
2453 }
2403 } 2454 }
2404 } 2455 }
2405 2456
2406 // The break target may be already bound (by the condition), or 2457 // The break target may be already bound (by the condition), or
2407 // there may not be a valid frame. Bind it only if needed. 2458 // there may not be a valid frame. Bind it only if needed.
2408 if (node->break_target()->is_linked()) { 2459 if (node->break_target()->is_linked()) {
2409 node->break_target()->Bind(); 2460 node->break_target()->Bind();
2410 } 2461 }
2411 break; 2462 break;
2412 } 2463 }
(...skipping 4420 matching lines...) Expand 10 before | Expand all | Expand 10 after
6833 6884
6834 // Slow-case: Go through the JavaScript implementation. 6885 // Slow-case: Go through the JavaScript implementation.
6835 __ bind(&slow); 6886 __ bind(&slow);
6836 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 6887 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
6837 } 6888 }
6838 6889
6839 6890
6840 #undef __ 6891 #undef __
6841 6892
6842 } } // namespace v8::internal 6893 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | test/mjsunit/regress/regress-260.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698