oracle/graal · error · GraalError

Emitting code to return the current value of the timestamp c

Error message

Emitting code to return the current value of the timestamp counter is not currently supported on %s

What it means

emitTimeStamp() is a default LIRGeneratorTool method that throws GraalError for architectures without an instruction to read the timestamp counter. Hitting it means lowering reached a 'read timestamp counter' node (e.g., an rdtsc-style intrinsic) on a backend that has not implemented the operation.

Source

Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/gen/LIRGeneratorTool.java:1037

    default void emitProtectionKeyRegisterWrite(Value value) {
        throw new GraalError("Emitting code to write a value to the protection key register is not currently supported on %s", target().arch);
    }

    /**
     * Read contents of the protection key register.
     *
     * @return value read from the register
     */
    default Value emitProtectionKeyRegisterRead() {
        throw new GraalError("Emitting code to read the contents of the protection key register is not currently supported on %s", target().arch);
    }

    default VirtualStackSlot allocateStackMemory(int sizeInBytes, int alignmentInBytes) {
        return getResult().getFrameMapBuilder().allocateStackMemory(sizeInBytes, alignmentInBytes);
    }

    default Value emitTimeStamp() {
        throw new GraalError("Emitting code to return the current value of the timestamp counter is not currently supported on %s", target().arch);
    }

    @SuppressWarnings("unused")
    default void emitProcid(AllocatableValue dst) {
        throw new GraalError("Emitting code to return the current value of the procid is not currently supported on %s", target().arch);
    }

    default Value emitReadCallerStackPointer(Stamp wordStamp) {
        /*
         * We do not know the frame size yet. So we load the address of the first spill slot
         * relative to the beginning of the frame, which is equivalent to the stack pointer of the
         * caller.
         */
        return emitAddress(StackSlot.get(getLIRKind(wordStamp), 0, true));
    }

    default Value emitReadReturnAddress(Stamp wordStamp, int returnAddressSize) {
        return emitMove(StackSlot.get(getLIRKind(wordStamp), -returnAddressSize, true));

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Replace the timestamp intrinsic with a supported mechanism on that platform (e.g., System.nanoTime(), a native call)
  2. Gate the node's lowering on target().arch so unsupported architectures never emit it
  3. Implement emitTimeStamp in the relevant backend LIRGenerator

Example fix

// before
@NodeIntrinsic public static native long timeStamp();
... timeStamp() ... // lowers on every arch, throws on unported ones

// after
if (arch instanceof AMD64) { emitTimeStamp(); } else { System.nanoTime(); }
Defensive patterns

Strategy: validation

Validate before calling

if (backendOverrides(lirGen.getClass(), "emitTimeStamp")) {
    ts = gen.emitTimeStamp();
} else {
    ts = emitNativeCallToClockMono(); // supported on every arch
}

Prevention

When it happens

Trigger: Lowering a timestamp-counter node/intrinsic on a backend whose LIRGenerator does not override emitTimeStamp(). The offending architecture is printed in the message via target().arch.

Common situations: Benchmarks, entropy sources, or profiling code that reads hardware timestamps being JIT-compiled on an architecture without a ported rdtsc equivalent; new intrinsics added to the frontend before backend coverage.

Related errors


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