Chromium Code Reviews| 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 974 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 985 } | 985 } |
| 986 #endif | 986 #endif |
| 987 return array; | 987 return array; |
| 988 } | 988 } |
| 989 | 989 |
| 990 | 990 |
| 991 bool RegExpNode::GoTo(RegExpCompiler* compiler) { | 991 bool RegExpNode::GoTo(RegExpCompiler* compiler) { |
| 992 // TODO(erikcorry): Implement support. | 992 // TODO(erikcorry): Implement support. |
| 993 if (info_.follows_word_interest || | 993 if (info_.follows_word_interest || |
| 994 info_.follows_newline_interest || | 994 info_.follows_newline_interest || |
| 995 info_.follows_start_interest || | 995 info_.follows_start_interest) { |
| 996 info_.at_end) { | |
| 997 return false; | 996 return false; |
| 998 } | 997 } |
| 999 if (label_.is_bound()) { | 998 if (label_.is_bound()) { |
| 1000 compiler->macro_assembler()->GoTo(&label_); | 999 compiler->macro_assembler()->GoTo(&label_); |
| 1001 return true; | 1000 return true; |
| 1002 } else { | 1001 } else { |
| 1003 if (compiler->recursion_depth() > RegExpCompiler::kMaxRecursion) { | 1002 if (compiler->recursion_depth() > RegExpCompiler::kMaxRecursion) { |
| 1004 compiler->macro_assembler()->GoTo(&label_); | 1003 compiler->macro_assembler()->GoTo(&label_); |
| 1005 compiler->AddWork(this); | 1004 compiler->AddWork(this); |
| 1006 return true; | 1005 return true; |
| 1007 } else { | 1006 } else { |
| 1008 compiler->IncrementRecursionDepth(); | 1007 compiler->IncrementRecursionDepth(); |
| 1009 bool how_it_went = Emit(compiler); | 1008 bool how_it_went = Emit(compiler); |
| 1010 compiler->DecrementRecursionDepth(); | 1009 compiler->DecrementRecursionDepth(); |
| 1011 return how_it_went; | 1010 return how_it_went; |
| 1012 } | 1011 } |
| 1013 } | 1012 } |
| 1014 } | 1013 } |
| 1015 | 1014 |
| 1016 | 1015 |
| 1016 // EndNodes are special. Because they can be very common and they are very | |
| 1017 // short we normally inline them. That is, if we are asked to emit a GoTo | |
| 1018 // we just emit the entire node. Since they don't have successors this | |
| 1019 // works. | |
| 1017 bool EndNode::GoTo(RegExpCompiler* compiler) { | 1020 bool EndNode::GoTo(RegExpCompiler* compiler) { |
| 1018 if (info()->follows_word_interest || | 1021 if (info()->follows_word_interest || |
| 1019 info()->follows_newline_interest || | 1022 info()->follows_newline_interest || |
| 1020 info()->follows_start_interest || | 1023 info()->follows_start_interest) { |
| 1021 info()->at_end) { | |
| 1022 return false; | 1024 return false; |
| 1023 } | 1025 } |
| 1024 if (!label()->is_bound()) { | 1026 return Emit(compiler); |
| 1025 Bind(compiler->macro_assembler()); | |
| 1026 } | |
| 1027 switch (action_) { | |
| 1028 case ACCEPT: | |
| 1029 compiler->macro_assembler()->Succeed(); | |
| 1030 break; | |
| 1031 case BACKTRACK: | |
| 1032 compiler->macro_assembler()->Backtrack(); | |
| 1033 break; | |
| 1034 } | |
| 1035 return true; | |
| 1036 } | 1027 } |
| 1037 | 1028 |
| 1038 | 1029 |
| 1039 Label* RegExpNode::label() { | 1030 Label* RegExpNode::label() { |
| 1040 return &label_; | 1031 return &label_; |
| 1041 } | 1032 } |
| 1042 | 1033 |
| 1043 | 1034 |
| 1044 bool EndNode::Emit(RegExpCompiler* compiler) { | 1035 bool EndNode::Emit(RegExpCompiler* compiler) { |
| 1045 RegExpMacroAssembler* macro = compiler->macro_assembler(); | 1036 RegExpMacroAssembler* macro = compiler->macro_assembler(); |
| 1046 switch (action_) { | 1037 switch (action_) { |
| 1047 case ACCEPT: | 1038 case ACCEPT: |
| 1048 Bind(macro); | 1039 if (!label()->is_bound()) Bind(macro); |
| 1040 if (info()->at_end) { | |
| 1041 Label succeed; | |
| 1042 // LoadCurrentCharacter will go to the label if we are at the end of the | |
| 1043 // input string. | |
| 1044 macro->LoadCurrentCharacter(0, &succeed); | |
| 1045 macro->Backtrack(); | |
| 1046 macro->Bind(&succeed); | |
| 1047 } | |
| 1049 macro->Succeed(); | 1048 macro->Succeed(); |
| 1050 return true; | 1049 return true; |
| 1051 case BACKTRACK: | 1050 case BACKTRACK: |
| 1052 Bind(macro); | 1051 if (!label()->is_bound()) Bind(macro); |
| 1052 ASSERT(!info()->at_end); | |
| 1053 macro->Backtrack(); | 1053 macro->Backtrack(); |
| 1054 return true; | 1054 return true; |
| 1055 } | 1055 } |
| 1056 return false; | 1056 return false; |
| 1057 } | 1057 } |
| 1058 | 1058 |
| 1059 | 1059 |
| 1060 void GuardedAlternative::AddGuard(Guard* guard) { | 1060 void GuardedAlternative::AddGuard(Guard* guard) { |
| 1061 if (guards_ == NULL) | 1061 if (guards_ == NULL) |
| 1062 guards_ = new ZoneList<Guard*>(1); | 1062 guards_ = new ZoneList<Guard*>(1); |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 1081 } | 1081 } |
| 1082 | 1082 |
| 1083 | 1083 |
| 1084 ActionNode* ActionNode::StorePosition(int reg, RegExpNode* on_success) { | 1084 ActionNode* ActionNode::StorePosition(int reg, RegExpNode* on_success) { |
| 1085 ActionNode* result = new ActionNode(STORE_POSITION, on_success); | 1085 ActionNode* result = new ActionNode(STORE_POSITION, on_success); |
| 1086 result->data_.u_position_register.reg = reg; | 1086 result->data_.u_position_register.reg = reg; |
| 1087 return result; | 1087 return result; |
| 1088 } | 1088 } |
| 1089 | 1089 |
| 1090 | 1090 |
| 1091 ActionNode* ActionNode::SavePosition(int reg, RegExpNode* on_success) { | |
| 1092 ActionNode* result = new ActionNode(SAVE_POSITION, on_success); | |
| 1093 result->data_.u_position_register.reg = reg; | |
| 1094 return result; | |
| 1095 } | |
| 1096 | |
| 1097 | |
| 1098 ActionNode* ActionNode::RestorePosition(int reg, RegExpNode* on_success) { | 1091 ActionNode* ActionNode::RestorePosition(int reg, RegExpNode* on_success) { |
| 1099 ActionNode* result = new ActionNode(RESTORE_POSITION, on_success); | 1092 ActionNode* result = new ActionNode(RESTORE_POSITION, on_success); |
| 1100 result->data_.u_position_register.reg = reg; | 1093 result->data_.u_position_register.reg = reg; |
| 1101 return result; | 1094 return result; |
| 1102 } | 1095 } |
| 1103 | 1096 |
| 1104 | 1097 |
| 1105 ActionNode* ActionNode::BeginSubmatch(int reg, RegExpNode* on_success) { | 1098 ActionNode* ActionNode::BeginSubmatch(int stack_reg, |
| 1099 int position_reg, | |
| 1100 RegExpNode* on_success) { | |
| 1106 ActionNode* result = new ActionNode(BEGIN_SUBMATCH, on_success); | 1101 ActionNode* result = new ActionNode(BEGIN_SUBMATCH, on_success); |
| 1107 result->data_.u_submatch_stack_pointer_register.reg = reg; | 1102 result->data_.u_submatch.stack_pointer_register = stack_reg; |
| 1103 result->data_.u_submatch.current_position_register = position_reg; | |
| 1108 return result; | 1104 return result; |
| 1109 } | 1105 } |
| 1110 | 1106 |
| 1111 | 1107 |
| 1112 ActionNode* ActionNode::EscapeSubmatch(int reg, RegExpNode* on_success) { | 1108 ActionNode* ActionNode::EscapeSubmatch(int stack_reg, |
| 1109 bool restore_position, | |
| 1110 int position_reg, | |
| 1111 RegExpNode* on_success) { | |
| 1113 ActionNode* result = new ActionNode(ESCAPE_SUBMATCH, on_success); | 1112 ActionNode* result = new ActionNode(ESCAPE_SUBMATCH, on_success); |
| 1114 result->data_.u_submatch_stack_pointer_register.reg = reg; | 1113 result->data_.u_submatch.stack_pointer_register = stack_reg; |
| 1114 if (restore_position) { | |
| 1115 result->data_.u_submatch.current_position_register = position_reg; | |
| 1116 } else { | |
| 1117 result->data_.u_submatch.current_position_register = -1; | |
| 1118 } | |
| 1115 return result; | 1119 return result; |
| 1116 } | 1120 } |
| 1117 | 1121 |
| 1118 | 1122 |
| 1119 #define DEFINE_ACCEPT(Type) \ | 1123 #define DEFINE_ACCEPT(Type) \ |
| 1120 void Type##Node::Accept(NodeVisitor* visitor) { \ | 1124 void Type##Node::Accept(NodeVisitor* visitor) { \ |
| 1121 visitor->Visit##Type(this); \ | 1125 visitor->Visit##Type(this); \ |
| 1122 } | 1126 } |
| 1123 FOR_EACH_NODE_TYPE(DEFINE_ACCEPT) | 1127 FOR_EACH_NODE_TYPE(DEFINE_ACCEPT) |
| 1124 #undef DEFINE_ACCEPT | 1128 #undef DEFINE_ACCEPT |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1313 } | 1317 } |
| 1314 macro_assembler->Bind(&success); | 1318 macro_assembler->Bind(&success); |
| 1315 } | 1319 } |
| 1316 | 1320 |
| 1317 | 1321 |
| 1318 | 1322 |
| 1319 bool TextNode::Emit(RegExpCompiler* compiler) { | 1323 bool TextNode::Emit(RegExpCompiler* compiler) { |
| 1320 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); | 1324 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); |
| 1321 Bind(macro_assembler); | 1325 Bind(macro_assembler); |
| 1322 int element_count = elms_->length(); | 1326 int element_count = elms_->length(); |
| 1327 ASSERT(element_count != 0); | |
| 1323 int cp_offset = 0; | 1328 int cp_offset = 0; |
| 1329 if (info()->at_end) { | |
| 1330 macro_assembler->Backtrack(); | |
| 1331 return true; | |
| 1332 } | |
| 1324 // First, handle straight character matches. | 1333 // First, handle straight character matches. |
| 1325 for (int i = 0; i < element_count; i++) { | 1334 for (int i = 0; i < element_count; i++) { |
| 1326 TextElement elm = elms_->at(i); | 1335 TextElement elm = elms_->at(i); |
| 1327 if (elm.type == TextElement::ATOM) { | 1336 if (elm.type == TextElement::ATOM) { |
| 1328 Vector<const uc16> quarks = elm.data.u_atom->data(); | 1337 Vector<const uc16> quarks = elm.data.u_atom->data(); |
| 1329 if (compiler->ignore_case()) { | 1338 if (compiler->ignore_case()) { |
| 1330 EmitAtomNonLetters(macro_assembler, | 1339 EmitAtomNonLetters(macro_assembler, |
| 1331 elm, | 1340 elm, |
| 1332 quarks, | 1341 quarks, |
| 1333 on_failure_->label(), | 1342 on_failure_->label(), |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1474 bool ok = on_success()->GoTo(compiler); | 1483 bool ok = on_success()->GoTo(compiler); |
| 1475 if (!ok) { | 1484 if (!ok) { |
| 1476 undo.Unuse(); | 1485 undo.Unuse(); |
| 1477 return false; | 1486 return false; |
| 1478 } | 1487 } |
| 1479 macro->Bind(&undo); | 1488 macro->Bind(&undo); |
| 1480 macro->PopRegister(data_.u_position_register.reg); | 1489 macro->PopRegister(data_.u_position_register.reg); |
| 1481 macro->Backtrack(); | 1490 macro->Backtrack(); |
| 1482 break; | 1491 break; |
| 1483 } | 1492 } |
| 1484 case SAVE_POSITION: | |
| 1485 macro->WriteCurrentPositionToRegister( | |
| 1486 data_.u_position_register.reg); | |
| 1487 break; | |
| 1488 case RESTORE_POSITION: | 1493 case RESTORE_POSITION: |
| 1489 macro->ReadCurrentPositionFromRegister( | 1494 macro->ReadCurrentPositionFromRegister( |
| 1490 data_.u_position_register.reg); | 1495 data_.u_position_register.reg); |
| 1491 break; | 1496 break; |
| 1492 case BEGIN_SUBMATCH: | 1497 case BEGIN_SUBMATCH: |
| 1498 macro->WriteCurrentPositionToRegister( | |
| 1499 data_.u_submatch.current_position_register); | |
| 1493 macro->WriteStackPointerToRegister( | 1500 macro->WriteStackPointerToRegister( |
| 1494 data_.u_submatch_stack_pointer_register.reg); | 1501 data_.u_submatch.stack_pointer_register); |
| 1495 break; | 1502 break; |
| 1496 case ESCAPE_SUBMATCH: | 1503 case ESCAPE_SUBMATCH: |
| 1504 if (info()->at_end) { | |
| 1505 Label at_end; | |
| 1506 // Load current character jumps to the label if we are beyond the string | |
| 1507 // end. | |
| 1508 macro->LoadCurrentCharacter(0, &at_end); | |
| 1509 macro->Backtrack(); | |
| 1510 macro->Bind(&at_end); | |
| 1511 } | |
| 1512 if (data_.u_submatch.current_position_register != -1) { | |
| 1513 macro->ReadCurrentPositionFromRegister( | |
| 1514 data_.u_submatch.current_position_register); | |
| 1515 } | |
| 1497 macro->ReadStackPointerFromRegister( | 1516 macro->ReadStackPointerFromRegister( |
| 1498 data_.u_submatch_stack_pointer_register.reg); | 1517 data_.u_submatch.stack_pointer_register); |
| 1499 break; | 1518 break; |
| 1500 default: | 1519 default: |
| 1501 UNREACHABLE(); | 1520 UNREACHABLE(); |
| 1502 return false; | 1521 return false; |
| 1503 } | 1522 } |
| 1504 return on_success()->GoTo(compiler); | 1523 return on_success()->GoTo(compiler); |
| 1505 } | 1524 } |
| 1506 | 1525 |
| 1507 | 1526 |
| 1508 bool BackReferenceNode::Emit(RegExpCompiler* compiler) { | 1527 bool BackReferenceNode::Emit(RegExpCompiler* compiler) { |
| 1509 RegExpMacroAssembler* macro = compiler->macro_assembler(); | 1528 RegExpMacroAssembler* macro = compiler->macro_assembler(); |
| 1510 Bind(macro); | 1529 Bind(macro); |
| 1511 // Check whether the registers are uninitialized and always | 1530 // Check whether the registers are uninitialized and always |
| 1512 // succeed if they are. | 1531 // succeed if they are. |
| 1513 macro->IfRegisterLT(start_reg_, 0, on_success()->label()); | 1532 macro->IfRegisterLT(start_reg_, 0, on_success()->label()); |
| 1514 macro->IfRegisterLT(end_reg_, 0, on_success()->label()); | 1533 macro->IfRegisterLT(end_reg_, 0, on_success()->label()); |
| 1515 ASSERT_EQ(start_reg_ + 1, end_reg_); | 1534 ASSERT_EQ(start_reg_ + 1, end_reg_); |
| 1516 if (compiler->ignore_case()) { | 1535 if (info()->at_end) { |
| 1517 macro->CheckNotBackReferenceIgnoreCase(start_reg_, on_failure_->label()); | 1536 // If we are constrained to match at the end of the input then succeed |
| 1537 // iff the back reference is empty. | |
| 1538 macro->CheckNotRegistersEqual(start_reg_, end_reg_, on_failure_->label()); | |
| 1518 } else { | 1539 } else { |
| 1519 macro->CheckNotBackReference(start_reg_, on_failure_->label()); | 1540 if (compiler->ignore_case()) { |
| 1541 macro->CheckNotBackReferenceIgnoreCase(start_reg_, on_failure_->label()); | |
| 1542 } else { | |
| 1543 macro->CheckNotBackReference(start_reg_, on_failure_->label()); | |
| 1544 } | |
| 1520 } | 1545 } |
| 1521 return on_success()->GoTo(compiler); | 1546 return on_success()->GoTo(compiler); |
| 1522 } | 1547 } |
| 1523 | 1548 |
| 1524 | 1549 |
| 1525 // ------------------------------------------------------------------- | 1550 // ------------------------------------------------------------------- |
| 1526 // Dot/dotty output | 1551 // Dot/dotty output |
| 1527 | 1552 |
| 1528 | 1553 |
| 1529 #ifdef DEBUG | 1554 #ifdef DEBUG |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1744 that->data_.u_store_register.value); | 1769 that->data_.u_store_register.value); |
| 1745 break; | 1770 break; |
| 1746 case ActionNode::INCREMENT_REGISTER: | 1771 case ActionNode::INCREMENT_REGISTER: |
| 1747 stream()->Add("label=\"$%i++\", shape=octagon", | 1772 stream()->Add("label=\"$%i++\", shape=octagon", |
| 1748 that->data_.u_increment_register.reg); | 1773 that->data_.u_increment_register.reg); |
| 1749 break; | 1774 break; |
| 1750 case ActionNode::STORE_POSITION: | 1775 case ActionNode::STORE_POSITION: |
| 1751 stream()->Add("label=\"$%i:=$pos\", shape=octagon", | 1776 stream()->Add("label=\"$%i:=$pos\", shape=octagon", |
| 1752 that->data_.u_position_register.reg); | 1777 that->data_.u_position_register.reg); |
| 1753 break; | 1778 break; |
| 1754 case ActionNode::SAVE_POSITION: | |
| 1755 stream()->Add("label=\"$%i:=$pos\", shape=octagon", | |
| 1756 that->data_.u_position_register.reg); | |
| 1757 break; | |
| 1758 case ActionNode::RESTORE_POSITION: | 1779 case ActionNode::RESTORE_POSITION: |
| 1759 stream()->Add("label=\"$pos:=$%i\", shape=octagon", | 1780 stream()->Add("label=\"$pos:=$%i\", shape=octagon", |
| 1760 that->data_.u_position_register.reg); | 1781 that->data_.u_position_register.reg); |
| 1761 break; | 1782 break; |
| 1762 case ActionNode::BEGIN_SUBMATCH: | 1783 case ActionNode::BEGIN_SUBMATCH: |
| 1763 stream()->Add("label=\"begin\", shape=septagon"); | 1784 stream()->Add("label=\"$%i:=$pos,begin\", shape=septagon", |
| 1785 that->data_.u_submatch.current_position_register); | |
| 1764 break; | 1786 break; |
| 1765 case ActionNode::ESCAPE_SUBMATCH: | 1787 case ActionNode::ESCAPE_SUBMATCH: |
| 1766 stream()->Add("label=\"escape\", shape=septagon"); | 1788 stream()->Add("label=\"escape\", shape=septagon"); |
| 1767 break; | 1789 break; |
| 1768 } | 1790 } |
| 1769 stream()->Add("];\n"); | 1791 stream()->Add("];\n"); |
| 1770 PrintAttributes(that); | 1792 PrintAttributes(that); |
| 1771 stream()->Add(" n%p -> n%p;\n", that, that->on_success()); | 1793 stream()->Add(" n%p -> n%p;\n", that, that->on_success()); |
| 1772 Visit(that->on_success()); | 1794 Visit(that->on_success()); |
| 1773 } | 1795 } |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1984 // if [body] | 2006 // if [body] |
| 1985 // then | 2007 // then |
| 1986 // $pos = $reg | 2008 // $pos = $reg |
| 1987 // escape submatch scope (drop all backtracks created in scope) | 2009 // escape submatch scope (drop all backtracks created in scope) |
| 1988 // succeed | 2010 // succeed |
| 1989 // else | 2011 // else |
| 1990 // end submatch scope (nothing to clean up, just exit the scope) | 2012 // end submatch scope (nothing to clean up, just exit the scope) |
| 1991 // fail | 2013 // fail |
| 1992 return ActionNode::BeginSubmatch( | 2014 return ActionNode::BeginSubmatch( |
| 1993 stack_pointer_register, | 2015 stack_pointer_register, |
| 1994 ActionNode::SavePosition( | 2016 position_register, |
| 1995 position_register, | 2017 body()->ToNode( |
| 1996 body()->ToNode( | 2018 compiler, |
| 1997 compiler, | 2019 ActionNode::EscapeSubmatch( |
| 1998 ActionNode::RestorePosition( | 2020 stack_pointer_register, |
| 1999 position_register, | 2021 true, // Also restore input position. |
| 2000 ActionNode::EscapeSubmatch(stack_pointer_register, | 2022 position_register, |
| 2001 on_success)), | 2023 on_success), |
| 2002 on_failure))); | 2024 on_failure)); |
| 2003 } else { | 2025 } else { |
| 2004 // begin submatch scope | 2026 // begin submatch scope |
| 2005 // try | 2027 // try |
| 2006 // first if (body) | 2028 // first if (body) |
| 2007 // then | 2029 // then |
| 2008 // escape submatch scope | 2030 // escape submatch scope |
| 2009 // fail | 2031 // fail |
| 2010 // else | 2032 // else |
| 2011 // backtrack | 2033 // backtrack |
| 2012 // second | 2034 // second |
| 2013 // end submatch scope | 2035 // end submatch scope |
| 2014 // restore current position | 2036 // restore current position |
| 2015 // succeed | 2037 // succeed |
| 2016 ChoiceNode* try_node = | 2038 ChoiceNode* try_node = |
| 2017 new ChoiceNode(1, ActionNode::RestorePosition(position_register, | 2039 new ChoiceNode(1, ActionNode::RestorePosition(position_register, |
| 2018 on_success)); | 2040 on_success)); |
| 2019 RegExpNode* body_node = body()->ToNode( | 2041 RegExpNode* body_node = body()->ToNode( |
| 2020 compiler, | 2042 compiler, |
| 2021 ActionNode::EscapeSubmatch(stack_pointer_register, on_failure), | 2043 ActionNode::EscapeSubmatch(stack_pointer_register, |
| 2044 false, // Don't also restore position | |
| 2045 0, // Unused arguments. | |
| 2046 on_failure), | |
| 2022 compiler->backtrack()); | 2047 compiler->backtrack()); |
| 2023 GuardedAlternative body_alt(body_node); | 2048 GuardedAlternative body_alt(body_node); |
| 2024 try_node->AddAlternative(body_alt); | 2049 try_node->AddAlternative(body_alt); |
| 2025 return ActionNode::BeginSubmatch(stack_pointer_register, | 2050 return ActionNode::BeginSubmatch(stack_pointer_register, |
| 2026 ActionNode::SavePosition( | 2051 position_register, |
| 2027 position_register, | 2052 try_node); |
| 2028 try_node)); | |
| 2029 } | 2053 } |
| 2030 } | 2054 } |
| 2031 | 2055 |
| 2032 | 2056 |
| 2033 RegExpNode* RegExpCapture::ToNode(RegExpCompiler* compiler, | 2057 RegExpNode* RegExpCapture::ToNode(RegExpCompiler* compiler, |
| 2034 RegExpNode* on_success, | 2058 RegExpNode* on_success, |
| 2035 RegExpNode* on_failure) { | 2059 RegExpNode* on_failure) { |
| 2036 return ToNode(body(), index(), compiler, on_success, on_failure); | 2060 return ToNode(body(), index(), compiler, on_success, on_failure); |
| 2037 } | 2061 } |
| 2038 | 2062 |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2263 | 2287 |
| 2264 RegExpNode* ActionNode::PropagateForward(NodeInfo* info) { | 2288 RegExpNode* ActionNode::PropagateForward(NodeInfo* info) { |
| 2265 NodeInfo full_info(*this->info()); | 2289 NodeInfo full_info(*this->info()); |
| 2266 full_info.AddFromPreceding(info); | 2290 full_info.AddFromPreceding(info); |
| 2267 RegExpNode* sibling = GetSibling(&full_info); | 2291 RegExpNode* sibling = GetSibling(&full_info); |
| 2268 if (sibling != NULL) return sibling; | 2292 if (sibling != NULL) return sibling; |
| 2269 EnsureSiblings(); | 2293 EnsureSiblings(); |
| 2270 ActionNode* action = new ActionNode(*this); | 2294 ActionNode* action = new ActionNode(*this); |
| 2271 action->info()->AddFromPreceding(&full_info); | 2295 action->info()->AddFromPreceding(&full_info); |
| 2272 AddSibling(action); | 2296 AddSibling(action); |
| 2273 action->set_on_success(action->on_success()->PropagateForward(info)); | 2297 if (type_ != ESCAPE_SUBMATCH) { |
| 2298 action->set_on_success(action->on_success()->PropagateForward(info)); | |
| 2299 } | |
| 2274 return action; | 2300 return action; |
| 2275 } | 2301 } |
| 2276 | 2302 |
| 2277 | 2303 |
| 2278 RegExpNode* ChoiceNode::PropagateForward(NodeInfo* info) { | 2304 RegExpNode* ChoiceNode::PropagateForward(NodeInfo* info) { |
| 2279 NodeInfo full_info(*this->info()); | 2305 NodeInfo full_info(*this->info()); |
| 2280 full_info.AddFromPreceding(info); | 2306 full_info.AddFromPreceding(info); |
| 2281 RegExpNode* sibling = GetSibling(&full_info); | 2307 RegExpNode* sibling = GetSibling(&full_info); |
| 2282 if (sibling != NULL) return sibling; | 2308 if (sibling != NULL) return sibling; |
| 2283 EnsureSiblings(); | 2309 EnsureSiblings(); |
| 2284 ChoiceNode* choice = new ChoiceNode(*this); | 2310 ChoiceNode* choice = new ChoiceNode(*this); |
| 2285 choice->info()->AddFromPreceding(&full_info); | 2311 choice->info()->AddFromPreceding(&full_info); |
| 2286 AddSibling(choice); | 2312 AddSibling(choice); |
| 2287 ZoneList<GuardedAlternative>* old_alternatives = alternatives(); | 2313 ZoneList<GuardedAlternative>* old_alternatives = alternatives(); |
| 2288 int count = old_alternatives->length(); | 2314 int count = old_alternatives->length(); |
| 2289 choice->alternatives_ = new ZoneList<GuardedAlternative>(count); | 2315 choice->alternatives_ = new ZoneList<GuardedAlternative>(count); |
| 2290 for (int i = 0; i < count; i++) { | 2316 for (int i = 0; i < count; i++) { |
| 2291 GuardedAlternative alternative = old_alternatives->at(i); | 2317 GuardedAlternative alternative = old_alternatives->at(i); |
| 2292 alternative.set_node(alternative.node()->PropagateForward(info)); | 2318 alternative.set_node(alternative.node()->PropagateForward(info)); |
| 2293 choice->alternatives()->Add(alternative); | 2319 choice->alternatives()->Add(alternative); |
| 2294 } | 2320 } |
| 2321 if (!choice->on_failure_->IsBacktrack()) { | |
| 2322 choice->on_failure_ = choice->on_failure_->PropagateForward(info); | |
| 2323 } | |
| 2295 return choice; | 2324 return choice; |
| 2296 } | 2325 } |
| 2297 | 2326 |
| 2298 | 2327 |
| 2299 RegExpNode* EndNode::PropagateForward(NodeInfo* info) { | 2328 RegExpNode* EndNode::PropagateForward(NodeInfo* info) { |
| 2300 return PropagateToEndpoint(this, info); | 2329 return PropagateToEndpoint(this, info); |
| 2301 } | 2330 } |
| 2302 | 2331 |
| 2303 | 2332 |
| 2304 RegExpNode* BackReferenceNode::PropagateForward(NodeInfo* info) { | 2333 RegExpNode* BackReferenceNode::PropagateForward(NodeInfo* info) { |
| 2305 return PropagateToEndpoint(this, info); | 2334 NodeInfo full_info(*this->info()); |
| 2335 full_info.AddFromPreceding(info); | |
| 2336 RegExpNode* sibling = GetSibling(&full_info); | |
| 2337 if (sibling != NULL) return sibling; | |
| 2338 EnsureSiblings(); | |
| 2339 BackReferenceNode* back_ref = new BackReferenceNode(*this); | |
| 2340 back_ref->info()->AddFromPreceding(&full_info); | |
| 2341 AddSibling(back_ref); | |
| 2342 // TODO(erikcorry): A back reference has to have two successors (by default | |
|
Christian Plesner Hansen
2008/11/28 08:44:53
I wonder if maybe we always have to propagate to t
| |
| 2343 // the same node). The first is used if the back reference matches a non- | |
| 2344 // empty back reference, the second if it matches an empty one. This doesn't | |
| 2345 // matter for at_end, which is the only one implemented right now, but it will | |
| 2346 // matter for other pieces of info. | |
| 2347 back_ref->set_on_success(back_ref->on_success()->PropagateForward(info)); | |
| 2348 return back_ref; | |
| 2306 } | 2349 } |
| 2307 | 2350 |
| 2308 | 2351 |
| 2309 RegExpNode* TextNode::PropagateForward(NodeInfo* info) { | 2352 RegExpNode* TextNode::PropagateForward(NodeInfo* info) { |
| 2310 return PropagateToEndpoint(this, info); | 2353 return PropagateToEndpoint(this, info); |
| 2311 } | 2354 } |
| 2312 | 2355 |
| 2313 | 2356 |
| 2314 // ------------------------------------------------------------------- | 2357 // ------------------------------------------------------------------- |
| 2315 // Splay tree | 2358 // Splay tree |
| (...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2665 captured_body, | 2708 captured_body, |
| 2666 compiler.backtrack()); | 2709 compiler.backtrack()); |
| 2667 if (node_return != NULL) *node_return = node; | 2710 if (node_return != NULL) *node_return = node; |
| 2668 Analysis analysis(ignore_case); | 2711 Analysis analysis(ignore_case); |
| 2669 analysis.EnsureAnalyzed(node); | 2712 analysis.EnsureAnalyzed(node); |
| 2670 | 2713 |
| 2671 if (!FLAG_irregexp) { | 2714 if (!FLAG_irregexp) { |
| 2672 return Handle<FixedArray>::null(); | 2715 return Handle<FixedArray>::null(); |
| 2673 } | 2716 } |
| 2674 | 2717 |
| 2718 if (is_multiline && !FLAG_attempt_multiline_irregexp) { | |
| 2719 return Handle<FixedArray>::null(); | |
| 2720 } | |
| 2721 | |
| 2675 if (FLAG_irregexp_native) { | 2722 if (FLAG_irregexp_native) { |
| 2676 #ifdef ARM | 2723 #ifdef ARM |
| 2677 UNIMPLEMENTED(); | 2724 UNIMPLEMENTED(); |
| 2678 #else // IA32 | 2725 #else // IA32 |
| 2679 RegExpMacroAssemblerIA32 macro_assembler(RegExpMacroAssemblerIA32::UC16, | 2726 RegExpMacroAssemblerIA32 macro_assembler(RegExpMacroAssemblerIA32::UC16, |
| 2680 (input->capture_count + 1) * 2); | 2727 (input->capture_count + 1) * 2); |
| 2681 return compiler.Assemble(¯o_assembler, | 2728 return compiler.Assemble(¯o_assembler, |
| 2682 node, | 2729 node, |
| 2683 input->capture_count); | 2730 input->capture_count); |
| 2684 #endif | 2731 #endif |
| 2685 } | 2732 } |
| 2686 byte codes[1024]; | 2733 byte codes[1024]; |
| 2687 IrregexpAssembler assembler(Vector<byte>(codes, 1024)); | 2734 IrregexpAssembler assembler(Vector<byte>(codes, 1024)); |
| 2688 RegExpMacroAssemblerIrregexp macro_assembler(&assembler); | 2735 RegExpMacroAssemblerIrregexp macro_assembler(&assembler); |
| 2689 return compiler.Assemble(¯o_assembler, | 2736 return compiler.Assemble(¯o_assembler, |
| 2690 node, | 2737 node, |
| 2691 input->capture_count); | 2738 input->capture_count); |
| 2692 } | 2739 } |
| 2693 | 2740 |
| 2694 | 2741 |
| 2695 }} // namespace v8::internal | 2742 }} // namespace v8::internal |
| OLD | NEW |