Redline: a mutable global reaching a second instance gets a copy
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 52/100
Research direction
Start with emitGlobalGet and emitGlobalSet in NativeEmitters, then inspect the context layout and initializeImportGlobals in both runners. Trace how imported globals are represented across two instances and run the full spec suite. Done means a shared mutable global remains shared across instances without changing the module-defined global fast path.
Written by the indexing model from the issue text.
Description
Redline shares a mutable global with the first instance that receives it. If the same global reaches a second instance, that instance gets a copy instead, so writes by one are not visible to the other. Every other execution mode shares it.
Reproducing
Module A exports a mutable global, module B imports it and increments it, then A reads it back:
interpreter: exporter reads 101
redline: exporter reads 100
The same happens without any exporting module, by passing one host-created global to two instances: after each of them increments it, the host object reads 11 rather than 12.
A global used by a single instance is shared correctly, and memories and tables are unaffected — they are reached through a pointer, so an importing machine simply uses the same one.
Cause
CtxBuffer.GLOBALS_PTR points at one contiguous array of 8-byte slots per machine, indexed by global index, and compiled code reads a global with a single load:
globalsPtr = load_i64(ctxPtr, GLOBALS_PTR);
rawVal = load_i64(globalsPtr, globalIdx * 8);
A global's storage therefore has to live inside that machine's array at that module's index, and two machines cannot both hold the same global at their own index. initializeImportGlobals adopts a global that is not yet bound to any machine, and copies the value for one that is.
Suggested fix
Add indirection for imported globals only. Their slot would hold a pointer to the real storage rather than the value, making global.get two loads:
slot = load_i64(globalsPtr, idx * 8);
val = load_i64(slot, 0);
Imports occupy indices [0, importGlobalCount), so the compiler knows statically which globals need the extra load. Module-defined globals — the common case — keep the single-load fast path and cost nothing.
Touches emitGlobalGet/emitGlobalSet in NativeEmitters, the context layout, and initializeImportGlobals in both runners. It changes the compiled-code ABI, so it needs the full spec suite behind it.
Impact
Marginal in practice: it needs two instances plus a shared mutable global. Not a regression — the copy predates the current import work, which fixed the single-instance case.
- Dominant language
- Java
- Stars
- 301
- Forks
- 21
- Avg merge
- 2d 4h
- Merged PRs (30d)
- 34
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from bytecodealliance/endive
-
Difficulty 5/5 Over a week Newbie friendliness 35/100
bytecodealliance/endive#181 · 2 comments · 1 reaction ·
-
Difficulty 5/5 Over a week Newbie friendliness 35/100
bytecodealliance/endive#170 · 7 comments ·
-
Difficulty 4/5 3-5 days Newbie friendliness 48/100
bytecodealliance/endive#102 · 3 comments ·
-
Difficulty 3/5 1-2 days Newbie friendliness 58/100
bytecodealliance/endive#99 · 1 comment ·
-
Difficulty 5/5 Over a week Newbie friendliness 35/100
bytecodealliance/endive#86 ·
All issues in bytecodealliance/endive
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
infinispan/infinispan#18150 ·
-
area/frontend
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
untriaged
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
opensearch-project/k-NN#3597 ·
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 88/100