WebKit Bugzilla
Attachment 360299 Details for
Bug 193801
: [JSC] RegExpConstructor should not have own IsoSubspace
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-193801-20190127111548.patch (text/plain), 74.84 KB, created by
Yusuke Suzuki
on 2019-01-27 11:15:49 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Yusuke Suzuki
Created:
2019-01-27 11:15:49 PST
Size:
74.84 KB
patch
obsolete
>Subversion Revision: 240551 >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index 64b553ed70d30bc84e1b306ae116da25e7ddecb3..cf7c40dd3cf1c49a5fe4156b56deab3e1c60d543 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,103 @@ >+2019-01-27 Yusuke Suzuki <ysuzuki@apple.com> >+ >+ [JSC] RegExpConstructor should not have own IsoSubspace >+ https://bugs.webkit.org/show_bug.cgi?id=193801 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ This patch finally removes RegExpConstructor's cached data to JSGlobalObject and remove IsoSubspace for RegExpConstructor. >+ sizeof(RegExpConstructor) != sizeof(InternalFunction), so that we have 16KB memory just for RegExpConstructor. But cached >+ regexp matching data (e.g. `RegExp.$1`) is per-JSGlobalObject one, and we can move this data to JSGlobalObject and remove >+ it from RegExpConstructor members. >+ >+ We introduce RegExpGlobalData, which holds the per-global RegExp matching data. And we perform `performMatch` etc. with >+ JSGlobalObject instead of RegExpConstructor. This change requires small changes in DFG / FTL's RecordRegExpCachedResult >+ node since its 1st argument is changed from RegExpConstructor to JSGlobalObject. >+ >+ We also move emptyRegExp from RegExpPrototype to VM's RegExpCache because it is more natural place to put it. >+ >+ * CMakeLists.txt: >+ * JavaScriptCore.xcodeproj/project.pbxproj: >+ * Sources.txt: >+ * dfg/DFGOperations.cpp: >+ * dfg/DFGSpeculativeJIT.cpp: >+ (JSC::DFG::SpeculativeJIT::compileRecordRegExpCachedResult): >+ * dfg/DFGStrengthReductionPhase.cpp: >+ (JSC::DFG::StrengthReductionPhase::handleNode): >+ * ftl/FTLAbstractHeapRepository.cpp: >+ * ftl/FTLAbstractHeapRepository.h: >+ * ftl/FTLLowerDFGToB3.cpp: >+ (JSC::FTL::DFG::LowerDFGToB3::compileRecordRegExpCachedResult): >+ * runtime/JSGlobalObject.cpp: >+ (JSC::JSGlobalObject::init): >+ (JSC::JSGlobalObject::visitChildren): >+ * runtime/JSGlobalObject.h: >+ (JSC::JSGlobalObject::regExpGlobalData): >+ (JSC::JSGlobalObject::regExpGlobalDataOffset): >+ (JSC::JSGlobalObject::regExpConstructor const): Deleted. >+ * runtime/RegExpCache.cpp: >+ (JSC::RegExpCache::initialize): >+ * runtime/RegExpCache.h: >+ (JSC::RegExpCache::emptyRegExp const): >+ * runtime/RegExpCachedResult.cpp: >+ (JSC::RegExpCachedResult::visitAggregate): >+ (JSC::RegExpCachedResult::visitChildren): Deleted. >+ * runtime/RegExpCachedResult.h: >+ (JSC::RegExpCachedResult::RegExpCachedResult): Deleted. >+ * runtime/RegExpConstructor.cpp: >+ (JSC::RegExpConstructor::RegExpConstructor): >+ (JSC::regExpConstructorDollar): >+ (JSC::regExpConstructorInput): >+ (JSC::regExpConstructorMultiline): >+ (JSC::regExpConstructorLastMatch): >+ (JSC::regExpConstructorLastParen): >+ (JSC::regExpConstructorLeftContext): >+ (JSC::regExpConstructorRightContext): >+ (JSC::setRegExpConstructorInput): >+ (JSC::setRegExpConstructorMultiline): >+ (JSC::RegExpConstructor::destroy): Deleted. >+ (JSC::RegExpConstructor::visitChildren): Deleted. >+ (JSC::RegExpConstructor::getBackref): Deleted. >+ (JSC::RegExpConstructor::getLastParen): Deleted. >+ (JSC::RegExpConstructor::getLeftContext): Deleted. >+ (JSC::RegExpConstructor::getRightContext): Deleted. >+ * runtime/RegExpConstructor.h: >+ (JSC::RegExpConstructor::performMatch): Deleted. >+ (JSC::RegExpConstructor::recordMatch): Deleted. >+ * runtime/RegExpGlobalData.cpp: Added. >+ (JSC::RegExpGlobalData::visitAggregate): >+ (JSC::RegExpGlobalData::getBackref): >+ (JSC::RegExpGlobalData::getLastParen): >+ (JSC::RegExpGlobalData::getLeftContext): >+ (JSC::RegExpGlobalData::getRightContext): >+ * runtime/RegExpGlobalData.h: Added. >+ (JSC::RegExpGlobalData::cachedResult): >+ (JSC::RegExpGlobalData::setMultiline): >+ (JSC::RegExpGlobalData::multiline const): >+ (JSC::RegExpGlobalData::input): >+ (JSC::RegExpGlobalData::offsetOfCachedResult): >+ * runtime/RegExpGlobalDataInlines.h: Added. >+ (JSC::RegExpGlobalData::setInput): >+ (JSC::RegExpGlobalData::performMatch): >+ (JSC::RegExpGlobalData::recordMatch): >+ * runtime/RegExpObject.cpp: >+ (JSC::RegExpObject::matchGlobal): >+ * runtime/RegExpObjectInlines.h: >+ (JSC::RegExpObject::execInline): >+ (JSC::RegExpObject::matchInline): >+ (JSC::collectMatches): >+ * runtime/RegExpPrototype.cpp: >+ (JSC::RegExpPrototype::finishCreation): >+ (JSC::regExpProtoFuncSearchFast): >+ (JSC::RegExpPrototype::visitChildren): Deleted. >+ * runtime/RegExpPrototype.h: >+ * runtime/StringPrototype.cpp: >+ (JSC::removeUsingRegExpSearch): >+ (JSC::replaceUsingRegExpSearch): >+ * runtime/VM.cpp: >+ (JSC::VM::VM): >+ * runtime/VM.h: >+ > 2019-01-26 Devin Rousso <drousso@apple.com> > > Web Inspector: provide a way to edit the user agent of a remote target >diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt >index 7b43f3c89f1f41edad1a7f9b3d6db67a935a7ecc..8070fa2a1da7ca5a2a55b1304eeb549d8c2aeec8 100644 >--- a/Source/JavaScriptCore/CMakeLists.txt >+++ b/Source/JavaScriptCore/CMakeLists.txt >@@ -905,6 +905,8 @@ set(JavaScriptCore_PRIVATE_FRAMEWORK_HEADERS > runtime/PutDirectIndexMode.h > runtime/PutPropertySlot.h > runtime/RegExp.h >+ runtime/RegExpCachedResult.h >+ runtime/RegExpGlobalData.h > runtime/RegExpKey.h > runtime/RegExpObject.h > runtime/RuntimeFlags.h >diff --git a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj >index 880eda2cd486d897c94a7f2312bda1b22939955a..db455bc63fb753cec60669b1ed9186c0bfcdab9d 100644 >--- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj >+++ b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj >@@ -1733,6 +1733,7 @@ > E3201C1E1F8E824C0076A032 /* ScriptFetchParameters.h in Headers */ = {isa = PBXBuildFile; fileRef = E38D060C1F8E814100649CF2 /* ScriptFetchParameters.h */; settings = {ATTRIBUTES = (Private, ); }; }; > E322E5A31DA64439006E7709 /* DFGSnippetParams.h in Headers */ = {isa = PBXBuildFile; fileRef = E322E5A11DA64435006E7709 /* DFGSnippetParams.h */; }; > E322E5A71DA644A8006E7709 /* FTLSnippetParams.h in Headers */ = {isa = PBXBuildFile; fileRef = E322E5A51DA644A4006E7709 /* FTLSnippetParams.h */; }; >+ E325956421FDA2C9008EDC9C /* RegExpGlobalDataInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E325956321FDA2C8008EDC9C /* RegExpGlobalDataInlines.h */; }; > E3282BBB1FE930AF00EDAF71 /* YarrErrorCode.h in Headers */ = {isa = PBXBuildFile; fileRef = E3282BBA1FE930A400EDAF71 /* YarrErrorCode.h */; settings = {ATTRIBUTES = (Private, ); }; }; > E328C6C71DA4304500D255FD /* MaxFrameExtentForSlowPathCall.h in Headers */ = {isa = PBXBuildFile; fileRef = 65860177185A8F5E00030EEE /* MaxFrameExtentForSlowPathCall.h */; settings = {ATTRIBUTES = (Private, ); }; }; > E328C6C81DA4306100D255FD /* RegisterAtOffsetList.h in Headers */ = {isa = PBXBuildFile; fileRef = 6540C79D1B82D99D000F6B79 /* RegisterAtOffsetList.h */; settings = {ATTRIBUTES = (Private, ); }; }; >@@ -1741,6 +1742,7 @@ > E328DAE91D38D005001A2529 /* BytecodeGraph.h in Headers */ = {isa = PBXBuildFile; fileRef = E3D264281D38C042000BE174 /* BytecodeGraph.h */; settings = {ATTRIBUTES = (Private, ); }; }; > E328DAEB1D38D005001A2529 /* BytecodeRewriter.h in Headers */ = {isa = PBXBuildFile; fileRef = E3D2642A1D38C042000BE174 /* BytecodeRewriter.h */; settings = {ATTRIBUTES = (Private, ); }; }; > E32AB2441DCD75F400D7533A /* MacroAssemblerHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = E380A76B1DCD7195000F89E6 /* MacroAssemblerHelpers.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ E334CBB521FD96A9000EB178 /* RegExpGlobalData.h in Headers */ = {isa = PBXBuildFile; fileRef = E334CBB321FD96A9000EB178 /* RegExpGlobalData.h */; settings = {ATTRIBUTES = (Private, ); }; }; > E33637A61B63220200EE0840 /* ReflectObject.h in Headers */ = {isa = PBXBuildFile; fileRef = E33637A41B63220200EE0840 /* ReflectObject.h */; settings = {ATTRIBUTES = (Private, ); }; }; > E33B3E261B7ABD750048DB2E /* InspectorInstrumentationObject.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = E33B3E251B7ABD750048DB2E /* InspectorInstrumentationObject.lut.h */; }; > E33E8D1D1B9013C300346B52 /* JSNativeStdFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = E33E8D1B1B9013C300346B52 /* JSNativeStdFunction.h */; settings = {ATTRIBUTES = (Private, ); }; }; >@@ -1767,6 +1769,7 @@ > E3A0531C21342B680022EC14 /* WasmSectionParser.h in Headers */ = {isa = PBXBuildFile; fileRef = E3A0531821342B670022EC14 /* WasmSectionParser.h */; }; > E3A32BC71FC83147007D7E76 /* WeakMapImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = E3A32BC61FC8312E007D7E76 /* WeakMapImpl.h */; }; > E3A421431D6F58930007C617 /* PreciseJumpTargetsInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E3A421421D6F588F0007C617 /* PreciseJumpTargetsInlines.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ E3AC277721FDB4940024452C /* RegExpCachedResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 86F75EFC151C062F007C9BA3 /* RegExpCachedResult.h */; settings = {ATTRIBUTES = (Private, ); }; }; > E3BFA5D021E853A1009C0EBA /* DFGDesiredGlobalProperty.h in Headers */ = {isa = PBXBuildFile; fileRef = E3BFA5CD21E853A1009C0EBA /* DFGDesiredGlobalProperty.h */; }; > E3BFD0BC1DAF808E0065DEA2 /* AccessCaseSnippetParams.h in Headers */ = {isa = PBXBuildFile; fileRef = E3BFD0BA1DAF807C0065DEA2 /* AccessCaseSnippetParams.h */; }; > E3C295DD1ED2CBDA00D3016F /* ObjectPropertyChangeAdaptiveWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = E3C295DC1ED2CBAA00D3016F /* ObjectPropertyChangeAdaptiveWatchpoint.h */; }; >@@ -4650,6 +4653,7 @@ > E322E5A11DA64435006E7709 /* DFGSnippetParams.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGSnippetParams.h; path = dfg/DFGSnippetParams.h; sourceTree = "<group>"; }; > E322E5A41DA644A4006E7709 /* FTLSnippetParams.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLSnippetParams.cpp; path = ftl/FTLSnippetParams.cpp; sourceTree = "<group>"; }; > E322E5A51DA644A4006E7709 /* FTLSnippetParams.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLSnippetParams.h; path = ftl/FTLSnippetParams.h; sourceTree = "<group>"; }; >+ E325956321FDA2C8008EDC9C /* RegExpGlobalDataInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpGlobalDataInlines.h; sourceTree = "<group>"; }; > E326C4961ECBEF5700A9A905 /* ClassInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ClassInfo.cpp; sourceTree = "<group>"; }; > E3282BB91FE930A300EDAF71 /* YarrErrorCode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = YarrErrorCode.cpp; path = yarr/YarrErrorCode.cpp; sourceTree = "<group>"; }; > E3282BBA1FE930A400EDAF71 /* YarrErrorCode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = YarrErrorCode.h; path = yarr/YarrErrorCode.h; sourceTree = "<group>"; }; >@@ -4657,6 +4661,8 @@ > E3305FB020B0F78700CEB82B /* InByIdVariant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InByIdVariant.cpp; sourceTree = "<group>"; }; > E3305FB120B0F78800CEB82B /* InByIdVariant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InByIdVariant.h; sourceTree = "<group>"; }; > E3305FB220B0F78800CEB82B /* InByIdStatus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InByIdStatus.cpp; sourceTree = "<group>"; }; >+ E334CBB221FD96A8000EB178 /* RegExpGlobalData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegExpGlobalData.cpp; sourceTree = "<group>"; }; >+ E334CBB321FD96A9000EB178 /* RegExpGlobalData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpGlobalData.h; sourceTree = "<group>"; }; > E33637A31B63220200EE0840 /* ReflectObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ReflectObject.cpp; sourceTree = "<group>"; }; > E33637A41B63220200EE0840 /* ReflectObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReflectObject.h; sourceTree = "<group>"; }; > E33B3E251B7ABD750048DB2E /* InspectorInstrumentationObject.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorInstrumentationObject.lut.h; sourceTree = "<group>"; }; >@@ -7077,6 +7083,9 @@ > 86F75EFC151C062F007C9BA3 /* RegExpCachedResult.h */, > BCD202BD0E1706A7002C7E82 /* RegExpConstructor.cpp */, > BCD202BE0E1706A7002C7E82 /* RegExpConstructor.h */, >+ E334CBB221FD96A8000EB178 /* RegExpGlobalData.cpp */, >+ E334CBB321FD96A9000EB178 /* RegExpGlobalData.h */, >+ E325956321FDA2C8008EDC9C /* RegExpGlobalDataInlines.h */, > 0F7C39FA1C8F629300480151 /* RegExpInlines.h */, > A1712B4011C7B235007A5315 /* RegExpKey.h */, > 86F75EFD151C062F007C9BA3 /* RegExpMatchesArray.cpp */, >@@ -9561,8 +9570,11 @@ > 0FA7A8EC18B413C80052371D /* Reg.h in Headers */, > BC18C45A0E16F5CD00B34460 /* RegExp.h in Headers */, > A1712B3F11C7B228007A5315 /* RegExpCache.h in Headers */, >+ E3AC277721FDB4940024452C /* RegExpCachedResult.h in Headers */, > BCD202C20E1706A7002C7E82 /* RegExpConstructor.h in Headers */, > BCD202D60E170708002C7E82 /* RegExpConstructor.lut.h in Headers */, >+ E334CBB521FD96A9000EB178 /* RegExpGlobalData.h in Headers */, >+ E325956421FDA2C9008EDC9C /* RegExpGlobalDataInlines.h in Headers */, > 0F7C39FB1C8F629300480151 /* RegExpInlines.h in Headers */, > A1712B4111C7B235007A5315 /* RegExpKey.h in Headers */, > BC18C45B0E16F5CD00B34460 /* RegExpObject.h in Headers */, >diff --git a/Source/JavaScriptCore/Sources.txt b/Source/JavaScriptCore/Sources.txt >index 7a74608c4333b0a68f707fcacde3cf1e86b465f3..6485d6bde549b2d485334e2dafa3ba1988a3d8a6 100644 >--- a/Source/JavaScriptCore/Sources.txt >+++ b/Source/JavaScriptCore/Sources.txt >@@ -902,6 +902,7 @@ runtime/RegExp.cpp > runtime/RegExpCache.cpp > runtime/RegExpCachedResult.cpp > runtime/RegExpConstructor.cpp >+runtime/RegExpGlobalData.cpp > runtime/RegExpMatchesArray.cpp > runtime/RegExpObject.cpp > runtime/RegExpPrototype.cpp >diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp >index d4a0a7aeee88bee483cb4af518097108535a1338..22750b7997af9c9a6b0eea3a5acfced1458c7f2e 100644 >--- a/Source/JavaScriptCore/dfg/DFGOperations.cpp >+++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp >@@ -65,7 +65,7 @@ > #include "ObjectConstructor.h" > #include "Operations.h" > #include "ParseInt.h" >-#include "RegExpConstructor.h" >+#include "RegExpGlobalDataInlines.h" > #include "RegExpMatchesArray.h" > #include "RegExpObjectInlines.h" > #include "Repatch.h" >@@ -1174,7 +1174,6 @@ EncodedJSValue JIT_OPERATION operationRegExpExecNonGlobalOrSticky(ExecState* exe > > auto scope = DECLARE_THROW_SCOPE(vm); > >- RegExpConstructor* regExpConstructor = globalObject->regExpConstructor(); > String input = string->value(exec); > RETURN_IF_EXCEPTION(scope, { }); > >@@ -1187,7 +1186,7 @@ EncodedJSValue JIT_OPERATION operationRegExpExecNonGlobalOrSticky(ExecState* exe > } > > RETURN_IF_EXCEPTION(scope, { }); >- regExpConstructor->recordMatch(vm, regExp, string, result); >+ globalObject->regExpGlobalData().recordMatch(vm, globalObject, regExp, string, result); > return JSValue::encode(array); > } > >@@ -1217,19 +1216,17 @@ EncodedJSValue JIT_OPERATION operationRegExpMatchFastGlobalString(ExecState* exe > String s = string->value(exec); > RETURN_IF_EXCEPTION(scope, { }); > >- RegExpConstructor* regExpConstructor = globalObject->regExpConstructor(); >- > if (regExp->unicode()) { > unsigned stringLength = s.length(); > RELEASE_AND_RETURN(scope, JSValue::encode(collectMatches( >- vm, exec, string, s, regExpConstructor, regExp, >+ vm, exec, string, s, globalObject, regExp, > [&] (size_t end) -> size_t { > return advanceStringUnicode(s, stringLength, end); > }))); > } > > RELEASE_AND_RETURN(scope, JSValue::encode(collectMatches( >- vm, exec, string, s, regExpConstructor, regExp, >+ vm, exec, string, s, globalObject, regExp, > [&] (size_t end) -> size_t { > return end + 1; > }))); >diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp >index 2e8663a3315b9422cb9d19d470069b8064502940..16e431c4a79b9cb5bad88135c6ad05fce4793d30 100644 >--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp >+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp >@@ -58,7 +58,7 @@ > #include "JSLexicalEnvironment.h" > #include "JSPropertyNameEnumerator.h" > #include "LinkBuffer.h" >-#include "RegExpConstructor.h" >+#include "RegExpObject.h" > #include "ScopedArguments.h" > #include "ScratchRegisterAllocator.h" > #include "SuperSampler.h" >@@ -11491,45 +11491,45 @@ void SpeculativeJIT::compileMaterializeNewObject(Node* node) > > void SpeculativeJIT::compileRecordRegExpCachedResult(Node* node) > { >- Edge constructorEdge = m_jit.graph().varArgChild(node, 0); >+ Edge globalObjectEdge = m_jit.graph().varArgChild(node, 0); > Edge regExpEdge = m_jit.graph().varArgChild(node, 1); > Edge stringEdge = m_jit.graph().varArgChild(node, 2); > Edge startEdge = m_jit.graph().varArgChild(node, 3); > Edge endEdge = m_jit.graph().varArgChild(node, 4); > >- SpeculateCellOperand constructor(this, constructorEdge); >+ SpeculateCellOperand globalObject(this, globalObjectEdge); > SpeculateCellOperand regExp(this, regExpEdge); > SpeculateCellOperand string(this, stringEdge); > SpeculateInt32Operand start(this, startEdge); > SpeculateInt32Operand end(this, endEdge); > >- GPRReg constructorGPR = constructor.gpr(); >+ GPRReg globalObjectGPR = globalObject.gpr(); > GPRReg regExpGPR = regExp.gpr(); > GPRReg stringGPR = string.gpr(); > GPRReg startGPR = start.gpr(); > GPRReg endGPR = end.gpr(); > >- ptrdiff_t offset = RegExpConstructor::offsetOfCachedResult(); >+ ptrdiff_t offset = JSGlobalObject::regExpGlobalDataOffset() + RegExpGlobalData::offsetOfCachedResult(); > > m_jit.storePtr( > regExpGPR, >- JITCompiler::Address(constructorGPR, offset + RegExpCachedResult::offsetOfLastRegExp())); >+ JITCompiler::Address(globalObjectGPR, offset + RegExpCachedResult::offsetOfLastRegExp())); > m_jit.storePtr( > stringGPR, >- JITCompiler::Address(constructorGPR, offset + RegExpCachedResult::offsetOfLastInput())); >+ JITCompiler::Address(globalObjectGPR, offset + RegExpCachedResult::offsetOfLastInput())); > m_jit.store32( > startGPR, > JITCompiler::Address( >- constructorGPR, >+ globalObjectGPR, > offset + RegExpCachedResult::offsetOfResult() + OBJECT_OFFSETOF(MatchResult, start))); > m_jit.store32( > endGPR, > JITCompiler::Address( >- constructorGPR, >+ globalObjectGPR, > offset + RegExpCachedResult::offsetOfResult() + OBJECT_OFFSETOF(MatchResult, end))); > m_jit.store8( > TrustedImm32(0), >- JITCompiler::Address(constructorGPR, offset + RegExpCachedResult::offsetOfReified())); >+ JITCompiler::Address(globalObjectGPR, offset + RegExpCachedResult::offsetOfReified())); > > noResult(node); > } >diff --git a/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp b/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp >index 18bec693e2d0f70cd6dd5e90cb01a7c086d350b9..c7fd52a8eb9755ad1b1b29957f13f4bbe16c48c1 100644 >--- a/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp >+++ b/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp >@@ -37,7 +37,7 @@ > #include "DFGVariableAccessDataDump.h" > #include "JSCInlines.h" > #include "MathCommon.h" >-#include "RegExpConstructor.h" >+#include "RegExpObject.h" > #include "StringPrototype.h" > #include <cstdlib> > #include <wtf/text/StringBuilder.h> >@@ -620,8 +620,7 @@ class StrengthReductionPhase : public Phase { > } > m_graph.registerStructure(structure); > >- RegExpConstructor* constructor = globalObject->regExpConstructor(); >- FrozenValue* constructorFrozenValue = m_graph.freeze(constructor); >+ FrozenValue* globalObjectFrozenValue = m_graph.freeze(globalObject); > > MatchResult result; > Vector<int> ovector; >@@ -736,7 +735,7 @@ class StrengthReductionPhase : public Phase { > } else > m_graph.convertToConstant(m_node, jsBoolean(!!result)); > >- // Whether it's Exec or Test, we need to tell the constructor and RegExpObject what's up. >+ // Whether it's Exec or Test, we need to tell the globalObject and RegExpObject what's up. > // Because SetRegExpObjectLastIndex may exit and it clobbers exit state, we do that > // first. > >@@ -756,7 +755,7 @@ class StrengthReductionPhase : public Phase { > unsigned firstChild = m_graph.m_varArgChildren.size(); > m_graph.m_varArgChildren.append( > m_insertionSet.insertConstantForUse( >- m_nodeIndex, origin, constructorFrozenValue, KnownCellUse)); >+ m_nodeIndex, origin, globalObjectFrozenValue, KnownCellUse)); > m_graph.m_varArgChildren.append( > m_insertionSet.insertConstantForUse( > m_nodeIndex, origin, regExpFrozenValue, KnownCellUse)); >diff --git a/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.cpp b/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.cpp >index 68d847d91bfa1f6ae5a663c1ba7f7fada35059d1..c035112580c6b8a2958965654bc1c81ed7ae97d5 100644 >--- a/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.cpp >+++ b/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.cpp >@@ -39,7 +39,6 @@ > #include "JSPropertyNameEnumerator.h" > #include "JSScope.h" > #include "JSCInlines.h" >-#include "RegExpConstructor.h" > #include "RegExpObject.h" > #include "ScopedArguments.h" > #include "ScopedArgumentsTable.h" >diff --git a/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h b/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h >index 9f3aa2fe7dc3ecfeb0c870b81a87cbc11f288051..e50541ba526b06682d0053f546bea2de2abd532a 100644 >--- a/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h >+++ b/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h >@@ -33,6 +33,7 @@ > #include "HasOwnPropertyCache.h" > #include "IndexingType.h" > #include "JSFixedArray.h" >+#include "JSGlobalObject.h" > #include "JSMap.h" > #include "JSSet.h" > #include "JSWeakMap.h" >@@ -75,6 +76,11 @@ namespace JSC { namespace FTL { > macro(JSFunction_executable, JSFunction::offsetOfExecutable()) \ > macro(JSFunction_scope, JSFunction::offsetOfScopeChain()) \ > macro(JSFunction_rareData, JSFunction::offsetOfRareData()) \ >+ macro(JSGlobalObject_regExpGlobalData_cachedResult_lastRegExp, JSGlobalObject::regExpGlobalDataOffset() + RegExpGlobalData::offsetOfCachedResult() + RegExpCachedResult::offsetOfLastRegExp()) \ >+ macro(JSGlobalObject_regExpGlobalData_cachedResult_lastInput, JSGlobalObject::regExpGlobalDataOffset() + RegExpGlobalData::offsetOfCachedResult() + RegExpCachedResult::offsetOfLastInput()) \ >+ macro(JSGlobalObject_regExpGlobalData_cachedResult_result_start, JSGlobalObject::regExpGlobalDataOffset() + RegExpGlobalData::offsetOfCachedResult() + RegExpCachedResult::offsetOfResult() + OBJECT_OFFSETOF(MatchResult, start)) \ >+ macro(JSGlobalObject_regExpGlobalData_cachedResult_result_end, JSGlobalObject::regExpGlobalDataOffset() + RegExpGlobalData::offsetOfCachedResult() + RegExpCachedResult::offsetOfResult() + OBJECT_OFFSETOF(MatchResult, end)) \ >+ macro(JSGlobalObject_regExpGlobalData_cachedResult_reified, JSGlobalObject::regExpGlobalDataOffset() + RegExpGlobalData::offsetOfCachedResult() + RegExpCachedResult::offsetOfReified()) \ > macro(JSObject_butterfly, JSObject::butterflyOffset()) \ > macro(JSPropertyNameEnumerator_cachedInlineCapacity, JSPropertyNameEnumerator::cachedInlineCapacityOffset()) \ > macro(JSPropertyNameEnumerator_cachedPropertyNamesVector, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()) \ >@@ -87,11 +93,6 @@ namespace JSC { namespace FTL { > macro(JSString_value, JSString::offsetOfValue()) \ > macro(JSSymbolTableObject_symbolTable, JSSymbolTableObject::offsetOfSymbolTable()) \ > macro(JSWrapperObject_internalValue, JSWrapperObject::internalValueOffset()) \ >- macro(RegExpConstructor_cachedResult_lastRegExp, RegExpConstructor::offsetOfCachedResult() + RegExpCachedResult::offsetOfLastRegExp()) \ >- macro(RegExpConstructor_cachedResult_lastInput, RegExpConstructor::offsetOfCachedResult() + RegExpCachedResult::offsetOfLastInput()) \ >- macro(RegExpConstructor_cachedResult_result_start, RegExpConstructor::offsetOfCachedResult() + RegExpCachedResult::offsetOfResult() + OBJECT_OFFSETOF(MatchResult, start)) \ >- macro(RegExpConstructor_cachedResult_result_end, RegExpConstructor::offsetOfCachedResult() + RegExpCachedResult::offsetOfResult() + OBJECT_OFFSETOF(MatchResult, end)) \ >- macro(RegExpConstructor_cachedResult_reified, RegExpConstructor::offsetOfCachedResult() + RegExpCachedResult::offsetOfReified()) \ > macro(RegExpObject_regExp, RegExpObject::offsetOfRegExp()) \ > macro(RegExpObject_lastIndex, RegExpObject::offsetOfLastIndex()) \ > macro(RegExpObject_lastIndexIsWritable, RegExpObject::offsetOfLastIndexIsWritable()) \ >diff --git a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp b/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp >index ae1fa909136f74647c4cea289da0a8fa6d3faa04..d7618ddc05c83121d262f8c2ebfc109c94aeb5e6 100644 >--- a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp >+++ b/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp >@@ -11303,25 +11303,25 @@ class LowerDFGToB3 { > > void compileRecordRegExpCachedResult() > { >- Edge constructorEdge = m_graph.varArgChild(m_node, 0); >+ Edge globalObjectEdge = m_graph.varArgChild(m_node, 0); > Edge regExpEdge = m_graph.varArgChild(m_node, 1); > Edge stringEdge = m_graph.varArgChild(m_node, 2); > Edge startEdge = m_graph.varArgChild(m_node, 3); > Edge endEdge = m_graph.varArgChild(m_node, 4); > >- LValue constructor = lowCell(constructorEdge); >+ LValue globalObject = lowCell(globalObjectEdge); > LValue regExp = lowCell(regExpEdge); > LValue string = lowCell(stringEdge); > LValue start = lowInt32(startEdge); > LValue end = lowInt32(endEdge); > >- m_out.storePtr(regExp, constructor, m_heaps.RegExpConstructor_cachedResult_lastRegExp); >- m_out.storePtr(string, constructor, m_heaps.RegExpConstructor_cachedResult_lastInput); >- m_out.store32(start, constructor, m_heaps.RegExpConstructor_cachedResult_result_start); >- m_out.store32(end, constructor, m_heaps.RegExpConstructor_cachedResult_result_end); >+ m_out.storePtr(regExp, globalObject, m_heaps.JSGlobalObject_regExpGlobalData_cachedResult_lastRegExp); >+ m_out.storePtr(string, globalObject, m_heaps.JSGlobalObject_regExpGlobalData_cachedResult_lastInput); >+ m_out.store32(start, globalObject, m_heaps.JSGlobalObject_regExpGlobalData_cachedResult_result_start); >+ m_out.store32(end, globalObject, m_heaps.JSGlobalObject_regExpGlobalData_cachedResult_result_end); > m_out.store32As8( > m_out.constInt32(0), >- m_out.address(constructor, m_heaps.RegExpConstructor_cachedResult_reified)); >+ m_out.address(globalObject, m_heaps.JSGlobalObject_regExpGlobalData_cachedResult_reified)); > } > > struct ArgumentsLength { >diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp >index c5b0b301da56308cfc99e1f35acabf7ae0692319..676ec0ee4a3199dd9b6711eb9abc5dbfeab22808 100644 >--- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp >+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp >@@ -149,6 +149,7 @@ > #include "ProxyObject.h" > #include "ProxyRevoke.h" > #include "ReflectObject.h" >+#include "RegExpCache.h" > #include "RegExpConstructor.h" > #include "RegExpMatchesArray.h" > #include "RegExpObject.h" >@@ -685,7 +686,8 @@ void JSGlobalObject::init(VM& vm) > ArrayConstructor* arrayConstructor = ArrayConstructor::create(vm, this, ArrayConstructor::createStructure(vm, this, m_functionPrototype.get()), m_arrayPrototype.get(), m_speciesGetterSetter.get()); > m_arrayConstructor.set(vm, this, arrayConstructor); > >- m_regExpConstructor.set(vm, this, RegExpConstructor::create(vm, RegExpConstructor::createStructure(vm, this, m_functionPrototype.get()), m_regExpPrototype.get(), m_speciesGetterSetter.get())); >+ RegExpConstructor* regExpConstructor = RegExpConstructor::create(vm, RegExpConstructor::createStructure(vm, this, m_functionPrototype.get()), m_regExpPrototype.get(), m_speciesGetterSetter.get()); >+ m_regExpGlobalData.cachedResult().record(vm, this, vm.regExpCache()->emptyRegExp(), jsEmptyString(&vm), MatchResult(0, 0)); > > JSArrayBufferConstructor* arrayBufferConstructor = JSArrayBufferConstructor::create(vm, JSArrayBufferConstructor::createStructure(vm, this, m_functionPrototype.get()), m_arrayBufferPrototype.get(), m_speciesGetterSetter.get()); > m_arrayBufferPrototype->putDirectWithoutTransition(vm, vm.propertyNames->constructor, arrayBufferConstructor, static_cast<unsigned>(PropertyAttribute::DontEnum)); >@@ -765,12 +767,12 @@ m_ ## lowerName ## Prototype->putDirectWithoutTransition(vm, vm.propertyNames->c > m_objectPrototype->putDirectWithoutTransition(vm, vm.propertyNames->constructor, objectConstructor, static_cast<unsigned>(PropertyAttribute::DontEnum)); > m_functionPrototype->putDirectWithoutTransition(vm, vm.propertyNames->constructor, functionConstructor, static_cast<unsigned>(PropertyAttribute::DontEnum)); > m_arrayPrototype->putDirectWithoutTransition(vm, vm.propertyNames->constructor, arrayConstructor, static_cast<unsigned>(PropertyAttribute::DontEnum)); >- m_regExpPrototype->putDirectWithoutTransition(vm, vm.propertyNames->constructor, m_regExpConstructor.get(), static_cast<unsigned>(PropertyAttribute::DontEnum)); >+ m_regExpPrototype->putDirectWithoutTransition(vm, vm.propertyNames->constructor, regExpConstructor, static_cast<unsigned>(PropertyAttribute::DontEnum)); > > putDirectWithoutTransition(vm, vm.propertyNames->Object, objectConstructor, static_cast<unsigned>(PropertyAttribute::DontEnum)); > putDirectWithoutTransition(vm, vm.propertyNames->Function, functionConstructor, static_cast<unsigned>(PropertyAttribute::DontEnum)); > putDirectWithoutTransition(vm, vm.propertyNames->Array, arrayConstructor, static_cast<unsigned>(PropertyAttribute::DontEnum)); >- putDirectWithoutTransition(vm, vm.propertyNames->RegExp, m_regExpConstructor.get(), static_cast<unsigned>(PropertyAttribute::DontEnum)); >+ putDirectWithoutTransition(vm, vm.propertyNames->RegExp, regExpConstructor, static_cast<unsigned>(PropertyAttribute::DontEnum)); > > putDirectWithoutTransition(vm, vm.propertyNames->builtinNames().ObjectPrivateName(), objectConstructor, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); > putDirectWithoutTransition(vm, vm.propertyNames->builtinNames().ArrayPrivateName(), arrayConstructor, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly); >@@ -905,7 +907,7 @@ putDirectWithoutTransition(vm, vm.propertyNames-> jsName, lowerName ## Construct > GlobalPropertyInfo(vm.propertyNames->builtinNames().BuiltinLogPrivateName(), builtinLog, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), > GlobalPropertyInfo(vm.propertyNames->builtinNames().BuiltinDescribePrivateName(), builtinDescribe, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), > GlobalPropertyInfo(vm.propertyNames->builtinNames().NumberPrivateName(), numberConstructor, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), >- GlobalPropertyInfo(vm.propertyNames->builtinNames().RegExpPrivateName(), m_regExpConstructor.get(), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), >+ GlobalPropertyInfo(vm.propertyNames->builtinNames().RegExpPrivateName(), regExpConstructor, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), > GlobalPropertyInfo(vm.propertyNames->builtinNames().StringPrivateName(), stringConstructor, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), > GlobalPropertyInfo(vm.propertyNames->builtinNames().absPrivateName(), privateFuncAbs, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), > GlobalPropertyInfo(vm.propertyNames->builtinNames().floorPrivateName(), privateFuncFloor, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), >@@ -1560,7 +1562,6 @@ void JSGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor) > visitor.append(thisObject->m_globalScopeExtension); > visitor.append(thisObject->m_globalCallee); > visitor.append(thisObject->m_stackOverflowFrameCallee); >- visitor.append(thisObject->m_regExpConstructor); > visitor.append(thisObject->m_errorConstructor); > thisObject->m_evalErrorStructure.visit(visitor); > thisObject->m_rangeErrorStructure.visit(visitor); >@@ -1705,6 +1706,7 @@ void JSGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor) > visitor.append(thisObject->m_speciesGetterSetter); > thisObject->m_typedArrayProto.visit(visitor); > thisObject->m_typedArraySuperConstructor.visit(visitor); >+ thisObject->m_regExpGlobalData.visitAggregate(visitor); > } > > ExecState* JSGlobalObject::globalExec() >diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h >index c05e02b8e6dff5831f884a5d84956ebd82b9d694..60c24262d181091f5de24957804c7f138ef2c9a7 100644 >--- a/Source/JavaScriptCore/runtime/JSGlobalObject.h >+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h >@@ -39,6 +39,7 @@ > #include "LazyProperty.h" > #include "LazyClassStructure.h" > #include "NumberPrototype.h" >+#include "RegExpGlobalData.h" > #include "RuntimeFlags.h" > #include "SpecialPointer.h" > #include "StringPrototype.h" >@@ -259,7 +260,6 @@ class JSGlobalObject : public JSSegmentedVariableObject { > WriteBarrier<JSScope> m_globalScopeExtension; > WriteBarrier<JSCallee> m_globalCallee; > WriteBarrier<JSCallee> m_stackOverflowFrameCallee; >- WriteBarrier<RegExpConstructor> m_regExpConstructor; > > WriteBarrier<ErrorConstructor> m_errorConstructor; > LazyClassStructure m_evalErrorStructure; >@@ -446,6 +446,7 @@ class JSGlobalObject : public JSSegmentedVariableObject { > std::unique_ptr<JSGlobalObjectRareData> m_rareData; > > WeakRandom m_weakRandom; >+ RegExpGlobalData m_regExpGlobalData; > > JSCallee* stackOverflowFrameCallee() const { return m_stackOverflowFrameCallee.get(); } > >@@ -576,8 +577,6 @@ class JSGlobalObject : public JSSegmentedVariableObject { > > GetterSetter* speciesGetterSetter() const { return m_speciesGetterSetter.get(); } > >- RegExpConstructor* regExpConstructor() const { return m_regExpConstructor.get(); } >- > ArrayConstructor* arrayConstructor() const { return m_arrayConstructor.get(); } > ObjectConstructor* objectConstructor() const { return m_objectConstructor.get(); } > JSPromiseConstructor* promiseConstructor() const { return m_promiseConstructor.get(); } >@@ -766,6 +765,9 @@ class JSGlobalObject : public JSSegmentedVariableObject { > JS_EXPORT_PRIVATE void setRemoteDebuggingEnabled(bool); > JS_EXPORT_PRIVATE bool remoteDebuggingEnabled() const; > >+ RegExpGlobalData& regExpGlobalData() { return m_regExpGlobalData; } >+ static ptrdiff_t regExpGlobalDataOffset() { return OBJECT_OFFSETOF(JSGlobalObject, m_regExpGlobalData); } >+ > #if ENABLE(REMOTE_INSPECTOR) > Inspector::JSGlobalObjectInspectorController& inspectorController() const { return *m_inspectorController.get(); } > JSGlobalObjectDebuggable& inspectorDebuggable() { return *m_inspectorDebuggable.get(); } >diff --git a/Source/JavaScriptCore/runtime/RegExpCache.cpp b/Source/JavaScriptCore/runtime/RegExpCache.cpp >index 8f4660a78b423b153196a1d11fd7c0dfa894161e..2cb29c4023edb8940ca3666cd02aae9636e2f326 100644 >--- a/Source/JavaScriptCore/runtime/RegExpCache.cpp >+++ b/Source/JavaScriptCore/runtime/RegExpCache.cpp >@@ -56,6 +56,11 @@ RegExpCache::RegExpCache(VM* vm) > { > } > >+void RegExpCache::initialize(VM& vm) >+{ >+ m_emptyRegExp.set(vm, RegExp::create(vm, "", NoFlags)); >+} >+ > void RegExpCache::finalize(Handle<Unknown> handle, void*) > { > RegExp* regExp = static_cast<RegExp*>(handle.get().asCell()); >diff --git a/Source/JavaScriptCore/runtime/RegExpCache.h b/Source/JavaScriptCore/runtime/RegExpCache.h >index 4ae95f0c2f35f56838664fc5aecaa1de91b22d6b..2f5bdc3c55186fb3f17e6c7822e4bc305983eae2 100644 >--- a/Source/JavaScriptCore/runtime/RegExpCache.h >+++ b/Source/JavaScriptCore/runtime/RegExpCache.h >@@ -46,6 +46,10 @@ class RegExpCache : private WeakHandleOwner { > RegExpCache(VM* vm); > void deleteAllCode(); > >+ void initialize(VM&); >+ >+ RegExp* emptyRegExp() const { return m_emptyRegExp.get(); } >+ > private: > > static const unsigned maxStrongCacheablePatternLength = 256; >@@ -59,6 +63,7 @@ class RegExpCache : private WeakHandleOwner { > RegExpCacheMap m_weakCache; // Holds all regular expressions currently live. > int m_nextEntryInStrongCache; > std::array<Strong<RegExp>, maxStrongCacheableEntries> m_strongCache; // Holds a select few regular expressions that have compiled and executed >+ Strong<RegExp> m_emptyRegExp; > VM* m_vm; > }; > >diff --git a/Source/JavaScriptCore/runtime/RegExpCachedResult.cpp b/Source/JavaScriptCore/runtime/RegExpCachedResult.cpp >index 5b45ee309280c6904efe8f66d6a15b6d8a4ae950..c6a6b032dfa228ba583007387d676d79e8093bb1 100644 >--- a/Source/JavaScriptCore/runtime/RegExpCachedResult.cpp >+++ b/Source/JavaScriptCore/runtime/RegExpCachedResult.cpp >@@ -31,7 +31,7 @@ > > namespace JSC { > >-void RegExpCachedResult::visitChildren(SlotVisitor& visitor) >+void RegExpCachedResult::visitAggregate(SlotVisitor& visitor) > { > visitor.append(m_lastInput); > visitor.append(m_lastRegExp); >diff --git a/Source/JavaScriptCore/runtime/RegExpCachedResult.h b/Source/JavaScriptCore/runtime/RegExpCachedResult.h >index 40cc064f853c1b4c1ad3de40653fd088e65518ee..88a6c663e713dac9d933d8d088a66efc011cc2d2 100644 >--- a/Source/JavaScriptCore/runtime/RegExpCachedResult.h >+++ b/Source/JavaScriptCore/runtime/RegExpCachedResult.h >@@ -25,7 +25,7 @@ > > #pragma once > >-#include "RegExpObject.h" >+#include "RegExp.h" > > namespace JSC { > >@@ -43,14 +43,6 @@ class JSString; > // m_reifiedResult and m_reifiedInput hold the cached results. > class RegExpCachedResult { > public: >- RegExpCachedResult(VM& vm, JSObject* owner, RegExp* emptyRegExp) >- : m_result(0, 0) >- , m_reified(false) >- { >- m_lastInput.set(vm, owner, jsEmptyString(&vm)); >- m_lastRegExp.set(vm, owner, emptyRegExp); >- } >- > ALWAYS_INLINE void record(VM& vm, JSObject* owner, RegExp* regExp, JSString* input, MatchResult result) > { > vm.heap.writeBarrier(owner); >@@ -71,7 +63,7 @@ class RegExpCachedResult { > return m_reified ? m_reifiedInput.get() : m_lastInput.get(); > } > >- void visitChildren(SlotVisitor&); >+ void visitAggregate(SlotVisitor&); > > static ptrdiff_t offsetOfLastRegExp() { return OBJECT_OFFSETOF(RegExpCachedResult, m_lastRegExp); } > static ptrdiff_t offsetOfLastInput() { return OBJECT_OFFSETOF(RegExpCachedResult, m_lastInput); } >@@ -79,8 +71,8 @@ class RegExpCachedResult { > static ptrdiff_t offsetOfReified() { return OBJECT_OFFSETOF(RegExpCachedResult, m_reified); } > > private: >- MatchResult m_result; >- bool m_reified; >+ MatchResult m_result { 0, 0 }; >+ bool m_reified { false }; > WriteBarrier<JSString> m_lastInput; > WriteBarrier<RegExp> m_lastRegExp; > WriteBarrier<JSArray> m_reifiedResult; >diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp >index 3467924654e5e3cf26e377305385f5e9d3fb2cf3..16a45ad28fbc2d95c44ef78b3287e2bb808d53bb 100644 >--- a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp >+++ b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp >@@ -25,6 +25,7 @@ > #include "Error.h" > #include "GetterSetter.h" > #include "JSCInlines.h" >+#include "RegExpGlobalDataInlines.h" > #include "RegExpPrototype.h" > #include "StructureInlines.h" > >@@ -80,10 +81,8 @@ const ClassInfo RegExpConstructor::s_info = { "Function", &InternalFunction::s_i > static EncodedJSValue JSC_HOST_CALL callRegExpConstructor(ExecState*); > static EncodedJSValue JSC_HOST_CALL constructWithRegExpConstructor(ExecState*); > >-RegExpConstructor::RegExpConstructor(VM& vm, Structure* structure, RegExpPrototype* regExpPrototype) >+RegExpConstructor::RegExpConstructor(VM& vm, Structure* structure) > : InternalFunction(vm, structure, callRegExpConstructor, constructWithRegExpConstructor) >- , m_cachedResult(vm, this, regExpPrototype->emptyRegExp()) >- , m_multiline(false) > { > } > >@@ -98,95 +97,62 @@ void RegExpConstructor::finishCreation(VM& vm, RegExpPrototype* regExpPrototype, > putDirectNonIndexAccessor(vm, vm.propertyNames->speciesSymbol, speciesSymbol, PropertyAttribute::Accessor | PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum); > } > >-void RegExpConstructor::destroy(JSCell* cell) >-{ >- static_cast<RegExpConstructor*>(cell)->RegExpConstructor::~RegExpConstructor(); >-} >- >-void RegExpConstructor::visitChildren(JSCell* cell, SlotVisitor& visitor) >-{ >- RegExpConstructor* thisObject = jsCast<RegExpConstructor*>(cell); >- ASSERT_GC_OBJECT_INHERITS(thisObject, info()); >- Base::visitChildren(thisObject, visitor); >- thisObject->m_cachedResult.visitChildren(visitor); >-} >- >-JSValue RegExpConstructor::getBackref(ExecState* exec, unsigned i) >-{ >- JSArray* array = m_cachedResult.lastResult(exec, this); >- >- if (i < array->length()) { >- JSValue result = JSValue(array).get(exec, i); >- ASSERT(result.isString() || result.isUndefined()); >- if (!result.isUndefined()) >- return result; >- } >- return jsEmptyString(exec); >-} >- >-JSValue RegExpConstructor::getLastParen(ExecState* exec) >-{ >- JSArray* array = m_cachedResult.lastResult(exec, this); >- unsigned length = array->length(); >- if (length > 1) { >- JSValue result = JSValue(array).get(exec, length - 1); >- ASSERT(result.isString() || result.isUndefined()); >- if (!result.isUndefined()) >- return result; >- } >- return jsEmptyString(exec); >-} >- >-JSValue RegExpConstructor::getLeftContext(ExecState* exec) >-{ >- return m_cachedResult.leftContext(exec, this); >-} >- >-JSValue RegExpConstructor::getRightContext(ExecState* exec) >-{ >- return m_cachedResult.rightContext(exec, this); >-} >- > template<int N> > EncodedJSValue regExpConstructorDollar(ExecState* exec, EncodedJSValue thisValue, PropertyName) > { >- return JSValue::encode(jsCast<RegExpConstructor*>(JSValue::decode(thisValue))->getBackref(exec, N)); >+ VM& vm = exec->vm(); >+ JSGlobalObject* globalObject = jsCast<RegExpConstructor*>(JSValue::decode(thisValue))->globalObject(vm); >+ return JSValue::encode(globalObject->regExpGlobalData().getBackref(exec, globalObject, N)); > } > >-EncodedJSValue regExpConstructorInput(ExecState*, EncodedJSValue thisValue, PropertyName) >+EncodedJSValue regExpConstructorInput(ExecState* exec, EncodedJSValue thisValue, PropertyName) > { >- return JSValue::encode(jsCast<RegExpConstructor*>(JSValue::decode(thisValue))->input()); >+ VM& vm = exec->vm(); >+ JSGlobalObject* globalObject = jsCast<RegExpConstructor*>(JSValue::decode(thisValue))->globalObject(vm); >+ return JSValue::encode(globalObject->regExpGlobalData().input()); > } > >-EncodedJSValue regExpConstructorMultiline(ExecState*, EncodedJSValue thisValue, PropertyName) >+EncodedJSValue regExpConstructorMultiline(ExecState* exec, EncodedJSValue thisValue, PropertyName) > { >- return JSValue::encode(jsBoolean(jsCast<RegExpConstructor*>(JSValue::decode(thisValue))->multiline())); >+ VM& vm = exec->vm(); >+ JSGlobalObject* globalObject = jsCast<RegExpConstructor*>(JSValue::decode(thisValue))->globalObject(vm); >+ return JSValue::encode(jsBoolean(globalObject->regExpGlobalData().multiline())); > } > > EncodedJSValue regExpConstructorLastMatch(ExecState* exec, EncodedJSValue thisValue, PropertyName) > { >- return JSValue::encode(jsCast<RegExpConstructor*>(JSValue::decode(thisValue))->getBackref(exec, 0)); >+ VM& vm = exec->vm(); >+ JSGlobalObject* globalObject = jsCast<RegExpConstructor*>(JSValue::decode(thisValue))->globalObject(vm); >+ return JSValue::encode(globalObject->regExpGlobalData().getBackref(exec, globalObject, 0)); > } > > EncodedJSValue regExpConstructorLastParen(ExecState* exec, EncodedJSValue thisValue, PropertyName) > { >- return JSValue::encode(jsCast<RegExpConstructor*>(JSValue::decode(thisValue))->getLastParen(exec)); >+ VM& vm = exec->vm(); >+ JSGlobalObject* globalObject = jsCast<RegExpConstructor*>(JSValue::decode(thisValue))->globalObject(vm); >+ return JSValue::encode(globalObject->regExpGlobalData().getLastParen(exec, globalObject)); > } > > EncodedJSValue regExpConstructorLeftContext(ExecState* exec, EncodedJSValue thisValue, PropertyName) > { >- return JSValue::encode(jsCast<RegExpConstructor*>(JSValue::decode(thisValue))->getLeftContext(exec)); >+ VM& vm = exec->vm(); >+ JSGlobalObject* globalObject = jsCast<RegExpConstructor*>(JSValue::decode(thisValue))->globalObject(vm); >+ return JSValue::encode(globalObject->regExpGlobalData().getLeftContext(exec, globalObject)); > } > > EncodedJSValue regExpConstructorRightContext(ExecState* exec, EncodedJSValue thisValue, PropertyName) > { >- return JSValue::encode(jsCast<RegExpConstructor*>(JSValue::decode(thisValue))->getRightContext(exec)); >+ VM& vm = exec->vm(); >+ JSGlobalObject* globalObject = jsCast<RegExpConstructor*>(JSValue::decode(thisValue))->globalObject(vm); >+ return JSValue::encode(globalObject->regExpGlobalData().getRightContext(exec, globalObject)); > } > > bool setRegExpConstructorInput(ExecState* exec, EncodedJSValue thisValue, EncodedJSValue value) > { >- if (auto constructor = jsDynamicCast<RegExpConstructor*>(exec->vm(), JSValue::decode(thisValue))) { >- constructor->setInput(exec, JSValue::decode(value).toString(exec)); >+ VM& vm = exec->vm(); >+ if (auto constructor = jsDynamicCast<RegExpConstructor*>(vm, JSValue::decode(thisValue))) { >+ JSGlobalObject* globalObject = constructor->globalObject(vm); >+ globalObject->regExpGlobalData().setInput(exec, globalObject, JSValue::decode(value).toString(exec)); > return true; > } > return false; >@@ -194,8 +160,10 @@ bool setRegExpConstructorInput(ExecState* exec, EncodedJSValue thisValue, Encode > > bool setRegExpConstructorMultiline(ExecState* exec, EncodedJSValue thisValue, EncodedJSValue value) > { >- if (auto constructor = jsDynamicCast<RegExpConstructor*>(exec->vm(), JSValue::decode(thisValue))) { >- constructor->setMultiline(JSValue::decode(value).toBoolean(exec)); >+ VM& vm = exec->vm(); >+ if (auto constructor = jsDynamicCast<RegExpConstructor*>(vm, JSValue::decode(thisValue))) { >+ JSGlobalObject* globalObject = constructor->globalObject(vm); >+ globalObject->regExpGlobalData().setMultiline(JSValue::decode(value).toBoolean(exec)); > return true; > } > return false; >diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.h b/Source/JavaScriptCore/runtime/RegExpConstructor.h >index a7a0de800e9e0a7ede6eb3a77c18229f1035f582..3f901c53d441b1d17b3c18e67ace8a454398c39b 100644 >--- a/Source/JavaScriptCore/runtime/RegExpConstructor.h >+++ b/Source/JavaScriptCore/runtime/RegExpConstructor.h >@@ -35,15 +35,9 @@ class RegExpConstructor final : public InternalFunction { > typedef InternalFunction Base; > static const unsigned StructureFlags = Base::StructureFlags | HasStaticPropertyTable; > >- template<typename CellType> >- static IsoSubspace* subspaceFor(VM& vm) >- { >- return &vm.regExpConstructorSpace; >- } >- > static RegExpConstructor* create(VM& vm, Structure* structure, RegExpPrototype* regExpPrototype, GetterSetter* species) > { >- RegExpConstructor* constructor = new (NotNull, allocateCell<RegExpConstructor>(vm.heap)) RegExpConstructor(vm, structure, regExpPrototype); >+ RegExpConstructor* constructor = new (NotNull, allocateCell<RegExpConstructor>(vm.heap)) RegExpConstructor(vm, structure); > constructor->finishCreation(vm, regExpPrototype, species); > return constructor; > } >@@ -55,77 +49,15 @@ class RegExpConstructor final : public InternalFunction { > > DECLARE_INFO; > >- MatchResult performMatch(VM&, RegExp*, JSString*, const String&, int startOffset, int** ovector); >- MatchResult performMatch(VM&, RegExp*, JSString*, const String&, int startOffset); >- void recordMatch(VM&, RegExp*, JSString*, const MatchResult&); >- >- void setMultiline(bool multiline) { m_multiline = multiline; } >- bool multiline() const { return m_multiline; } >- >- JSValue getBackref(ExecState*, unsigned); >- JSValue getLastParen(ExecState*); >- JSValue getLeftContext(ExecState*); >- JSValue getRightContext(ExecState*); >- >- void setInput(ExecState* exec, JSString* string) { m_cachedResult.setInput(exec, this, string); } >- JSString* input() { return m_cachedResult.input(); } >- >- static void visitChildren(JSCell*, SlotVisitor&); >- >- static ptrdiff_t offsetOfCachedResult() { return OBJECT_OFFSETOF(RegExpConstructor, m_cachedResult); } >- > protected: > void finishCreation(VM&, RegExpPrototype*, GetterSetter* species); > > private: >- RegExpConstructor(VM&, Structure*, RegExpPrototype*); >- static void destroy(JSCell*); >- >- RegExpCachedResult m_cachedResult; >- bool m_multiline; >- Vector<int> m_ovector; >+ RegExpConstructor(VM&, Structure*); > }; > > JSObject* constructRegExp(ExecState*, JSGlobalObject*, const ArgList&, JSObject* callee = nullptr, JSValue newTarget = jsUndefined()); > >-/* >- To facilitate result caching, exec(), test(), match(), search(), and replace() dipatch regular >- expression matching through the performMatch function. We use cached results to calculate, >- e.g., RegExp.lastMatch and RegExp.leftParen. >-*/ >-ALWAYS_INLINE MatchResult RegExpConstructor::performMatch(VM& vm, RegExp* regExp, JSString* string, const String& input, int startOffset, int** ovector) >-{ >- int position = regExp->match(vm, input, startOffset, m_ovector); >- >- if (ovector) >- *ovector = m_ovector.data(); >- >- if (position == -1) >- return MatchResult::failed(); >- >- ASSERT(!m_ovector.isEmpty()); >- ASSERT(m_ovector[0] == position); >- ASSERT(m_ovector[1] >= position); >- size_t end = m_ovector[1]; >- >- m_cachedResult.record(vm, this, regExp, string, MatchResult(position, end)); >- >- return MatchResult(position, end); >-} >-ALWAYS_INLINE MatchResult RegExpConstructor::performMatch(VM& vm, RegExp* regExp, JSString* string, const String& input, int startOffset) >-{ >- MatchResult result = regExp->match(vm, input, startOffset); >- if (result) >- m_cachedResult.record(vm, this, regExp, string, result); >- return result; >-} >- >-ALWAYS_INLINE void RegExpConstructor::recordMatch(VM& vm, RegExp* regExp, JSString* string, const MatchResult& result) >-{ >- ASSERT(result); >- m_cachedResult.record(vm, this, regExp, string, result); >-} >- > ALWAYS_INLINE bool isRegExp(VM& vm, ExecState* exec, JSValue value) > { > auto scope = DECLARE_THROW_SCOPE(vm); >diff --git a/Source/JavaScriptCore/runtime/RegExpGlobalData.cpp b/Source/JavaScriptCore/runtime/RegExpGlobalData.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..c36daf2f519874ed31256feacf7cd58ffc6c88ed >--- /dev/null >+++ b/Source/JavaScriptCore/runtime/RegExpGlobalData.cpp >@@ -0,0 +1,72 @@ >+/* >+ * Copyright (C) 2019 Apple Inc. All Rights Reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include "config.h" >+#include "RegExpGlobalData.h" >+ >+namespace JSC { >+ >+void RegExpGlobalData::visitAggregate(SlotVisitor& visitor) >+{ >+ m_cachedResult.visitAggregate(visitor); >+} >+ >+JSValue RegExpGlobalData::getBackref(ExecState* exec, JSGlobalObject* owner, unsigned i) >+{ >+ JSArray* array = m_cachedResult.lastResult(exec, owner); >+ >+ if (i < array->length()) { >+ JSValue result = JSValue(array).get(exec, i); >+ ASSERT(result.isString() || result.isUndefined()); >+ if (!result.isUndefined()) >+ return result; >+ } >+ return jsEmptyString(exec); >+} >+ >+JSValue RegExpGlobalData::getLastParen(ExecState* exec, JSGlobalObject* owner) >+{ >+ JSArray* array = m_cachedResult.lastResult(exec, owner); >+ unsigned length = array->length(); >+ if (length > 1) { >+ JSValue result = JSValue(array).get(exec, length - 1); >+ ASSERT(result.isString() || result.isUndefined()); >+ if (!result.isUndefined()) >+ return result; >+ } >+ return jsEmptyString(exec); >+} >+ >+JSValue RegExpGlobalData::getLeftContext(ExecState* exec, JSGlobalObject* owner) >+{ >+ return m_cachedResult.leftContext(exec, owner); >+} >+ >+JSValue RegExpGlobalData::getRightContext(ExecState* exec, JSGlobalObject* owner) >+{ >+ return m_cachedResult.rightContext(exec, owner); >+} >+ >+} // namespace JSC >diff --git a/Source/JavaScriptCore/runtime/RegExpGlobalData.h b/Source/JavaScriptCore/runtime/RegExpGlobalData.h >new file mode 100644 >index 0000000000000000000000000000000000000000..bd76c360de9754ab00a75fd033bb03d791daed48 >--- /dev/null >+++ b/Source/JavaScriptCore/runtime/RegExpGlobalData.h >@@ -0,0 +1,63 @@ >+/* >+ * Copyright (C) 2019 Apple Inc. All Rights Reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#pragma once >+ >+#include "RegExpCachedResult.h" >+ >+namespace JSC { >+ >+class JSGlobalObject; >+ >+class RegExpGlobalData { >+public: >+ RegExpCachedResult& cachedResult() { return m_cachedResult; } >+ >+ void setMultiline(bool multiline) { m_multiline = multiline; } >+ bool multiline() const { return m_multiline; } >+ >+ void setInput(ExecState*, JSGlobalObject* owner, JSString*); >+ JSString* input() { return m_cachedResult.input(); } >+ >+ void visitAggregate(SlotVisitor&); >+ >+ JSValue getBackref(ExecState*, JSGlobalObject* owner, unsigned); >+ JSValue getLastParen(ExecState*, JSGlobalObject* owner); >+ JSValue getLeftContext(ExecState*, JSGlobalObject* owner); >+ JSValue getRightContext(ExecState*, JSGlobalObject* owner); >+ >+ MatchResult performMatch(VM&, JSGlobalObject*, RegExp*, JSString*, const String&, int startOffset, int** ovector); >+ MatchResult performMatch(VM&, JSGlobalObject*, RegExp*, JSString*, const String&, int startOffset); >+ void recordMatch(VM&, JSGlobalObject*, RegExp*, JSString*, const MatchResult&); >+ >+ static ptrdiff_t offsetOfCachedResult() { return OBJECT_OFFSETOF(RegExpGlobalData, m_cachedResult); } >+ >+private: >+ RegExpCachedResult m_cachedResult; >+ bool m_multiline { false }; >+ Vector<int> m_ovector; >+}; >+ >+} >diff --git a/Source/JavaScriptCore/runtime/RegExpGlobalDataInlines.h b/Source/JavaScriptCore/runtime/RegExpGlobalDataInlines.h >new file mode 100644 >index 0000000000000000000000000000000000000000..7be610f81ba04c6937f80cffbe69345b2294bc17 >--- /dev/null >+++ b/Source/JavaScriptCore/runtime/RegExpGlobalDataInlines.h >@@ -0,0 +1,75 @@ >+/* >+ * Copyright (C) 2019 Apple Inc. All Rights Reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#pragma once >+ >+#include "RegExpGlobalData.h" >+ >+namespace JSC { >+ >+inline void RegExpGlobalData::setInput(ExecState* exec, JSGlobalObject* owner, JSString* string) >+{ >+ m_cachedResult.setInput(exec, owner, string); >+} >+ >+/* >+ To facilitate result caching, exec(), test(), match(), search(), and replace() dipatch regular >+ expression matching through the performMatch function. We use cached results to calculate, >+ e.g., RegExp.lastMatch and RegExp.leftParen. >+*/ >+ALWAYS_INLINE MatchResult RegExpGlobalData::performMatch(VM& vm, JSGlobalObject* owner, RegExp* regExp, JSString* string, const String& input, int startOffset, int** ovector) >+{ >+ int position = regExp->match(vm, input, startOffset, m_ovector); >+ >+ if (ovector) >+ *ovector = m_ovector.data(); >+ >+ if (position == -1) >+ return MatchResult::failed(); >+ >+ ASSERT(!m_ovector.isEmpty()); >+ ASSERT(m_ovector[0] == position); >+ ASSERT(m_ovector[1] >= position); >+ size_t end = m_ovector[1]; >+ >+ m_cachedResult.record(vm, owner, regExp, string, MatchResult(position, end)); >+ >+ return MatchResult(position, end); >+} >+ALWAYS_INLINE MatchResult RegExpGlobalData::performMatch(VM& vm, JSGlobalObject* owner, RegExp* regExp, JSString* string, const String& input, int startOffset) >+{ >+ MatchResult result = regExp->match(vm, input, startOffset); >+ if (result) >+ m_cachedResult.record(vm, owner, regExp, string, result); >+ return result; >+} >+ >+ALWAYS_INLINE void RegExpGlobalData::recordMatch(VM& vm, JSGlobalObject* owner, RegExp* regExp, JSString* string, const MatchResult& result) >+{ >+ ASSERT(result); >+ m_cachedResult.record(vm, owner, regExp, string, result); >+} >+ >+} >diff --git a/Source/JavaScriptCore/runtime/RegExpObject.cpp b/Source/JavaScriptCore/runtime/RegExpObject.cpp >index 8989381f25d9b9fc183d794359af1e218c953b7a..03fbe4603630610adba1c8e2ebd80c56419097ca 100644 >--- a/Source/JavaScriptCore/runtime/RegExpObject.cpp >+++ b/Source/JavaScriptCore/runtime/RegExpObject.cpp >@@ -28,7 +28,6 @@ > #include "JSString.h" > #include "Lookup.h" > #include "JSCInlines.h" >-#include "RegExpConstructor.h" > #include "RegExpObjectInlines.h" > > namespace JSC { >@@ -189,20 +188,19 @@ JSValue RegExpObject::matchGlobal(ExecState* exec, JSGlobalObject* globalObject, > > String s = string->value(exec); > RETURN_IF_EXCEPTION(scope, { }); >- RegExpConstructor* regExpConstructor = globalObject->regExpConstructor(); > > ASSERT(!s.isNull()); > if (regExp->unicode()) { > unsigned stringLength = s.length(); > RELEASE_AND_RETURN(scope, collectMatches( >- vm, exec, string, s, regExpConstructor, regExp, >+ vm, exec, string, s, globalObject, regExp, > [&] (size_t end) -> size_t { > return advanceStringUnicode(s, stringLength, end); > })); > } > > RELEASE_AND_RETURN(scope, collectMatches( >- vm, exec, string, s, regExpConstructor, regExp, >+ vm, exec, string, s, globalObject, regExp, > [&] (size_t end) -> size_t { > return end + 1; > })); >diff --git a/Source/JavaScriptCore/runtime/RegExpObjectInlines.h b/Source/JavaScriptCore/runtime/RegExpObjectInlines.h >index 09aa17f58016564f9c680f42d51c5e8860577c0d..d02dfcdcfa77561d6bdc2abf0281a58e98f531ec 100644 >--- a/Source/JavaScriptCore/runtime/RegExpObjectInlines.h >+++ b/Source/JavaScriptCore/runtime/RegExpObjectInlines.h >@@ -27,7 +27,7 @@ > #include "JSGlobalObject.h" > #include "JSString.h" > #include "JSCInlines.h" >-#include "RegExpConstructor.h" >+#include "RegExpGlobalDataInlines.h" > #include "RegExpMatchesArray.h" > #include "RegExpObject.h" > >@@ -66,7 +66,6 @@ inline JSValue RegExpObject::execInline(ExecState* exec, JSGlobalObject* globalO > auto scope = DECLARE_THROW_SCOPE(vm); > > RegExp* regExp = this->regExp(); >- RegExpConstructor* regExpConstructor = globalObject->regExpConstructor(); > String input = string->value(exec); > RETURN_IF_EXCEPTION(scope, { }); > >@@ -95,7 +94,7 @@ inline JSValue RegExpObject::execInline(ExecState* exec, JSGlobalObject* globalO > if (globalOrSticky) > setLastIndex(exec, result.end); > RETURN_IF_EXCEPTION(scope, { }); >- regExpConstructor->recordMatch(vm, regExp, string, result); >+ globalObject->regExpGlobalData().recordMatch(vm, globalObject, regExp, string, result); > return array; > } > >@@ -107,13 +106,12 @@ inline MatchResult RegExpObject::matchInline( > auto scope = DECLARE_THROW_SCOPE(vm); > > RegExp* regExp = this->regExp(); >- RegExpConstructor* regExpConstructor = globalObject->regExpConstructor(); > String input = string->value(exec); > RETURN_IF_EXCEPTION(scope, { }); > > if (!regExp->global() && !regExp->sticky()) { > scope.release(); >- return regExpConstructor->performMatch(vm, regExp, string, input, 0); >+ return globalObject->regExpGlobalData().performMatch(vm, globalObject, regExp, string, input, 0); > } > > unsigned lastIndex = getRegExpObjectLastIndexAsUnsigned(exec, this, input); >@@ -121,7 +119,7 @@ inline MatchResult RegExpObject::matchInline( > if (lastIndex == UINT_MAX) > return MatchResult::failed(); > >- MatchResult result = regExpConstructor->performMatch(vm, regExp, string, input, lastIndex); >+ MatchResult result = globalObject->regExpGlobalData().performMatch(vm, globalObject, regExp, string, input, lastIndex); > RETURN_IF_EXCEPTION(scope, { }); > scope.release(); > setLastIndex(exec, result.end); >@@ -145,11 +143,11 @@ inline unsigned advanceStringUnicode(String s, unsigned length, unsigned current > } > > template<typename FixEndFunc> >-JSValue collectMatches(VM& vm, ExecState* exec, JSString* string, const String& s, RegExpConstructor* constructor, RegExp* regExp, const FixEndFunc& fixEnd) >+JSValue collectMatches(VM& vm, ExecState* exec, JSString* string, const String& s, JSGlobalObject* globalObject, RegExp* regExp, const FixEndFunc& fixEnd) > { > auto scope = DECLARE_THROW_SCOPE(vm); > >- MatchResult result = constructor->performMatch(vm, regExp, string, s, 0); >+ MatchResult result = globalObject->regExpGlobalData().performMatch(vm, globalObject, regExp, string, s, 0); > RETURN_IF_EXCEPTION(scope, { }); > if (!result) > return jsNull(); >@@ -171,7 +169,7 @@ JSValue collectMatches(VM& vm, ExecState* exec, JSString* string, const String& > } > if (!length) > end = fixEnd(end); >- result = constructor->performMatch(vm, regExp, string, s, end); >+ result = globalObject->regExpGlobalData().performMatch(vm, globalObject, regExp, string, s, end); > if (UNLIKELY(scope.exception())) { > hasException = true; > return; >@@ -194,12 +192,12 @@ JSValue collectMatches(VM& vm, ExecState* exec, JSString* string, const String& > if (result.empty()) > end = fixEnd(end); > >- // Using RegExpConstructor::performMatch() instead of calling RegExp::match() >+ // Using RegExpGlobalData::performMatch() instead of calling RegExp::match() > // directly is a surprising but profitable choice: it means that when we do OOM, we > // will leave the cached result in the state it ought to have had just before the > // OOM! On the other hand, if this loop concludes that the result is small enough, > // then the iterate() loop below will overwrite the cached result anyway. >- result = constructor->performMatch(vm, regExp, string, s, end); >+ result = globalObject->regExpGlobalData().performMatch(vm, globalObject, regExp, string, s, end); > RETURN_IF_EXCEPTION(scope, { }); > } while (result); > >diff --git a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp >index 7831679638d3e4b37b5f2bdc599d536604e38bc2..b6a5891ca8bf2d1f65600499e70bc1ccfb497e14 100644 >--- a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp >+++ b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp >@@ -35,7 +35,6 @@ > #include "ObjectPrototype.h" > #include "RegExp.h" > #include "RegExpCache.h" >-#include "RegExpConstructor.h" > #include "RegExpObject.h" > #include "RegExpObjectInlines.h" > #include "StringObject.h" >@@ -83,17 +82,6 @@ void RegExpPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject) > JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->searchSymbol, regExpPrototypeSearchCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum)); > JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->splitSymbol, regExpPrototypeSplitCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum)); > JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->test, regExpPrototypeTestCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum)); >- >- m_emptyRegExp.set(vm, this, RegExp::create(vm, "", NoFlags)); >-} >- >-void RegExpPrototype::visitChildren(JSCell* cell, SlotVisitor& visitor) >-{ >- RegExpPrototype* thisObject = jsCast<RegExpPrototype*>(cell); >- ASSERT_GC_OBJECT_INHERITS(thisObject, info()); >- Base::visitChildren(thisObject, visitor); >- >- visitor.append(thisObject->m_emptyRegExp); > } > > // ------------------------------ Functions --------------------------- >@@ -497,8 +485,8 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncSearchFast(ExecState* exec) > String s = string->value(exec); > RETURN_IF_EXCEPTION(scope, encodedJSValue()); > >- RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); >- MatchResult result = regExpConstructor->performMatch(vm, regExp, string, s, 0); >+ JSGlobalObject* globalObject = exec->lexicalGlobalObject(); >+ MatchResult result = globalObject->regExpGlobalData().performMatch(vm, globalObject, regExp, string, s, 0); > RETURN_IF_EXCEPTION(scope, encodedJSValue()); > return JSValue::encode(result ? jsNumber(result.start) : jsNumber(-1)); > } >diff --git a/Source/JavaScriptCore/runtime/RegExpPrototype.h b/Source/JavaScriptCore/runtime/RegExpPrototype.h >index 5cc84902fb978c2666dbdac691da1a409d6ac99b..7754860f4668e6befdef9a9ae5ae1507edf1f3a7 100644 >--- a/Source/JavaScriptCore/runtime/RegExpPrototype.h >+++ b/Source/JavaScriptCore/runtime/RegExpPrototype.h >@@ -44,17 +44,11 @@ class RegExpPrototype final : public JSNonFinalObject { > return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info()); > } > >- JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&); >- >- RegExp* emptyRegExp() const { return m_emptyRegExp.get(); } >- > protected: > RegExpPrototype(VM&, Structure*); > > private: > void finishCreation(VM&, JSGlobalObject*); >- >- WriteBarrier<RegExp> m_emptyRegExp; > }; > > EncodedJSValue JSC_HOST_CALL regExpProtoFuncMatchFast(ExecState*); >diff --git a/Source/JavaScriptCore/runtime/StringPrototype.cpp b/Source/JavaScriptCore/runtime/StringPrototype.cpp >index 240ba5ef549a623c4d4fd256d09bc0ccc102c85c..16b3e97ca9df2dd893b5f2822ea5029990d54930 100644 >--- a/Source/JavaScriptCore/runtime/StringPrototype.cpp >+++ b/Source/JavaScriptCore/runtime/StringPrototype.cpp >@@ -43,7 +43,7 @@ > #include "PropertyNameArray.h" > #include "RegExpCache.h" > #include "RegExpConstructor.h" >-#include "RegExpObject.h" >+#include "RegExpGlobalDataInlines.h" > #include "SuperSampler.h" > #include <algorithm> > #include <unicode/uconfig.h> >@@ -483,11 +483,11 @@ static ALWAYS_INLINE JSString* removeUsingRegExpSearch(VM& vm, ExecState* exec, > unsigned startPosition = 0; > > Vector<StringRange, 16> sourceRanges; >- RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); >+ JSGlobalObject* globalObject = exec->lexicalGlobalObject(); > unsigned sourceLen = source.length(); > > while (true) { >- MatchResult result = regExpConstructor->performMatch(vm, regExp, string, source, startPosition); >+ MatchResult result = globalObject->regExpGlobalData().performMatch(vm, globalObject, regExp, string, source, startPosition); > RETURN_IF_EXCEPTION(scope, nullptr); > if (!result) > break; >@@ -542,7 +542,7 @@ static ALWAYS_INLINE JSString* replaceUsingRegExpSearch( > > // FIXME: This is wrong because we may be called directly from the FTL. > // https://bugs.webkit.org/show_bug.cgi?id=154874 >- RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); >+ JSGlobalObject* globalObject = exec->lexicalGlobalObject(); > > size_t lastIndex = 0; > unsigned startPosition = 0; >@@ -561,7 +561,7 @@ static ALWAYS_INLINE JSString* replaceUsingRegExpSearch( > RETURN_IF_EXCEPTION(scope, nullptr); > while (true) { > int* ovector; >- MatchResult result = regExpConstructor->performMatch(vm, regExp, string, source, startPosition, &ovector); >+ MatchResult result = globalObject->regExpGlobalData().performMatch(vm, globalObject, regExp, string, source, startPosition, &ovector); > RETURN_IF_EXCEPTION(scope, nullptr); > if (!result) > break; >@@ -627,7 +627,7 @@ static ALWAYS_INLINE JSString* replaceUsingRegExpSearch( > } else { > do { > int* ovector; >- MatchResult result = regExpConstructor->performMatch(vm, regExp, string, source, startPosition, &ovector); >+ MatchResult result = globalObject->regExpGlobalData().performMatch(vm, globalObject, regExp, string, source, startPosition, &ovector); > RETURN_IF_EXCEPTION(scope, nullptr); > if (!result) > break; >diff --git a/Source/JavaScriptCore/runtime/VM.cpp b/Source/JavaScriptCore/runtime/VM.cpp >index 15c66a7949d766cb0ac6f00b5f12197bd1f5d7f0..0a640b2ef41d855eb7277b18e4fca854150face6 100644 >--- a/Source/JavaScriptCore/runtime/VM.cpp >+++ b/Source/JavaScriptCore/runtime/VM.cpp >@@ -124,7 +124,6 @@ > #include "PropertyMapHashTable.h" > #include "ProxyRevoke.h" > #include "RegExpCache.h" >-#include "RegExpConstructor.h" > #include "RegExpObject.h" > #include "RegisterAtOffsetList.h" > #include "RuntimeType.h" >@@ -309,7 +308,6 @@ VM::VM(VMType vmType, HeapType heapType) > #endif > , propertyTableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), PropertyTable) > , proxyRevokeSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), ProxyRevoke) >- , regExpConstructorSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), RegExpConstructor) > , structureRareDataSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), StructureRareData) > , structureSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), Structure) > , weakSetSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), JSWeakSet) >@@ -434,6 +432,7 @@ VM::VM(VMType vmType, HeapType heapType) > sentinelSetBucket.set(*this, JSSet::BucketType::createSentinel(*this)); > sentinelMapBucket.set(*this, JSMap::BucketType::createSentinel(*this)); > >+ m_regExpCache->initialize(*this); > smallStrings.initializeCommonStrings(*this); > > Thread::current().setCurrentAtomicStringTable(existingEntryAtomicStringTable); >diff --git a/Source/JavaScriptCore/runtime/VM.h b/Source/JavaScriptCore/runtime/VM.h >index 925b8a6e7f93d5daeef201c4e63401d902feaf06..df5886d7240196421174349aef0a3d9877492fcd 100644 >--- a/Source/JavaScriptCore/runtime/VM.h >+++ b/Source/JavaScriptCore/runtime/VM.h >@@ -129,6 +129,7 @@ class JSWebAssemblyInstance; > class LLIntOffsetsExtractor; > class NativeExecutable; > class PromiseDeferredTimer; >+class RegExp; > class RegExpCache; > class Register; > class RegisterAtOffsetList; >@@ -384,7 +385,6 @@ class VM : public ThreadSafeRefCounted<VM>, public DoublyLinkedListNode<VM> { > #endif > IsoSubspace propertyTableSpace; > IsoSubspace proxyRevokeSpace; >- IsoSubspace regExpConstructorSpace; > IsoSubspace structureRareDataSpace; > IsoSubspace structureSpace; > IsoSubspace weakSetSpace;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 193801
:
360231
|
360280
|
360282
|
360283
|
360295
|
360299
|
360301