Skip to content

Revisit object alignment related API #1458

@wks

Description

@wks

TODO:

  • Refactor the VMBinding trait to use LOG_MIN_ALIGNMENT and LOG_MAX_ALIGNMENT, and require LOG_MIN_ALIGNMENT <= LOG_MAX_ALIGNMENT.
  • Introduce plan-specific alignment requirement, or provide a reasonable default value.
  • Remove the assertion in Allocator::align_allocation_inner that checks VM::MIN_ALIGNMENT >= BYTES_IN_INT if we think it is reasonable.

As we noticed in #1456, the allocator has an assertion MIN_ALIGNMENT >= BYTES_IN_INT. It can be traced back to the JikesRVM MMTk, but we need to investigate whether we still need it, in case some code paths in the allocator still assumes MIN_ALIGNMENT >= 4.

MIN_ALIGNMENT and MAX_ALIGNMENT

In JikesRVM, there are two constants MIN_ALIGNMENT and MAX_ALIGNMENT:

public final class Constants {
  /**
   * This value specifies the <i>minimum</i> allocation alignment
   * requirement of the VM.  When making allocation requests, both
   * <code>align</code> and <code>offset</code> must be multiples of
   * <code>MIN_ALIGNMENT</code>.
   *
   * This value is required to be a power of 2.
   */
  public static final byte LOG_MIN_ALIGNMENT = VM.LOG_MIN_ALIGNMENT;
  public static final int MIN_ALIGNMENT = 1 << LOG_MIN_ALIGNMENT;

  /**
   * The maximum alignment request the vm will make. This must be a
   * power of two multiple of the minimum alignment.
   */
  public static final int MAX_ALIGNMENT = MIN_ALIGNMENT << VM.MAX_ALIGNMENT_SHIFT;
}

And in the VM class:

class VM {
  /** The log base two of the minimum allocation alignment */
  public static final byte LOG_MIN_ALIGNMENT;
  /** The log base two of (MAX_ALIGNMENT/MIN_ALIGNMENT) */
  public static final byte MAX_ALIGNMENT_SHIFT;
}

In the Rust MMTk, we have

pub trait VM {
    /// Allowed minimal alignment in bytes.
    const MIN_ALIGNMENT: usize = 1 << DEFAULT_LOG_MIN_ALIGNMENT;
    /// Allowed maximum alignment in bytes.
    const MAX_ALIGNMENT: usize = 1 << DEFAULT_LOG_MAX_ALIGNMENT;
}

There are subtle differences between JikesRVM and the Rust MMTk.

In JikesRVM, those two constants are always powers of two. It should be the same for the Rust MMTk, but we haven't explicitly documented it, nor have we used LOG_MIN_ALIGNMENT and LOG_MAX_ALIGNMENT to force them to be powers of two on the API level.

**In JikesRVM, the doc comment of MAX_ALIGNMENT says "The maximum alignment request the vm will make" **. In the Rust MMTk, it instead says "'Allowed' maximum alignment...". It is ambiguous what "allow" means. It can be interpreted as "the VM will only allow mmtk-core to align objects within that range", but I don't think it is what it means.

I think we should refactor the API so that

  1. We change them to LOG_MIN_ALIGNMENT and LOG_MAX_ALIGNMENT to force them to be powers of two.
  2. We require LOG_MIN_ALIGNMENT <= LOG_MAX_ALIGNMENT, and we do static assertions about this.
  3. We specify that they represent the min and max alignment requests the VM will make.

In other words, the range is now a promise made by the VM, that is, whenever the VM calls memory_manager::alloc, the align argument will never be smaller than the min value, and never be larger than the max value.

Plan-specific or MMTk-specific alignment requirement

For the convenience of implementation, the MMTk may have stricter requirements than what the VM requests.

For example, to use VO bits, all ObjectReference must be word-aligned. This requires all objects must be at least one word in size, and must be at least one word aligned. Note that it is OK to make it aligned at an offset. For example, if JikesRVM were able to run on a 64-bit machine, it is OK to put its header at an address where (start + 4) % 8 == 0, while defining ObjectReference = start + 4. That means align = 8 && offset = 4. That's still 8-byte aligned.

We need a way to let the allocator be aware of such requirements.

Does the Allocator assume any minimum value of VM::MIN_ALIGNMENT?

As we mentioned before, there is currently an assertion in align_allocation_inner:

debug_assert!(VM::MIN_ALIGNMENT >= BYTES_IN_INT);

Currently VM::MIN_ALIGNMENT is only used in one place in align_allocation_inner:

    if alignment <= known_alignment || VM::MAX_ALIGNMENT <= VM::MIN_ALIGNMENT {
        return region;
    }

And VM::MAX_ALIGNMENT <= VM:MIN_ALIGNMENT is very strange, although it can be traced back to JikesRVM, too. (See this commit)

No other code depends on VM:MIN_ALIGNMENT.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions