| 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 |