OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |