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

Side by Side Diff: src/jsregexp.cc

Issue 18744: * Irregexp: Handle backtrack past look-ahead. (Closed)
Patch Set: 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 1343 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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 &registers_to_pop,
1542 &registers_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
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
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
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
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
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
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
4682 EmbeddedVector<byte, 1024> codes; 4787 EmbeddedVector<byte, 1024> codes;
4683 RegExpMacroAssemblerIrregexp macro_assembler(codes); 4788 RegExpMacroAssemblerIrregexp macro_assembler(codes);
4684 return compiler.Assemble(&macro_assembler, 4789 return compiler.Assemble(&macro_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
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