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

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

Issue 269049: Split the AST LoopStatement type into separate types for do/while,... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 2 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
« src/prettyprinter.cc ('K') | « src/x64/codegen-x64.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 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 1274 matching lines...) Expand 10 before | Expand all | Expand 10 after
1285 1285
1286 // We may not have a valid frame here so bind the break target only 1286 // We may not have a valid frame here so bind the break target only
1287 // if needed. 1287 // if needed.
1288 if (node->break_target()->is_linked()) { 1288 if (node->break_target()->is_linked()) {
1289 node->break_target()->Bind(); 1289 node->break_target()->Bind();
1290 } 1290 }
1291 node->break_target()->Unuse(); 1291 node->break_target()->Unuse();
1292 } 1292 }
1293 1293
1294 1294
1295 void CodeGenerator::VisitLoopStatement(LoopStatement* node) { 1295 void CodeGenerator::VisitDoWhileStatement(DoWhileStatement* node) {
1296 ASSERT(!in_spilled_code()); 1296 ASSERT(!in_spilled_code());
1297 Comment cmnt(masm_, "[ LoopStatement"); 1297 Comment cmnt(masm_, "[ DoWhileStatement");
1298 CodeForStatementPosition(node); 1298 CodeForStatementPosition(node);
1299 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); 1299 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
1300 1300 JumpTarget body(JumpTarget::BIDIRECTIONAL);
1301 // Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a 1301 IncrementLoopNesting();
1302 // known result for the test expression, with no side effects. 1302
1303 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW; 1303 ConditionAnalysis info = AnalyzeCondition(node->cond());
1304 if (node->cond() == NULL) { 1304 // Label the top of the loop for the backward jump if necessary.
1305 ASSERT(node->type() == LoopStatement::FOR_LOOP); 1305 switch (info) {
1306 info = ALWAYS_TRUE; 1306 case ALWAYS_TRUE:
1307 } else { 1307 // Use the continue target.
1308 Literal* lit = node->cond()->AsLiteral(); 1308 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
1309 if (lit != NULL) { 1309 node->continue_target()->Bind();
1310 if (lit->IsTrue()) { 1310 break;
1311 info = ALWAYS_TRUE; 1311 case ALWAYS_FALSE:
1312 } else if (lit->IsFalse()) { 1312 // No need to label it.
1313 info = ALWAYS_FALSE; 1313 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
1314 } 1314 break;
1315 case DONT_KNOW:
1316 // Continue is the test, so use the backward body target.
1317 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
1318 body.Bind();
1319 break;
1320 }
1321
1322 CheckStack(); // TODO(1222600): ignore if body contains calls.
1323 Visit(node->body());
1324
1325 // Compile the test.
1326 switch (info) {
1327 case ALWAYS_TRUE:
1328 // If control flow can fall off the end of the body, jump back
1329 // to the top and bind the break target at the exit.
1330 if (has_valid_frame()) {
1331 node->continue_target()->Jump();
1332 }
1333 if (node->break_target()->is_linked()) {
1334 node->break_target()->Bind();
1335 }
1336 break;
1337 case ALWAYS_FALSE:
1338 // We may have had continues or breaks in the body.
1339 if (node->continue_target()->is_linked()) {
1340 node->continue_target()->Bind();
1341 }
1342 if (node->break_target()->is_linked()) {
1343 node->break_target()->Bind();
1344 }
1345 break;
1346 case DONT_KNOW:
1347 // We have to compile the test expression if it can be reached by
1348 // control flow falling out of the body or via continue.
1349 if (node->continue_target()->is_linked()) {
1350 node->continue_target()->Bind();
1351 }
1352 if (has_valid_frame()) {
1353 ControlDestination dest(&body, node->break_target(), false);
1354 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
1355 }
1356 if (node->break_target()->is_linked()) {
1357 node->break_target()->Bind();
1358 }
1359 break;
1360 }
1361
1362 DecrementLoopNesting();
1363 node->continue_target()->Unuse();
1364 node->break_target()->Unuse();
1365 }
1366
1367
1368 void CodeGenerator::VisitWhileStatement(WhileStatement* node) {
1369 ASSERT(!in_spilled_code());
1370 Comment cmnt(masm_, "[ WhileStatement");
1371 CodeForStatementPosition(node);
1372
1373 // If the condition is always false and has no side effects, we do not
1374 // need to compile anything.
1375 ConditionAnalysis info = AnalyzeCondition(node->cond());
1376 if (info == ALWAYS_FALSE) return;
1377
1378 // Do not duplicate conditions that may have function literal
1379 // subexpressions. This can cause us to compile the function literal
1380 // twice.
1381 bool test_at_bottom = !node->may_have_function_literal();
1382 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
1383 IncrementLoopNesting();
1384 JumpTarget body;
1385 if (test_at_bottom) {
1386 body.set_direction(JumpTarget::BIDIRECTIONAL);
1387 }
1388
1389 // Based on the condition analysis, compile the test as necessary.
1390 switch (info) {
1391 case ALWAYS_TRUE:
1392 // We will not compile the test expression. Label the top of the
1393 // loop with the continue target.
1394 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
1395 node->continue_target()->Bind();
1396 break;
1397 case DONT_KNOW: {
1398 if (test_at_bottom) {
1399 // Continue is the test at the bottom, no need to label the test
1400 // at the top. The body is a backward target.
1401 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
1402 } else {
1403 // Label the test at the top as the continue target. The body
1404 // is a forward-only target.
1405 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
1406 node->continue_target()->Bind();
1407 }
1408 // Compile the test with the body as the true target and preferred
1409 // fall-through and with the break target as the false target.
1410 ControlDestination dest(&body, node->break_target(), true);
1411 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
1412
1413 if (dest.false_was_fall_through()) {
1414 // If we got the break target as fall-through, the test may have
1415 // been unconditionally false (if there are no jumps to the
1416 // body).
1417 if (!body.is_linked()) {
1418 DecrementLoopNesting();
1419 return;
1420 }
1421
1422 // Otherwise, jump around the body on the fall through and then
1423 // bind the body target.
1424 node->break_target()->Unuse();
1425 node->break_target()->Jump();
1426 body.Bind();
1427 }
1428 break;
1315 } 1429 }
1316 } 1430 case ALWAYS_FALSE:
1317 1431 UNREACHABLE();
1318 switch (node->type()) { 1432 break;
1319 case LoopStatement::DO_LOOP: { 1433 }
1320 JumpTarget body(JumpTarget::BIDIRECTIONAL); 1434
1321 IncrementLoopNesting(); 1435 CheckStack(); // TODO(1222600): ignore if body contains calls.
1322 1436 Visit(node->body());
1323 // Label the top of the loop for the backward jump if necessary. 1437
1324 if (info == ALWAYS_TRUE) { 1438 // Based on the condition analysis, compile the backward jump as
1325 // Use the continue target. 1439 // necessary.
1326 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL); 1440 switch (info) {
1327 node->continue_target()->Bind(); 1441 case ALWAYS_TRUE:
1328 } else if (info == ALWAYS_FALSE) { 1442 // The loop body has been labeled with the continue target.
1329 // No need to label it. 1443 if (has_valid_frame()) {
1330 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY); 1444 node->continue_target()->Jump();
1331 } else { 1445 }
1332 // Continue is the test, so use the backward body target. 1446 break;
1333 ASSERT(info == DONT_KNOW); 1447 case DONT_KNOW:
1334 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY); 1448 if (test_at_bottom) {
1335 body.Bind(); 1449 // If we have chosen to recompile the test at the bottom,
1336 } 1450 // then it is the continue target.
1337 1451 if (node->continue_target()->is_linked()) {
1338 CheckStack(); // TODO(1222600): ignore if body contains calls. 1452 node->continue_target()->Bind();
1339 Visit(node->body()); 1453 }
1340 1454 if (has_valid_frame()) {
1341 // Compile the test. 1455 // The break target is the fall-through (body is a backward
1342 if (info == ALWAYS_TRUE) { 1456 // jump from here and thus an invalid fall-through).
1343 // If control flow can fall off the end of the body, jump back 1457 ControlDestination dest(&body, node->break_target(), false);
1344 // to the top and bind the break target at the exit. 1458 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
1459 }
1460 } else {
1461 // If we have chosen not to recompile the test at the
1462 // bottom, jump back to the one at the top.
1345 if (has_valid_frame()) { 1463 if (has_valid_frame()) {
1346 node->continue_target()->Jump(); 1464 node->continue_target()->Jump();
1347 } 1465 }
1348 if (node->break_target()->is_linked()) { 1466 }
1349 node->break_target()->Bind(); 1467 break;
1350 } 1468 case ALWAYS_FALSE:
1351 1469 UNREACHABLE();
1352 } else if (info == ALWAYS_FALSE) { 1470 break;
1353 // We may have had continues or breaks in the body. 1471 }
1472
1473 // The break target may be already bound (by the condition), or there
1474 // may not be a valid frame. Bind it only if needed.
1475 if (node->break_target()->is_linked()) {
1476 node->break_target()->Bind();
1477 }
1478 DecrementLoopNesting();
1479 }
1480
1481
1482 void CodeGenerator::VisitForStatement(ForStatement* node) {
1483 ASSERT(!in_spilled_code());
1484 Comment cmnt(masm_, "[ ForStatement");
1485 CodeForStatementPosition(node);
1486
1487 // Compile the init expression if present.
1488 if (node->init() != NULL) {
1489 Visit(node->init());
1490 }
1491
1492 // If the condition is always false and has no side effects, we do not
1493 // need to compile anything else.
1494 ConditionAnalysis info = AnalyzeCondition(node->cond());
1495 if (info == ALWAYS_FALSE) return;
1496
1497 // Do not duplicate conditions that may have function literal
1498 // subexpressions. This can cause us to compile the function literal
1499 // twice.
1500 bool test_at_bottom = !node->may_have_function_literal();
1501 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
1502 IncrementLoopNesting();
1503
1504 // Target for backward edge if no test at the bottom, otherwise
1505 // unused.
1506 JumpTarget loop(JumpTarget::BIDIRECTIONAL);
1507
1508 // Target for backward edge if there is a test at the bottom,
1509 // otherwise used as target for test at the top.
1510 JumpTarget body;
1511 if (test_at_bottom) {
1512 body.set_direction(JumpTarget::BIDIRECTIONAL);
1513 }
1514
1515 // Based on the condition analysis, compile the test as necessary.
1516 switch (info) {
1517 case ALWAYS_TRUE:
1518 // We will not compile the test expression. Label the top of the
1519 // loop.
1520 if (node->next() == NULL) {
1521 // Use the continue target if there is no update expression.
1522 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
1523 node->continue_target()->Bind();
1524 } else {
1525 // Otherwise use the backward loop target.
1526 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
1527 loop.Bind();
1528 }
1529 break;
1530 case DONT_KNOW: {
1531 if (test_at_bottom) {
1532 // Continue is either the update expression or the test at the
1533 // bottom, no need to label the test at the top.
1534 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
1535 } else if (node->next() == NULL) {
1536 // We are not recompiling the test at the bottom and there is no
1537 // update expression.
1538 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
1539 node->continue_target()->Bind();
1540 } else {
1541 // We are not recompiling the test at the bottom and there is an
1542 // update expression.
1543 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
1544 loop.Bind();
1545 }
1546
1547 // Compile the test with the body as the true target and preferred
1548 // fall-through and with the break target as the false target.
1549 ControlDestination dest(&body, node->break_target(), true);
1550 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
1551
1552 if (dest.false_was_fall_through()) {
1553 // If we got the break target as fall-through, the test may have
1554 // been unconditionally false (if there are no jumps to the
1555 // body).
1556 if (!body.is_linked()) {
1557 DecrementLoopNesting();
1558 return;
1559 }
1560
1561 // Otherwise, jump around the body on the fall through and then
1562 // bind the body target.
1563 node->break_target()->Unuse();
1564 node->break_target()->Jump();
1565 body.Bind();
1566 }
1567 break;
1568 }
1569 case ALWAYS_FALSE:
1570 UNREACHABLE();
1571 break;
1572 }
1573
1574 CheckStack(); // TODO(1222600): ignore if body contains calls.
1575 Visit(node->body());
1576
1577 // If there is an update expression, compile it if necessary.
1578 if (node->next() != NULL) {
1579 if (node->continue_target()->is_linked()) {
1580 node->continue_target()->Bind();
1581 }
1582
1583 // Control can reach the update by falling out of the body or by a
1584 // continue.
1585 if (has_valid_frame()) {
1586 // Record the source position of the statement as this code which
1587 // is after the code for the body actually belongs to the loop
1588 // statement and not the body.
1589 CodeForStatementPosition(node);
1590 Visit(node->next());
1591 }
1592 }
1593
1594 // Based on the condition analysis, compile the backward jump as
1595 // necessary.
1596 switch (info) {
1597 case ALWAYS_TRUE:
1598 if (has_valid_frame()) {
1599 if (node->next() == NULL) {
1600 node->continue_target()->Jump();
1601 } else {
1602 loop.Jump();
1603 }
1604 }
1605 break;
1606 case DONT_KNOW:
1607 if (test_at_bottom) {
1354 if (node->continue_target()->is_linked()) { 1608 if (node->continue_target()->is_linked()) {
1609 // We can have dangling jumps to the continue target if there
1610 // was no update expression.
1355 node->continue_target()->Bind(); 1611 node->continue_target()->Bind();
1356 } 1612 }
1357 if (node->break_target()->is_linked()) { 1613 // Control can reach the test at the bottom by falling out of
1358 node->break_target()->Bind(); 1614 // the body, by a continue in the body, or from the update
1359 } 1615 // expression.
1360
1361 } else {
1362 ASSERT(info == DONT_KNOW);
1363 // We have to compile the test expression if it can be reached by
1364 // control flow falling out of the body or via continue.
1365 if (node->continue_target()->is_linked()) {
1366 node->continue_target()->Bind();
1367 }
1368 if (has_valid_frame()) { 1616 if (has_valid_frame()) {
1617 // The break target is the fall-through (body is a backward
1618 // jump from here).
1369 ControlDestination dest(&body, node->break_target(), false); 1619 ControlDestination dest(&body, node->break_target(), false);
1370 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); 1620 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
1371 } 1621 }
1372 if (node->break_target()->is_linked()) { 1622 } else {
1373 node->break_target()->Bind(); 1623 // Otherwise, jump back to the test at the top.
1374 }
1375 }
1376 break;
1377 }
1378
1379 case LoopStatement::WHILE_LOOP: {
1380 // Do not duplicate conditions that may have function literal
1381 // subexpressions. This can cause us to compile the function
1382 // literal twice.
1383 bool test_at_bottom = !node->may_have_function_literal();
1384
1385 IncrementLoopNesting();
1386
1387 // If the condition is always false and has no side effects, we
1388 // do not need to compile anything.
1389 if (info == ALWAYS_FALSE) break;
1390
1391 JumpTarget body;
1392 if (test_at_bottom) {
1393 body.set_direction(JumpTarget::BIDIRECTIONAL);
1394 }
1395
1396 // Based on the condition analysis, compile the test as necessary.
1397 if (info == ALWAYS_TRUE) {
1398 // We will not compile the test expression. Label the top of
1399 // the loop with the continue target.
1400 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
1401 node->continue_target()->Bind();
1402 } else {
1403 ASSERT(info == DONT_KNOW); // ALWAYS_FALSE cannot reach here.
1404 if (test_at_bottom) {
1405 // Continue is the test at the bottom, no need to label the
1406 // test at the top. The body is a backward target.
1407 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
1408 } else {
1409 // Label the test at the top as the continue target. The
1410 // body is a forward-only target.
1411 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
1412 node->continue_target()->Bind();
1413 }
1414 // Compile the test with the body as the true target and
1415 // preferred fall-through and with the break target as the
1416 // false target.
1417 ControlDestination dest(&body, node->break_target(), true);
1418 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
1419
1420 if (dest.false_was_fall_through()) {
1421 // If we got the break target as fall-through, the test may
1422 // have been unconditionally false (if there are no jumps to
1423 // the body).
1424 if (!body.is_linked()) break;
1425
1426 // Otherwise, jump around the body on the fall through and
1427 // then bind the body target.
1428 node->break_target()->Unuse();
1429 node->break_target()->Jump();
1430 body.Bind();
1431 }
1432 }
1433
1434 CheckStack(); // TODO(1222600): ignore if body contains calls.
1435 Visit(node->body());
1436
1437 // Based on the condition analysis, compile the backward jump as
1438 // necessary.
1439 if (info == ALWAYS_TRUE) {
1440 // The loop body has been labeled with the continue target.
1441 if (has_valid_frame()) {
1442 node->continue_target()->Jump();
1443 }
1444 } else {
1445 ASSERT(info == DONT_KNOW); // ALWAYS_FALSE cannot reach here.
1446 if (test_at_bottom) {
1447 // If we have chosen to recompile the test at the bottom,
1448 // then it is the continue target.
1449 if (node->continue_target()->is_linked()) {
1450 node->continue_target()->Bind();
1451 }
1452 if (has_valid_frame()) {
1453 // The break target is the fall-through (body is a backward
1454 // jump from here and thus an invalid fall-through).
1455 ControlDestination dest(&body, node->break_target(), false);
1456 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
1457 }
1458 } else {
1459 // If we have chosen not to recompile the test at the
1460 // bottom, jump back to the one at the top.
1461 if (has_valid_frame()) {
1462 node->continue_target()->Jump();
1463 }
1464 }
1465 }
1466
1467 // The break target may be already bound (by the condition), or
1468 // there may not be a valid frame. Bind it only if needed.
1469 if (node->break_target()->is_linked()) {
1470 node->break_target()->Bind();
1471 }
1472 break;
1473 }
1474
1475 case LoopStatement::FOR_LOOP: {
1476 // Do not duplicate conditions that may have function literal
1477 // subexpressions. This can cause us to compile the function
1478 // literal twice.
1479 bool test_at_bottom = !node->may_have_function_literal();
1480
1481 // Compile the init expression if present.
1482 if (node->init() != NULL) {
1483 Visit(node->init());
1484 }
1485
1486 IncrementLoopNesting();
1487
1488 // If the condition is always false and has no side effects, we
1489 // do not need to compile anything else.
1490 if (info == ALWAYS_FALSE) break;
1491
1492 // Target for backward edge if no test at the bottom, otherwise
1493 // unused.
1494 JumpTarget loop(JumpTarget::BIDIRECTIONAL);
1495
1496 // Target for backward edge if there is a test at the bottom,
1497 // otherwise used as target for test at the top.
1498 JumpTarget body;
1499 if (test_at_bottom) {
1500 body.set_direction(JumpTarget::BIDIRECTIONAL);
1501 }
1502
1503 // Based on the condition analysis, compile the test as necessary.
1504 if (info == ALWAYS_TRUE) {
1505 // We will not compile the test expression. Label the top of
1506 // the loop.
1507 if (node->next() == NULL) {
1508 // Use the continue target if there is no update expression.
1509 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
1510 node->continue_target()->Bind();
1511 } else {
1512 // Otherwise use the backward loop target.
1513 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
1514 loop.Bind();
1515 }
1516 } else {
1517 ASSERT(info == DONT_KNOW);
1518 if (test_at_bottom) {
1519 // Continue is either the update expression or the test at
1520 // the bottom, no need to label the test at the top.
1521 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
1522 } else if (node->next() == NULL) {
1523 // We are not recompiling the test at the bottom and there
1524 // is no update expression.
1525 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
1526 node->continue_target()->Bind();
1527 } else {
1528 // We are not recompiling the test at the bottom and there
1529 // is an update expression.
1530 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
1531 loop.Bind();
1532 }
1533
1534 // Compile the test with the body as the true target and
1535 // preferred fall-through and with the break target as the
1536 // false target.
1537 ControlDestination dest(&body, node->break_target(), true);
1538 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
1539
1540 if (dest.false_was_fall_through()) {
1541 // If we got the break target as fall-through, the test may
1542 // have been unconditionally false (if there are no jumps to
1543 // the body).
1544 if (!body.is_linked()) break;
1545
1546 // Otherwise, jump around the body on the fall through and
1547 // then bind the body target.
1548 node->break_target()->Unuse();
1549 node->break_target()->Jump();
1550 body.Bind();
1551 }
1552 }
1553
1554 CheckStack(); // TODO(1222600): ignore if body contains calls.
1555 Visit(node->body());
1556
1557 // If there is an update expression, compile it if necessary.
1558 if (node->next() != NULL) {
1559 if (node->continue_target()->is_linked()) {
1560 node->continue_target()->Bind();
1561 }
1562
1563 // Control can reach the update by falling out of the body or
1564 // by a continue.
1565 if (has_valid_frame()) {
1566 // Record the source position of the statement as this code
1567 // which is after the code for the body actually belongs to
1568 // the loop statement and not the body.
1569 CodeForStatementPosition(node);
1570 Visit(node->next());
1571 }
1572 }
1573
1574 // Based on the condition analysis, compile the backward jump as
1575 // necessary.
1576 if (info == ALWAYS_TRUE) {
1577 if (has_valid_frame()) { 1624 if (has_valid_frame()) {
1578 if (node->next() == NULL) { 1625 if (node->next() == NULL) {
1579 node->continue_target()->Jump(); 1626 node->continue_target()->Jump();
1580 } else { 1627 } else {
1581 loop.Jump(); 1628 loop.Jump();
1582 } 1629 }
1583 } 1630 }
1584 } else {
1585 ASSERT(info == DONT_KNOW); // ALWAYS_FALSE cannot reach here.
1586 if (test_at_bottom) {
1587 if (node->continue_target()->is_linked()) {
1588 // We can have dangling jumps to the continue target if
1589 // there was no update expression.
1590 node->continue_target()->Bind();
1591 }
1592 // Control can reach the test at the bottom by falling out
1593 // of the body, by a continue in the body, or from the
1594 // update expression.
1595 if (has_valid_frame()) {
1596 // The break target is the fall-through (body is a
1597 // backward jump from here).
1598 ControlDestination dest(&body, node->break_target(), false);
1599 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true);
1600 }
1601 } else {
1602 // Otherwise, jump back to the test at the top.
1603 if (has_valid_frame()) {
1604 if (node->next() == NULL) {
1605 node->continue_target()->Jump();
1606 } else {
1607 loop.Jump();
1608 }
1609 }
1610 }
1611 }
1612
1613 // The break target may be already bound (by the condition), or
1614 // there may not be a valid frame. Bind it only if needed.
1615 if (node->break_target()->is_linked()) {
1616 node->break_target()->Bind();
1617 } 1631 }
1618 break; 1632 break;
1619 } 1633 case ALWAYS_FALSE:
1634 UNREACHABLE();
1635 break;
1620 } 1636 }
1621 1637
1638 // The break target may be already bound (by the condition), or there
1639 // may not be a valid frame. Bind it only if needed.
1640 if (node->break_target()->is_linked()) {
1641 node->break_target()->Bind();
1642 }
1622 DecrementLoopNesting(); 1643 DecrementLoopNesting();
1623 node->continue_target()->Unuse();
1624 node->break_target()->Unuse();
1625 } 1644 }
1626 1645
1627 1646
1628 void CodeGenerator::VisitForInStatement(ForInStatement* node) { 1647 void CodeGenerator::VisitForInStatement(ForInStatement* node) {
1629 ASSERT(!in_spilled_code()); 1648 ASSERT(!in_spilled_code());
1630 VirtualFrame::SpilledScope spilled_scope; 1649 VirtualFrame::SpilledScope spilled_scope;
1631 Comment cmnt(masm_, "[ ForInStatement"); 1650 Comment cmnt(masm_, "[ ForInStatement");
1632 CodeForStatementPosition(node); 1651 CodeForStatementPosition(node);
1633 1652
1634 JumpTarget primitive; 1653 JumpTarget primitive;
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
1806 node->break_target()->Bind(); 1825 node->break_target()->Bind();
1807 frame_->Drop(5); 1826 frame_->Drop(5);
1808 1827
1809 // Exit. 1828 // Exit.
1810 exit.Bind(); 1829 exit.Bind();
1811 1830
1812 node->continue_target()->Unuse(); 1831 node->continue_target()->Unuse();
1813 node->break_target()->Unuse(); 1832 node->break_target()->Unuse();
1814 } 1833 }
1815 1834
1816 void CodeGenerator::VisitTryCatch(TryCatch* node) { 1835 void CodeGenerator::VisitTryCatchStatement(TryCatchStatement* node) {
1817 ASSERT(!in_spilled_code()); 1836 ASSERT(!in_spilled_code());
1818 VirtualFrame::SpilledScope spilled_scope; 1837 VirtualFrame::SpilledScope spilled_scope;
1819 Comment cmnt(masm_, "[ TryCatch"); 1838 Comment cmnt(masm_, "[ TryCatchStatement");
1820 CodeForStatementPosition(node); 1839 CodeForStatementPosition(node);
1821 1840
1822 JumpTarget try_block; 1841 JumpTarget try_block;
1823 JumpTarget exit; 1842 JumpTarget exit;
1824 1843
1825 try_block.Call(); 1844 try_block.Call();
1826 // --- Catch block --- 1845 // --- Catch block ---
1827 frame_->EmitPush(rax); 1846 frame_->EmitPush(rax);
1828 1847
1829 // Store the caught exception in the catch variable. 1848 // Store the caught exception in the catch variable.
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
1945 } else { 1964 } else {
1946 shadows[i]->other_target()->Jump(); 1965 shadows[i]->other_target()->Jump();
1947 } 1966 }
1948 } 1967 }
1949 } 1968 }
1950 1969
1951 exit.Bind(); 1970 exit.Bind();
1952 } 1971 }
1953 1972
1954 1973
1955 void CodeGenerator::VisitTryFinally(TryFinally* node) { 1974 void CodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* node) {
1956 ASSERT(!in_spilled_code()); 1975 ASSERT(!in_spilled_code());
1957 VirtualFrame::SpilledScope spilled_scope; 1976 VirtualFrame::SpilledScope spilled_scope;
1958 Comment cmnt(masm_, "[ TryFinally"); 1977 Comment cmnt(masm_, "[ TryFinallyStatement");
1959 CodeForStatementPosition(node); 1978 CodeForStatementPosition(node);
1960 1979
1961 // State: Used to keep track of reason for entering the finally 1980 // State: Used to keep track of reason for entering the finally
1962 // block. Should probably be extended to hold information for 1981 // block. Should probably be extended to hold information for
1963 // break/continue from within the try block. 1982 // break/continue from within the try block.
1964 enum { FALLING, THROWING, JUMPING }; 1983 enum { FALLING, THROWING, JUMPING };
1965 1984
1966 JumpTarget try_block; 1985 JumpTarget try_block;
1967 JumpTarget finally_block; 1986 JumpTarget finally_block;
1968 1987
(...skipping 5704 matching lines...) Expand 10 before | Expand all | Expand 10 after
7673 int CompareStub::MinorKey() { 7692 int CompareStub::MinorKey() {
7674 // Encode the two parameters in a unique 16 bit value. 7693 // Encode the two parameters in a unique 16 bit value.
7675 ASSERT(static_cast<unsigned>(cc_) < (1 << 15)); 7694 ASSERT(static_cast<unsigned>(cc_) < (1 << 15));
7676 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0); 7695 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0);
7677 } 7696 }
7678 7697
7679 7698
7680 #undef __ 7699 #undef __
7681 7700
7682 } } // namespace v8::internal 7701 } } // namespace v8::internal
OLDNEW
« src/prettyprinter.cc ('K') | « src/x64/codegen-x64.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698