TODO:
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
- We change them to
LOG_MIN_ALIGNMENT and LOG_MAX_ALIGNMENT to force them to be powers of two.
- We require
LOG_MIN_ALIGNMENT <= LOG_MAX_ALIGNMENT, and we do static assertions about this.
- 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.
TODO:
VMBindingtrait to useLOG_MIN_ALIGNMENTandLOG_MAX_ALIGNMENT, and requireLOG_MIN_ALIGNMENT <= LOG_MAX_ALIGNMENT.Allocator::align_allocation_innerthat checksVM::MIN_ALIGNMENT >= BYTES_IN_INTif 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 assumesMIN_ALIGNMENT >= 4.MIN_ALIGNMENTandMAX_ALIGNMENTIn JikesRVM, there are two constants
MIN_ALIGNMENTandMAX_ALIGNMENT:And in the VM class:
In the Rust MMTk, we have
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_ALIGNMENTandLOG_MAX_ALIGNMENTto force them to be powers of two on the API level.**In JikesRVM, the doc comment of
MAX_ALIGNMENTsays "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
LOG_MIN_ALIGNMENTandLOG_MAX_ALIGNMENTto force them to be powers of two.LOG_MIN_ALIGNMENT <= LOG_MAX_ALIGNMENT, and we do static assertions about this.In other words, the range is now a promise made by the VM, that is, whenever the VM calls
memory_manager::alloc, thealignargument 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
ObjectReferencemust 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 definingObjectReference = start + 4. That meansalign = 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:Currently
VM::MIN_ALIGNMENTis only used in one place inalign_allocation_inner:And
VM::MAX_ALIGNMENT <= VM:MIN_ALIGNMENTis very strange, although it can be traced back to JikesRVM, too. (See this commit)No other code depends on
VM:MIN_ALIGNMENT.