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

Unified Diff: src/jsregexp.cc

Issue 18587: Eliminate the code that handles fallback to JSCRE. The only way to get... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
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 side-by-side diff with in-line comments
Download patch
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,
« no previous file with comments | « src/jsregexp.h ('k') | src/regexp-macro-assembler.h » ('j') | src/regexp-macro-assembler.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698