⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 259747 in webkit


Ignore:
Timestamp:
Apr 8, 2020, 1:01:39 PM (6 years ago)
Author:
ysuzuki@apple.com
Message:

[JSC] Threading JSGlobalObject in RegExp::match properly
https://bugs.webkit.org/show_bug.cgi?id=210174

Reviewed by Saam Barati.

We thread JSGlobalObject* properly in RegExp::match instead of accessing VM::topCallFrame, which is too hacky.

  • runtime/RegExp.cpp:

(JSC::RegExp::match):
(JSC::RegExp::matchConcurrently):

  • runtime/RegExp.h:
  • runtime/RegExpGlobalData.h:
  • runtime/RegExpGlobalDataInlines.h:

(JSC::RegExpGlobalData::performMatch):

  • runtime/RegExpInlines.h:

(JSC::RegExp::matchInline):

  • runtime/RegExpMatchesArray.h:

(JSC::createRegExpMatchesArray):

  • runtime/RegExpObjectInlines.h:

(JSC::RegExpObject::matchInline):
(JSC::collectMatches):

  • runtime/RegExpPrototype.cpp:

(JSC::regExpProtoFuncSearchFast):
(JSC::genericSplit):
(JSC::regExpProtoFuncSplitFast):

  • runtime/StringPrototype.cpp:

(JSC::removeUsingRegExpSearch):
(JSC::replaceUsingRegExpSearch):

  • testRegExp.cpp:

(testOneRegExp):
(runFromFiles):

Location:
trunk/Source/JavaScriptCore
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r259744 r259747  
     12020-04-08  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] Threading JSGlobalObject in RegExp::match properly
     4        https://bugs.webkit.org/show_bug.cgi?id=210174
     5
     6        Reviewed by Saam Barati.
     7
     8        We thread JSGlobalObject* properly in RegExp::match instead of accessing VM::topCallFrame, which is too hacky.
     9
     10        * runtime/RegExp.cpp:
     11        (JSC::RegExp::match):
     12        (JSC::RegExp::matchConcurrently):
     13        * runtime/RegExp.h:
     14        * runtime/RegExpGlobalData.h:
     15        * runtime/RegExpGlobalDataInlines.h:
     16        (JSC::RegExpGlobalData::performMatch):
     17        * runtime/RegExpInlines.h:
     18        (JSC::RegExp::matchInline):
     19        * runtime/RegExpMatchesArray.h:
     20        (JSC::createRegExpMatchesArray):
     21        * runtime/RegExpObjectInlines.h:
     22        (JSC::RegExpObject::matchInline):
     23        (JSC::collectMatches):
     24        * runtime/RegExpPrototype.cpp:
     25        (JSC::regExpProtoFuncSearchFast):
     26        (JSC::genericSplit):
     27        (JSC::regExpProtoFuncSplitFast):
     28        * runtime/StringPrototype.cpp:
     29        (JSC::removeUsingRegExpSearch):
     30        (JSC::replaceUsingRegExpSearch):
     31        * testRegExp.cpp:
     32        (testOneRegExp):
     33        (runFromFiles):
     34
    1352020-04-08  Devin Rousso  <drousso@apple.com>
    236
  • trunk/Source/JavaScriptCore/runtime/RegExp.cpp

    r259092 r259747  
    287287}
    288288
    289 int RegExp::match(VM& vm, const String& s, unsigned startOffset, Vector<int>& ovector)
    290 {
    291     return matchInline(vm, s, startOffset, ovector);
     289int RegExp::match(JSGlobalObject* globalObject, const String& s, unsigned startOffset, Vector<int>& ovector)
     290{
     291    return matchInline(globalObject, globalObject->vm(), s, startOffset, ovector);
    292292}
    293293
     
    300300        return false;
    301301
    302     position = matchInline<Vector<int>&, Yarr::MatchFrom::CompilerThread>(vm, s, startOffset, ovector);
     302    position = matchInline<Vector<int>&, Yarr::MatchFrom::CompilerThread>(nullptr, vm, s, startOffset, ovector);
    303303    if (m_state == ParseError)
    304304        return false;
     
    351351}
    352352
    353 MatchResult RegExp::match(VM& vm, const String& s, unsigned startOffset)
    354 {
    355     return matchInline(vm, s, startOffset);
     353MatchResult RegExp::match(JSGlobalObject* globalObject, const String& s, unsigned startOffset)
     354{
     355    return matchInline(globalObject, globalObject->vm(), s, startOffset);
    356356}
    357357
     
    363363        return false;
    364364
    365     result = matchInline<Yarr::MatchFrom::CompilerThread>(vm, s, startOffset);
     365    result = matchInline<Yarr::MatchFrom::CompilerThread>(nullptr, vm, s, startOffset);
    366366    return true;
    367367}
  • trunk/Source/JavaScriptCore/runtime/RegExp.h

    r259092 r259747  
    7777    }
    7878
    79     JS_EXPORT_PRIVATE int match(VM&, const String&, unsigned startOffset, Vector<int>& ovector);
     79    JS_EXPORT_PRIVATE int match(JSGlobalObject*, const String&, unsigned startOffset, Vector<int>& ovector);
    8080
    8181    // Returns false if we couldn't run the regular expression for any reason.
    8282    bool matchConcurrently(VM&, const String&, unsigned startOffset, int& position, Vector<int>& ovector);
    8383   
    84     JS_EXPORT_PRIVATE MatchResult match(VM&, const String&, unsigned startOffset);
     84    JS_EXPORT_PRIVATE MatchResult match(JSGlobalObject*, const String&, unsigned startOffset);
    8585
    8686    bool matchConcurrently(VM&, const String&, unsigned startOffset, MatchResult&);
     
    8888    // Call these versions of the match functions if you're desperate for performance.
    8989    template<typename VectorType, Yarr::MatchFrom thread = Yarr::MatchFrom::VMThread>
    90     int matchInline(VM&, const String&, unsigned startOffset, VectorType& ovector);
     90    int matchInline(JSGlobalObject* nullOrGlobalObject, VM&, const String&, unsigned startOffset, VectorType& ovector);
    9191    template<Yarr::MatchFrom thread = Yarr::MatchFrom::VMThread>
    92     MatchResult matchInline(VM&, const String&, unsigned startOffset);
     92    MatchResult matchInline(JSGlobalObject* nullOrGlobalObject, VM&, const String&, unsigned startOffset);
    9393   
    9494    unsigned numSubpatterns() const { return m_numSubpatterns; }
  • trunk/Source/JavaScriptCore/runtime/RegExpGlobalData.h

    r251425 r259747  
    4949    JSValue getRightContext(JSGlobalObject*);
    5050
    51     MatchResult performMatch(VM&, JSGlobalObject*, RegExp*, JSString*, const String&, int startOffset, int** ovector);
    52     MatchResult performMatch(VM&, JSGlobalObject*, RegExp*, JSString*, const String&, int startOffset);
     51    MatchResult performMatch(JSGlobalObject*, RegExp*, JSString*, const String&, int startOffset, int** ovector);
     52    MatchResult performMatch(JSGlobalObject*, RegExp*, JSString*, const String&, int startOffset);
    5353    void recordMatch(VM&, JSGlobalObject*, RegExp*, JSString*, const MatchResult&);
    5454
  • trunk/Source/JavaScriptCore/runtime/RegExpGlobalDataInlines.h

    r251425 r259747  
    4040   e.g., RegExp.lastMatch and RegExp.leftParen.
    4141*/
    42 ALWAYS_INLINE MatchResult RegExpGlobalData::performMatch(VM& vm, JSGlobalObject* owner, RegExp* regExp, JSString* string, const String& input, int startOffset, int** ovector)
     42ALWAYS_INLINE MatchResult RegExpGlobalData::performMatch(JSGlobalObject* owner, RegExp* regExp, JSString* string, const String& input, int startOffset, int** ovector)
    4343{
    44     int position = regExp->match(vm, input, startOffset, m_ovector);
     44    ASSERT(owner);
     45    VM& vm = owner->vm();
     46    auto scope = DECLARE_THROW_SCOPE(vm);
     47    int position = regExp->match(owner, input, startOffset, m_ovector);
     48    RETURN_IF_EXCEPTION(scope, MatchResult::failed());
    4549
    4650    if (ovector)
     
    6064}
    6165
    62 ALWAYS_INLINE MatchResult RegExpGlobalData::performMatch(VM& vm, JSGlobalObject* owner, RegExp* regExp, JSString* string, const String& input, int startOffset)
     66ALWAYS_INLINE MatchResult RegExpGlobalData::performMatch(JSGlobalObject* owner, RegExp* regExp, JSString* string, const String& input, int startOffset)
    6367{
    64     MatchResult result = regExp->match(vm, input, startOffset);
     68    ASSERT(owner);
     69    VM& vm = owner->vm();
     70    auto scope = DECLARE_THROW_SCOPE(vm);
     71    MatchResult result = regExp->match(owner, input, startOffset);
     72    RETURN_IF_EXCEPTION(scope, MatchResult::failed());
    6573    if (result)
    6674        m_cachedResult.record(vm, owner, regExp, string, result);
  • trunk/Source/JavaScriptCore/runtime/RegExpInlines.h

    r259092 r259747  
    9999
    100100template<typename VectorType, Yarr::MatchFrom matchFrom>
    101 ALWAYS_INLINE int RegExp::matchInline(VM& vm, const String& s, unsigned startOffset, VectorType& ovector)
     101ALWAYS_INLINE int RegExp::matchInline(JSGlobalObject* nullOrGlobalObject, VM& vm, const String& s, unsigned startOffset, VectorType& ovector)
    102102{
    103103#if ENABLE(REGEXP_TRACING)
     
    109109
    110110    auto throwError = [&] {
    111         auto throwScope = DECLARE_THROW_SCOPE(vm);
    112         // FIXME: Revisit JSGlobalObject.
    113         // https://bugs.webkit.org/show_bug.cgi?id=203204
    114         JSGlobalObject* globalObject = vm.topCallFrame->lexicalGlobalObject(vm);
    115         throwScope.throwException(globalObject, errorToThrow(globalObject));
     111        if (matchFrom == Yarr::MatchFrom::CompilerThread)
     112            return -1;
     113        if (nullOrGlobalObject) {
     114            auto throwScope = DECLARE_THROW_SCOPE(vm);
     115            throwScope.throwException(nullOrGlobalObject, errorToThrow(nullOrGlobalObject));
     116        }
    116117        if (!hasHardError(m_constructionErrorCode))
    117118            reset();
     
    142143            // JIT'ed code couldn't handle expression, so punt back to the interpreter.
    143144            byteCodeCompileIfNecessary(&vm);
    144             if (m_state == ParseError) {
    145                 if (matchFrom == Yarr::MatchFrom::CompilerThread)
    146                     return -1;
     145            if (m_state == ParseError)
    147146                return throwError();
    148             }
    149147            result = Yarr::interpret(m_regExpBytecode.get(), s, startOffset, reinterpret_cast<unsigned*>(offsetVector));
    150148        }
     
    233231
    234232template<Yarr::MatchFrom matchFrom>
    235 ALWAYS_INLINE MatchResult RegExp::matchInline(VM& vm, const String& s, unsigned startOffset)
     233ALWAYS_INLINE MatchResult RegExp::matchInline(JSGlobalObject* nullOrGlobalObject, VM& vm, const String& s, unsigned startOffset)
    236234{
    237235#if ENABLE(REGEXP_TRACING)
     
    243241
    244242    auto throwError = [&] {
    245         auto throwScope = DECLARE_THROW_SCOPE(vm);
    246         // FIXME: Revisit JSGlobalObject.
    247         // https://bugs.webkit.org/show_bug.cgi?id=203204
    248         JSGlobalObject* globalObject = vm.topCallFrame->lexicalGlobalObject(vm);
    249         throwScope.throwException(globalObject, errorToThrow(globalObject));
     243        if (matchFrom == Yarr::MatchFrom::CompilerThread)
     244            return MatchResult::failed();
     245        if (nullOrGlobalObject) {
     246            auto throwScope = DECLARE_THROW_SCOPE(vm);
     247            throwScope.throwException(nullOrGlobalObject, errorToThrow(nullOrGlobalObject));
     248        }
    250249        if (!hasHardError(m_constructionErrorCode))
    251250            reset();
  • trunk/Source/JavaScriptCore/runtime/RegExpMatchesArray.h

    r252374 r259747  
    6868
    6969    Vector<int, 32> subpatternResults;
    70     int position = regExp->matchInline(vm, inputValue, startOffset, subpatternResults);
     70    int position = regExp->matchInline(globalObject, vm, inputValue, startOffset, subpatternResults);
    7171    if (position == -1) {
    7272        result = MatchResult::failed();
  • trunk/Source/JavaScriptCore/runtime/RegExpObjectInlines.h

    r259246 r259747  
    107107    if (!regExp->global() && !regExp->sticky()) {
    108108        scope.release();
    109         return globalObject->regExpGlobalData().performMatch(vm, globalObject, regExp, string, input, 0);
     109        return globalObject->regExpGlobalData().performMatch(globalObject, regExp, string, input, 0);
    110110    }
    111111
     
    118118    }
    119119   
    120     MatchResult result = globalObject->regExpGlobalData().performMatch(vm, globalObject, regExp, string, input, lastIndex);
     120    MatchResult result = globalObject->regExpGlobalData().performMatch(globalObject, regExp, string, input, lastIndex);
    121121    RETURN_IF_EXCEPTION(scope, { });
    122122    scope.release();
     
    146146    auto scope = DECLARE_THROW_SCOPE(vm);
    147147
    148     MatchResult result = globalObject->regExpGlobalData().performMatch(vm, globalObject, regExp, string, s, 0);
     148    MatchResult result = globalObject->regExpGlobalData().performMatch(globalObject, regExp, string, s, 0);
    149149    RETURN_IF_EXCEPTION(scope, { });
    150150    if (!result)
     
    168168        if (!length)
    169169            end = fixEnd(end);
    170         result = globalObject->regExpGlobalData().performMatch(vm, globalObject, regExp, string, s, end);
     170        result = globalObject->regExpGlobalData().performMatch(globalObject, regExp, string, s, end);
    171171        if (UNLIKELY(scope.exception())) {
    172172            hasException = true;
     
    196196                // OOM! On the other hand, if this loop concludes that the result is small enough,
    197197                // then the iterate() loop below will overwrite the cached result anyway.
    198                 result = globalObject->regExpGlobalData().performMatch(vm, globalObject, regExp, string, s, end);
     198                result = globalObject->regExpGlobalData().performMatch(globalObject, regExp, string, s, end);
    199199                RETURN_IF_EXCEPTION(scope, { });
    200200            } while (result);
  • trunk/Source/JavaScriptCore/runtime/RegExpPrototype.cpp

    r259547 r259747  
    487487    RETURN_IF_EXCEPTION(scope, encodedJSValue());
    488488
    489     MatchResult result = globalObject->regExpGlobalData().performMatch(vm, globalObject, regExp, string, s, 0);
     489    MatchResult result = globalObject->regExpGlobalData().performMatch(globalObject, regExp, string, s, 0);
    490490    RETURN_IF_EXCEPTION(scope, encodedJSValue());
    491491    return JSValue::encode(result ? jsNumber(result.start) : jsNumber(-1));
     
    506506template<typename ControlFunc, typename PushFunc>
    507507void genericSplit(
    508     VM& vm, RegExp* regexp, const String& input, unsigned inputSize, unsigned& position,
     508    JSGlobalObject* globalObject, RegExp* regexp, const String& input, unsigned inputSize, unsigned& position,
    509509    unsigned& matchPosition, bool regExpIsSticky, bool regExpIsUnicode,
    510510    const ControlFunc& control, const PushFunc& push)
    511511{
     512    VM& vm = globalObject->vm();
     513    auto scope = DECLARE_THROW_SCOPE(vm);
    512514    Vector<int> ovector;
    513515       
    514516    while (matchPosition < inputSize) {
    515         if (control() == AbortSplit)
    516             return;
     517        {
     518            auto result = control();
     519            RETURN_IF_EXCEPTION(scope, void());
     520            if (result == AbortSplit)
     521                return;
     522        }
    517523       
    518524        ovector.shrink(0);
     
    520526        // a. Perform ? Set(splitter, "lastIndex", q, true).
    521527        // b. Let z be ? RegExpExec(splitter, S).
    522         int mpos = regexp->match(vm, input, matchPosition, ovector);
     528        int mpos = regexp->match(globalObject, input, matchPosition, ovector);
     529        RETURN_IF_EXCEPTION(scope, void());
    523530
    524531        // c. If z is null, let q be AdvanceStringIndex(S, q, unicodeMatching).
     
    556563        // 1. Let T be a String value equal to the substring of S consisting of the elements at indices p (inclusive) through q (exclusive).
    557564        // 2. Perform ! CreateDataProperty(A, ! ToString(lengthA), T).
    558         if (push(true, position, matchPosition - position) == AbortSplit)
    559             return;
     565        {
     566            auto result = push(true, position, matchPosition - position);
     567            RETURN_IF_EXCEPTION(scope, void());
     568            if (result == AbortSplit)
     569                return;
     570        }
    560571       
    561572        // 5. Let p be e.
     
    570581            // b. Perform ! CreateDataProperty(A, ! ToString(lengthA), nextCapture).
    571582            int sub = ovector[i * 2];
    572             if (push(sub >= 0, sub, ovector[i * 2 + 1] - sub) == AbortSplit)
     583            auto result = push(sub >= 0, sub, ovector[i * 2 + 1] - sub);
     584            RETURN_IF_EXCEPTION(scope, void());
     585            if (result == AbortSplit)
    573586                return;
    574587        }
     
    631644        // c. Perform ! CreateDataProperty(A, "0", S).
    632645        // d. Return A.
    633         if (!regexp->match(vm, input, 0)) {
     646        auto matchResult = regexp->match(globalObject, input, 0);
     647        RETURN_IF_EXCEPTION(scope, encodedJSValue());
     648        if (!matchResult) {
    634649            result->putDirectIndex(globalObject, 0, inputString);
    635650            RETURN_IF_EXCEPTION(scope, encodedJSValue());
     
    647662   
    648663    genericSplit(
    649         vm, regexp, input, inputSize, position, matchPosition, regExpIsSticky, regExpIsUnicode,
     664        globalObject, regexp, input, inputSize, position, matchPosition, regExpIsSticky, regExpIsUnicode,
    650665        [&] () -> SplitControl {
    651666            if (resultLength >= maxSizeForDirectPath)
     
    679694    unsigned dryRunCount = 0;
    680695    genericSplit(
    681         vm, regexp, input, inputSize, position, matchPosition, regExpIsSticky, regExpIsUnicode,
     696        globalObject, regexp, input, inputSize, position, matchPosition, regExpIsSticky, regExpIsUnicode,
    682697        [&] () -> SplitControl {
    683698            if (resultLength + dryRunCount > MAX_STORAGE_VECTOR_LENGTH)
     
    691706            return ContinueSplit;
    692707        });
     708    RETURN_IF_EXCEPTION(scope, encodedJSValue());
    693709   
    694710    if (resultLength + dryRunCount > MAX_STORAGE_VECTOR_LENGTH) {
     
    702718   
    703719    genericSplit(
    704         vm, regexp, input, inputSize, position, matchPosition, regExpIsSticky, regExpIsUnicode,
     720        globalObject, regexp, input, inputSize, position, matchPosition, regExpIsSticky, regExpIsUnicode,
    705721        [&] () -> SplitControl {
    706722            return ContinueSplit;
  • trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp

    r259547 r259747  
    490490
    491491    while (true) {
    492         MatchResult result = globalObject->regExpGlobalData().performMatch(vm, globalObject, regExp, string, source, startPosition);
     492        MatchResult result = globalObject->regExpGlobalData().performMatch(globalObject, regExp, string, source, startPosition);
    493493        RETURN_IF_EXCEPTION(scope, nullptr);
    494494        if (!result)
     
    561561        while (true) {
    562562            int* ovector;
    563             MatchResult result = globalObject->regExpGlobalData().performMatch(vm, globalObject, regExp, string, source, startPosition, &ovector);
     563            MatchResult result = globalObject->regExpGlobalData().performMatch(globalObject, regExp, string, source, startPosition, &ovector);
    564564            RETURN_IF_EXCEPTION(scope, nullptr);
    565565            if (!result)
     
    621621        do {
    622622            int* ovector;
    623             MatchResult result = globalObject->regExpGlobalData().performMatch(vm, globalObject, regExp, string, source, startPosition, &ovector);
     623            MatchResult result = globalObject->regExpGlobalData().performMatch(globalObject, regExp, string, source, startPosition, &ovector);
    624624            RETURN_IF_EXCEPTION(scope, nullptr);
    625625            if (!result)
  • trunk/Source/JavaScriptCore/testRegExp.cpp

    r253443 r259747  
    189189}
    190190
    191 static bool testOneRegExp(VM& vm, RegExp* regexp, RegExpTest* regExpTest, bool verbose, unsigned int lineNumber)
     191static bool testOneRegExp(JSGlobalObject* globalObject, RegExp* regexp, RegExpTest* regExpTest, bool verbose, unsigned lineNumber)
    192192{
    193193    bool result = true;
    194194    Vector<int> outVector;
    195195    outVector.resize(regExpTest->expectVector.size());
    196     int matchResult = regexp->match(vm, regExpTest->subject, regExpTest->offset, outVector);
     196    int matchResult = regexp->match(globalObject, regExpTest->subject, regExpTest->offset, outVector);
    197197
    198198    if (matchResult != regExpTest->result) {
     
    466466                if (regexp && regExpTest) {
    467467                    ++tests;
    468                     if (!testOneRegExp(vm, regexp, regExpTest, verbose, lineNumber)) {
     468                    if (!testOneRegExp(globalObject, regexp, regExpTest, verbose, lineNumber)) {
    469469                        failures++;
    470470                        printf("Failure on line %u\n", lineNumber);
Note: See TracChangeset for help on using the changeset viewer.