Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: 4a781308731b113c7fe7dcd01719a070a0361eb5
https://github.com/WebKit/WebKit/commit/4a781308731b113c7fe7dcd01719a070a0361eb5
Author: Sosuke Suzuki <[email protected]>
Date: 2026-05-31 (Sun, 31 May 2026)
Changed paths:
A JSTests/microbenchmarks/string-iterator-for-of-ascii.js
A JSTests/microbenchmarks/string-iterator-for-of-surrogate-pairs.js
A JSTests/microbenchmarks/string-iterator-spread-surrogate-pairs.js
A JSTests/stress/iterator-fast-path-mode-mixing.js
A JSTests/stress/string-iterator-fast-path.js
A JSTests/stress/string-iterator-surrogate-pairs.js
M Source/JavaScriptCore/CMakeLists.txt
M Source/JavaScriptCore/DerivedSources-input.xcfilelist
M Source/JavaScriptCore/DerivedSources.make
M Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
R Source/JavaScriptCore/builtins/StringIteratorPrototype.js
M Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.cpp
M Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h
M Source/JavaScriptCore/bytecode/IterationModeMetadata.h
M Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
M Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
M Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
M Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
M Source/JavaScriptCore/dfg/DFGClobberize.h
M Source/JavaScriptCore/dfg/DFGCloneHelper.h
M Source/JavaScriptCore/dfg/DFGDoesGC.cpp
M Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
M Source/JavaScriptCore/dfg/DFGNode.h
M Source/JavaScriptCore/dfg/DFGNodeType.h
M Source/JavaScriptCore/dfg/DFGOperations.cpp
M Source/JavaScriptCore/dfg/DFGOperations.h
M Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
M Source/JavaScriptCore/dfg/DFGSafeToExecute.h
M Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
M Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
M Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
M Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
M Source/JavaScriptCore/ftl/FTLCapabilities.cpp
M Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
M Source/JavaScriptCore/jit/JITOperations.cpp
M Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
M Source/JavaScriptCore/runtime/IteratorOperations.cpp
M Source/JavaScriptCore/runtime/JSGlobalObject.cpp
M Source/JavaScriptCore/runtime/JSGlobalObject.h
M Source/JavaScriptCore/runtime/JSStringIterator.h
M Source/JavaScriptCore/runtime/JSStringIteratorInlines.h
M Source/JavaScriptCore/runtime/StringIteratorPrototype.cpp
M Source/JavaScriptCore/runtime/StringPrototype.cpp
M Source/JavaScriptCore/runtime/StringPrototype.h
Log Message:
-----------
[JSC] Add String fast iteration
https://bugs.webkit.org/show_bug.cgi?id=315330
Reviewed by Yusuke Suzuki.
Extend the iterator_open / iterator_next fast iteration protocol (currently
JSArray / JSMap / JSSet) to JSString. LLInt / Baseline use the
JSStringIterator::nextWithAdvance() helper, so no iterator result object is
allocated and surrogate pairs become a substring instead of a rope.
For DFG / FTL, iterator_next is lowered to a new tuple-returning node
StringIteratorNext(string, position) -> <resultString, nextPosition>. The
iterator's Index field is read and written with GetInternalField /
PutInternalField around the node, so the node itself never references the
JSStringIterator. This keeps the iterator's field accesses visible to
ObjectAllocationSinking, which can then eliminate the JSStringIterator
allocation entirely. The node inlines the resolved 8-bit single-character fast
path (the result is a cached single-character string, so there is no
allocation) and falls back to operationStringIteratorNext for ropes, 16-bit
strings, and surrogate pairs. nextWithAdvance() and the operation share a
common JSStringIterator::advance() core so the LLInt/Baseline and DFG/FTL paths
cannot diverge.
StringIteratorPrototype.next becomes a C++ host function used by the generic
path. Since this adds a 4th fast mode, we also limit the number of fast modes
inlined per iteration site to 2; beyond that, new iterable types are recorded
as Generic.
ToT Patched
string-iterator-for-of-ascii 108.2338+-1.7953 ^
26.2858+-0.6488 ^ definitely 4.1176x faster
string-iterator-for-of-surrogate-pairs 712.0298+-10.1006 ^
392.1395+-4.2522 ^ definitely 1.8158x faster
Tests: JSTests/microbenchmarks/string-iterator-for-of-ascii.js
JSTests/microbenchmarks/string-iterator-for-of-surrogate-pairs.js
JSTests/microbenchmarks/string-iterator-spread-surrogate-pairs.js
JSTests/stress/iterator-fast-path-mode-mixing.js
JSTests/stress/string-iterator-fast-path.js
* JSTests/microbenchmarks/string-iterator-for-of-ascii.js: Added.
(sumCodePoints):
* JSTests/microbenchmarks/string-iterator-for-of-surrogate-pairs.js: Added.
(sumCodePoints):
* JSTests/microbenchmarks/string-iterator-spread-surrogate-pairs.js: Added.
(spread):
* JSTests/stress/iterator-fast-path-mode-mixing.js: Added.
(shouldBe):
(countValues):
(sumValues):
(generatorValues):
* JSTests/stress/string-iterator-fast-path.js: Added.
(shouldBe):
(sumCodePoints):
(collect):
(firstChar):
(countValues):
(makeRope):
(exhaustManually):
(joinChars):
(String.prototype.Symbol.iterator):
* JSTests/stress/string-iterator-surrogate-pairs.js: Added.
(assert):
(referenceSegments):
(forOfSegments):
(manualSegments):
(dump):
(check):
(runExactCases):
(runBoundaryCombinations):
(rnd):
(randomUnit):
(runRandomStrings):
* Source/JavaScriptCore/bytecode/IterationModeMetadata.h:
(JSC::canUseFastIterationMode):
* Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleIteratorOpen):
(JSC::DFG::ByteCodeParser::handleIteratorNext):
* 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/DFGNode.h:
(JSC::DFG::Node::isTuple const):
(JSC::DFG::Node::tupleSize const):
* 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:
(JSC::DFG::SpeculativeJIT::cellTupleResultWithoutUsingChildren):
* 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::compileCompareStrictEq):
* Source/JavaScriptCore/jit/JITOperations.cpp:
(JSC::JSC_DEFINE_JIT_OPERATION):
* Source/JavaScriptCore/runtime/CommonSlowPaths.cpp:
(JSC::iteratorOpenTryFastImpl):
(JSC::iteratorNextTryFastImpl):
* Source/JavaScriptCore/runtime/IteratorOperations.cpp:
(JSC::getIterationMode):
* Source/JavaScriptCore/runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::visitChildrenImpl):
* Source/JavaScriptCore/runtime/JSGlobalObject.h:
* Source/JavaScriptCore/runtime/JSStringIterator.h:
* Source/JavaScriptCore/runtime/JSStringIteratorInlines.h:
(JSC::JSStringIterator::advance):
(JSC::JSStringIterator::nextWithAdvance):
* Source/JavaScriptCore/runtime/StringIteratorPrototype.cpp:
(JSC::StringIteratorPrototype::finishCreation):
(JSC::JSC_DEFINE_HOST_FUNCTION):
* Source/JavaScriptCore/runtime/StringPrototype.cpp:
(JSC::StringPrototype::finishCreation):
* Source/JavaScriptCore/runtime/StringPrototype.h:
Canonical link: https://commits.webkit.org/314265@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications