Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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;
}