RegExpRunStatus RegExpShared::execute(JSContext *cx, const jschar *chars, size_t length, size_t *lastIndex, MatchPairs &matches) { /* Protect inlined chars from root analysis poisoning. */ SkipRoot skip(cx, &chars); /* Compile the code at point-of-use. */ if (!compileIfNecessary(cx)) return RegExpRunStatus_Error; /* Ensure sufficient memory for output vector. */ if (!matches.initArray(pairCount())) return RegExpRunStatus_Error; /* * |displacement| emulates sticky mode by matching from this offset * into the char buffer and subtracting the delta off at the end. */ size_t origLength = length; size_t start = *lastIndex; size_t displacement = 0; if (sticky()) { displacement = start; chars += displacement; length -= displacement; start = 0; } unsigned *outputBuf = matches.rawBuf(); unsigned result; #if ENABLE_YARR_JIT if (codeBlock.isFallBack()) result = JSC::Yarr::interpret(cx, bytecode, chars, length, start, outputBuf); else result = codeBlock.execute(chars, start, length, (int *)outputBuf).start; #else result = JSC::Yarr::interpret(cx, bytecode, chars, length, start, outputBuf); #endif if (result == JSC::Yarr::offsetNoMatch) return RegExpRunStatus_Success_NotFound; matches.displace(displacement); matches.checkAgainst(origLength); *lastIndex = matches[0].limit; return RegExpRunStatus_Success; }
RegExpRunStatus RegExpShared::execute(JSContext *cx, const jschar *chars, size_t length, size_t *lastIndex, MatchPairs **output) { const size_t origLength = length; size_t backingPairCount = RegExpCode::getOutputSize(pairCount()); LifoAlloc &alloc = cx->tempLifoAlloc(); MatchPairs *matchPairs = MatchPairs::create(alloc, pairCount(), backingPairCount); if (!matchPairs) return RegExpRunStatus_Error; /* * |displacement| emulates sticky mode by matching from this offset * into the char buffer and subtracting the delta off at the end. */ size_t start = *lastIndex; size_t displacement = 0; if (sticky()) { displacement = *lastIndex; chars += displacement; length -= displacement; start = 0; } RegExpRunStatus status = code.execute(cx, chars, length, start, matchPairs->buffer(), backingPairCount); switch (status) { case RegExpRunStatus_Error: return status; case RegExpRunStatus_Success_NotFound: *output = matchPairs; return status; default: JS_ASSERT(status == RegExpRunStatus_Success); } matchPairs->displace(displacement); matchPairs->checkAgainst(origLength); *lastIndex = matchPairs->pair(0).limit; *output = matchPairs; return RegExpRunStatus_Success; }
RegExpRunStatus RegExpShared::execute(JSContext *cx, const jschar *chars, size_t length, size_t *lastIndex, MatchPairs &matches) { TraceLogger *logger = TraceLoggerForMainThread(cx->runtime()); /* Compile the code at point-of-use. */ if (!compileIfNecessary(cx, chars, length)) return RegExpRunStatus_Error; /* Ensure sufficient memory for output vector. */ if (!matches.initArray(pairCount())) return RegExpRunStatus_Error; /* * |displacement| emulates sticky mode by matching from this offset * into the char buffer and subtracting the delta off at the end. */ size_t origLength = length; size_t start = *lastIndex; size_t displacement = 0; if (sticky()) { displacement = start; chars += displacement; length -= displacement; start = 0; } #ifndef JS_YARR // Reset the Irregexp backtrack stack if it grows during execution. irregexp::RegExpStackScope stackScope(cx->runtime()); #endif if (canStringMatch) { int res = StringFindPattern(chars+start, length-start, source->chars(), source->length()); if (res == -1) return RegExpRunStatus_Success_NotFound; matches[0].start = res + start; matches[0].limit = res + start + source->length(); matches.displace(displacement); matches.checkAgainst(origLength); *lastIndex = matches[0].limit; return RegExpRunStatus_Success; } #ifdef JS_YARR unsigned result; // Yarr wants plain integers for its output buffer (whatever). JS_STATIC_ASSERT(sizeof(int32_t) == sizeof(int)); JS_STATIC_ASSERT(sizeof(int32_t) == sizeof(unsigned)); #ifdef JS_ION if (codeBlock.isFallBack()) { AutoTraceLog logInterpret(logger, TraceLogger::YarrInterpret); result = JSC::Yarr::interpret(cx, bytecode, chars, length, start, (unsigned *) matches.pairsRaw()); } else { AutoTraceLog logJIT(logger, TraceLogger::YarrJIT); result = codeBlock.execute(chars, start, length, (int *) matches.pairsRaw()).start; } #else // JS_ION { AutoTraceLog logInterpret(logger, TraceLogger::YarrInterpret); result = JSC::Yarr::interpret(cx, bytecode, chars, length, start, (unsigned *) matches.pairsRaw()); } #endif // JS_ION if (result == JSC::Yarr::offsetError) { reportYarrError(cx, nullptr, JSC::Yarr::RuntimeError); return RegExpRunStatus_Error; } if (result == JSC::Yarr::offsetNoMatch) return RegExpRunStatus_Success_NotFound; #else // JS_YARR if (hasByteCode()) { AutoTraceLog logInterpreter(logger, TraceLogger::IrregexpExecute); RegExpRunStatus result = irregexp::InterpretCode(cx, byteCode, chars, start, length, &matches); if (result == RegExpRunStatus_Success) { matches.displace(displacement); matches.checkAgainst(origLength); *lastIndex = matches[0].limit; } return result; } #ifdef JS_ION while (true) { RegExpRunStatus result; { AutoTraceLog logJIT(logger, TraceLogger::IrregexpExecute); result = irregexp::ExecuteCode(cx, jitCode, chars, start, length, &matches); } if (result == RegExpRunStatus_Error) { // The RegExp engine might exit with an exception if an interrupt // was requested. Check this case and retry until a clean result is // obtained. bool interrupted; { JSRuntime::AutoLockForInterrupt lock(cx->runtime()); interrupted = cx->runtime()->interrupt; } if (interrupted) { if (!InvokeInterruptCallback(cx)) return RegExpRunStatus_Error; continue; } js_ReportOverRecursed(cx); return RegExpRunStatus_Error; } if (result == RegExpRunStatus_Success_NotFound) return RegExpRunStatus_Success_NotFound; JS_ASSERT(result == RegExpRunStatus_Success); break; } #else // JS_ION MOZ_CRASH(); #endif // JS_ION #endif // JS_YARR matches.displace(displacement); matches.checkAgainst(origLength); *lastIndex = matches[0].limit; return RegExpRunStatus_Success; }
RegExpRunStatus RegExpShared::execute(JSContext *cx, const jschar *chars, size_t length, size_t *lastIndex, MatchPairs &matches) { TraceLogger *logger = TraceLoggerForMainThread(cx->runtime()); { /* Compile the code at point-of-use. */ AutoTraceLog logCompile(logger, TraceLogger::YarrCompile); if (!compileIfNecessary(cx)) return RegExpRunStatus_Error; } /* Ensure sufficient memory for output vector. */ if (!matches.initArray(pairCount())) return RegExpRunStatus_Error; /* * |displacement| emulates sticky mode by matching from this offset * into the char buffer and subtracting the delta off at the end. */ size_t origLength = length; size_t start = *lastIndex; size_t displacement = 0; if (sticky()) { displacement = start; chars += displacement; length -= displacement; start = 0; } unsigned *outputBuf = matches.rawBuf(); unsigned result; #if ENABLE_YARR_JIT if (codeBlock.isFallBack()) { AutoTraceLog logInterpret(logger, TraceLogger::YarrInterpret); result = JSC::Yarr::interpret(cx, bytecode, chars, length, start, outputBuf); } else { AutoTraceLog logJIT(logger, TraceLogger::YarrJIT); result = codeBlock.execute(chars, start, length, (int *)outputBuf).start; } #else { AutoTraceLog logInterpret(logger, TraceLogger::YarrInterpret); result = JSC::Yarr::interpret(cx, bytecode, chars, length, start, outputBuf); } #endif if (result == JSC::Yarr::offsetError) { reportYarrError(cx, nullptr, JSC::Yarr::RuntimeError); return RegExpRunStatus_Error; } if (result == JSC::Yarr::offsetNoMatch) return RegExpRunStatus_Success_NotFound; matches.displace(displacement); matches.checkAgainst(origLength); *lastIndex = matches[0].limit; return RegExpRunStatus_Success; }