Skip to content

[JSC] Implement String#split in C++#64204

Merged
webkit-commit-queue merged 1 commit into
WebKit:mainfrom
sosukesuzuki:eng/string-prototype-split-jit-inline
May 8, 2026
Merged

[JSC] Implement String#split in C++#64204
webkit-commit-queue merged 1 commit into
WebKit:mainfrom
sosukesuzuki:eng/string-prototype-split-jit-inline

Conversation

@sosukesuzuki
Copy link
Copy Markdown
Contributor

@sosukesuzuki sosukesuzuki commented May 4, 2026

1a01603

[JSC] Implement `String#split` in C++
https://bugs.webkit.org/show_bug.cgi?id=314009

Reviewed by Yusuke Suzuki.

Move String.prototype.split from a JS builtin to a C++ host function and add
a StringSplit DFG node. The node does not inline anything itself; it just
dispatches to operationStringSplit (string separator) or
operationStringSplitRegExp (primordial RegExp separator).

To make the RegExp fast path safe, splitSymbol is added to
regExpPrimordialPropertiesWatchpointSet, m_stringSymbolSplitWatchpointSet
is introduced (mirroring the replace counterpart), and
m_regExpSpeciesWatchpointSet is added so an override of
RegExp[Symbol.species] invalidates the shortcut. Per-instance @@split
overrides are caught by the existing structure check in
isSymbolSplitFastAndNonObservable.

                                    TipOfTree                  Patched

regexp-split-digit-literal       83.6760+-2.5457     ^     74.9740+-1.7527        ^ definitely 1.1161x faster
regexp-split-digit-cached        86.0425+-1.5091     ^     76.5833+-1.9675        ^ definitely 1.1235x faster
string-split-slash-short         93.2927+-3.7145     ^     76.8576+-0.6003        ^ definitely 1.2138x faster
string-split-comma-short         96.1436+-6.8025     ^     77.8741+-1.0157        ^ definitely 1.2346x faster

Tests: JSTests/microbenchmarks/regexp-split-digit-cached.js
       JSTests/microbenchmarks/regexp-split-digit-literal.js
       JSTests/microbenchmarks/string-split-comma-short.js
       JSTests/microbenchmarks/string-split-slash-short.js

* JSTests/microbenchmarks/regexp-split-digit-cached.js: Added.
(split):
* JSTests/microbenchmarks/regexp-split-digit-literal.js: Added.
(split):
* JSTests/microbenchmarks/string-split-comma-short.js: Added.
(split):
* JSTests/microbenchmarks/string-split-slash-short.js: Added.
(split):
* Source/JavaScriptCore/builtins/BuiltinNames.h:
* Source/JavaScriptCore/builtins/StringPrototype.js:
(split): Deleted.
* Source/JavaScriptCore/bytecode/LinkTimeConstant.h:
* Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp:
(JSC::DFG::BackwardsPropagationPhase::propagate):
* Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleIntrinsicCall):
* Source/JavaScriptCore/dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* Source/JavaScriptCore/dfg/DFGCloneHelper.h:
* Source/JavaScriptCore/dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* Source/JavaScriptCore/dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* Source/JavaScriptCore/dfg/DFGGraph.h:
* Source/JavaScriptCore/dfg/DFGJITCode.cpp:
(JSC::DFG::JITData::JITData):
(JSC::DFG::JITData::tryInitialize):
* Source/JavaScriptCore/dfg/DFGJITCode.h:
* Source/JavaScriptCore/dfg/DFGNodeType.h:
* Source/JavaScriptCore/dfg/DFGOperations.cpp:
(JSC::DFG::JSC_DEFINE_JIT_OPERATION):
* Source/JavaScriptCore/dfg/DFGOperations.h:
* Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp:
* Source/JavaScriptCore/dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp:
* Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h:
* Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* Source/JavaScriptCore/ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileStringSplit):
* Source/JavaScriptCore/runtime/Intrinsic.h:
* Source/JavaScriptCore/runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
* Source/JavaScriptCore/runtime/JSGlobalObject.h:
* Source/JavaScriptCore/runtime/RegExpObject.h:
* Source/JavaScriptCore/runtime/RegExpObjectInlines.h:
(JSC::RegExpObject::isSymbolReplaceFastAndNonObservable):
(JSC::RegExpObject::isSymbolSplitFastAndNonObservable):
* Source/JavaScriptCore/runtime/RegExpPrototype.cpp:
(JSC::regExpSplitFast):
(JSC::JSC_DEFINE_HOST_FUNCTION):
* Source/JavaScriptCore/runtime/RegExpPrototype.h:
* Source/JavaScriptCore/runtime/StringPrototype.cpp:
(JSC::StringPrototype::finishCreation):
(JSC::stringSplitFast):
(JSC::JSC_DEFINE_HOST_FUNCTION):
* Source/JavaScriptCore/runtime/StringPrototype.h:

Canonical link: https://commits.webkit.org/312843@main

885a6ec

Misc iOS, visionOS, tvOS & watchOS macOS Linux Windows
✅ 🧪 style ✅ 🛠 ios ✅ 🛠 mac ✅ 🛠 wpe 🛠 win
✅ 🛠 ios-sim ✅ 🛠 mac-AS-debug loading-orange 🧪 wpe-wk2 🧪 win-tests
✅ 🧪 webkitperl ✅ 🧪 ios-wk2 ✅ 🧪 api-mac ✅ 🧪 api-wpe
✅ 🧪 ios-wk2-wpt ❌ 🧪 api-mac-debug ✅ 🛠 gtk3-libwebrtc
✅ 🛠 🧪 jsc ✅ 🧪 api-ios ✅ 🧪 mac-wk1 ✅ 🛠 gtk
✅ 🛠 🧪 jsc-debug-arm64 ✅ 🛠 ios-safer-cpp ✅ 🧪 mac-wk2 ✅ 🧪 gtk-wk2
✅ 🛠 vision ✅ 🧪 mac-AS-debug-wk2 ✅ 🧪 api-gtk
✅ 🛠 🧪 merge ✅ 🛠 vision-sim ✅ 🧪 mac-wk2-stress ✅ 🛠 playstation
✅ 🧪 vision-wk2 ✅ 🧪 mac-intel-wk2 ✅ 🛠 jsc-armv7
✅ 🛠 tv ✅ 🛠 mac-safer-cpp ✅ 🧪 jsc-armv7-tests
✅ 🛠 tv-sim
✅ 🛠 watch
✅ 🛠 watch-sim

@sosukesuzuki sosukesuzuki self-assigned this May 4, 2026
@sosukesuzuki sosukesuzuki added the JavaScriptCore For bugs in JavaScriptCore, the JS engine used by WebKit, other than kxmlcore issues. label May 4, 2026
@webkit-ews-buildbot
Copy link
Copy Markdown
Collaborator

iOS Safer C++ Build #18112 (2509a17)

❌ Found 1 failing file with 2 issues. Please address these issues before landing. See WebKit Guidelines for Safer C++ Programming.
(cc @rniwa)

@webkit-ews-buildbot webkit-ews-buildbot added the merging-blocked Applied to prevent a change from being merged label May 4, 2026
@webkit-ews-buildbot
Copy link
Copy Markdown
Collaborator

macOS Safer C++ Build #99775 (2509a17)

❌ Found 1 failing file with 2 issues. Please address these issues before landing. See WebKit Guidelines for Safer C++ Programming.
(cc @rniwa)

@sosukesuzuki sosukesuzuki removed the merging-blocked Applied to prevent a change from being merged label May 7, 2026
@sosukesuzuki sosukesuzuki force-pushed the eng/string-prototype-split-jit-inline branch from 2509a17 to ec8b532 Compare May 7, 2026 00:51
@sosukesuzuki sosukesuzuki force-pushed the eng/string-prototype-split-jit-inline branch from ec8b532 to 885a6ec Compare May 7, 2026 01:02
@sosukesuzuki sosukesuzuki marked this pull request as ready for review May 7, 2026 03:30
@sosukesuzuki sosukesuzuki requested a review from a team as a code owner May 7, 2026 03:30
@sosukesuzuki sosukesuzuki added the merge-queue Applied to send a pull request to merge-queue label May 8, 2026
https://bugs.webkit.org/show_bug.cgi?id=314009

Reviewed by Yusuke Suzuki.

Move String.prototype.split from a JS builtin to a C++ host function and add
a StringSplit DFG node. The node does not inline anything itself; it just
dispatches to operationStringSplit (string separator) or
operationStringSplitRegExp (primordial RegExp separator).

To make the RegExp fast path safe, splitSymbol is added to
regExpPrimordialPropertiesWatchpointSet, m_stringSymbolSplitWatchpointSet
is introduced (mirroring the replace counterpart), and
m_regExpSpeciesWatchpointSet is added so an override of
RegExp[Symbol.species] invalidates the shortcut. Per-instance @@split
overrides are caught by the existing structure check in
isSymbolSplitFastAndNonObservable.

                                    TipOfTree                  Patched

regexp-split-digit-literal       83.6760+-2.5457     ^     74.9740+-1.7527        ^ definitely 1.1161x faster
regexp-split-digit-cached        86.0425+-1.5091     ^     76.5833+-1.9675        ^ definitely 1.1235x faster
string-split-slash-short         93.2927+-3.7145     ^     76.8576+-0.6003        ^ definitely 1.2138x faster
string-split-comma-short         96.1436+-6.8025     ^     77.8741+-1.0157        ^ definitely 1.2346x faster

Tests: JSTests/microbenchmarks/regexp-split-digit-cached.js
       JSTests/microbenchmarks/regexp-split-digit-literal.js
       JSTests/microbenchmarks/string-split-comma-short.js
       JSTests/microbenchmarks/string-split-slash-short.js

* JSTests/microbenchmarks/regexp-split-digit-cached.js: Added.
(split):
* JSTests/microbenchmarks/regexp-split-digit-literal.js: Added.
(split):
* JSTests/microbenchmarks/string-split-comma-short.js: Added.
(split):
* JSTests/microbenchmarks/string-split-slash-short.js: Added.
(split):
* Source/JavaScriptCore/builtins/BuiltinNames.h:
* Source/JavaScriptCore/builtins/StringPrototype.js:
(split): Deleted.
* Source/JavaScriptCore/bytecode/LinkTimeConstant.h:
* Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp:
(JSC::DFG::BackwardsPropagationPhase::propagate):
* Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleIntrinsicCall):
* Source/JavaScriptCore/dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* Source/JavaScriptCore/dfg/DFGCloneHelper.h:
* Source/JavaScriptCore/dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* Source/JavaScriptCore/dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* Source/JavaScriptCore/dfg/DFGGraph.h:
* Source/JavaScriptCore/dfg/DFGJITCode.cpp:
(JSC::DFG::JITData::JITData):
(JSC::DFG::JITData::tryInitialize):
* Source/JavaScriptCore/dfg/DFGJITCode.h:
* Source/JavaScriptCore/dfg/DFGNodeType.h:
* Source/JavaScriptCore/dfg/DFGOperations.cpp:
(JSC::DFG::JSC_DEFINE_JIT_OPERATION):
* Source/JavaScriptCore/dfg/DFGOperations.h:
* Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp:
* Source/JavaScriptCore/dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp:
* Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h:
* Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* Source/JavaScriptCore/ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileStringSplit):
* Source/JavaScriptCore/runtime/Intrinsic.h:
* Source/JavaScriptCore/runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
* Source/JavaScriptCore/runtime/JSGlobalObject.h:
* Source/JavaScriptCore/runtime/RegExpObject.h:
* Source/JavaScriptCore/runtime/RegExpObjectInlines.h:
(JSC::RegExpObject::isSymbolReplaceFastAndNonObservable):
(JSC::RegExpObject::isSymbolSplitFastAndNonObservable):
* Source/JavaScriptCore/runtime/RegExpPrototype.cpp:
(JSC::regExpSplitFast):
(JSC::JSC_DEFINE_HOST_FUNCTION):
* Source/JavaScriptCore/runtime/RegExpPrototype.h:
* Source/JavaScriptCore/runtime/StringPrototype.cpp:
(JSC::StringPrototype::finishCreation):
(JSC::stringSplitFast):
(JSC::JSC_DEFINE_HOST_FUNCTION):
* Source/JavaScriptCore/runtime/StringPrototype.h:

Canonical link: https://commits.webkit.org/312843@main
@webkit-commit-queue webkit-commit-queue force-pushed the eng/string-prototype-split-jit-inline branch from 885a6ec to 1a01603 Compare May 8, 2026 00:32
@webkit-commit-queue
Copy link
Copy Markdown
Collaborator

Committed 312843@main (1a01603): https://commits.webkit.org/312843@main

Reviewed commits have been landed. Closing PR #64204 and removing active labels.

@webkit-commit-queue webkit-commit-queue merged commit 1a01603 into WebKit:main May 8, 2026
@webkit-commit-queue webkit-commit-queue removed the merge-queue Applied to send a pull request to merge-queue label May 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

JavaScriptCore For bugs in JavaScriptCore, the JS engine used by WebKit, other than kxmlcore issues.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants