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);