Skip to content

LoadStatics Annotation

opencode-agent[bot] edited this page May 10, 2026 · 1 revision

@LoadStatics Annotation

Annotation marking methods whose static field table must be reloaded before execution, used during VM boot and kernel entry.

Overview

JNode maintains two static field tablesVmSharedStatics (global code and metadata) and VmIsolatedStatics (per-isolate field values) — in a dual-statics architecture. When the VM boots, the boot image contains pre-compiled classes with their static fields initialized. However, certain methods — particularly those that run before the isolate system is fully set up — need to load the current processor's static field table at every entry, ensuring they always reference the correct data.

@LoadStatics marks these methods. The JIT compiler emits a STATICS register load at the method prologue, loading the current processor's isolated statics table into a dedicated CPU register. This register is then used for all subsequent static field accesses within that method.

Key Components

Class / File Role
core/src/classlib/org/jnode/annotation/LoadStatics.java Annotation definition
core/src/core/org/jnode/vm/classmgr/VmMethod.java hasLoadStaticsPragma() method
core/src/core/org/jnode/vm/classmgr/ClassDecoder.java Pragma annotation registration (MethodPragmaFlags.LOADSTATICS)
core/src/core/org/jnode/vm/x86/compiler/l1a/X86StackFrame.java L1 compiler statics loading at method prologue
core/src/core/org/jnode/vm/x86/compiler/l2/X86StackFrame.java L2 compiler statics loading at method prologue
core/src/core/org/jnode/vm/scheduler/VmProcessor.java Processor state including VmIsolatedStatics reference
core/src/core/org/jnode/vm/scheduler/VmThread.java Thread state with isolate bindings
core/src/core/org/jnode/boot/Main.java Boot entry point using @LoadStatics

How It Works

Annotation Definition

@Documented
@Retention(CLASS)
@Target(METHOD)
public @interface LoadStatics {
}

Unlike @SharedStatics (which is a TYPE target marking an entire class), @LoadStatics is a METHOD target marking individual methods.

Pragma Registration

During class loading, ClassDecoder registers the annotation as a method pragma:

new PragmaAnnotation(LoadStatics.class, MethodPragmaFlags.LOADSTATICS)

This sets the LOADSTATICS bit in VmMethod.pragmaFlags. The bit is checked at compile time via VmMethod.hasLoadStaticsPragma().

Compiler Integration

The L1 and L2 compilers both check for the pragma in their stack frame setup code:

if (method.hasLoadStaticsPragma()) {
    helper.writeLoadSTATICS(helper.genLabel("$$edi"), "init", false);
}

When the JIT compiler generates code for a @LoadStatics method, it emits a STATICS register load at the method prologue — before any user code executes. This register holds the pointer to the current processor's VmIsolatedStatics table.

Typical Usage Pattern

@LoadStatics is typically paired with @Uninterruptible, since the methods requiring statics reloading are low-level kernel entry points:

@LoadStatics
@Uninterruptible
public static int vmMain() {
    // At this point, the statics table is guaranteed to be loaded
    VmSystem.initialize();
    // ...
}

Methods Using @LoadStatics

  • Main.vmMain() — VM entry point after kernel assembly
  • VmThread.run() — thread body (needs correct isolate statics)
  • VmProcessor.reschedule() — scheduler interrupt handler
  • VmProcessor.handleException() — CPU exception handler
  • VmType.initialize() — class initialization

Gotchas & Non-Obvious Behavior

  • Prologue overhead — Every @LoadStatics method pays the cost of a statics register load at entry. Use sparingly.
  • @LoadStatics vs @SharedStatics — They are independent concerns: @SharedStatics controls which static table a class uses (shared vs per-isolate), while @LoadStatics controls whether the statics register is reloaded at method entry.
  • @LoadStatics is NOT for class-level sharing — If you want a class's statics shared across isolates, use @SharedStatics on the class, not @LoadStatics on methods.
  • Static field access depends on the register — Once the STATICS register is loaded, all static field accesses within the method use that table. Code must enter through the @LoadStatics entry point to guarantee the register is set.
  • @Uninterruptible is commonly paired — Since these methods run during sensitive boot/transition periods, @Uninterruptible prevents thread switches that could invalidate the assumptions.

Related Pages

Clone this wiki locally