Improve regex performance on msvc by removing statically allocated recursion stack, and using a std::vector instead.

[SVN r59414]
This commit is contained in:
John Maddock
2010-02-01 13:10:28 +00:00
parent c8e56504d9
commit d686c89333
5 changed files with 63 additions and 51 deletions

View File

@ -366,7 +366,7 @@ public:
BidiIterator l_base) BidiIterator l_base)
: m_result(what), base(first), last(end), : m_result(what), base(first), last(end),
position(first), backstop(l_base), re(e), traits_inst(e.get_traits()), position(first), backstop(l_base), re(e), traits_inst(e.get_traits()),
m_independent(false), next_count(&rep_obj), rep_obj(&next_count), recursion_stack_position(0) m_independent(false), next_count(&rep_obj), rep_obj(&next_count)/*, recursion_stack_position(0)*/
{ {
construct_init(e, f); construct_init(e, f);
} }
@ -488,8 +488,8 @@ private:
// the bitmask to use when determining whether a match_any matches a newline or not: // the bitmask to use when determining whether a match_any matches a newline or not:
unsigned char match_any_mask; unsigned char match_any_mask;
// recursion information: // recursion information:
recursion_info<results_type> recursion_stack[50]; std::vector<recursion_info<results_type> > recursion_stack;
unsigned recursion_stack_position; //unsigned recursion_stack_position;
#ifdef BOOST_REGEX_NON_RECURSIVE #ifdef BOOST_REGEX_NON_RECURSIVE
// //

View File

@ -735,7 +735,7 @@ inline bool perl_matcher<BidiIterator, Allocator, traits>::match_assert_backref(
int id = -index-1; int id = -index-1;
if(id >= 10000) if(id >= 10000)
id = re.get_data().get_id(id); id = re.get_data().get_id(id);
result = recursion_stack_position && ((recursion_stack[recursion_stack_position-1].id == id) || (index == 0)); result = !recursion_stack.empty() && ((recursion_stack.back().id == id) || (index == 0));
pstate = pstate->next.p; pstate = pstate->next.p;
} }
return result; return result;

View File

@ -898,19 +898,20 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_recursion()
// //
// Set new call stack: // Set new call stack:
// //
if(recursion_stack_position >= static_cast<int>(sizeof(recursion_stack)/sizeof(recursion_stack[0]))) if(recursion_stack.capacity() == 0)
{ {
return false; recursion_stack.reserve(50);
} }
recursion_stack[recursion_stack_position].preturn_address = pstate->next.p; recursion_stack.push_back(recursion_info<results_type>());
recursion_stack[recursion_stack_position].results = *m_presult; recursion_stack.back().preturn_address = pstate->next.p;
recursion_stack.back().results = *m_presult;
if(static_cast<const re_recurse*>(pstate)->state_id > 0) if(static_cast<const re_recurse*>(pstate)->state_id > 0)
{ {
push_repeater_count(static_cast<const re_recurse*>(pstate)->state_id, &next_count); push_repeater_count(static_cast<const re_recurse*>(pstate)->state_id, &next_count);
} }
pstate = static_cast<const re_jump*>(pstate)->alt.p; pstate = static_cast<const re_jump*>(pstate)->alt.p;
recursion_stack[recursion_stack_position].id = static_cast<const re_brace*>(pstate)->index; recursion_stack.back().id = static_cast<const re_brace*>(pstate)->index;
++recursion_stack_position; //++recursion_stack_position;
//BOOST_ASSERT(recursion_stack[recursion_stack_position-1].id); //BOOST_ASSERT(recursion_stack[recursion_stack_position-1].id);
return true; return true;
@ -927,14 +928,15 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_endmark()
{ {
m_presult->set_second(position, index); m_presult->set_second(position, index);
} }
if(recursion_stack_position) if(!recursion_stack.empty())
{ {
if(index == recursion_stack[recursion_stack_position-1].id) if(index == recursion_stack.back().id)
{ {
--recursion_stack_position; //--recursion_stack_position;
pstate = recursion_stack[recursion_stack_position].preturn_address; pstate = recursion_stack.back().preturn_address;
*m_presult = recursion_stack[recursion_stack_position].results; *m_presult = recursion_stack.back().results;
push_recursion(recursion_stack[recursion_stack_position].id, recursion_stack[recursion_stack_position].preturn_address, &recursion_stack[recursion_stack_position].results); push_recursion(recursion_stack.back().id, recursion_stack.back().preturn_address, &recursion_stack.back().results);
recursion_stack.pop_back();
} }
} }
} }
@ -951,13 +953,14 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_endmark()
template <class BidiIterator, class Allocator, class traits> template <class BidiIterator, class Allocator, class traits>
bool perl_matcher<BidiIterator, Allocator, traits>::match_match() bool perl_matcher<BidiIterator, Allocator, traits>::match_match()
{ {
if(recursion_stack_position) if(!recursion_stack.empty())
{ {
BOOST_ASSERT(0 == recursion_stack[recursion_stack_position-1].id); BOOST_ASSERT(0 == recursion_stack.back().id);
--recursion_stack_position; //--recursion_stack_position;
pstate = recursion_stack[recursion_stack_position].preturn_address; pstate = recursion_stack.back().preturn_address;
*m_presult = recursion_stack[recursion_stack_position].results; *m_presult = recursion_stack.back().results;
push_recursion(recursion_stack[recursion_stack_position].id, recursion_stack[recursion_stack_position].preturn_address, &recursion_stack[recursion_stack_position].results); push_recursion(recursion_stack.back().id, recursion_stack.back().preturn_address, &recursion_stack.back().results);
recursion_stack.pop_back();
return true; return true;
} }
if((m_match_flags & match_not_null) && (position == (*m_presult)[0].first)) if((m_match_flags & match_not_null) && (position == (*m_presult)[0].first))
@ -1523,10 +1526,11 @@ bool perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion(bool r)
saved_recursion<results_type>* pmp = static_cast<saved_recursion<results_type>*>(m_backup_state); saved_recursion<results_type>* pmp = static_cast<saved_recursion<results_type>*>(m_backup_state);
if(!r) if(!r)
{ {
recursion_stack[recursion_stack_position].id = pmp->recursion_id; recursion_stack.push_back(recursion_info<results_type>());
recursion_stack[recursion_stack_position].preturn_address = pmp->preturn_address; recursion_stack.back().id = pmp->recursion_id;
recursion_stack[recursion_stack_position].results = pmp->results; recursion_stack.back().preturn_address = pmp->preturn_address;
++recursion_stack_position; recursion_stack.back().results = pmp->results;
//++recursion_stack_position;
} }
boost::re_detail::inplace_destroy(pmp++); boost::re_detail::inplace_destroy(pmp++);
m_backup_state = pmp; m_backup_state = pmp;
@ -1539,7 +1543,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_pop(bool r)
saved_state* pmp = static_cast<saved_state*>(m_backup_state); saved_state* pmp = static_cast<saved_state*>(m_backup_state);
if(!r) if(!r)
{ {
--recursion_stack_position; recursion_stack.pop_back();
} }
boost::re_detail::inplace_destroy(pmp++); boost::re_detail::inplace_destroy(pmp++);
m_backup_state = pmp; m_backup_state = pmp;

View File

@ -857,16 +857,17 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_recursion()
// //
// Set new call stack: // Set new call stack:
// //
if(recursion_stack_position >= static_cast<int>(sizeof(recursion_stack)/sizeof(recursion_stack[0]))) if(recursion_stack.capacity() == 0)
{ {
return false; recursion_stack.reserve(50);
} }
recursion_stack[recursion_stack_position].preturn_address = pstate->next.p; recursion_stack.push_back(recursion_info<results_type>());
recursion_stack[recursion_stack_position].results = *m_presult; recursion_stack.back().preturn_address = pstate->next.p;
recursion_stack[recursion_stack_position].repeater_stack = next_count; recursion_stack.back().results = *m_presult;
recursion_stack.back().repeater_stack = next_count;
pstate = static_cast<const re_jump*>(pstate)->alt.p; pstate = static_cast<const re_jump*>(pstate)->alt.p;
recursion_stack[recursion_stack_position].id = static_cast<const re_brace*>(pstate)->index; recursion_stack.back().id = static_cast<const re_brace*>(pstate)->index;
++recursion_stack_position; //++recursion_stack_position;
repeater_count<BidiIterator>* saved = next_count; repeater_count<BidiIterator>* saved = next_count;
repeater_count<BidiIterator> r(&next_count); // resets all repeat counts since we're recursing and starting fresh on those repeater_count<BidiIterator> r(&next_count); // resets all repeat counts since we're recursing and starting fresh on those
@ -876,9 +877,10 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_recursion()
if(!result) if(!result)
{ {
--recursion_stack_position; //--recursion_stack_position;
next_count = recursion_stack[recursion_stack_position].repeater_stack; next_count = recursion_stack.back().repeater_stack;
*m_presult = recursion_stack[recursion_stack_position].results; *m_presult = recursion_stack.back().results;
recursion_stack.pop_back();
return false; return false;
} }
return true; return true;
@ -895,20 +897,21 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_endmark()
{ {
m_presult->set_second(position, index); m_presult->set_second(position, index);
} }
if(recursion_stack_position) if(!recursion_stack.empty())
{ {
if(index == recursion_stack[recursion_stack_position-1].id) if(index == recursion_stack.back().id)
{ {
--recursion_stack_position; //--recursion_stack_position;
recursion_info<results_type> saved = recursion_stack[recursion_stack_position]; recursion_info<results_type> saved = recursion_stack.back();
recursion_stack.pop_back();
const re_syntax_base* saved_state = pstate = saved.preturn_address; const re_syntax_base* saved_state = pstate = saved.preturn_address;
repeater_count<BidiIterator>* saved_count = next_count; repeater_count<BidiIterator>* saved_count = next_count;
next_count = saved.repeater_stack; next_count = saved.repeater_stack;
*m_presult = saved.results; *m_presult = saved.results;
if(!match_all_states()) if(!match_all_states())
{ {
recursion_stack[recursion_stack_position] = saved; recursion_stack.push_back(saved);
++recursion_stack_position; //++recursion_stack_position;
next_count = saved_count; next_count = saved_count;
return false; return false;
} }
@ -928,17 +931,19 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_endmark()
template <class BidiIterator, class Allocator, class traits> template <class BidiIterator, class Allocator, class traits>
bool perl_matcher<BidiIterator, Allocator, traits>::match_match() bool perl_matcher<BidiIterator, Allocator, traits>::match_match()
{ {
if(recursion_stack_position) if(!recursion_stack.empty())
{ {
BOOST_ASSERT(0 == recursion_stack[recursion_stack_position-1].id); BOOST_ASSERT(0 == recursion_stack.back().id);
--recursion_stack_position; //--recursion_stack_position;
const re_syntax_base* saved_state = pstate = recursion_stack[recursion_stack_position].preturn_address; const re_syntax_base* saved_state = pstate = recursion_stack.back().preturn_address;
*m_presult = recursion_stack[recursion_stack_position].results; *m_presult = recursion_stack.back().results;
recursion_stack.pop_back();
if(!match_all_states()) if(!match_all_states())
{ {
recursion_stack[recursion_stack_position].preturn_address = saved_state; recursion_stack.push_back(recursion_info<results_type>());
recursion_stack[recursion_stack_position].results = *m_presult; recursion_stack.back().preturn_address = saved_state;
++recursion_stack_position; recursion_stack.back().results = *m_presult;
//++recursion_stack_position;
return false; return false;
} }
return true; return true;

View File

@ -100,6 +100,9 @@ int handle_argument(const std::string& what)
#endif #endif
#ifdef BOOST_HAS_PCRE #ifdef BOOST_HAS_PCRE
time_pcre = true; time_pcre = true;
#endif
#ifdef BOOST_HAS_XPRESSIVE
time_xpressive = true;
#endif #endif
} }
else if(what == "-test-matches") else if(what == "-test-matches")