oracle/graal · error · GraalError

Out of scratch registers: %s

Error message

Out of scratch registers: %s

What it means

Thrown by readPrimitiveArrayUnaligned when the array constant's type is not a primitive array. Buffer-based byte reads are only valid on primitive guest arrays; reference arrays and non-array objects have no byte buffer to decode from.

Source

Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/aarch64/AArch64MacroAssembler.java:97

        public ScratchRegister(Register register) {
            this.register = register;
        }

        public Register getRegister() {
            return register;
        }

        @Override
        public void close() {
            assert nextFreeScratchRegister > 0 : "Close called too often";
            nextFreeScratchRegister--;
        }
    }

    public ScratchRegister getScratchRegister() {
        if (nextFreeScratchRegister == getScratchRegisters().length) {
            throw new GraalError("Out of scratch registers: " + nextFreeScratchRegister);
        }
        return getScratchRegisters()[nextFreeScratchRegister++];
    }

    @Override
    public void bind(Label l) {
        super.bind(l);
        // Clear last ldr/str instruction to prevent the labeled ldr/str being merged.
        lastImmLoadStoreEncoding = null;
    }

    /**
     * Retrieves pc relative offset between current position and provided bound label.
     */
    public int getPCRelativeOffset(Label label) {
        assert label.isBound();
        registerPatchInCodeSnippetRecord(position(), label);
        int offset = label.position() - position();

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Verify arrayType.isArray() && getComponentType().isPrimitive() before the read
  2. Match the kind to the actual component type of the array you pass
  3. For reference arrays use readArrayElement and handle elements as object constants

Example fix

// before
JavaConstant v = vmAccess.readPrimitiveArrayUnaligned(refArrayConst, JavaKind.Int, offset);

// after
EspressoResolvedObjectType t = ((EspressoExternalObjectConstant) refArrayConst).getType();
JavaConstant v = (t.isArray() && t.getComponentType().isPrimitive())
        ? vmAccess.readPrimitiveArrayUnaligned(refArrayConst, t.getComponentType().getJavaKind(), offset)
        : vmAccess.readArrayElement(refArrayConst, offset / 4);
Defensive patterns

Strategy: validation

Validate before calling

EspressoResolvedObjectType t = ((EspressoExternalObjectConstant) array).getType();
if (!(t.isArray() && t.getComponentType().isPrimitive())) {
    throw new IllegalArgumentException("unaligned read requires a primitive array, got " + t);
}

Type guard

static boolean isPrimitiveArrayConstant(JavaConstant c) {
    return c instanceof EspressoExternalObjectConstant o
            && o.getType().isArray()
            && o.getType().getComponentType().isPrimitive();
}

Prevention

When it happens

Trigger: Calling readPrimitiveArrayUnaligned with an Object[] constant, an espresso String, or any non-array object constant while the kind itself is a valid primitive.

Common situations: Reading a field that is a reference array by mistake; kind/array mismatch where the kind came from one field and the array constant from another; refactors mixing up variables.

Related errors


AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14). Data as JSON: /api/errors/47a0a3b390833d76. Report an issue: GitHub.