/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/eclipse-1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.mmtk.harness.vm; import org.mmtk.harness.scheduler.Scheduler; import org.mmtk.policy.ImmortalSpace; import org.mmtk.utility.heap.VMRequest; import org.vmmagic.unboxed.*; import org.vmmagic.unboxed.harness.MemoryConstants; import org.vmmagic.unboxed.harness.SimulatedMemory; import org.vmmagic.pragma.*; @Uninterruptible public class Memory extends org.mmtk.vm.Memory { /** * Allows for the VM to reserve space between HEAP_START() * and AVAILABLE_START() for its own purposes. MMTk should * expect to encounter objects in this range, but may not * allocate in this range. * * MMTk expects the virtual address space between AVAILABLE_START() * and AVAILABLE_END() to be contiguous and unmapped. * Allows for the VM to reserve space between HEAP_END() * and AVAILABLE_END() for its own purposes. MMTk should * expect to encounter objects in this range, but may not * allocate in this range. * * MMTk expects the virtual address space between AVAILABLE_START() * and AVAILABLE_END() to be contiguous and unmapped. * * @return The high bound of the memory that MMTk can allocate. */ private static ImmortalSpace vmSpace = null; private static Extent VMSPACE_SIZE = Extent.fromIntZeroExtend(0x10000000); // Uncomment the below to exercise MMTk's 64-bit address space handling // public static final Address HEAP_START = ArchitecturalWord.getModel().bitsInWord() == 32 ? // Address.fromIntZeroExtend(0x10000000) : // Address.fromLong(0x210000000L) ; // public static final Address HEAP_END = ArchitecturalWord.getModel().bitsInWord() == 32 ? // Address.fromIntZeroExtend(0xA0000000) : // Address.fromLong(0x2A0000000L); public static final Address HEAP_START = Address.fromIntZeroExtend(0x10000000); public static final Address HEAP_END = Address.fromIntZeroExtend(0xA0000000); /** * Return the space associated with/reserved for the VM. In the * case of Jikes RVM this is the boot image space.<p> * * @return The space managed by the virtual machine. */ @Interruptible public ImmortalSpace getVMSpace() { if (vmSpace == null) { vmSpace = new ImmortalSpace("vm", 0, VMRequest.create(VMSPACE_SIZE, false)); } return vmSpace; } /** Global preparation for a collection. */ public void globalPrepareVMSpace() { // Nothing in vmSpace } /** Per-collector preparation for a collection. */ public void collectorPrepareVMSpace() { // Nothing in vmSpace } /** Per-collector post-collection work. */ public void collectorReleaseVMSpace() { // Nothing in vmSpace } /** Global post-collection work. */ public void globalReleaseVMSpace() { // Nothing in vmSpace } /** * Sets the range of addresses associated with a heap. * * @param id the heap identifier * @param start the address of the start of the heap * @param end the address of the end of the heap */ public void setHeapRange(int id, Address start, Address end) { // TODO: More checking possible } /** * Demand zero mmaps an area of virtual memory. * * @param start the address of the start of the area to be mapped * @param size the size, in bytes, of the area to be mapped * @return 0 if successful, otherwise the system errno */ public int dzmmap(Address start, int size) { if (SimulatedMemory.map(start, size)) { return 0; } return -1; } /** * Protects access to an area of virtual memory. * * @param start the address of the start of the area to be mapped * @param size the size, in bytes, of the area to be mapped * @return <code>true</code> if successful, otherwise * <code>false</code> */ public boolean mprotect(Address start, int size) { return SimulatedMemory.protect(start, size); } /** * Allows access to an area of virtual memory. * * @param start the address of the start of the area to be mapped * @param size the size, in bytes, of the area to be mapped * @return <code>true</code> if successful, otherwise * <code>false</code> */ public boolean munprotect(Address start, int size) { return SimulatedMemory.unprotect(start, size); } /** * Zero a region of memory. * @param start Start of address range (inclusive) * @param len Length in bytes of range to zero * Returned: nothing */ public void zero(Address start, Extent len) { SimulatedMemory.zero(start, len); } /** * Zero a range of pages of memory. * @param start Start of address range (must be a page address) * @param len Length in bytes of range (must be multiple of page size) */ public void zeroPages(Address start, int len) { SimulatedMemory.zeroPages(start, len); } /** * Logs the contents of an address and the surrounding memory to the * error output. * * @param start the address of the memory to be dumped * @param beforeBytes the number of bytes before the address to be * included * @param afterBytes the number of bytes after the address to be * included */ public void dumpMemory(Address start, int beforeBytes, int afterBytes) { SimulatedMemory.dumpMemory(start, beforeBytes, afterBytes); } /** * Wait for preceeding cache flush/invalidate instructions to complete * on all processors. Ensures that all memory writes before this * point are visible to all processors. */ @Inline public void sync() { Scheduler.yield(); // Nothing required } /** * Wait for all preceeding instructions to complete and discard any * prefetched instructions on this processor. Also prevents the * compiler from performing code motion across this point. */ @Inline public void isync() { Scheduler.yield(); // Nothing required } /* * NOTE: The following methods must be implemented by subclasses of this * class, but are internal to the VM<->MM interface glue, so are never * called by MMTk users. */ /** @return The lowest address in the virtual address space known to MMTk */ protected Address getHeapStartConstant() { return HEAP_START; } /** @return The highest address in the virtual address space known to MMTk */ protected Address getHeapEndConstant() { return HEAP_END; } /** @return The lowest address in the contiguous address space available to MMTk */ protected Address getAvailableStartConstant() { return HEAP_START.plus(VMSPACE_SIZE); } /** @return The highest address in the contiguous address space available to MMTk */ protected Address getAvailableEndConstant() { return HEAP_END; } /** @return The log base two of the size of an address */ protected byte getLogBytesInAddressConstant() { return (byte) MemoryConstants.LOG_BYTES_IN_WORD; } /** @return The log base two of the size of a word */ protected byte getLogBytesInWordConstant() { return (byte) MemoryConstants.LOG_BYTES_IN_WORD; } /** @return The log base two of the size of an OS page */ protected byte getLogBytesInPageConstant() { return MemoryConstants.LOG_BYTES_IN_PAGE; } /** @return The log base two of the minimum allocation alignment */ protected byte getLogMinAlignmentConstant() { return (byte) MemoryConstants.LOG_BYTES_IN_WORD; } /** @return The log base two of (MAX_ALIGNMENT/MIN_ALIGNMENT) */ protected byte getMaxAlignmentShiftConstant() { return 1; } /** @return The maximum number of bytes of padding to prepend to an object */ protected int getMaxBytesPaddingConstant() { return MemoryConstants.BYTES_IN_WORD; } /** @return The value to store in alignment holes */ protected int getAlignmentValueConstant() { return ObjectModel.ALIGNMENT_VALUE; } }