Index: src/jsregexp.cc |
diff --git a/src/jsregexp.cc b/src/jsregexp.cc |
index 879f671a9f058ac077ac1b6dd6ab02f9c2361973..852d431be0cbd13312567ade88c8cacad25d2729 100644 |
--- a/src/jsregexp.cc |
+++ b/src/jsregexp.cc |
@@ -263,7 +263,6 @@ Handle<Object> RegExpImpl::AtomExec(Handle<JSRegExp> re, |
// Irregexp implementation. |
- |
// Ensures that the regexp object contains a compiled version of the |
// source for either ASCII or non-ASCII strings. |
// If the compiled version doesn't already exist, it is compiled |
@@ -271,25 +270,26 @@ Handle<Object> RegExpImpl::AtomExec(Handle<JSRegExp> re, |
// If compilation fails, an exception is thrown and this function |
// returns false. |
bool RegExpImpl::EnsureCompiledIrregexp(Handle<JSRegExp> re, bool is_ascii) { |
- int index; |
- if (is_ascii) { |
- index = JSRegExp::kIrregexpASCIICodeIndex; |
- } else { |
- index = JSRegExp::kIrregexpUC16CodeIndex; |
- } |
- Object* entry = re->DataAt(index); |
- if (!entry->IsTheHole()) { |
- // A value has already been compiled. |
- if (entry->IsJSObject()) { |
- // If it's a JS value, it's an error. |
- Top::Throw(entry); |
- return false; |
- } |
- return true; |
- } |
+#ifdef V8_NATIVE_REGEXP |
+ if (re->DataAt(JSRegExp::code_index(is_ascii))->IsCode()) return true; |
+#else // ! V8_NATIVE_REGEXP (RegExp interpreter code) |
+ if (re->DataAt(JSRegExp::code_index(is_ascii))->IsByteArray()) return true; |
+#endif |
+ return CompileIrregexp(re, is_ascii); |
+} |
+ |
+bool RegExpImpl::CompileIrregexp(Handle<JSRegExp> re, bool is_ascii) { |
// Compile the RegExp. |
CompilationZoneScope zone_scope(DELETE_ON_EXIT); |
+ Object* entry = re->DataAt(JSRegExp::code_index(is_ascii)); |
+ if (entry->IsJSObject()) { |
+ // If it's a JSObject, a previous compilation failed and threw this object. |
+ // Re-throw the object without trying again. |
+ Top::Throw(entry); |
+ return false; |
+ } |
+ ASSERT(entry->IsTheHole()); |
JSRegExp::Flags flags = re->GetFlags(); |
@@ -302,7 +302,7 @@ bool RegExpImpl::EnsureCompiledIrregexp(Handle<JSRegExp> re, bool is_ascii) { |
FlatStringReader reader(pattern); |
if (!ParseRegExp(&reader, flags.is_multiline(), &compile_data)) { |
// Throw an exception if we fail to parse the pattern. |
- // THIS SHOULD NOT HAPPEN. We already parsed it successfully once. |
+ // THIS SHOULD NOT HAPPEN. We already pre-parsed it successfully once. |
ThrowRegExpException(re, |
pattern, |
compile_data.error, |
@@ -325,17 +325,15 @@ bool RegExpImpl::EnsureCompiledIrregexp(Handle<JSRegExp> re, bool is_ascii) { |
Handle<Object> regexp_err = |
Factory::NewSyntaxError("malformed_regexp", array); |
Top::Throw(*regexp_err); |
- re->SetDataAt(index, *regexp_err); |
+ re->SetDataAt(JSRegExp::code_index(is_ascii), *regexp_err); |
return false; |
} |
- NoHandleAllocation no_handles; |
- |
- FixedArray* data = FixedArray::cast(re->data()); |
- data->set(index, result.code); |
- int register_max = IrregexpMaxRegisterCount(data); |
+ Handle<FixedArray> data = Handle<FixedArray>(FixedArray::cast(re->data())); |
+ data->set(JSRegExp::code_index(is_ascii), result.code); |
+ int register_max = IrregexpMaxRegisterCount(*data); |
if (result.num_registers > register_max) { |
- SetIrregexpMaxRegisterCount(data, result.num_registers); |
+ SetIrregexpMaxRegisterCount(*data, result.num_registers); |
} |
return true; |
@@ -364,24 +362,12 @@ int RegExpImpl::IrregexpNumberOfRegisters(FixedArray* re) { |
ByteArray* RegExpImpl::IrregexpByteCode(FixedArray* re, bool is_ascii) { |
- int index; |
- if (is_ascii) { |
- index = JSRegExp::kIrregexpASCIICodeIndex; |
- } else { |
- index = JSRegExp::kIrregexpUC16CodeIndex; |
- } |
- return ByteArray::cast(re->get(index)); |
+ return ByteArray::cast(re->get(JSRegExp::code_index(is_ascii))); |
} |
Code* RegExpImpl::IrregexpNativeCode(FixedArray* re, bool is_ascii) { |
- int index; |
- if (is_ascii) { |
- index = JSRegExp::kIrregexpASCIICodeIndex; |
- } else { |
- index = JSRegExp::kIrregexpUC16CodeIndex; |
- } |
- return Code::cast(re->get(index)); |
+ return Code::cast(re->get(JSRegExp::code_index(is_ascii))); |
} |
@@ -408,6 +394,7 @@ Handle<Object> RegExpImpl::IrregexpExec(Handle<JSRegExp> jsregexp, |
int number_of_capture_registers = |
(IrregexpNumberOfCaptures(FixedArray::cast(jsregexp->data())) + 1) * 2; |
+#ifndef V8_NATIVE_REGEXP |
#ifdef DEBUG |
if (FLAG_trace_regexp_bytecodes) { |
String* pattern = jsregexp->Pattern(); |
@@ -415,6 +402,7 @@ Handle<Object> RegExpImpl::IrregexpExec(Handle<JSRegExp> jsregexp, |
PrintF("\n\nSubject string: '%s'\n\n", *(subject->ToCString())); |
} |
#endif |
+#endif |
if (!subject->IsFlat()) { |
FlattenString(subject); |
@@ -422,88 +410,83 @@ Handle<Object> RegExpImpl::IrregexpExec(Handle<JSRegExp> jsregexp, |
last_match_info->EnsureSize(number_of_capture_registers + kLastMatchOverhead); |
- bool rc; |
- // We have to initialize this with something to make gcc happy but we can't |
- // initialize it with its real value until after the GC-causing things are |
- // over. |
- FixedArray* array = NULL; |
+ Handle<FixedArray> array; |
// Dispatch to the correct RegExp implementation. |
- Handle<String> original_subject = subject; |
Handle<FixedArray> regexp(FixedArray::cast(jsregexp->data())); |
- if (UseNativeRegexp()) { |
+#ifdef V8_NATIVE_REGEXP |
#if V8_TARGET_ARCH_IA32 |
- OffsetsVector captures(number_of_capture_registers); |
- int* captures_vector = captures.vector(); |
- RegExpMacroAssemblerIA32::Result res; |
- do { |
- bool is_ascii = subject->IsAsciiRepresentation(); |
- if (!EnsureCompiledIrregexp(jsregexp, is_ascii)) { |
- return Handle<Object>::null(); |
- } |
- Handle<Code> code(RegExpImpl::IrregexpNativeCode(*regexp, is_ascii)); |
- res = RegExpMacroAssemblerIA32::Match(code, |
- subject, |
- captures_vector, |
- captures.length(), |
- previous_index); |
- // If result is RETRY, the string have changed representation, and we |
- // must restart from scratch. |
- } while (res == RegExpMacroAssemblerIA32::RETRY); |
- if (res == RegExpMacroAssemblerIA32::EXCEPTION) { |
- ASSERT(Top::has_pending_exception()); |
- return Handle<Object>::null(); |
- } |
- ASSERT(res == RegExpMacroAssemblerIA32::SUCCESS |
- || res == RegExpMacroAssemblerIA32::FAILURE); |
- |
- rc = (res == RegExpMacroAssemblerIA32::SUCCESS); |
- if (!rc) return Factory::null_value(); |
- |
- array = last_match_info->elements(); |
- ASSERT(array->length() >= number_of_capture_registers + kLastMatchOverhead); |
- // The captures come in (start, end+1) pairs. |
- for (int i = 0; i < number_of_capture_registers; i += 2) { |
- SetCapture(array, i, captures_vector[i]); |
- SetCapture(array, i + 1, captures_vector[i + 1]); |
- } |
-#else // !V8_TARGET_ARCH_IA32 |
- UNREACHABLE(); |
-#endif |
- } else { |
+ OffsetsVector captures(number_of_capture_registers); |
+ int* captures_vector = captures.vector(); |
+ RegExpMacroAssemblerIA32::Result res; |
+ do { |
bool is_ascii = subject->IsAsciiRepresentation(); |
if (!EnsureCompiledIrregexp(jsregexp, is_ascii)) { |
return Handle<Object>::null(); |
} |
- // Now that we have done EnsureCompiledIrregexp we can get the number of |
- // registers. |
- int number_of_registers = |
- IrregexpNumberOfRegisters(FixedArray::cast(jsregexp->data())); |
- OffsetsVector registers(number_of_registers); |
- int* register_vector = registers.vector(); |
- for (int i = number_of_capture_registers - 1; i >= 0; i--) { |
- register_vector[i] = -1; |
- } |
- Handle<ByteArray> byte_codes(IrregexpByteCode(*regexp, is_ascii)); |
- |
- rc = IrregexpInterpreter::Match(byte_codes, |
- subject, |
- register_vector, |
- previous_index); |
- if (!rc) return Factory::null_value(); |
- |
- array = last_match_info->elements(); |
- ASSERT(array->length() >= number_of_capture_registers + kLastMatchOverhead); |
- // The captures come in (start, end+1) pairs. |
- for (int i = 0; i < number_of_capture_registers; i += 2) { |
- SetCapture(array, i, register_vector[i]); |
- SetCapture(array, i + 1, register_vector[i + 1]); |
- } |
+ Handle<Code> code(RegExpImpl::IrregexpNativeCode(*regexp, is_ascii)); |
+ res = RegExpMacroAssemblerIA32::Match(code, |
+ subject, |
+ captures_vector, |
+ captures.length(), |
+ previous_index); |
+ // If result is RETRY, the string have changed representation, and we |
+ // must restart from scratch. |
+ } while (res == RegExpMacroAssemblerIA32::RETRY); |
+ if (res == RegExpMacroAssemblerIA32::EXCEPTION) { |
+ ASSERT(Top::has_pending_exception()); |
+ return Handle<Object>::null(); |
} |
+ ASSERT(res == RegExpMacroAssemblerIA32::SUCCESS |
+ || res == RegExpMacroAssemblerIA32::FAILURE); |
- SetLastCaptureCount(array, number_of_capture_registers); |
- SetLastSubject(array, *original_subject); |
- SetLastInput(array, *original_subject); |
+ if (res != RegExpMacroAssemblerIA32::SUCCESS) return Factory::null_value(); |
+ |
+ array = Handle<FixedArray>(last_match_info->elements()); |
+ ASSERT(array->length() >= number_of_capture_registers + kLastMatchOverhead); |
+ // The captures come in (start, end+1) pairs. |
+ for (int i = 0; i < number_of_capture_registers; i += 2) { |
+ SetCapture(*array, i, captures_vector[i]); |
+ SetCapture(*array, i + 1, captures_vector[i + 1]); |
+ } |
+#else // !V8_TARGET_ARCH_IA32 |
+ UNREACHABLE(); |
+#endif // V8_TARGET_ARCH_IA32 |
+#else // !V8_NATIVE_REGEXP |
+ bool is_ascii = subject->IsAsciiRepresentation(); |
+ if (!EnsureCompiledIrregexp(jsregexp, is_ascii)) { |
+ return Handle<Object>::null(); |
+ } |
+ // Now that we have done EnsureCompiledIrregexp we can get the number of |
+ // registers. |
+ int number_of_registers = |
+ IrregexpNumberOfRegisters(FixedArray::cast(jsregexp->data())); |
+ OffsetsVector registers(number_of_registers); |
+ int* register_vector = registers.vector(); |
+ for (int i = number_of_capture_registers - 1; i >= 0; i--) { |
+ register_vector[i] = -1; |
+ } |
+ Handle<ByteArray> byte_codes(IrregexpByteCode(*regexp, is_ascii)); |
+ |
+ if (!IrregexpInterpreter::Match(byte_codes, |
+ subject, |
+ register_vector, |
+ previous_index)) { |
+ return Factory::null_value(); |
+ } |
+ |
+ array = Handle<FixedArray>(last_match_info->elements()); |
+ ASSERT(array->length() >= number_of_capture_registers + kLastMatchOverhead); |
+ // The captures come in (start, end+1) pairs. |
+ for (int i = 0; i < number_of_capture_registers; i += 2) { |
+ SetCapture(*array, i, register_vector[i]); |
+ SetCapture(*array, i + 1, register_vector[i + 1]); |
+ } |
+#endif // V8_NATIVE_REGEXP |
+ |
+ SetLastCaptureCount(*array, number_of_capture_registers); |
+ SetLastSubject(*array, *subject); |
+ SetLastInput(*array, *subject); |
return last_match_info; |
} |
@@ -4474,35 +4457,38 @@ RegExpEngine::CompilationResult RegExpEngine::Compile(RegExpCompileData* data, |
NodeInfo info = *node->info(); |
- if (RegExpImpl::UseNativeRegexp()) { |
+#ifdef V8_NATIVE_REGEXP |
#ifdef V8_TARGET_ARCH_ARM |
- UNREACHABLE(); |
+ // ARM native regexp not implemented yet. |
+ UNREACHABLE(); |
#endif |
#ifdef V8_TARGET_ARCH_X64 |
- UNREACHABLE(); |
+ // X64 native regexp not implemented yet. |
+ UNREACHABLE(); |
#endif |
#ifdef V8_TARGET_ARCH_IA32 |
- RegExpMacroAssemblerIA32::Mode mode; |
- if (is_ascii) { |
- mode = RegExpMacroAssemblerIA32::ASCII; |
- } else { |
- mode = RegExpMacroAssemblerIA32::UC16; |
- } |
- RegExpMacroAssemblerIA32 macro_assembler(mode, |
- (data->capture_count + 1) * 2); |
- return compiler.Assemble(¯o_assembler, |
- node, |
- data->capture_count, |
- pattern); |
-#endif |
+ RegExpMacroAssemblerIA32::Mode mode; |
+ if (is_ascii) { |
+ mode = RegExpMacroAssemblerIA32::ASCII; |
+ } else { |
+ mode = RegExpMacroAssemblerIA32::UC16; |
} |
+ RegExpMacroAssemblerIA32 macro_assembler(mode, |
+ (data->capture_count + 1) * 2); |
+ return compiler.Assemble(¯o_assembler, |
+ node, |
+ data->capture_count, |
+ pattern); |
+#endif |
+#else // ! V8_NATIVE_REGEXP |
+ // Interpreted regexp. |
EmbeddedVector<byte, 1024> codes; |
RegExpMacroAssemblerIrregexp macro_assembler(codes); |
return compiler.Assemble(¯o_assembler, |
node, |
data->capture_count, |
pattern); |
+#endif // V8_NATIVE_REGEXP |
} |
- |
}} // namespace v8::internal |