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

Side by Side Diff: src/jsregexp.cc

Issue 18708: Irregexp Issue 187: Captures in look-aheads are correctly cleared when backtracking. (Closed)
Patch Set: Addressed review comments Created 11 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/jsregexp.h ('k') | src/parser.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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 &registers_to_pop,
1541 &registers_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
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
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
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
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
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
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
4681 EmbeddedVector<byte, 1024> codes; 4786 EmbeddedVector<byte, 1024> codes;
4682 RegExpMacroAssemblerIrregexp macro_assembler(codes); 4787 RegExpMacroAssemblerIrregexp macro_assembler(codes);
4683 return compiler.Assemble(&macro_assembler, 4788 return compiler.Assemble(&macro_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
OLDNEW
« no previous file with comments | « src/jsregexp.h ('k') | src/parser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698