Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions .github/openclaw/qualification/stack/check-jsc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@ set -euo pipefail
: "${WEBKIT_CHECKOUT:?}" "${JSC:?}" "${RESULT_DIR:?}"
mkdir -p "$RESULT_DIR"
cd "$WEBKIT_CHECKOUT"
for mode in default interpreter optimizer eager-ftl; do
for mode in default interpreter baseline dfg optimizer eager-ftl concurrent; do
args=()
case "$mode" in
interpreter) args=(--useJIT=false);;
baseline) args=(--useDFGJIT=false --useFTLJIT=false);;
dfg) args=(--useFTLJIT=false --useConcurrentJIT=false);;
optimizer) args=(--useBytecodeOptimizer=true);;
eager-ftl) args=(--useConcurrentJIT=false --thresholdForOptimizeAfterWarmUp=10 --thresholdForFTLOptimizeAfterWarmUp=20);;
eager-ftl) args=(--useConcurrentJIT=false --thresholdForJITAfterWarmUp=10 --thresholdForOptimizeAfterWarmUp=10 --thresholdForFTLOptimizeAfterWarmUp=20);;
concurrent) args=(--gcAtEnd=true --useConcurrentGC=true);;
esac
for fixture in callsite-syntax-positions.js stack-position-regressions.js callsite-async-position.mjs; do
for fixture in callsite-syntax-positions.js stack-position-regressions.js stack-position-regressions-cache.js callsite-async-position.mjs; do
module=(); case "$fixture" in *.mjs) module=(-m);; esac
"$JSC" "${args[@]}" "${module[@]}" "JSTests/stress/$fixture" > "$RESULT_DIR/$mode-$fixture.log" 2>&1
done
Expand All @@ -21,7 +24,7 @@ for kind in owned persistent; do
args=(--diskCachePath="$cache")
if test "$kind" = persistent; then args+=(--diskCachePayloadIsPersistentForTesting=true); fi
for repeat in cold warm; do
for fixture in callsite-syntax-positions.js stack-position-regressions.js callsite-async-position.mjs; do
for fixture in callsite-syntax-positions.js stack-position-regressions.js stack-position-regressions-cache.js callsite-async-position.mjs; do
module=(); case "$fixture" in *.mjs) module=(-m);; esac
"$JSC" "${args[@]}" "${module[@]}" "JSTests/stress/$fixture" > "$RESULT_DIR/cache-$kind-$repeat-$fixture.log" 2>&1
done
Expand Down
6 changes: 3 additions & 3 deletions .github/openclaw/qualify-engine.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ tar -xzf "$ARTIFACT_DIR/bun-webkit-linux-amd64.tar.gz" -C "$QUALIFICATION_DIR/en
jsc="$QUALIFICATION_DIR/engine/bun-webkit/bin/jsc"
"$jsc" --useDollarVM=true -e 'if(typeof $vm.moduleNamespaceForRequire!=="function")throw Error("namespace hook absent")'
Tools/Scripts/run-jsc-stress-tests JSTests/stress --jsc "$jsc" --child-processes 16 \
--filter 'promise|microtask|dynamic-import|bun-async-context|module-loader|top-level-await|async-module|module-namespace|intl-segmenter|callsite-syntax-positions|stack-position-regressions' \
--filter 'promise|microtask|dynamic-import|bun-async-context|module-loader|top-level-await|async-module|module-namespace|intl-segmenter|callsite-syntax-positions|stack-position-regressions|error-stack' \
--output-dir "$QUALIFICATION_DIR/jsc-stress" --no-retry > "$QUALIFICATION_DIR/jsc-stress.log" 2>&1
python3 .github/openclaw/verify-jsc-results.py "$QUALIFICATION_DIR/jsc-stress" --require module-namespace-esmodule-marker.js --require callsite-syntax-positions.js --require stack-position-regressions.js
python3 .github/openclaw/verify-jsc-results.py "$QUALIFICATION_DIR/jsc-stress" --require module-namespace-esmodule-marker.js --require callsite-syntax-positions.js --require stack-position-regressions.js --require stack-position-regressions-cache.js
python3 .github/openclaw/check-stack-visitor.py "$jsc" > "$QUALIFICATION_DIR/stack-visitor.log"
WEBKIT_CHECKOUT="$PWD" JSC="$jsc" RESULT_DIR="$QUALIFICATION_DIR/jsc-stack" bash .github/openclaw/qualification/stack/check-jsc.sh
Tools/Scripts/run-jsc-stress-tests JSTests/modules.yaml --jsc "$jsc" --child-processes 16 \
Expand Down Expand Up @@ -38,5 +38,5 @@ for name,minimum in [('jsc-stress',1400),('jsc-modules',1600)]:
assert len(lines)>=minimum,(name,len(lines))
assert all(line.endswith(': PASS') for line in lines),name+' failures'
counts[name]=len(lines)
(root/'engine-gate.json').write_text(json.dumps({'passed':True,'source':sys.argv[2],'stress_counts':counts,'sampling_tiers':4,'arraybuffer_execution_modes':5,'stack_execution_modes':4,'stack_cache':json.loads((root/'jsc-stack/cache-files.json').read_text())},indent=2)+'\n')
(root/'engine-gate.json').write_text(json.dumps({'passed':True,'source':sys.argv[2],'stress_counts':counts,'sampling_tiers':4,'arraybuffer_execution_modes':5,'stack_execution_modes':7,'stack_cache':json.loads((root/'jsc-stack/cache-files.json').read_text())},indent=2)+'\n')
PY
6 changes: 5 additions & 1 deletion .github/openclaw/release-notes.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
This release rebases the qualified OpenClaw engine patches onto upstream `5718a6ec579b98362ea7276a426deedcc6281ef5`.
This release adds engine PR #8's repeated stack-coordinate cache to the qualified OpenClaw engine on upstream `5718a6ec579b98362ea7276a426deedcc6281ef5`.

- Cache requested provider-relative stack line and column conversions under the existing line-table lock, preserving document offsets, builtin overrides, and persistent bytecode format; thanks @steipete. Regressions cover repeated reads, independent providers, UTF-16 columns, and compressed line-table boundaries across interpreter/JIT tiers and cache modes.

The previously released engine changes remain included:

- Release free allocator memory from idle compiler threads and long Atomics waits; thanks @Jarred-Sumner.
- Preserve Segmenter surrogate boundaries, opt-in Proxy global prototypes, module-loader AsyncLocalStorage context, and per-VM worker heap/stack budgets; thanks @steipete and @robobun.
Expand Down
27 changes: 26 additions & 1 deletion .github/workflows/openclaw-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ jobs:
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
fetch-depth: 64
ref: ${{ github.event.pull_request.head.sha || github.sha }}
fetch-depth: 0
persist-credentials: false
sparse-checkout-cone-mode: false
sparse-checkout: |
Expand Down Expand Up @@ -86,3 +87,27 @@ jobs:
${{ runner.temp }}/qualification/sync/runtime-cache/*.json
if-no-files-found: error
retention-days: 7
macos-fork-artifact:
if: github.repository == 'openclaw/WebKit'
runs-on: blacksmith-32vcpu-ubuntu-2404
timeout-minutes: 150
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
fetch-depth: 0
persist-credentials: false
sparse-checkout-cone-mode: false
sparse-checkout: |
/*
!/LayoutTests/
!/JSTests/*
!/PerformanceTests/
!/Websites/
!/ManualTests/
!/WebDriverTests/
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020
with:
node-version: '26.3.0'
- name: Build the macOS fork artifact on Linux without publishing
run: python3 .github/openclaw/artifacts.py build --lane bun-webkit-macos-arm64 --output "$RUNNER_TEMP/macos-fork-artifact"
20 changes: 20 additions & 0 deletions JSTests/stress/stack-position-regressions-cache.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Exercise cached offsets from independent providers, including equal offsets
// with different line tables, UTF-16 columns, and compressed-table boundaries.
const sources = [];
for (const terminator of ["\n", "\r\n", "\u2028", "\u2029"]) {
for (const lines of [0, 1, 63, 64, 65, 127]) {
const prefix = "/* 🦞 */ ";
const body = prefix + "(function positionCacheProbe() { return new Error('cache'); })";
const source = terminator.repeat(lines) + body;
sources.push({ create: eval(source), line: lines + 1, column: body.indexOf("new Error") + 1 });
}
}
for (let repeat = 0; repeat < Math.min(testLoopCount, 30); ++repeat) {
for (const { create, line, column } of sources) {
const error = create();
// Anonymous eval frames omit their URL from stack strings, but expose
// the same computed coordinates through JSC's error properties.
if (error.line !== line || error.column !== column)
throw new Error(`Expected ${line}:${column}, got ${error.line}:${error.column}`);
}
}
19 changes: 17 additions & 2 deletions OPENCLAW.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,11 @@ Batch 1 is published from `openclaw/batch-1` so concurrently reviewed batch-2
engine changes can land on `openclaw/main` without entering this release. All publication
branches require the same protected environment and full-SHA/green-job checks.

Pull requests run **OpenClaw engine checks**, a read-only Linux build using the same
lane recipe and Bun qualification gate. It also runs the ArrayBuffer accounting
Pull requests run **OpenClaw engine checks** at the exact PR head, with a native
Linux build using the same lane recipe and Bun qualification gate, plus the
macOS arm64 fork artifact cross-built on a separate Linux runner. Both jobs are
read-only; the macOS lane proves compilation, not native macOS execution.
The native job also runs the ArrayBuffer accounting
and confirmed parked-waiter inspection regression with LLInt, DFG, FTL and
concurrent GC. This workflow provides the pre-merge check; it cannot publish.

Expand Down Expand Up @@ -145,6 +148,12 @@ baseline. Engine and Bun headers and libraries must be rebuilt together.

No changes yet.

## Repeated stack coordinates (2026-10-05)

- Cache source-relative stack line and column lookups on demand, including syntax-selected positions; carries engine PR #8 onto the rebased release line, thanks @steipete.
- Build both fork engine artifacts at the exact pull-request head before landing, with native Linux qualification and a Linux-hosted macOS arm64 compilation check.
- Require the repeated-coordinate regression and surrounding error-stack stress cases, with seven direct stack execution modes including interpreter, baseline-only, DFG-only, eager FTL and concurrent GC, while retaining every rebased release gate.

## Rebased engine batch

- Keep syntax-selected stack positions separate from exception ranges for calls, constructors, property reads, and async continuations. Preserve the positions across bytecode rewriting, optimization, and cache replay.
Expand Down Expand Up @@ -222,3 +231,9 @@ regressions. A combined regression inspects a worker during the new idle-memory
purge and notification windows. VM inspection runs before the idle-purge branch,
with the waiter-list lock dropped and VM heap access restored only for inspection;
both paths recheck notification/termination before waiting again.

The source provider caches only requested line/column conversions under its existing
line-table lock. Coordinates remain relative to the provider's text; document
offsets and builtin provider overrides retain their existing behavior. The cache
fills only when a reader requests a position, and the persistent bytecode-cache
format is unchanged.
9 changes: 6 additions & 3 deletions Source/JavaScriptCore/parser/SourceProvider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,8 +320,12 @@ static unsigned lineEndFor(StringView text, const EncodedLineStarts& lineStarts,
LineColumn LineStartTable::lineColumnForOffset(StringView text, unsigned offset)
{
Locker locker { m_lock };
auto line = EncodedLineStarts { ensureBuilt(text).bytes }.lineContaining(offset);
return { line.line0Based, offset - line.start };
// Syntax-selected stack positions bypass the per-instruction expression cache.
// Cache provider-relative coordinates so document offsets remain applied by the caller.
return m_cachedLineColumns.ensure(offset, [&] {
auto line = EncodedLineStarts { ensureBuilt(text).bytes }.lineContaining(offset);
return LineColumn { line.line0Based, offset - line.start };
}).iterator->value;
}

LineStartTable::PositionInfo LineStartTable::positionInfoForOffset(StringView text, unsigned offset)
Expand Down Expand Up @@ -365,4 +369,3 @@ LineColumn BuiltinsSourceProvider::lineColumnInTextForOffset(unsigned offset)
}

} // namespace JSC

5 changes: 4 additions & 1 deletion Source/JavaScriptCore/parser/SourceProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ WTF_ALLOW_UNSAFE_BUFFER_USAGE_BEGIN
#include <JavaScriptCore/SourceOrigin.h>
#include <JavaScriptCore/SourceTaintedOrigin.h>
#include <span>
#include <wtf/HashMap.h>
#include <wtf/Lock.h>
#include <wtf/Noncopyable.h>
#include <wtf/RefCountedFixedVector.h>
Expand Down Expand Up @@ -125,6 +126,8 @@ class LineStartTable {

mutable Lock m_lock;
LineStarts m_lineStarts WTF_GUARDED_BY_LOCK(m_lock);
using LineColumnMap = UncheckedKeyHashMap<uint64_t, LineColumn, WTF::IntHash<uint64_t>, WTF::UnsignedWithZeroKeyHashTraits<uint64_t>>;
LineColumnMap m_cachedLineColumns WTF_GUARDED_BY_LOCK(m_lock);
};

class JS_EXPORT_PRIVATE SourceProvider : public ThreadSafeRefCounted<SourceProvider> {
Expand Down Expand Up @@ -505,4 +508,4 @@ class SourceProviderBufferGuard {
SourceProvider* m_sourceProvider { nullptr };
};

} // namespace JSC
} // namespace JSC