Index: src/jsregexp.cc |
=================================================================== |
--- src/jsregexp.cc (revision 1142) |
+++ src/jsregexp.cc (working copy) |
@@ -298,21 +298,10 @@ |
return AtomExec(regexp, subject, index); |
case JSRegExp::IRREGEXP: { |
Handle<Object> result = IrregexpExec(regexp, subject, index); |
- if (!result.is_null() || Top::has_pending_exception()) { |
- return result; |
- } |
- // We couldn't handle the regexp using Irregexp, so fall back |
- // on JSCRE. |
- // Reset the JSRegExp to use JSCRE. |
- JscrePrepare(regexp, |
- Handle<String>(regexp->Pattern()), |
- regexp->GetFlags()); |
- // Fall-through to JSCRE. |
+ if (result.is_null()) ASSERT(Top::has_pending_exception()); |
+ return result; |
} |
case JSRegExp::JSCRE: |
- if (FLAG_disable_jscre) { |
- UNIMPLEMENTED(); |
- } |
return JscreExec(regexp, subject, index); |
default: |
UNREACHABLE(); |
@@ -328,22 +317,10 @@ |
return AtomExecGlobal(regexp, subject); |
case JSRegExp::IRREGEXP: { |
Handle<Object> result = IrregexpExecGlobal(regexp, subject); |
- if (!result.is_null() || Top::has_pending_exception()) { |
- return result; |
- } |
- // Empty handle as result but no exception thrown means that |
- // the regexp contains features not yet handled by the irregexp |
- // compiler. |
- // We have to fall back on JSCRE. Reset the JSRegExp to use JSCRE. |
- JscrePrepare(regexp, |
- Handle<String>(regexp->Pattern()), |
- regexp->GetFlags()); |
- // Fall-through to JSCRE. |
+ if (result.is_null()) ASSERT(Top::has_pending_exception()); |
+ return result; |
} |
case JSRegExp::JSCRE: |
- if (FLAG_disable_jscre) { |
- UNIMPLEMENTED(); |
- } |
return JscreExecGlobal(regexp, subject); |
default: |
UNREACHABLE(); |
@@ -460,7 +437,7 @@ |
&JSREMalloc, |
&JSREFree); |
if (*code == NULL && (malloc_failure->IsRetryAfterGC() || |
- malloc_failure->IsOutOfMemoryFailure())) { |
+ malloc_failure->IsOutOfMemoryFailure())) { |
return malloc_failure; |
} else { |
// It doesn't matter which object we return here, we just need to return |
@@ -1198,7 +1175,13 @@ |
public: |
RegExpCompiler(int capture_count, bool ignore_case, bool is_ascii); |
- int AllocateRegister() { return next_register_++; } |
+ int AllocateRegister() { |
+ if (next_register_ >= RegExpMacroAssembler::kMaxRegister) { |
+ reg_exp_too_big_ = true; |
+ return next_register_; |
+ } |
+ return next_register_++; |
+ } |
Handle<FixedArray> Assemble(RegExpMacroAssembler* assembler, |
RegExpNode* start, |
@@ -1218,6 +1201,8 @@ |
inline int recursion_depth() { return recursion_depth_; } |
inline void IncrementRecursionDepth() { recursion_depth_++; } |
inline void DecrementRecursionDepth() { recursion_depth_--; } |
+ |
+ void SetRegExpTooBig() { reg_exp_too_big_ = true; } |
inline bool ignore_case() { return ignore_case_; } |
inline bool ascii() { return ascii_; } |
@@ -1231,6 +1216,7 @@ |
RegExpMacroAssembler* macro_assembler_; |
bool ignore_case_; |
bool ascii_; |
+ bool reg_exp_too_big_; |
}; |
@@ -1245,6 +1231,18 @@ |
}; |
+static Handle<FixedArray> IrregexpRegExpTooBig(Handle<String> pattern) { |
+ Handle<JSArray> array = Factory::NewJSArray(2); |
+ SetElement(array, 0, pattern); |
+ const char* message = "RegExp too big"; |
+ SetElement(array, 1, Factory::NewStringFromUtf8(CStrVector(message))); |
+ Handle<Object> regexp_err = |
+ Factory::NewSyntaxError("malformed_regexp", array); |
+ Top::Throw(*regexp_err); |
+ return Handle<FixedArray>(); |
+} |
+ |
+ |
// Attempts to compile the regexp using an Irregexp code generator. Returns |
// a fixed array or a null handle depending on whether it succeeded. |
RegExpCompiler::RegExpCompiler(int capture_count, bool ignore_case, bool ascii) |
@@ -1252,8 +1250,10 @@ |
work_list_(NULL), |
recursion_depth_(0), |
ignore_case_(ignore_case), |
- ascii_(ascii) { |
+ ascii_(ascii), |
+ reg_exp_too_big_(false) { |
accept_ = new EndNode(EndNode::ACCEPT); |
+ ASSERT(next_register_ - 1 <= RegExpMacroAssembler::kMaxRegister); |
} |
@@ -1273,17 +1273,13 @@ |
Label fail; |
macro_assembler->PushBacktrack(&fail); |
Trace new_trace; |
- if (!start->Emit(this, &new_trace)) { |
- fail.Unuse(); |
- return Handle<FixedArray>::null(); |
- } |
+ start->Emit(this, &new_trace); |
macro_assembler_->Bind(&fail); |
macro_assembler_->Fail(); |
while (!work_list.is_empty()) { |
Lasse Reichstein
2009/01/26 13:48:53
You could bail out of this loop if the regexp is t
Erik Corry
2009/01/26 19:59:21
Unfortunately I can't because there are labels tha
|
- if (!work_list.RemoveLast()->Emit(this, &new_trace)) { |
- return Handle<FixedArray>::null(); |
- } |
+ work_list.RemoveLast()->Emit(this, &new_trace); |
} |
+ if (reg_exp_too_big_) return IrregexpRegExpTooBig(pattern); |
Handle<FixedArray> array = |
Factory::NewFixedArray(RegExpImpl::kIrregexpDataLength); |
array->set(RegExpImpl::kIrregexpImplementationIndex, |
@@ -1303,6 +1299,7 @@ |
return array; |
} |
+ |
bool Trace::DeferredAction::Mentions(int that) { |
if (type() == ActionNode::CLEAR_CAPTURES) { |
Interval range = static_cast<DeferredClearCaptures*>(this)->range(); |
@@ -1465,7 +1462,7 @@ |
// This is called as we come into a loop choice node and some other tricky |
// nodes. It normalizes the state of the code generator to ensure we can |
// generate generic code. |
-bool Trace::Flush(RegExpCompiler* compiler, RegExpNode* successor) { |
+void Trace::Flush(RegExpCompiler* compiler, RegExpNode* successor) { |
RegExpMacroAssembler* assembler = compiler->macro_assembler(); |
ASSERT(actions_ != NULL || |
@@ -1482,7 +1479,8 @@ |
if (cp_offset_ != 0) assembler->AdvanceCurrentPosition(cp_offset_); |
// Create a new trivial state and generate the node with that. |
Trace new_state; |
- return successor->Emit(compiler, &new_state); |
+ successor->Emit(compiler, &new_state); |
+ return; |
Lasse Reichstein
2009/01/26 13:48:53
The return is superfluous.
Erik Corry
2009/01/26 19:59:21
I don't think so!
Lasse Reichstein
2009/01/27 06:54:28
Argh, easily fooled by missing indentation. Ignore
|
} |
// Generate deferred actions here along with code to undo them again. |
@@ -1504,11 +1502,10 @@ |
Label undo; |
assembler->PushBacktrack(&undo); |
Trace new_state; |
- bool ok = successor->Emit(compiler, &new_state); |
+ successor->Emit(compiler, &new_state); |
// On backtrack we need to restore state. |
assembler->Bind(&undo); |
- if (!ok) return false; |
if (backtrack() != NULL) { |
assembler->PopCurrentPosition(); |
} |
@@ -1518,14 +1515,13 @@ |
} else { |
assembler->GoTo(backtrack()); |
} |
- |
- return true; |
} |
-bool NegativeSubmatchSuccess::Emit(RegExpCompiler* compiler, Trace* trace) { |
+void NegativeSubmatchSuccess::Emit(RegExpCompiler* compiler, Trace* trace) { |
if (!trace->is_trivial()) { |
- return trace->Flush(compiler, this); |
+ trace->Flush(compiler, this); |
+ return; |
} |
RegExpMacroAssembler* assembler = compiler->macro_assembler(); |
if (!label()->is_bound()) { |
@@ -1536,13 +1532,13 @@ |
// Now that we have unwound the stack we find at the top of the stack the |
// backtrack that the BeginSubmatch node got. |
assembler->Backtrack(); |
- return true; |
} |
-bool EndNode::Emit(RegExpCompiler* compiler, Trace* trace) { |
+void EndNode::Emit(RegExpCompiler* compiler, Trace* trace) { |
if (!trace->is_trivial()) { |
- return trace->Flush(compiler, this); |
+ trace->Flush(compiler, this); |
+ return; |
} |
RegExpMacroAssembler* assembler = compiler->macro_assembler(); |
if (!label()->is_bound()) { |
@@ -1551,16 +1547,15 @@ |
switch (action_) { |
case ACCEPT: |
assembler->Succeed(); |
- return true; |
+ return; |
case BACKTRACK: |
assembler->GoTo(trace->backtrack()); |
- return true; |
+ return; |
case NEGATIVE_SUBMATCH_SUCCESS: |
// This case is handled in a different virtual method. |
UNREACHABLE(); |
} |
UNIMPLEMENTED(); |
- return false; |
} |
@@ -1957,8 +1952,8 @@ |
// If we get here code has been generated for this node too many times or |
// recursion is too deep. Time to switch to a generic version. The code for |
// generic versions above can handle deep recursion properly. |
- bool ok = trace->Flush(compiler, this); |
- return ok ? DONE : FAIL; |
+ trace->Flush(compiler, this); |
+ return DONE; |
} |
@@ -2374,7 +2369,7 @@ |
// Emit the code to check for a ^ in multiline mode (1-character lookbehind |
// that matches newline or the start of input). |
-static bool EmitHat(RegExpCompiler* compiler, |
+static void EmitHat(RegExpCompiler* compiler, |
RegExpNode* on_success, |
Trace* trace) { |
RegExpMacroAssembler* assembler = compiler->macro_assembler(); |
@@ -2401,12 +2396,12 @@ |
assembler->CheckCharacter('\n', &ok); |
assembler->CheckNotCharacter('\r', new_trace.backtrack()); |
assembler->Bind(&ok); |
- return on_success->Emit(compiler, &new_trace); |
+ on_success->Emit(compiler, &new_trace); |
} |
// Emit the code to handle \b and \B (word-boundary or non-word-boundary). |
-static bool EmitBoundaryCheck(AssertionNode::AssertionNodeType type, |
+static void EmitBoundaryCheck(AssertionNode::AssertionNodeType type, |
RegExpCompiler* compiler, |
RegExpNode* on_success, |
Trace* trace) { |
@@ -2468,11 +2463,11 @@ |
assembler->Bind(&ok); |
- return on_success->Emit(compiler, &new_trace); |
+ on_success->Emit(compiler, &new_trace); |
} |
-bool AssertionNode::Emit(RegExpCompiler* compiler, Trace* trace) { |
+void AssertionNode::Emit(RegExpCompiler* compiler, Trace* trace) { |
RegExpMacroAssembler* assembler = compiler->macro_assembler(); |
switch (type_) { |
case AT_END: { |
@@ -2486,12 +2481,14 @@ |
assembler->CheckNotAtStart(trace->backtrack()); |
break; |
case AFTER_NEWLINE: |
- return EmitHat(compiler, on_success(), trace); |
+ EmitHat(compiler, on_success(), trace); |
+ return; |
case AT_NON_BOUNDARY: |
case AT_BOUNDARY: |
- return EmitBoundaryCheck(type_, compiler, on_success(), trace); |
+ EmitBoundaryCheck(type_, compiler, on_success(), trace); |
+ return; |
} |
- return on_success()->Emit(compiler, trace); |
+ on_success()->Emit(compiler, trace); |
} |
@@ -2634,12 +2631,16 @@ |
// pass from left to right. Instead we pass over the text node several times, |
// emitting code for some character positions every time. See the comment on |
// TextEmitPass for details. |
-bool TextNode::Emit(RegExpCompiler* compiler, Trace* trace) { |
+void TextNode::Emit(RegExpCompiler* compiler, Trace* trace) { |
LimitResult limit_result = LimitVersions(compiler, trace); |
- if (limit_result == FAIL) return false; |
- if (limit_result == DONE) return true; |
+ if (limit_result == DONE) return; |
ASSERT(limit_result == CONTINUE); |
+ if (trace->cp_offset() + Length() > RegExpMacroAssembler::kMaxCPOffset) { |
+ compiler->SetRegExpTooBig(); |
+ return; |
+ } |
+ |
if (compiler->ascii()) { |
int dummy = 0; |
TextEmitPass(compiler, NON_ASCII_MATCH, false, trace, false, &dummy); |
@@ -2697,9 +2698,9 @@ |
&bound_checked_to); |
Trace successor_trace(*trace); |
- successor_trace.AdvanceCurrentPositionInTrace(Length(), compiler->ascii()); |
+ successor_trace.AdvanceCurrentPositionInTrace(Length(), compiler); |
RecursionCheck rc(compiler); |
- return on_success()->Emit(compiler, &successor_trace); |
+ on_success()->Emit(compiler, &successor_trace); |
} |
@@ -2708,7 +2709,7 @@ |
} |
-void Trace::AdvanceCurrentPositionInTrace(int by, bool ascii) { |
+void Trace::AdvanceCurrentPositionInTrace(int by, RegExpCompiler* compiler) { |
ASSERT(by > 0); |
// We don't have an instruction for shifting the current character register |
// down or for using a shifted value for anything so lets just forget that |
@@ -2717,8 +2718,12 @@ |
// Adjust the offsets of the quick check performed information. This |
// information is used to find out what we already determined about the |
// characters by means of mask and compare. |
- quick_check_performed_.Advance(by, ascii); |
+ quick_check_performed_.Advance(by, compiler->ascii()); |
cp_offset_ += by; |
+ if (cp_offset_ > RegExpMacroAssembler::kMaxCPOffset) { |
+ compiler->SetRegExpTooBig(); |
+ cp_offset_ = 0; |
+ } |
bound_checked_up_to_ = Max(0, bound_checked_up_to_ - by); |
} |
@@ -2789,7 +2794,7 @@ |
} |
-bool LoopChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) { |
+void LoopChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) { |
RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); |
if (trace->stop_node() == this) { |
int text_length = GreedyLoopTextLength(&(alternatives_->at(0))); |
@@ -2799,13 +2804,14 @@ |
ASSERT(trace->cp_offset() == text_length); |
macro_assembler->AdvanceCurrentPosition(text_length); |
macro_assembler->GoTo(trace->loop_label()); |
- return true; |
+ return; |
} |
ASSERT(trace->stop_node() == NULL); |
if (!trace->is_trivial()) { |
- return trace->Flush(compiler, this); |
+ trace->Flush(compiler, this); |
+ return; |
} |
- return ChoiceNode::Emit(compiler, trace); |
+ ChoiceNode::Emit(compiler, trace); |
} |
@@ -2958,7 +2964,7 @@ |
*/ |
-bool ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) { |
+void ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) { |
RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); |
int choice_count = alternatives_->length(); |
#ifdef DEBUG |
@@ -2973,8 +2979,7 @@ |
#endif |
LimitResult limit_result = LimitVersions(compiler, trace); |
- if (limit_result == DONE) return true; |
- if (limit_result == FAIL) return false; |
+ if (limit_result == DONE) return; |
ASSERT(limit_result == CONTINUE); |
RecursionCheck rc(compiler); |
@@ -3005,13 +3010,8 @@ |
macro_assembler->Bind(&loop_label); |
greedy_match_trace.set_stop_node(this); |
greedy_match_trace.set_loop_label(&loop_label); |
- bool ok = alternatives_->at(0).node()->Emit(compiler, |
- &greedy_match_trace); |
+ alternatives_->at(0).node()->Emit(compiler, &greedy_match_trace); |
macro_assembler->Bind(&greedy_match_failed); |
- if (!ok) { |
- greedy_loop_label.Unuse(); |
- return false; |
- } |
} |
Label second_choice; // For use in greedy matches. |
@@ -3083,10 +3083,7 @@ |
for (int j = 0; j < guard_count; j++) { |
GenerateGuard(macro_assembler, guards->at(j), &new_trace); |
} |
- if (!alternative.node()->Emit(compiler, &new_trace)) { |
- greedy_loop_label.Unuse(); |
- return false; |
- } |
+ alternative.node()->Emit(compiler, &new_trace); |
preload_is_current = false; |
} |
macro_assembler->Bind(&alt_gen->after); |
@@ -3104,26 +3101,23 @@ |
// label was bound. |
for (int i = first_normal_choice; i < choice_count - 1; i++) { |
AlternativeGeneration* alt_gen = alt_gens.at(i); |
- if (!EmitOutOfLineContinuation(compiler, |
- current_trace, |
- alternatives_->at(i), |
- alt_gen, |
- preload_characters, |
- alt_gens.at(i + 1)->expects_preload)) { |
- return false; |
- } |
+ EmitOutOfLineContinuation(compiler, |
+ current_trace, |
+ alternatives_->at(i), |
+ alt_gen, |
+ preload_characters, |
+ alt_gens.at(i + 1)->expects_preload); |
} |
- return true; |
} |
-bool ChoiceNode::EmitOutOfLineContinuation(RegExpCompiler* compiler, |
+void ChoiceNode::EmitOutOfLineContinuation(RegExpCompiler* compiler, |
Trace* trace, |
GuardedAlternative alternative, |
AlternativeGeneration* alt_gen, |
int preload_characters, |
bool next_expects_preload) { |
- if (!alt_gen->possible_success.is_linked()) return true; |
+ if (!alt_gen->possible_success.is_linked()) return; |
RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); |
macro_assembler->Bind(&alt_gen->possible_success); |
@@ -3138,7 +3132,7 @@ |
for (int j = 0; j < guard_count; j++) { |
GenerateGuard(macro_assembler, guards->at(j), &out_of_line_trace); |
} |
- bool ok = alternative.node()->Emit(compiler, &out_of_line_trace); |
+ alternative.node()->Emit(compiler, &out_of_line_trace); |
macro_assembler->Bind(&reload_current_char); |
// Reload the current character, since the next quick check expects that. |
// We don't need to check bounds here because we only get into this |
@@ -3148,22 +3142,20 @@ |
false, |
preload_characters); |
macro_assembler->GoTo(&(alt_gen->after)); |
- return ok; |
} else { |
out_of_line_trace.set_backtrack(&(alt_gen->after)); |
for (int j = 0; j < guard_count; j++) { |
GenerateGuard(macro_assembler, guards->at(j), &out_of_line_trace); |
} |
- return alternative.node()->Emit(compiler, &out_of_line_trace); |
+ alternative.node()->Emit(compiler, &out_of_line_trace); |
} |
} |
-bool ActionNode::Emit(RegExpCompiler* compiler, Trace* trace) { |
+void ActionNode::Emit(RegExpCompiler* compiler, Trace* trace) { |
RegExpMacroAssembler* assembler = compiler->macro_assembler(); |
LimitResult limit_result = LimitVersions(compiler, trace); |
- if (limit_result == DONE) return true; |
- if (limit_result == FAIL) return false; |
+ if (limit_result == DONE) return; |
ASSERT(limit_result == CONTINUE); |
RecursionCheck rc(compiler); |
@@ -3174,21 +3166,24 @@ |
new_capture(data_.u_position_register.reg, trace); |
Trace new_trace = *trace; |
new_trace.add_action(&new_capture); |
- return on_success()->Emit(compiler, &new_trace); |
+ on_success()->Emit(compiler, &new_trace); |
+ break; |
} |
case INCREMENT_REGISTER: { |
Trace::DeferredIncrementRegister |
new_increment(data_.u_increment_register.reg); |
Trace new_trace = *trace; |
new_trace.add_action(&new_increment); |
- return on_success()->Emit(compiler, &new_trace); |
+ on_success()->Emit(compiler, &new_trace); |
+ break; |
} |
case SET_REGISTER: { |
Trace::DeferredSetRegister |
new_set(data_.u_store_register.reg, data_.u_store_register.value); |
Trace new_trace = *trace; |
new_trace.add_action(&new_set); |
- return on_success()->Emit(compiler, &new_trace); |
+ on_success()->Emit(compiler, &new_trace); |
+ break; |
} |
case CLEAR_CAPTURES: { |
Trace::DeferredClearCaptures |
@@ -3196,15 +3191,20 @@ |
data_.u_clear_captures.range_to)); |
Trace new_trace = *trace; |
new_trace.add_action(&new_capture); |
- return on_success()->Emit(compiler, &new_trace); |
+ on_success()->Emit(compiler, &new_trace); |
+ break; |
} |
case BEGIN_SUBMATCH: |
- if (!trace->is_trivial()) return trace->Flush(compiler, this); |
- assembler->WriteCurrentPositionToRegister( |
- data_.u_submatch.current_position_register, 0); |
- assembler->WriteStackPointerToRegister( |
- data_.u_submatch.stack_pointer_register); |
- return on_success()->Emit(compiler, trace); |
+ if (!trace->is_trivial()) { |
+ trace->Flush(compiler, this); |
+ } else { |
+ assembler->WriteCurrentPositionToRegister( |
+ data_.u_submatch.current_position_register, 0); |
+ assembler->WriteStackPointerToRegister( |
+ data_.u_submatch.stack_pointer_register); |
+ on_success()->Emit(compiler, trace); |
+ } |
+ break; |
case EMPTY_MATCH_CHECK: { |
int start_pos_reg = data_.u_empty_match_check.start_register; |
int stored_pos = 0; |
@@ -3215,50 +3215,55 @@ |
// If we know we haven't advanced and there is no minimum we |
// can just backtrack immediately. |
assembler->GoTo(trace->backtrack()); |
- return true; |
} else if (know_dist && stored_pos < trace->cp_offset()) { |
// If we know we've advanced we can generate the continuation |
// immediately. |
- return on_success()->Emit(compiler, trace); |
+ on_success()->Emit(compiler, trace); |
+ } else if (!trace->is_trivial()) { |
+ trace->Flush(compiler, this); |
+ } else { |
+ Label skip_empty_check; |
+ // If we have a minimum number of repetitions we check the current |
+ // number first and skip the empty check if it's not enough. |
+ if (has_minimum) { |
+ int limit = data_.u_empty_match_check.repetition_limit; |
+ assembler->IfRegisterLT(rep_reg, limit, &skip_empty_check); |
+ } |
+ // If the match is empty we bail out, otherwise we fall through |
+ // to the on-success continuation. |
+ assembler->IfRegisterEqPos(data_.u_empty_match_check.start_register, |
+ trace->backtrack()); |
+ assembler->Bind(&skip_empty_check); |
+ on_success()->Emit(compiler, trace); |
} |
- if (!trace->is_trivial()) return trace->Flush(compiler, this); |
- Label skip_empty_check; |
- // If we have a minimum number of repetitions we check the current |
- // number first and skip the empty check if it's not enough. |
- if (has_minimum) { |
- int limit = data_.u_empty_match_check.repetition_limit; |
- assembler->IfRegisterLT(rep_reg, limit, &skip_empty_check); |
- } |
- // If the match is empty we bail out, otherwise we fall through |
- // to the on-success continuation. |
- assembler->IfRegisterEqPos(data_.u_empty_match_check.start_register, |
- trace->backtrack()); |
- assembler->Bind(&skip_empty_check); |
- return on_success()->Emit(compiler, trace); |
+ break; |
} |
case POSITIVE_SUBMATCH_SUCCESS: |
- if (!trace->is_trivial()) return trace->Flush(compiler, this); |
- assembler->ReadCurrentPositionFromRegister( |
- data_.u_submatch.current_position_register); |
- assembler->ReadStackPointerFromRegister( |
- data_.u_submatch.stack_pointer_register); |
- return on_success()->Emit(compiler, trace); |
+ if (!trace->is_trivial()) { |
+ trace->Flush(compiler, this); |
+ } else { |
+ assembler->ReadCurrentPositionFromRegister( |
+ data_.u_submatch.current_position_register); |
+ assembler->ReadStackPointerFromRegister( |
+ data_.u_submatch.stack_pointer_register); |
+ on_success()->Emit(compiler, trace); |
+ } |
+ break; |
default: |
UNREACHABLE(); |
- return false; |
} |
} |
-bool BackReferenceNode::Emit(RegExpCompiler* compiler, Trace* trace) { |
+void BackReferenceNode::Emit(RegExpCompiler* compiler, Trace* trace) { |
RegExpMacroAssembler* assembler = compiler->macro_assembler(); |
if (!trace->is_trivial()) { |
- return trace->Flush(compiler, this); |
+ trace->Flush(compiler, this); |
+ return; |
} |
LimitResult limit_result = LimitVersions(compiler, trace); |
- if (limit_result == DONE) return true; |
- if (limit_result == FAIL) return false; |
+ if (limit_result == DONE) return; |
ASSERT(limit_result == CONTINUE); |
RecursionCheck rc(compiler); |
@@ -3270,7 +3275,7 @@ |
} else { |
assembler->CheckNotBackReference(start_reg_, trace->backtrack()); |
} |
- return on_success()->Emit(compiler, trace); |
+ on_success()->Emit(compiler, trace); |
} |
@@ -4638,6 +4643,9 @@ |
bool is_multiline, |
Handle<String> pattern, |
bool is_ascii) { |
+ if ((data->capture_count + 1) * 2 - 1 > RegExpMacroAssembler::kMaxRegister) { |
+ return IrregexpRegExpTooBig(pattern); |
+ } |
RegExpCompiler compiler(data->capture_count, ignore_case, is_ascii); |
// Wrap the body of the regexp in capture #0. |
RegExpNode* captured_body = RegExpCapture::ToNode(data->tree, |