-
Notifications
You must be signed in to change notification settings - Fork 0
Field Offset Calculation
Runtime computation of instance field positions within Java objects and TIB array indexing for type metadata access.
Field offset calculation determines where each instance field resides in memory relative to an object's base address. This is critical for JIT compilers to generate efficient field access code, for the VM to perform fast GETFIELD/PUTFIELD operations, and for understanding object memory layout. JNode calculates field offsets during class loading and stores them in VmInstanceField objects for runtime use.
Every JNode object consists of:
┌─────────────────────────────────────────────────────────────┐
│ OBJECT HEADER (2 slots) │
├─────────────────────┬───────────────────────────────────────┤
│ FLAGS_SLOT (-2) │ TIB_SLOT (-1) │
└─────────────────────┴───────────────────────────────────────┘
│ │
▼ ▼
Offset -2 * SLOT_SIZE Offset -1 * SLOT_SIZE
│ │
▼ ▼
[Object Start] ──────────► Instance Fields Start at Offset 0
The header consumes 2 slots (defined in ObjectLayout.HEADER_SLOTS). Instance fields begin at offset 0, immediately after the header.
During class loading, ClassDecoder assigns preliminary field offsets in declaration order:
// ClassDecoder.java:761-775
final int fieldOffset = objectSize; // Start after header
if (wide)
objectSize += 8; // long/double
else if (Modifier.isPrimitive(signature))
objectSize += 4; // int, float, etc.
else
objectSize += slotSize; // reference (4 or 8 bytes)
fs = new VmInstanceField(name, signature, modifiers, fieldOffset, cls, slotSize);The offset is initially relative to the class's own object size. Later, ClassResolver.resolveFieldOffsets() adjusts these to be relative to the complete object (including superclass fields).
Subclass field offsets must account for the complete inheritance chain:
// VmNormalClass.java:143-146
for (VmInstanceField inf : instanceFields) {
inf.resolveOffset(superClassSize); // Add superclass field size
}At runtime, the stored offset is used directly:
// VmInstanceField.java:60-62
public final int getOffset() {
return offset;
}The JIT compilers use this offset to generate direct memory accesses like:
-
mov eax, [ebx + offset](GETFIELD) -
mov [ebx + offset], value(PUTFIELD)
The TIB (Type Information Block) is an Object[] array containing type metadata. Indexes are defined in TIBLayout:
| Index | Constant | Type | Purpose |
|---|---|---|---|
| 0 | VMTYPE_INDEX | VmType | The VmType instance |
| 1 | IMT_INDEX | Object[] | Interface Method Table |
| 2 | IMTCOLLISIONS_INDEX | boolean[] | IMT collision flags |
| 3 | COMPILED_IMT_INDEX | Object | Compiled IMT |
| 4 | SUPERCLASSES_INDEX | VmType[] | Superclass chain |
| 5+ | FIRST_METHOD_INDEX | — | Virtual method table |
TIB array indexing is distinct from field offset calculation—it addresses the TIB array itself, not object instance fields.
| Class / File | Role |
|---|---|
core/src/core/org/jnode/vm/classmgr/ObjectLayout.java |
Defines FLAGS_SLOT (-2), TIB_SLOT (-1), HEADER_SLOTS (2), OBJECT_ALIGN (8) |
core/src/core/org/jnode/vm/classmgr/TIBLayout.java |
TIB array index constants (VMTYPE_INDEX through SUPERCLASSES_INDEX) |
core/src/core/org/jnode/vm/classmgr/VmInstanceField.java |
Stores runtime field offset in offset field, provides getOffset() |
core/src/core/org/jnode/vm/classmgr/ClassDecoder.java |
Initial field offset calculation during class loading (lines 761-775) |
core/src/core/org/jnode/vm/classmgr/VmNormalClass.java |
Resolves field offsets for inheritance (resolveOffset method) |
core/src/core/org/jnode/vm/classmgr/VmType.java |
Coordinates field layout computation |
-
Class Loading:
ClassDecoderreads bytecode field info and assigns sequential offsets starting at 0 (after the 2-slot header) -
Inheritance Resolution:
VmNormalClass.resolveFieldOffsets()adds the superclass size to each inherited field's offset -
Runtime Access: JIT-compiled code uses
VmInstanceField.getOffset()to generate direct memory accesses -
TIB Access: JIT compilers use
TIBLayoutconstants to index into the TIB array for method dispatch, type checking, and GC
- Negative header offsets: The object header extends before the object address—FLAGS_SLOT is at -2, TIB_SLOT at -1
- Slot size varies: 32-bit mode uses 4-byte slots, 64-bit uses 8-byte slots—offsets scale accordingly
-
Wide field alignment:
longanddoublefields (8 bytes) may introduce padding to maintain alignment -
Object alignment: Final object size is aligned to 8 bytes (
ObjectLayout.OBJECT_ALIGN), affecting heap allocation - TIB indexing vs field offsets: TIBLayout defines array indexes in the TIB metadata array, not object field positions
- Static fields not included: Static fields are stored in a separate statics area, not in the object layout
- Object-Layout — Object header structure and overall memory representation
- TIB — Type Information Block details and construction
- Type-System-Internals — VmType hierarchy and class loading
- JIT-Compilers — How compilers use field offsets for code generation
- Virtual-Methods-Dispatch — Method dispatch using TIB indexing