| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 1343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1354 if (range.to() > max_register) max_register = range.to(); | 1354 if (range.to() > max_register) max_register = range.to(); |
| 1355 } else { | 1355 } else { |
| 1356 affected_registers->Set(action->reg()); | 1356 affected_registers->Set(action->reg()); |
| 1357 if (action->reg() > max_register) max_register = action->reg(); | 1357 if (action->reg() > max_register) max_register = action->reg(); |
| 1358 } | 1358 } |
| 1359 } | 1359 } |
| 1360 return max_register; | 1360 return max_register; |
| 1361 } | 1361 } |
| 1362 | 1362 |
| 1363 | 1363 |
| 1364 void Trace::PushAffectedRegisters(RegExpMacroAssembler* assembler, | |
| 1365 int max_register, | |
| 1366 OutSet& affected_registers) { | |
| 1367 // Stay safe and check every half times the limit. | |
| 1368 // (Round up in case the limit is 1). | |
| 1369 int push_limit = (assembler->stack_limit_slack() + 1) / 2; | |
| 1370 for (int reg = 0, pushes = 0; reg <= max_register; reg++) { | |
| 1371 if (affected_registers.Get(reg)) { | |
| 1372 pushes++; | |
| 1373 RegExpMacroAssembler::StackCheckFlag check_stack_limit = | |
| 1374 (pushes % push_limit) == 0 ? | |
| 1375 RegExpMacroAssembler::kCheckStackLimit : | |
| 1376 RegExpMacroAssembler::kNoStackLimitCheck; | |
| 1377 assembler->PushRegister(reg, check_stack_limit); | |
| 1378 } | |
| 1379 } | |
| 1380 } | |
| 1381 | |
| 1382 | |
| 1383 void Trace::RestoreAffectedRegisters(RegExpMacroAssembler* assembler, | 1364 void Trace::RestoreAffectedRegisters(RegExpMacroAssembler* assembler, |
| 1384 int max_register, | 1365 int max_register, |
| 1385 OutSet& affected_registers) { | 1366 OutSet& registers_to_pop, |
| 1367 OutSet& registers_to_clear) { |
| 1386 for (int reg = max_register; reg >= 0; reg--) { | 1368 for (int reg = max_register; reg >= 0; reg--) { |
| 1387 if (affected_registers.Get(reg)) assembler->PopRegister(reg); | 1369 if (registers_to_pop.Get(reg)) assembler->PopRegister(reg); |
| 1370 else if (registers_to_clear.Get(reg)) { |
| 1371 int clear_to = reg; |
| 1372 while (reg > 0 && registers_to_clear.Get(reg - 1)) { |
| 1373 reg--; |
| 1374 } |
| 1375 assembler->ClearRegisters(reg, clear_to); |
| 1376 } |
| 1388 } | 1377 } |
| 1389 } | 1378 } |
| 1390 | 1379 |
| 1391 | 1380 |
| 1392 void Trace::PerformDeferredActions(RegExpMacroAssembler* assembler, | 1381 void Trace::PerformDeferredActions(RegExpMacroAssembler* assembler, |
| 1393 int max_register, | 1382 int max_register, |
| 1394 OutSet& affected_registers) { | 1383 OutSet& affected_registers, |
| 1384 OutSet* registers_to_pop, |
| 1385 OutSet* registers_to_clear) { |
| 1386 // The "+1" is to avoid a push_limit of zero if stack_limit_slack() is 1. |
| 1387 const int push_limit = (assembler->stack_limit_slack() + 1) / 2; |
| 1388 |
| 1395 for (int reg = 0; reg <= max_register; reg++) { | 1389 for (int reg = 0; reg <= max_register; reg++) { |
| 1396 if (!affected_registers.Get(reg)) { | 1390 if (!affected_registers.Get(reg)) { |
| 1397 continue; | 1391 continue; |
| 1398 } | 1392 } |
| 1393 // Count pushes performed to force a stack limit check occasionally. |
| 1394 int pushes = 0; |
| 1395 |
| 1396 // The chronologically first deferred action in the trace |
| 1397 // is used to infer the action needed to restore a register |
| 1398 // to its previous state (or not, if it's safe to ignore it). |
| 1399 enum DeferredActionUndoType { IGNORE, RESTORE, CLEAR }; |
| 1400 DeferredActionUndoType undo_action = IGNORE; |
| 1401 |
| 1399 int value = 0; | 1402 int value = 0; |
| 1400 bool absolute = false; | 1403 bool absolute = false; |
| 1401 bool clear = false; | 1404 bool clear = false; |
| 1402 int store_position = -1; | 1405 int store_position = -1; |
| 1403 // This is a little tricky because we are scanning the actions in reverse | 1406 // This is a little tricky because we are scanning the actions in reverse |
| 1404 // historical order (newest first). | 1407 // historical order (newest first). |
| 1405 for (DeferredAction* action = actions_; | 1408 for (DeferredAction* action = actions_; |
| 1406 action != NULL; | 1409 action != NULL; |
| 1407 action = action->next()) { | 1410 action = action->next()) { |
| 1408 if (action->Mentions(reg)) { | 1411 if (action->Mentions(reg)) { |
| 1409 switch (action->type()) { | 1412 switch (action->type()) { |
| 1410 case ActionNode::SET_REGISTER: { | 1413 case ActionNode::SET_REGISTER: { |
| 1411 Trace::DeferredSetRegister* psr = | 1414 Trace::DeferredSetRegister* psr = |
| 1412 static_cast<Trace::DeferredSetRegister*>(action); | 1415 static_cast<Trace::DeferredSetRegister*>(action); |
| 1413 value += psr->value(); | 1416 if (!absolute) { |
| 1414 absolute = true; | 1417 value += psr->value(); |
| 1418 absolute = true; |
| 1419 } |
| 1420 // SET_REGISTER is currently only used for newly introduced loop |
| 1421 // counters. They can have a significant previous value if they |
| 1422 // occour in a loop. TODO(lrn): Propagate this information, so |
| 1423 // we can set undo_action to IGNORE if we know there is no value to |
| 1424 // restore. |
| 1425 undo_action = RESTORE; |
| 1415 ASSERT_EQ(store_position, -1); | 1426 ASSERT_EQ(store_position, -1); |
| 1416 ASSERT(!clear); | 1427 ASSERT(!clear); |
| 1417 break; | 1428 break; |
| 1418 } | 1429 } |
| 1419 case ActionNode::INCREMENT_REGISTER: | 1430 case ActionNode::INCREMENT_REGISTER: |
| 1420 if (!absolute) { | 1431 if (!absolute) { |
| 1421 value++; | 1432 value++; |
| 1422 } | 1433 } |
| 1423 ASSERT_EQ(store_position, -1); | 1434 ASSERT_EQ(store_position, -1); |
| 1424 ASSERT(!clear); | 1435 ASSERT(!clear); |
| 1436 undo_action = RESTORE; |
| 1425 break; | 1437 break; |
| 1426 case ActionNode::STORE_POSITION: { | 1438 case ActionNode::STORE_POSITION: { |
| 1427 Trace::DeferredCapture* pc = | 1439 Trace::DeferredCapture* pc = |
| 1428 static_cast<Trace::DeferredCapture*>(action); | 1440 static_cast<Trace::DeferredCapture*>(action); |
| 1429 if (!clear && store_position == -1) { | 1441 if (!clear && store_position == -1) { |
| 1430 store_position = pc->cp_offset(); | 1442 store_position = pc->cp_offset(); |
| 1431 } | 1443 } |
| 1444 |
| 1445 // For captures we know that stores and clears alternate. |
| 1446 // Other register, are never cleared, and if the occur |
| 1447 // inside a loop, they might be assigned more than once. |
| 1448 if (reg <= 1) { |
| 1449 // Registers zero and one, aka "capture zero", is |
| 1450 // always set correctly if we succeed. There is no |
| 1451 // need to undo a setting on backtrack, because we |
| 1452 // will set it again or fail. |
| 1453 undo_action = IGNORE; |
| 1454 } else { |
| 1455 undo_action = pc->is_capture() ? CLEAR : RESTORE; |
| 1456 } |
| 1432 ASSERT(!absolute); | 1457 ASSERT(!absolute); |
| 1433 ASSERT_EQ(value, 0); | 1458 ASSERT_EQ(value, 0); |
| 1434 break; | 1459 break; |
| 1435 } | 1460 } |
| 1436 case ActionNode::CLEAR_CAPTURES: { | 1461 case ActionNode::CLEAR_CAPTURES: { |
| 1437 // Since we're scanning in reverse order, if we've already | 1462 // Since we're scanning in reverse order, if we've already |
| 1438 // set the position we have to ignore historically earlier | 1463 // set the position we have to ignore historically earlier |
| 1439 // clearing operations. | 1464 // clearing operations. |
| 1440 if (store_position == -1) | 1465 if (store_position == -1) { |
| 1441 clear = true; | 1466 clear = true; |
| 1467 } |
| 1468 undo_action = RESTORE; |
| 1442 ASSERT(!absolute); | 1469 ASSERT(!absolute); |
| 1443 ASSERT_EQ(value, 0); | 1470 ASSERT_EQ(value, 0); |
| 1444 break; | 1471 break; |
| 1445 } | 1472 } |
| 1446 default: | 1473 default: |
| 1447 UNREACHABLE(); | 1474 UNREACHABLE(); |
| 1448 break; | 1475 break; |
| 1449 } | 1476 } |
| 1450 } | 1477 } |
| 1451 } | 1478 } |
| 1479 // Prepare for the undo-action (e.g., push if it's going to be popped). |
| 1480 if (undo_action == RESTORE) { |
| 1481 pushes++; |
| 1482 RegExpMacroAssembler::StackCheckFlag stack_check = |
| 1483 RegExpMacroAssembler::kNoStackLimitCheck; |
| 1484 if (pushes == push_limit) { |
| 1485 stack_check = RegExpMacroAssembler::kCheckStackLimit; |
| 1486 pushes = 0; |
| 1487 } |
| 1488 |
| 1489 assembler->PushRegister(reg, stack_check); |
| 1490 registers_to_pop->Set(reg); |
| 1491 } else if (undo_action == CLEAR) { |
| 1492 registers_to_clear->Set(reg); |
| 1493 } |
| 1494 // Perform the chronologically last action (or accumulated increment) |
| 1495 // for the register. |
| 1452 if (store_position != -1) { | 1496 if (store_position != -1) { |
| 1453 assembler->WriteCurrentPositionToRegister(reg, store_position); | 1497 assembler->WriteCurrentPositionToRegister(reg, store_position); |
| 1454 } else if (clear) { | 1498 } else if (clear) { |
| 1455 assembler->ClearRegister(reg); | 1499 assembler->ClearRegisters(reg, reg); |
| 1456 } else if (absolute) { | 1500 } else if (absolute) { |
| 1457 assembler->SetRegister(reg, value); | 1501 assembler->SetRegister(reg, value); |
| 1458 } else if (value != 0) { | 1502 } else if (value != 0) { |
| 1459 assembler->AdvanceRegister(reg, value); | 1503 assembler->AdvanceRegister(reg, value); |
| 1460 } | 1504 } |
| 1461 } | 1505 } |
| 1462 } | 1506 } |
| 1463 | 1507 |
| 1464 | 1508 |
| 1465 // This is called as we come into a loop choice node and some other tricky | 1509 // This is called as we come into a loop choice node and some other tricky |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1480 // a normal situation. We may also have to forget some information gained | 1524 // a normal situation. We may also have to forget some information gained |
| 1481 // through a quick check that was already performed. | 1525 // through a quick check that was already performed. |
| 1482 if (cp_offset_ != 0) assembler->AdvanceCurrentPosition(cp_offset_); | 1526 if (cp_offset_ != 0) assembler->AdvanceCurrentPosition(cp_offset_); |
| 1483 // Create a new trivial state and generate the node with that. | 1527 // Create a new trivial state and generate the node with that. |
| 1484 Trace new_state; | 1528 Trace new_state; |
| 1485 return successor->Emit(compiler, &new_state); | 1529 return successor->Emit(compiler, &new_state); |
| 1486 } | 1530 } |
| 1487 | 1531 |
| 1488 // Generate deferred actions here along with code to undo them again. | 1532 // Generate deferred actions here along with code to undo them again. |
| 1489 OutSet affected_registers; | 1533 OutSet affected_registers; |
| 1534 |
| 1490 int max_register = FindAffectedRegisters(&affected_registers); | 1535 int max_register = FindAffectedRegisters(&affected_registers); |
| 1491 PushAffectedRegisters(assembler, max_register, affected_registers); | 1536 OutSet registers_to_pop; |
| 1492 PerformDeferredActions(assembler, max_register, affected_registers); | 1537 OutSet registers_to_clear; |
| 1538 PerformDeferredActions(assembler, |
| 1539 max_register, |
| 1540 affected_registers, |
| 1541 ®isters_to_pop, |
| 1542 ®isters_to_clear); |
| 1493 if (backtrack() != NULL) { | 1543 if (backtrack() != NULL) { |
| 1494 // Here we have a concrete backtrack location. These are set up by choice | 1544 // Here we have a concrete backtrack location. These are set up by choice |
| 1495 // nodes and so they indicate that we have a deferred save of the current | 1545 // nodes and so they indicate that we have a deferred save of the current |
| 1496 // position which we may need to emit here. | 1546 // position which we may need to emit here. |
| 1497 assembler->PushCurrentPosition(); | 1547 assembler->PushCurrentPosition(); |
| 1498 } | 1548 } |
| 1499 if (cp_offset_ != 0) { | 1549 if (cp_offset_ != 0) { |
| 1500 assembler->AdvanceCurrentPosition(cp_offset_); | 1550 assembler->AdvanceCurrentPosition(cp_offset_); |
| 1501 } | 1551 } |
| 1502 | 1552 |
| 1503 // Create a new trivial state and generate the node with that. | 1553 // Create a new trivial state and generate the node with that. |
| 1504 Label undo; | 1554 Label undo; |
| 1505 assembler->PushBacktrack(&undo); | 1555 assembler->PushBacktrack(&undo); |
| 1506 Trace new_state; | 1556 Trace new_state; |
| 1507 bool ok = successor->Emit(compiler, &new_state); | 1557 bool ok = successor->Emit(compiler, &new_state); |
| 1508 | 1558 |
| 1509 // On backtrack we need to restore state. | 1559 // On backtrack we need to restore state. |
| 1510 assembler->Bind(&undo); | 1560 assembler->Bind(&undo); |
| 1511 if (!ok) return false; | 1561 if (!ok) return false; |
| 1512 if (backtrack() != NULL) { | 1562 if (backtrack() != NULL) { |
| 1513 assembler->PopCurrentPosition(); | 1563 assembler->PopCurrentPosition(); |
| 1514 } | 1564 } |
| 1515 RestoreAffectedRegisters(assembler, max_register, affected_registers); | 1565 RestoreAffectedRegisters(assembler, |
| 1566 max_register, |
| 1567 registers_to_pop, |
| 1568 registers_to_clear); |
| 1516 if (backtrack() == NULL) { | 1569 if (backtrack() == NULL) { |
| 1517 assembler->Backtrack(); | 1570 assembler->Backtrack(); |
| 1518 } else { | 1571 } else { |
| 1519 assembler->GoTo(backtrack()); | 1572 assembler->GoTo(backtrack()); |
| 1520 } | 1573 } |
| 1521 | 1574 |
| 1522 return true; | 1575 return true; |
| 1523 } | 1576 } |
| 1524 | 1577 |
| 1525 | 1578 |
| 1526 bool NegativeSubmatchSuccess::Emit(RegExpCompiler* compiler, Trace* trace) { | 1579 bool NegativeSubmatchSuccess::Emit(RegExpCompiler* compiler, Trace* trace) { |
| 1527 if (!trace->is_trivial()) { | |
| 1528 return trace->Flush(compiler, this); | |
| 1529 } | |
| 1530 RegExpMacroAssembler* assembler = compiler->macro_assembler(); | 1580 RegExpMacroAssembler* assembler = compiler->macro_assembler(); |
| 1581 |
| 1582 // Omit flushing the trace. We discard the entire stack frame anyway. |
| 1583 |
| 1531 if (!label()->is_bound()) { | 1584 if (!label()->is_bound()) { |
| 1585 // We are completely independent of the trace, since we ignore it, |
| 1586 // so this code can be used as the generic version. |
| 1532 assembler->Bind(label()); | 1587 assembler->Bind(label()); |
| 1533 } | 1588 } |
| 1589 |
| 1590 // Throw away everything on the backtrack stack since the start |
| 1591 // of the negative submatch and restore the character position. |
| 1534 assembler->ReadCurrentPositionFromRegister(current_position_register_); | 1592 assembler->ReadCurrentPositionFromRegister(current_position_register_); |
| 1535 assembler->ReadStackPointerFromRegister(stack_pointer_register_); | 1593 assembler->ReadStackPointerFromRegister(stack_pointer_register_); |
| 1594 if (clear_capture_count_ > 0) { |
| 1595 // Clear any captures that might have been performed during the success |
| 1596 // of the body of the negative look-ahead. |
| 1597 int clear_capture_end = clear_capture_start_ + clear_capture_count_ - 1; |
| 1598 assembler->ClearRegisters(clear_capture_start_, clear_capture_end); |
| 1599 } |
| 1536 // Now that we have unwound the stack we find at the top of the stack the | 1600 // Now that we have unwound the stack we find at the top of the stack the |
| 1537 // backtrack that the BeginSubmatch node got. | 1601 // backtrack that the BeginSubmatch node got. |
| 1538 assembler->Backtrack(); | 1602 assembler->Backtrack(); |
| 1539 return true; | 1603 return true; |
| 1540 } | 1604 } |
| 1541 | 1605 |
| 1542 | 1606 |
| 1543 bool EndNode::Emit(RegExpCompiler* compiler, Trace* trace) { | 1607 bool EndNode::Emit(RegExpCompiler* compiler, Trace* trace) { |
| 1544 if (!trace->is_trivial()) { | 1608 if (!trace->is_trivial()) { |
| 1545 return trace->Flush(compiler, this); | 1609 return trace->Flush(compiler, this); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1581 } | 1645 } |
| 1582 | 1646 |
| 1583 | 1647 |
| 1584 ActionNode* ActionNode::IncrementRegister(int reg, RegExpNode* on_success) { | 1648 ActionNode* ActionNode::IncrementRegister(int reg, RegExpNode* on_success) { |
| 1585 ActionNode* result = new ActionNode(INCREMENT_REGISTER, on_success); | 1649 ActionNode* result = new ActionNode(INCREMENT_REGISTER, on_success); |
| 1586 result->data_.u_increment_register.reg = reg; | 1650 result->data_.u_increment_register.reg = reg; |
| 1587 return result; | 1651 return result; |
| 1588 } | 1652 } |
| 1589 | 1653 |
| 1590 | 1654 |
| 1591 ActionNode* ActionNode::StorePosition(int reg, RegExpNode* on_success) { | 1655 ActionNode* ActionNode::StorePosition(int reg, |
| 1656 bool is_capture, |
| 1657 RegExpNode* on_success) { |
| 1592 ActionNode* result = new ActionNode(STORE_POSITION, on_success); | 1658 ActionNode* result = new ActionNode(STORE_POSITION, on_success); |
| 1593 result->data_.u_position_register.reg = reg; | 1659 result->data_.u_position_register.reg = reg; |
| 1660 result->data_.u_position_register.is_capture = is_capture; |
| 1594 return result; | 1661 return result; |
| 1595 } | 1662 } |
| 1596 | 1663 |
| 1597 | 1664 |
| 1598 ActionNode* ActionNode::ClearCaptures(Interval range, | 1665 ActionNode* ActionNode::ClearCaptures(Interval range, |
| 1599 RegExpNode* on_success) { | 1666 RegExpNode* on_success) { |
| 1600 ActionNode* result = new ActionNode(CLEAR_CAPTURES, on_success); | 1667 ActionNode* result = new ActionNode(CLEAR_CAPTURES, on_success); |
| 1601 result->data_.u_clear_captures.range_from = range.from(); | 1668 result->data_.u_clear_captures.range_from = range.from(); |
| 1602 result->data_.u_clear_captures.range_to = range.to(); | 1669 result->data_.u_clear_captures.range_to = range.to(); |
| 1603 return result; | 1670 return result; |
| 1604 } | 1671 } |
| 1605 | 1672 |
| 1606 | 1673 |
| 1607 ActionNode* ActionNode::BeginSubmatch(int stack_reg, | 1674 ActionNode* ActionNode::BeginSubmatch(int stack_reg, |
| 1608 int position_reg, | 1675 int position_reg, |
| 1609 RegExpNode* on_success) { | 1676 RegExpNode* on_success) { |
| 1610 ActionNode* result = new ActionNode(BEGIN_SUBMATCH, on_success); | 1677 ActionNode* result = new ActionNode(BEGIN_SUBMATCH, on_success); |
| 1611 result->data_.u_submatch.stack_pointer_register = stack_reg; | 1678 result->data_.u_submatch.stack_pointer_register = stack_reg; |
| 1612 result->data_.u_submatch.current_position_register = position_reg; | 1679 result->data_.u_submatch.current_position_register = position_reg; |
| 1613 return result; | 1680 return result; |
| 1614 } | 1681 } |
| 1615 | 1682 |
| 1616 | 1683 |
| 1617 ActionNode* ActionNode::PositiveSubmatchSuccess(int stack_reg, | 1684 ActionNode* ActionNode::PositiveSubmatchSuccess(int stack_reg, |
| 1618 int position_reg, | 1685 int position_reg, |
| 1686 int clear_register_count, |
| 1687 int clear_register_from, |
| 1619 RegExpNode* on_success) { | 1688 RegExpNode* on_success) { |
| 1620 ActionNode* result = new ActionNode(POSITIVE_SUBMATCH_SUCCESS, on_success); | 1689 ActionNode* result = new ActionNode(POSITIVE_SUBMATCH_SUCCESS, on_success); |
| 1621 result->data_.u_submatch.stack_pointer_register = stack_reg; | 1690 result->data_.u_submatch.stack_pointer_register = stack_reg; |
| 1622 result->data_.u_submatch.current_position_register = position_reg; | 1691 result->data_.u_submatch.current_position_register = position_reg; |
| 1692 result->data_.u_submatch.clear_register_count = clear_register_count; |
| 1693 result->data_.u_submatch.clear_register_from = clear_register_from; |
| 1623 return result; | 1694 return result; |
| 1624 } | 1695 } |
| 1625 | 1696 |
| 1626 | 1697 |
| 1627 ActionNode* ActionNode::EmptyMatchCheck(int start_register, | 1698 ActionNode* ActionNode::EmptyMatchCheck(int start_register, |
| 1628 int repetition_register, | 1699 int repetition_register, |
| 1629 int repetition_limit, | 1700 int repetition_limit, |
| 1630 RegExpNode* on_success) { | 1701 RegExpNode* on_success) { |
| 1631 ActionNode* result = new ActionNode(EMPTY_MATCH_CHECK, on_success); | 1702 ActionNode* result = new ActionNode(EMPTY_MATCH_CHECK, on_success); |
| 1632 result->data_.u_empty_match_check.start_register = start_register; | 1703 result->data_.u_empty_match_check.start_register = start_register; |
| (...skipping 1531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3164 LimitResult limit_result = LimitVersions(compiler, trace); | 3235 LimitResult limit_result = LimitVersions(compiler, trace); |
| 3165 if (limit_result == DONE) return true; | 3236 if (limit_result == DONE) return true; |
| 3166 if (limit_result == FAIL) return false; | 3237 if (limit_result == FAIL) return false; |
| 3167 ASSERT(limit_result == CONTINUE); | 3238 ASSERT(limit_result == CONTINUE); |
| 3168 | 3239 |
| 3169 RecursionCheck rc(compiler); | 3240 RecursionCheck rc(compiler); |
| 3170 | 3241 |
| 3171 switch (type_) { | 3242 switch (type_) { |
| 3172 case STORE_POSITION: { | 3243 case STORE_POSITION: { |
| 3173 Trace::DeferredCapture | 3244 Trace::DeferredCapture |
| 3174 new_capture(data_.u_position_register.reg, trace); | 3245 new_capture(data_.u_position_register.reg, |
| 3246 data_.u_position_register.is_capture, |
| 3247 trace); |
| 3175 Trace new_trace = *trace; | 3248 Trace new_trace = *trace; |
| 3176 new_trace.add_action(&new_capture); | 3249 new_trace.add_action(&new_capture); |
| 3177 return on_success()->Emit(compiler, &new_trace); | 3250 return on_success()->Emit(compiler, &new_trace); |
| 3178 } | 3251 } |
| 3179 case INCREMENT_REGISTER: { | 3252 case INCREMENT_REGISTER: { |
| 3180 Trace::DeferredIncrementRegister | 3253 Trace::DeferredIncrementRegister |
| 3181 new_increment(data_.u_increment_register.reg); | 3254 new_increment(data_.u_increment_register.reg); |
| 3182 Trace new_trace = *trace; | 3255 Trace new_trace = *trace; |
| 3183 new_trace.add_action(&new_increment); | 3256 new_trace.add_action(&new_increment); |
| 3184 return on_success()->Emit(compiler, &new_trace); | 3257 return on_success()->Emit(compiler, &new_trace); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3229 int limit = data_.u_empty_match_check.repetition_limit; | 3302 int limit = data_.u_empty_match_check.repetition_limit; |
| 3230 assembler->IfRegisterLT(rep_reg, limit, &skip_empty_check); | 3303 assembler->IfRegisterLT(rep_reg, limit, &skip_empty_check); |
| 3231 } | 3304 } |
| 3232 // If the match is empty we bail out, otherwise we fall through | 3305 // If the match is empty we bail out, otherwise we fall through |
| 3233 // to the on-success continuation. | 3306 // to the on-success continuation. |
| 3234 assembler->IfRegisterEqPos(data_.u_empty_match_check.start_register, | 3307 assembler->IfRegisterEqPos(data_.u_empty_match_check.start_register, |
| 3235 trace->backtrack()); | 3308 trace->backtrack()); |
| 3236 assembler->Bind(&skip_empty_check); | 3309 assembler->Bind(&skip_empty_check); |
| 3237 return on_success()->Emit(compiler, trace); | 3310 return on_success()->Emit(compiler, trace); |
| 3238 } | 3311 } |
| 3239 case POSITIVE_SUBMATCH_SUCCESS: | 3312 case POSITIVE_SUBMATCH_SUCCESS: { |
| 3240 if (!trace->is_trivial()) return trace->Flush(compiler, this); | 3313 if (!trace->is_trivial()) return trace->Flush(compiler, this); |
| 3241 assembler->ReadCurrentPositionFromRegister( | 3314 assembler->ReadCurrentPositionFromRegister( |
| 3242 data_.u_submatch.current_position_register); | 3315 data_.u_submatch.current_position_register); |
| 3243 assembler->ReadStackPointerFromRegister( | 3316 assembler->ReadStackPointerFromRegister( |
| 3244 data_.u_submatch.stack_pointer_register); | 3317 data_.u_submatch.stack_pointer_register); |
| 3245 return on_success()->Emit(compiler, trace); | 3318 int clear_register_count = data_.u_submatch.clear_register_count; |
| 3319 if (clear_register_count == 0) { |
| 3320 return on_success()->Emit(compiler, trace); |
| 3321 } |
| 3322 int clear_registers_from = data_.u_submatch.clear_register_from; |
| 3323 Label clear_registers_backtrack; |
| 3324 Trace new_trace = *trace; |
| 3325 new_trace.set_backtrack(&clear_registers_backtrack); |
| 3326 bool ok = on_success()->Emit(compiler, &new_trace); |
| 3327 if (!ok) { return false; } |
| 3328 |
| 3329 assembler->Bind(&clear_registers_backtrack); |
| 3330 int clear_registers_to = clear_registers_from + clear_register_count - 1; |
| 3331 assembler->ClearRegisters(clear_registers_from, clear_registers_to); |
| 3332 |
| 3333 ASSERT(trace->backtrack() == NULL); |
| 3334 assembler->Backtrack(); |
| 3335 return true; |
| 3336 } |
| 3246 default: | 3337 default: |
| 3247 UNREACHABLE(); | 3338 UNREACHABLE(); |
| 3248 return false; | 3339 return false; |
| 3249 } | 3340 } |
| 3250 } | 3341 } |
| 3251 | 3342 |
| 3252 | 3343 |
| 3253 bool BackReferenceNode::Emit(RegExpCompiler* compiler, Trace* trace) { | 3344 bool BackReferenceNode::Emit(RegExpCompiler* compiler, Trace* trace) { |
| 3254 RegExpMacroAssembler* assembler = compiler->macro_assembler(); | 3345 RegExpMacroAssembler* assembler = compiler->macro_assembler(); |
| 3255 if (!trace->is_trivial()) { | 3346 if (!trace->is_trivial()) { |
| (...skipping 597 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3853 // backtrack. | 3944 // backtrack. |
| 3854 loop_return = ActionNode::EmptyMatchCheck(body_start_reg, | 3945 loop_return = ActionNode::EmptyMatchCheck(body_start_reg, |
| 3855 reg_ctr, | 3946 reg_ctr, |
| 3856 min, | 3947 min, |
| 3857 loop_return); | 3948 loop_return); |
| 3858 } | 3949 } |
| 3859 RegExpNode* body_node = body->ToNode(compiler, loop_return); | 3950 RegExpNode* body_node = body->ToNode(compiler, loop_return); |
| 3860 if (body_can_be_empty) { | 3951 if (body_can_be_empty) { |
| 3861 // If the body can be empty we need to store the start position | 3952 // If the body can be empty we need to store the start position |
| 3862 // so we can bail out if it was empty. | 3953 // so we can bail out if it was empty. |
| 3863 body_node = ActionNode::StorePosition(body_start_reg, body_node); | 3954 body_node = ActionNode::StorePosition(body_start_reg, false, body_node); |
| 3864 } | 3955 } |
| 3865 if (needs_capture_clearing) { | 3956 if (needs_capture_clearing) { |
| 3866 // Before entering the body of this loop we need to clear captures. | 3957 // Before entering the body of this loop we need to clear captures. |
| 3867 body_node = ActionNode::ClearCaptures(capture_registers, body_node); | 3958 body_node = ActionNode::ClearCaptures(capture_registers, body_node); |
| 3868 } | 3959 } |
| 3869 GuardedAlternative body_alt(body_node); | 3960 GuardedAlternative body_alt(body_node); |
| 3870 if (has_max) { | 3961 if (has_max) { |
| 3871 Guard* body_guard = new Guard(reg_ctr, Guard::LT, max); | 3962 Guard* body_guard = new Guard(reg_ctr, Guard::LT, max); |
| 3872 body_alt.AddGuard(body_guard); | 3963 body_alt.AddGuard(body_guard); |
| 3873 } | 3964 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3915 ChoiceNode* result = new ChoiceNode(2); | 4006 ChoiceNode* result = new ChoiceNode(2); |
| 3916 // Create a newline atom. | 4007 // Create a newline atom. |
| 3917 ZoneList<CharacterRange>* newline_ranges = | 4008 ZoneList<CharacterRange>* newline_ranges = |
| 3918 new ZoneList<CharacterRange>(3); | 4009 new ZoneList<CharacterRange>(3); |
| 3919 CharacterRange::AddClassEscape('n', newline_ranges); | 4010 CharacterRange::AddClassEscape('n', newline_ranges); |
| 3920 RegExpCharacterClass* newline_atom = new RegExpCharacterClass('n'); | 4011 RegExpCharacterClass* newline_atom = new RegExpCharacterClass('n'); |
| 3921 TextNode* newline_matcher = new TextNode( | 4012 TextNode* newline_matcher = new TextNode( |
| 3922 newline_atom, | 4013 newline_atom, |
| 3923 ActionNode::PositiveSubmatchSuccess(stack_pointer_register, | 4014 ActionNode::PositiveSubmatchSuccess(stack_pointer_register, |
| 3924 position_register, | 4015 position_register, |
| 4016 0, // No captures inside. |
| 4017 -1, // Ignored if no captures. |
| 3925 on_success)); | 4018 on_success)); |
| 3926 // Create an end-of-input matcher. | 4019 // Create an end-of-input matcher. |
| 3927 RegExpNode* end_of_line = ActionNode::BeginSubmatch( | 4020 RegExpNode* end_of_line = ActionNode::BeginSubmatch( |
| 3928 stack_pointer_register, | 4021 stack_pointer_register, |
| 3929 position_register, | 4022 position_register, |
| 3930 newline_matcher); | 4023 newline_matcher); |
| 3931 // Add the two alternatives to the ChoiceNode. | 4024 // Add the two alternatives to the ChoiceNode. |
| 3932 GuardedAlternative eol_alternative(end_of_line); | 4025 GuardedAlternative eol_alternative(end_of_line); |
| 3933 result->AddAlternative(eol_alternative); | 4026 result->AddAlternative(eol_alternative); |
| 3934 GuardedAlternative end_alternative(AssertionNode::AtEnd(on_success)); | 4027 GuardedAlternative end_alternative(AssertionNode::AtEnd(on_success)); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 3953 RegExpNode* RegExpEmpty::ToNode(RegExpCompiler* compiler, | 4046 RegExpNode* RegExpEmpty::ToNode(RegExpCompiler* compiler, |
| 3954 RegExpNode* on_success) { | 4047 RegExpNode* on_success) { |
| 3955 return on_success; | 4048 return on_success; |
| 3956 } | 4049 } |
| 3957 | 4050 |
| 3958 | 4051 |
| 3959 RegExpNode* RegExpLookahead::ToNode(RegExpCompiler* compiler, | 4052 RegExpNode* RegExpLookahead::ToNode(RegExpCompiler* compiler, |
| 3960 RegExpNode* on_success) { | 4053 RegExpNode* on_success) { |
| 3961 int stack_pointer_register = compiler->AllocateRegister(); | 4054 int stack_pointer_register = compiler->AllocateRegister(); |
| 3962 int position_register = compiler->AllocateRegister(); | 4055 int position_register = compiler->AllocateRegister(); |
| 4056 |
| 4057 const int registers_per_capture = 2; |
| 4058 const int register_of_first_capture = 2; |
| 4059 int register_count = capture_count_ * registers_per_capture; |
| 4060 int register_start = |
| 4061 register_of_first_capture + capture_from_ * registers_per_capture; |
| 4062 |
| 3963 RegExpNode* success; | 4063 RegExpNode* success; |
| 3964 if (is_positive()) { | 4064 if (is_positive()) { |
| 3965 return ActionNode::BeginSubmatch( | 4065 RegExpNode* node = ActionNode::BeginSubmatch( |
| 3966 stack_pointer_register, | 4066 stack_pointer_register, |
| 3967 position_register, | 4067 position_register, |
| 3968 body()->ToNode( | 4068 body()->ToNode( |
| 3969 compiler, | 4069 compiler, |
| 3970 ActionNode::PositiveSubmatchSuccess(stack_pointer_register, | 4070 ActionNode::PositiveSubmatchSuccess(stack_pointer_register, |
| 3971 position_register, | 4071 position_register, |
| 4072 register_count, |
| 4073 register_start, |
| 3972 on_success))); | 4074 on_success))); |
| 4075 return node; |
| 3973 } else { | 4076 } else { |
| 3974 // We use a ChoiceNode for a negative lookahead because it has most of | 4077 // We use a ChoiceNode for a negative lookahead because it has most of |
| 3975 // the characteristics we need. It has the body of the lookahead as its | 4078 // the characteristics we need. It has the body of the lookahead as its |
| 3976 // first alternative and the expression after the lookahead of the second | 4079 // first alternative and the expression after the lookahead of the second |
| 3977 // alternative. If the first alternative succeeds then the | 4080 // alternative. If the first alternative succeeds then the |
| 3978 // NegativeSubmatchSuccess will unwind the stack including everything the | 4081 // NegativeSubmatchSuccess will unwind the stack including everything the |
| 3979 // choice node set up and backtrack. If the first alternative fails then | 4082 // choice node set up and backtrack. If the first alternative fails then |
| 3980 // the second alternative is tried, which is exactly the desired result | 4083 // the second alternative is tried, which is exactly the desired result |
| 3981 // for a negative lookahead. The NegativeLookaheadChoiceNode is a special | 4084 // for a negative lookahead. The NegativeLookaheadChoiceNode is a special |
| 3982 // ChoiceNode that knows to ignore the first exit when calculating quick | 4085 // ChoiceNode that knows to ignore the first exit when calculating quick |
| 3983 // checks. | 4086 // checks. |
| 3984 GuardedAlternative body_alt( | 4087 GuardedAlternative body_alt( |
| 3985 body()->ToNode( | 4088 body()->ToNode( |
| 3986 compiler, | 4089 compiler, |
| 3987 success = new NegativeSubmatchSuccess(stack_pointer_register, | 4090 success = new NegativeSubmatchSuccess(stack_pointer_register, |
| 3988 position_register))); | 4091 position_register, |
| 4092 register_count, |
| 4093 register_start))); |
| 3989 ChoiceNode* choice_node = | 4094 ChoiceNode* choice_node = |
| 3990 new NegativeLookaheadChoiceNode(body_alt, | 4095 new NegativeLookaheadChoiceNode(body_alt, |
| 3991 GuardedAlternative(on_success)); | 4096 GuardedAlternative(on_success)); |
| 3992 return ActionNode::BeginSubmatch(stack_pointer_register, | 4097 return ActionNode::BeginSubmatch(stack_pointer_register, |
| 3993 position_register, | 4098 position_register, |
| 3994 choice_node); | 4099 choice_node); |
| 3995 } | 4100 } |
| 3996 } | 4101 } |
| 3997 | 4102 |
| 3998 | 4103 |
| 3999 RegExpNode* RegExpCapture::ToNode(RegExpCompiler* compiler, | 4104 RegExpNode* RegExpCapture::ToNode(RegExpCompiler* compiler, |
| 4000 RegExpNode* on_success) { | 4105 RegExpNode* on_success) { |
| 4001 return ToNode(body(), index(), compiler, on_success); | 4106 return ToNode(body(), index(), compiler, on_success); |
| 4002 } | 4107 } |
| 4003 | 4108 |
| 4004 | 4109 |
| 4005 RegExpNode* RegExpCapture::ToNode(RegExpTree* body, | 4110 RegExpNode* RegExpCapture::ToNode(RegExpTree* body, |
| 4006 int index, | 4111 int index, |
| 4007 RegExpCompiler* compiler, | 4112 RegExpCompiler* compiler, |
| 4008 RegExpNode* on_success) { | 4113 RegExpNode* on_success) { |
| 4009 int start_reg = RegExpCapture::StartRegister(index); | 4114 int start_reg = RegExpCapture::StartRegister(index); |
| 4010 int end_reg = RegExpCapture::EndRegister(index); | 4115 int end_reg = RegExpCapture::EndRegister(index); |
| 4011 RegExpNode* store_end = ActionNode::StorePosition(end_reg, on_success); | 4116 RegExpNode* store_end = ActionNode::StorePosition(end_reg, true, on_success); |
| 4012 RegExpNode* body_node = body->ToNode(compiler, store_end); | 4117 RegExpNode* body_node = body->ToNode(compiler, store_end); |
| 4013 return ActionNode::StorePosition(start_reg, body_node); | 4118 return ActionNode::StorePosition(start_reg, true, body_node); |
| 4014 } | 4119 } |
| 4015 | 4120 |
| 4016 | 4121 |
| 4017 RegExpNode* RegExpAlternative::ToNode(RegExpCompiler* compiler, | 4122 RegExpNode* RegExpAlternative::ToNode(RegExpCompiler* compiler, |
| 4018 RegExpNode* on_success) { | 4123 RegExpNode* on_success) { |
| 4019 ZoneList<RegExpTree*>* children = nodes(); | 4124 ZoneList<RegExpTree*>* children = nodes(); |
| 4020 RegExpNode* current = on_success; | 4125 RegExpNode* current = on_success; |
| 4021 for (int i = children->length() - 1; i >= 0; i--) { | 4126 for (int i = children->length() - 1; i >= 0; i--) { |
| 4022 current = children->at(i)->ToNode(compiler, current); | 4127 current = children->at(i)->ToNode(compiler, current); |
| 4023 } | 4128 } |
| (...skipping 658 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4682 EmbeddedVector<byte, 1024> codes; | 4787 EmbeddedVector<byte, 1024> codes; |
| 4683 RegExpMacroAssemblerIrregexp macro_assembler(codes); | 4788 RegExpMacroAssemblerIrregexp macro_assembler(codes); |
| 4684 return compiler.Assemble(¯o_assembler, | 4789 return compiler.Assemble(¯o_assembler, |
| 4685 node, | 4790 node, |
| 4686 data->capture_count, | 4791 data->capture_count, |
| 4687 pattern); | 4792 pattern); |
| 4688 } | 4793 } |
| 4689 | 4794 |
| 4690 | 4795 |
| 4691 }} // namespace v8::internal | 4796 }} // namespace v8::internal |
| OLD | NEW |