Title: [283874] trunk
Revision
283874
Author
[email protected]
Date
2021-10-10 01:49:45 -0700 (Sun, 10 Oct 2021)

Log Message

[JSC] Refine RegExp#compile based on regexp-legacy-features proposal
https://bugs.webkit.org/show_bug.cgi?id=231486

Reviewed by Alexey Shvayka.

JSTests:

* stress/regexp-recompile.js: Added.
(shouldBe):
(recompile):
(target):
* test262/expectations.yaml:

Source/_javascript_Core:

This patch refines RegExp#compile based regexp-legacy-features proposal[1].
We add legacyFeaturesDisabledFlag flag to RegExpObject so that we can
detect [[LegacyFeaturesEnabled]].

We also add regExpRecompiledWatchpoint to JSGlobalObject. We have strength
reduction in DFG / FTL, but we should recompile DFG / FTL code when RegExp
is recompiled. Since it is rare, instead of having this watchpoint per
RegExpObject, we hold it in JSGlobalObject.

[1]: https://github.com/tc39/proposal-regexp-legacy-features

* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileNewRegexp):
(JSC::DFG::SpeculativeJIT::compileSetRegExpObjectLastIndex):
* dfg/DFGStrengthReductionPhase.cpp:
(JSC::DFG::StrengthReductionPhase::handleNode):
* ftl/FTLAbstractHeapRepository.h:
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):
* ftl/FTLOperations.cpp:
(JSC::FTL::JSC_DEFINE_JIT_OPERATION):
* jit/JITOperations.cpp:
(JSC::JSC_DEFINE_JIT_OPERATION):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::JSGlobalObject):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::regExpRecompiledWatchpoint):
(JSC::JSGlobalObject::isRegExpRecompiled const):
* runtime/RegExpConstructor.cpp:
(JSC::areLegacyFeaturesEnabled):
(JSC::regExpCreate):
(JSC::constructRegExp):
* runtime/RegExpObject.cpp:
(JSC::RegExpObject::RegExpObject):
* runtime/RegExpObject.h:
* runtime/RegExpPrototype.cpp:
(JSC::JSC_DEFINE_HOST_FUNCTION):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (283873 => 283874)


--- trunk/JSTests/ChangeLog	2021-10-10 07:01:37 UTC (rev 283873)
+++ trunk/JSTests/ChangeLog	2021-10-10 08:49:45 UTC (rev 283874)
@@ -1,3 +1,16 @@
+2021-10-09  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Refine RegExp#compile based on regexp-legacy-features proposal
+        https://bugs.webkit.org/show_bug.cgi?id=231486
+
+        Reviewed by Alexey Shvayka.
+
+        * stress/regexp-recompile.js: Added.
+        (shouldBe):
+        (recompile):
+        (target):
+        * test262/expectations.yaml:
+
 2021-10-08  Tadeu Zagallo  <[email protected]>
 
         Implement the WebAssembly exception handling proposal

Added: trunk/JSTests/stress/regexp-recompile.js (0 => 283874)


--- trunk/JSTests/stress/regexp-recompile.js	                        (rev 0)
+++ trunk/JSTests/stress/regexp-recompile.js	2021-10-10 08:49:45 UTC (rev 283874)
@@ -0,0 +1,26 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+var flag = false;
+function recompile(regExp) {
+    if (flag)
+        regExp.compile("e");
+}
+noInline(recompile);
+
+function target() {
+    var regExp = /test/;
+    recompile(regExp);
+    regExp.lastIndex = 0;
+    return regExp.exec("Hey");
+}
+noInline(target);
+
+for (var i = 0; i < 1e4; ++i)
+    shouldBe(target(), null);
+flag = true;
+shouldBe(JSON.stringify(target()), `["e"]`);
+for (var i = 0; i < 1e4; ++i)
+    shouldBe(JSON.stringify(target()), `["e"]`);

Modified: trunk/JSTests/test262/expectations.yaml (283873 => 283874)


--- trunk/JSTests/test262/expectations.yaml	2021-10-10 07:01:37 UTC (rev 283873)
+++ trunk/JSTests/test262/expectations.yaml	2021-10-10 08:49:45 UTC (rev 283874)
@@ -5,12 +5,6 @@
 test/annexB/built-ins/Function/createdynfn-html-open-comment-params.js:
   default: "SyntaxError: Unexpected token '}'. Expected a parameter pattern or a ')' in parameter list."
   strict mode: "SyntaxError: Unexpected token '}'. Expected a parameter pattern or a ')' in parameter list."
-test/annexB/built-ins/RegExp/prototype/compile/this-cross-realm-instance.js:
-  default: 'Test262Error: `RegExp.prototype.compile.call(otherRealm_regexp)` throws TypeError Expected a TypeError to be thrown but no exception was thrown at all'
-  strict mode: 'Test262Error: `RegExp.prototype.compile.call(otherRealm_regexp)` throws TypeError Expected a TypeError to be thrown but no exception was thrown at all'
-test/annexB/built-ins/RegExp/prototype/compile/this-subclass-instance.js:
-  default: 'Test262Error: `subclass_regexp.compile()` throws TypeError Expected a TypeError to be thrown but no exception was thrown at all'
-  strict mode: 'Test262Error: `subclass_regexp.compile()` throws TypeError Expected a TypeError to be thrown but no exception was thrown at all'
 test/annexB/language/eval-code/direct/func-block-decl-eval-func-skip-early-err-block.js:
   default: 'Test262Error: An initialized binding is not created prior to evaluation Expected a ReferenceError to be thrown but no exception was thrown at all'
 test/annexB/language/eval-code/direct/func-block-decl-eval-func-skip-early-err-for-in.js:

Modified: trunk/Source/_javascript_Core/ChangeLog (283873 => 283874)


--- trunk/Source/_javascript_Core/ChangeLog	2021-10-10 07:01:37 UTC (rev 283873)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-10-10 08:49:45 UTC (rev 283874)
@@ -1,3 +1,50 @@
+2021-10-09  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Refine RegExp#compile based on regexp-legacy-features proposal
+        https://bugs.webkit.org/show_bug.cgi?id=231486
+
+        Reviewed by Alexey Shvayka.
+
+        This patch refines RegExp#compile based regexp-legacy-features proposal[1].
+        We add legacyFeaturesDisabledFlag flag to RegExpObject so that we can
+        detect [[LegacyFeaturesEnabled]].
+
+        We also add regExpRecompiledWatchpoint to JSGlobalObject. We have strength
+        reduction in DFG / FTL, but we should recompile DFG / FTL code when RegExp
+        is recompiled. Since it is rare, instead of having this watchpoint per
+        RegExpObject, we hold it in JSGlobalObject.
+
+        [1]: https://github.com/tc39/proposal-regexp-legacy-features
+
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileNewRegexp):
+        (JSC::DFG::SpeculativeJIT::compileSetRegExpObjectLastIndex):
+        * dfg/DFGStrengthReductionPhase.cpp:
+        (JSC::DFG::StrengthReductionPhase::handleNode):
+        * ftl/FTLAbstractHeapRepository.h:
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):
+        * ftl/FTLOperations.cpp:
+        (JSC::FTL::JSC_DEFINE_JIT_OPERATION):
+        * jit/JITOperations.cpp:
+        (JSC::JSC_DEFINE_JIT_OPERATION):
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::JSGlobalObject):
+        * runtime/JSGlobalObject.h:
+        (JSC::JSGlobalObject::regExpRecompiledWatchpoint):
+        (JSC::JSGlobalObject::isRegExpRecompiled const):
+        * runtime/RegExpConstructor.cpp:
+        (JSC::areLegacyFeaturesEnabled):
+        (JSC::regExpCreate):
+        (JSC::constructRegExp):
+        * runtime/RegExpObject.cpp:
+        (JSC::RegExpObject::RegExpObject):
+        * runtime/RegExpObject.h:
+        * runtime/RegExpPrototype.cpp:
+        (JSC::JSC_DEFINE_HOST_FUNCTION):
+
 2021-10-08  Saam Barati  <[email protected]>
 
         Run backwards propagation before we prune the graph after ForceOSRExit nodes in BytecodeParser

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (283873 => 283874)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2021-10-10 07:01:37 UTC (rev 283873)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2021-10-10 08:49:45 UTC (rev 283874)
@@ -11223,7 +11223,7 @@
 
     m_jit.storePtr(
         TrustedImmPtr(node->cellOperand()),
-        CCallHelpers::Address(resultGPR, RegExpObject::offsetOfRegExpAndLastIndexIsNotWritableFlag()));
+        CCallHelpers::Address(resultGPR, RegExpObject::offsetOfRegExpAndFlags()));
     m_jit.storeValue(lastIndexRegs, CCallHelpers::Address(resultGPR, RegExpObject::offsetOfLastIndex()));
     m_jit.mutatorFence(vm());
 
@@ -12773,7 +12773,7 @@
             ExoticObjectMode, JSValueRegs(), nullptr,
             m_jit.branchTestPtr(
                 JITCompiler::NonZero,
-                JITCompiler::Address(regExpGPR, RegExpObject::offsetOfRegExpAndLastIndexIsNotWritableFlag()),
+                JITCompiler::Address(regExpGPR, RegExpObject::offsetOfRegExpAndFlags()),
                 JITCompiler::TrustedImm32(RegExpObject::lastIndexIsNotWritableFlag)));
     }
 

Modified: trunk/Source/_javascript_Core/dfg/DFGStrengthReductionPhase.cpp (283873 => 283874)


--- trunk/Source/_javascript_Core/dfg/DFGStrengthReductionPhase.cpp	2021-10-10 07:01:37 UTC (rev 283873)
+++ trunk/Source/_javascript_Core/dfg/DFGStrengthReductionPhase.cpp	2021-10-10 08:49:45 UTC (rev 283874)
@@ -502,11 +502,25 @@
             if (m_node->op() == RegExpExec || m_node->op() == RegExpTest || m_node->op() == RegExpMatchFast) {
                 regExpObjectNode = m_node->child2().node();
                 if (RegExpObject* regExpObject = regExpObjectNode->dynamicCastConstant<RegExpObject*>(vm())) {
+                    JSGlobalObject* globalObject = regExpObject->globalObject(vm());
+                    if (globalObject->isRegExpRecompiled()) {
+                        if (verbose)
+                            dataLog("Giving up because RegExp recompile happens.\n");
+                        break;
+                    }
+                    m_graph.watchpoints().addLazily(globalObject->regExpRecompiledWatchpoint());
                     regExp = regExpObject->regExp();
                     regExpObjectNodeIsConstant = true;
-                } else if (regExpObjectNode->op() == NewRegexp)
+                } else if (regExpObjectNode->op() == NewRegexp) {
+                    JSGlobalObject* globalObject = m_graph.globalObjectFor(regExpObjectNode->origin.semantic);
+                    if (globalObject->isRegExpRecompiled()) {
+                        if (verbose)
+                            dataLog("Giving up because RegExp recompile happens.\n");
+                        break;
+                    }
+                    m_graph.watchpoints().addLazily(globalObject->regExpRecompiledWatchpoint());
                     regExp = regExpObjectNode->castOperand<RegExp*>();
-                else {
+                } else {
                     if (verbose)
                         dataLog("Giving up because the regexp is unknown.\n");
                     break;
@@ -835,11 +849,25 @@
             
             Node* regExpObjectNode = m_node->child2().node();
             RegExp* regExp;
-            if (RegExpObject* regExpObject = regExpObjectNode->dynamicCastConstant<RegExpObject*>(vm()))
+            if (RegExpObject* regExpObject = regExpObjectNode->dynamicCastConstant<RegExpObject*>(vm())) {
+                JSGlobalObject* globalObject = regExpObject->globalObject(vm());
+                if (globalObject->isRegExpRecompiled()) {
+                    if (verbose)
+                        dataLog("Giving up because RegExp recompile happens.\n");
+                    break;
+                }
+                m_graph.watchpoints().addLazily(globalObject->regExpRecompiledWatchpoint());
                 regExp = regExpObject->regExp();
-            else if (regExpObjectNode->op() == NewRegexp)
+            } else if (regExpObjectNode->op() == NewRegexp) {
+                JSGlobalObject* globalObject = m_graph.globalObjectFor(regExpObjectNode->origin.semantic);
+                if (globalObject->isRegExpRecompiled()) {
+                    if (verbose)
+                        dataLog("Giving up because RegExp recompile happens.\n");
+                    break;
+                }
+                m_graph.watchpoints().addLazily(globalObject->regExpRecompiledWatchpoint());
                 regExp = regExpObjectNode->castOperand<RegExp*>();
-            else {
+            } else {
                 if (verbose)
                     dataLog("Giving up because the regexp is unknown.\n");
                 break;

Modified: trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h (283873 => 283874)


--- trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h	2021-10-10 07:01:37 UTC (rev 283873)
+++ trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h	2021-10-10 08:49:45 UTC (rev 283874)
@@ -123,7 +123,7 @@
     macro(JSScope_next, JSScope::offsetOfNext()) \
     macro(JSSymbolTableObject_symbolTable, JSSymbolTableObject::offsetOfSymbolTable()) \
     macro(NativeExecutable_asString, NativeExecutable::offsetOfAsString()) \
-    macro(RegExpObject_regExpAndLastIndexIsNotWritableFlag, RegExpObject::offsetOfRegExpAndLastIndexIsNotWritableFlag()) \
+    macro(RegExpObject_regExpAndFlags, RegExpObject::offsetOfRegExpAndFlags()) \
     macro(RegExpObject_lastIndex, RegExpObject::offsetOfLastIndex()) \
     macro(ShadowChicken_Packet_callee, OBJECT_OFFSETOF(ShadowChicken::Packet, callee)) \
     macro(ShadowChicken_Packet_frame, OBJECT_OFFSETOF(ShadowChicken::Packet, frame)) \

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (283873 => 283874)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2021-10-10 07:01:37 UTC (rev 283873)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2021-10-10 08:49:45 UTC (rev 283874)
@@ -14290,7 +14290,7 @@
 
         auto structure = m_graph.registerStructure(globalObject->regExpStructure());
         LValue fastResultValue = allocateObject<RegExpObject>(structure, m_out.intPtrZero, slowCase);
-        m_out.storePtr(frozenPointer(regexp), fastResultValue, m_heaps.RegExpObject_regExpAndLastIndexIsNotWritableFlag);
+        m_out.storePtr(frozenPointer(regexp), fastResultValue, m_heaps.RegExpObject_regExpAndFlags);
         m_out.store64(lastIndex, fastResultValue, m_heaps.RegExpObject_lastIndex);
         mutatorFence();
         ValueFromBlock fastResult = m_out.anchor(fastResultValue);
@@ -14377,7 +14377,7 @@
             speculate(
                 ExoticObjectMode, noValue(), nullptr,
                 m_out.testNonZeroPtr(
-                    m_out.loadPtr(regExp, m_heaps.RegExpObject_regExpAndLastIndexIsNotWritableFlag),
+                    m_out.loadPtr(regExp, m_heaps.RegExpObject_regExpAndFlags),
                     m_out.constIntPtr(RegExpObject::lastIndexIsNotWritableFlag)));
 
             m_out.store64(value, regExp, m_heaps.RegExpObject_lastIndex);

Modified: trunk/Source/_javascript_Core/ftl/FTLOperations.cpp (283873 => 283874)


--- trunk/Source/_javascript_Core/ftl/FTLOperations.cpp	2021-10-10 07:01:37 UTC (rev 283873)
+++ trunk/Source/_javascript_Core/ftl/FTLOperations.cpp	2021-10-10 08:49:45 UTC (rev 283874)
@@ -689,7 +689,8 @@
         RELEASE_ASSERT(regExp);
         CodeBlock* codeBlock = baselineCodeBlockForOriginAndBaselineCodeBlock(materialization->origin(), callFrame->codeBlock()->baselineAlternative());
         Structure* structure = codeBlock->globalObject()->regExpStructure();
-        return RegExpObject::create(vm, structure, regExp);
+        static constexpr bool areLegacyFeaturesEnabled = true;
+        return RegExpObject::create(vm, structure, regExp, areLegacyFeaturesEnabled);
     }
 
     default:

Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (283873 => 283874)


--- trunk/Source/_javascript_Core/jit/JITOperations.cpp	2021-10-10 07:01:37 UTC (rev 283873)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp	2021-10-10 08:49:45 UTC (rev 283874)
@@ -1890,7 +1890,8 @@
 
     RegExp* regexp = static_cast<RegExp*>(regexpPtr);
     ASSERT(regexp->isValid());
-    return RegExpObject::create(vm, globalObject->regExpStructure(), regexp);
+    static constexpr bool areLegacyFeaturesEnabled = true;
+    return RegExpObject::create(vm, globalObject->regExpStructure(), regexp, areLegacyFeaturesEnabled);
 }
 
 // The only reason for returning an UnusedPtr (instead of void) is so that we can reuse the

Modified: trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp (283873 => 283874)


--- trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2021-10-10 07:01:37 UTC (rev 283873)
+++ trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2021-10-10 08:49:45 UTC (rev 283874)
@@ -612,7 +612,8 @@
     auto bytecode = pc->as<OpNewRegexp>();
     RegExp* regExp = jsCast<RegExp*>(getOperand(callFrame, bytecode.m_regexp));
     ASSERT(regExp->isValid());
-    LLINT_RETURN(RegExpObject::create(vm, globalObject->regExpStructure(), regExp));
+    static constexpr bool areLegacyFeaturesEnabled = true;
+    LLINT_RETURN(RegExpObject::create(vm, globalObject->regExpStructure(), regExp, areLegacyFeaturesEnabled));
 }
 
 LLINT_SLOW_PATH_DECL(slow_path_instanceof)

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (283873 => 283874)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2021-10-10 07:01:37 UTC (rev 283873)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2021-10-10 08:49:45 UTC (rev 283874)
@@ -608,6 +608,7 @@
     , m_havingABadTimeWatchpoint(WatchpointSet::create(IsWatched))
     , m_varInjectionWatchpoint(WatchpointSet::create(IsWatched))
     , m_varReadOnlyWatchpoint(WatchpointSet::create(IsWatched))
+    , m_regExpRecompiledWatchpoint(WatchpointSet::create(IsWatched))
     , m_weakRandom(Options::forceWeakRandomSeed() ? Options::forcedWeakRandomSeed() : static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0)))
     , m_arrayIteratorProtocolWatchpointSet(IsWatched)
     , m_mapIteratorProtocolWatchpointSet(IsWatched)

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.h (283873 => 283874)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.h	2021-10-10 07:01:37 UTC (rev 283873)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.h	2021-10-10 08:49:45 UTC (rev 283874)
@@ -487,6 +487,7 @@
     RefPtr<WatchpointSet> m_havingABadTimeWatchpoint;
     RefPtr<WatchpointSet> m_varInjectionWatchpoint;
     RefPtr<WatchpointSet> m_varReadOnlyWatchpoint;
+    RefPtr<WatchpointSet> m_regExpRecompiledWatchpoint;
 
     std::unique_ptr<JSGlobalObjectRareData> m_rareData;
 
@@ -1025,6 +1026,7 @@
     WatchpointSet* havingABadTimeWatchpoint() { return m_havingABadTimeWatchpoint.get(); }
     WatchpointSet* varInjectionWatchpoint() { return m_varInjectionWatchpoint.get(); }
     WatchpointSet* varReadOnlyWatchpoint() { return m_varReadOnlyWatchpoint.get(); }
+    WatchpointSet* regExpRecompiledWatchpoint() { return m_regExpRecompiledWatchpoint.get(); }
         
     bool isHavingABadTime() const
     {
@@ -1037,6 +1039,11 @@
     bool arrayPrototypeChainIsSane();
     bool stringPrototypeChainIsSane();
 
+    bool isRegExpRecompiled() const
+    {
+        return m_regExpRecompiledWatchpoint->hasBeenInvalidated();
+    }
+
     void setProfileGroup(unsigned value) { createRareDataIfNeeded(); m_rareData->profileGroup = value; }
     unsigned profileGroup() const
     { 

Modified: trunk/Source/_javascript_Core/runtime/RegExpConstructor.cpp (283873 => 283874)


--- trunk/Source/_javascript_Core/runtime/RegExpConstructor.cpp	2021-10-10 07:01:37 UTC (rev 283873)
+++ trunk/Source/_javascript_Core/runtime/RegExpConstructor.cpp	2021-10-10 08:49:45 UTC (rev 283874)
@@ -187,6 +187,13 @@
     return true;
 }
 
+static inline bool areLegacyFeaturesEnabled(JSGlobalObject* globalObject, JSValue newTarget)
+{
+    if (!newTarget)
+        return true;
+    return newTarget == globalObject->regExpConstructor();
+}
+
 inline Structure* getRegExpStructure(JSGlobalObject* globalObject, JSValue newTarget)
 {
     if (!newTarget)
@@ -232,7 +239,7 @@
 
     Structure* structure = getRegExpStructure(globalObject, newTarget);
     RETURN_IF_EXCEPTION(scope, nullptr);
-    return RegExpObject::create(vm, structure, regExp);
+    return RegExpObject::create(vm, structure, regExp, areLegacyFeaturesEnabled(globalObject, newTarget));
 }
 
 JSObject* constructRegExp(JSGlobalObject* globalObject, const ArgList& args,  JSObject* callee, JSValue newTarget)
@@ -271,7 +278,7 @@
             }
         }
 
-        return RegExpObject::create(vm, structure, regExp);
+        return RegExpObject::create(vm, structure, regExp, areLegacyFeaturesEnabled(globalObject, newTarget));
     }
 
     if (constructAsRegexp) {

Modified: trunk/Source/_javascript_Core/runtime/RegExpObject.cpp (283873 => 283874)


--- trunk/Source/_javascript_Core/runtime/RegExpObject.cpp	2021-10-10 07:01:37 UTC (rev 283873)
+++ trunk/Source/_javascript_Core/runtime/RegExpObject.cpp	2021-10-10 08:49:45 UTC (rev 283874)
@@ -32,9 +32,9 @@
 static JSC_DECLARE_CUSTOM_SETTER(regExpObjectSetLastIndexStrict);
 static JSC_DECLARE_CUSTOM_SETTER(regExpObjectSetLastIndexNonStrict);
 
-RegExpObject::RegExpObject(VM& vm, Structure* structure, RegExp* regExp)
+RegExpObject::RegExpObject(VM& vm, Structure* structure, RegExp* regExp, bool areLegacyFeaturesEnabled)
     : JSNonFinalObject(vm, structure)
-    , m_regExpAndLastIndexIsNotWritableFlag(bitwise_cast<uintptr_t>(regExp)) // lastIndexIsNotWritableFlag is not set.
+    , m_regExpAndFlags(bitwise_cast<uintptr_t>(regExp) | (areLegacyFeaturesEnabled ? 0 : legacyFeaturesDisabledFlag)) // lastIndexIsNotWritableFlag is not set.
 {
     m_lastIndex.setWithoutWriteBarrier(jsNumber(0));
 }

Modified: trunk/Source/_javascript_Core/runtime/RegExpObject.h (283873 => 283874)


--- trunk/Source/_javascript_Core/runtime/RegExpObject.h	2021-10-10 07:01:37 UTC (rev 283873)
+++ trunk/Source/_javascript_Core/runtime/RegExpObject.h	2021-10-10 08:49:45 UTC (rev 283874)
@@ -39,11 +39,14 @@
         return &vm.regExpObjectSpace;
     }
 
-    static constexpr uintptr_t lastIndexIsNotWritableFlag = 1;
+    static constexpr uintptr_t lastIndexIsNotWritableFlag = 0b01;
+    static constexpr uintptr_t legacyFeaturesDisabledFlag = 0b10;
+    static constexpr uintptr_t flagsMask = lastIndexIsNotWritableFlag | legacyFeaturesDisabledFlag;
+    static constexpr uintptr_t regExpMask = ~flagsMask;
 
-    static RegExpObject* create(VM& vm, Structure* structure, RegExp* regExp)
+    static RegExpObject* create(VM& vm, Structure* structure, RegExp* regExp, bool areLegacyFeaturesEnabled = true)
     {
-        RegExpObject* object = new (NotNull, allocateCell<RegExpObject>(vm.heap)) RegExpObject(vm, structure, regExp);
+        RegExpObject* object = new (NotNull, allocateCell<RegExpObject>(vm.heap)) RegExpObject(vm, structure, regExp, areLegacyFeaturesEnabled);
         object->finishCreation(vm);
         return object;
     }
@@ -50,7 +53,8 @@
 
     static RegExpObject* create(VM& vm, Structure* structure, RegExp* regExp, JSValue lastIndex)
     {
-        auto* object = create(vm, structure, regExp);
+        static constexpr bool areLegacyFeaturesEnabled = true;
+        auto* object = create(vm, structure, regExp, areLegacyFeaturesEnabled);
         object->m_lastIndex.set(vm, object, lastIndex);
         return object;
     }
@@ -57,14 +61,14 @@
 
     void setRegExp(VM& vm, RegExp* regExp)
     {
-        uintptr_t result = (m_regExpAndLastIndexIsNotWritableFlag & lastIndexIsNotWritableFlag) | bitwise_cast<uintptr_t>(regExp);
-        m_regExpAndLastIndexIsNotWritableFlag = result;
+        uintptr_t result = (m_regExpAndFlags & flagsMask) | bitwise_cast<uintptr_t>(regExp);
+        m_regExpAndFlags = result;
         vm.heap.writeBarrier(this, regExp);
     }
 
     RegExp* regExp() const
     {
-        return bitwise_cast<RegExp*>(m_regExpAndLastIndexIsNotWritableFlag & (~lastIndexIsNotWritableFlag));
+        return bitwise_cast<RegExp*>(m_regExpAndFlags & regExpMask);
     }
 
     bool setLastIndex(JSGlobalObject* globalObject, size_t lastIndex)
@@ -112,9 +116,9 @@
         return Structure::create(vm, globalObject, prototype, TypeInfo(RegExpObjectType, StructureFlags), info());
     }
 
-    static ptrdiff_t offsetOfRegExpAndLastIndexIsNotWritableFlag()
+    static ptrdiff_t offsetOfRegExpAndFlags()
     {
-        return OBJECT_OFFSETOF(RegExpObject, m_regExpAndLastIndexIsNotWritableFlag);
+        return OBJECT_OFFSETOF(RegExpObject, m_regExpAndFlags);
     }
 
     static ptrdiff_t offsetOfLastIndex()
@@ -128,8 +132,10 @@
         return sizeof(RegExpObject);
     }
 
+    bool areLegacyFeaturesEnabled() const { return !(m_regExpAndFlags & legacyFeaturesDisabledFlag); }
+
 private:
-    JS_EXPORT_PRIVATE RegExpObject(VM&, Structure*, RegExp*);
+    JS_EXPORT_PRIVATE RegExpObject(VM&, Structure*, RegExp*, bool areLegacyFeaturesEnabled);
     JS_EXPORT_PRIVATE void finishCreation(VM&);
 
     DECLARE_VISIT_CHILDREN;
@@ -136,12 +142,12 @@
 
     bool lastIndexIsWritable() const
     {
-        return !(m_regExpAndLastIndexIsNotWritableFlag & lastIndexIsNotWritableFlag);
+        return !(m_regExpAndFlags & lastIndexIsNotWritableFlag);
     }
 
     void setLastIndexIsNotWritable()
     {
-        m_regExpAndLastIndexIsNotWritableFlag = (m_regExpAndLastIndexIsNotWritableFlag | lastIndexIsNotWritableFlag);
+        m_regExpAndFlags = (m_regExpAndFlags | lastIndexIsNotWritableFlag);
     }
 
     JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, JSGlobalObject*, PropertyName, DeletePropertySlot&);
@@ -150,7 +156,7 @@
 
     MatchResult matchInline(JSGlobalObject*, JSString*);
 
-    uintptr_t m_regExpAndLastIndexIsNotWritableFlag { 0 };
+    uintptr_t m_regExpAndFlags { 0 };
     WriteBarrier<Unknown> m_lastIndex;
 };
 

Modified: trunk/Source/_javascript_Core/runtime/RegExpPrototype.cpp (283873 => 283874)


--- trunk/Source/_javascript_Core/runtime/RegExpPrototype.cpp	2021-10-10 07:01:37 UTC (rev 283873)
+++ trunk/Source/_javascript_Core/runtime/RegExpPrototype.cpp	2021-10-10 08:49:45 UTC (rev 283874)
@@ -132,6 +132,12 @@
     if (UNLIKELY(!thisRegExp))
         return throwVMTypeError(globalObject, scope);
 
+    if (thisRegExp->globalObject(vm) != globalObject)
+        return throwVMTypeError(globalObject, scope, "RegExp.prototype.compile function's Realm must be the same to |this| RegExp object"_s);
+
+    if (!thisRegExp->areLegacyFeaturesEnabled())
+        return throwVMTypeError(globalObject, scope, "|this| RegExp object's legacy features are not enabled"_s);
+
     RegExp* regExp;
     JSValue arg0 = callFrame->argument(0);
     JSValue arg1 = callFrame->argument(1);
@@ -155,6 +161,8 @@
     if (!regExp->isValid())
         return throwVMError(globalObject, scope, regExp->errorToThrow(globalObject));
 
+    globalObject->regExpRecompiledWatchpoint()->fireAll(vm, "RegExp is recompiled");
+
     thisRegExp->setRegExp(vm, regExp);
     scope.release();
     thisRegExp->setLastIndex(globalObject, 0);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to