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