001/*
002 *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003 *
004 *  This file is licensed to You under the Eclipse Public License (EPL);
005 *  You may not use this file except in compliance with the License. You
006 *  may obtain a copy of the License at
007 *
008 *      http://www.opensource.org/licenses/eclipse-1.0.php
009 *
010 *  See the COPYRIGHT.txt file distributed with this work for information
011 *  regarding copyright ownership.
012 */
013package org.jikesrvm.mm.mmtk;
014
015import static org.jikesrvm.HeapLayoutConstants.BOOT_IMAGE_DATA_START;
016import static org.jikesrvm.HeapLayoutConstants.BOOT_IMAGE_END;
017import static org.jikesrvm.HeapLayoutConstants.MAXIMUM_MAPPABLE;
018import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_DOUBLE;
019import static org.jikesrvm.runtime.JavaSizeConstants.LOG_BYTES_IN_INT;
020import static org.jikesrvm.runtime.JavaSizeConstants.LOG_BYTES_IN_LONG;
021import static org.jikesrvm.runtime.UnboxedSizeConstants.LOG_BYTES_IN_ADDRESS;
022import static org.jikesrvm.runtime.UnboxedSizeConstants.LOG_BYTES_IN_WORD;
023import static org.mmtk.utility.Constants.LOG_BYTES_IN_MBYTE;
024
025import org.jikesrvm.VM;
026import org.jikesrvm.objectmodel.JavaHeader;
027import org.jikesrvm.runtime.BootRecord;
028import org.jikesrvm.runtime.Magic;
029import org.mmtk.policy.ImmortalSpace;
030import org.mmtk.policy.Space;
031import org.mmtk.utility.heap.VMRequest;
032import org.vmmagic.pragma.Inline;
033import org.vmmagic.pragma.Interruptible;
034import org.vmmagic.pragma.Uninterruptible;
035import org.vmmagic.unboxed.Address;
036import org.vmmagic.unboxed.Extent;
037import org.vmmagic.unboxed.Offset;
038
039@Uninterruptible public class Memory extends org.mmtk.vm.Memory {
040
041  /**
042   * A lie about the size of a virtual memory page. MMTk currently
043   * assumes that the page size is known at bootimage building time (see RVM-816),
044   * so we need to pass some kind of value.
045   */
046  private static final int LOG_BYTES_IN_PAGE_LIE = 12;
047
048  @Override
049  protected final Address getHeapStartConstant() {
050    return BOOT_IMAGE_DATA_START;
051  }
052  @Override
053  protected final Address getHeapEndConstant() {
054    return MAXIMUM_MAPPABLE;
055  }
056  @Override
057  protected final Address getAvailableStartConstant() {
058    return BOOT_IMAGE_END;
059  }
060  @Override
061  protected final Address getAvailableEndConstant() {
062    return MAXIMUM_MAPPABLE;
063  }
064  @Override
065  protected final byte getLogBytesInAddressConstant() {
066    return LOG_BYTES_IN_ADDRESS;
067  }
068  @Override
069  protected final byte getLogBytesInWordConstant() {
070    return LOG_BYTES_IN_WORD;
071  }
072  @Override
073  protected final byte getLogBytesInPageConstant() {
074    return LOG_BYTES_IN_PAGE_LIE;
075  }
076  @Override
077  protected final byte getLogMinAlignmentConstant() {
078    return JavaHeader.LOG_MIN_ALIGNMENT;
079  }
080  @Override
081  protected final int getMaxBytesPaddingConstant() {
082    return BYTES_IN_DOUBLE;
083  }
084  @Override
085  protected final int getAlignmentValueConstant() {
086    return JavaHeader.ALIGNMENT_VALUE;
087  }
088
089  /** On Intel we align code to 16 bytes as recommended in the optimization manual. */
090  @Override
091  protected final byte getMaxAlignmentShiftConstant() {
092    return (VM.BuildForIA32 ? 1 : 0) + LOG_BYTES_IN_LONG - LOG_BYTES_IN_INT;
093  }
094
095  private static ImmortalSpace bootSpace;
096
097  private static final int BOOT_SEGMENT_MB;
098
099  static {
100    Offset bootSegmentBytes = BOOT_IMAGE_END.diff(BOOT_IMAGE_DATA_START);
101    BOOT_SEGMENT_MB = org.jikesrvm.runtime.Memory.alignUp(bootSegmentBytes.toInt(),
102        Space.BYTES_IN_CHUNK) >>> LOG_BYTES_IN_MBYTE;
103  }
104
105  /**
106   * Return the space associated with/reserved for the VM.  In the
107   * case of Jikes RVM this is the boot image space.<p>
108   *
109   * The boot image space must be mapped at the start of available
110   * virtual memory, hence we use the constructor that requests the
111   * lowest address in the address space.  The address space awarded
112   * to this space depends on the order in which the request is made.
113   * If this request is not the first request for virtual memory then
114   * the Space allocator will die with an error stating that the
115   * request could not be satisfied.  The remedy is to ensure it is
116   * initialized first.
117   *
118   * @return The space managed by the virtual machine.  In this case,
119   * the boot image space is returned.
120   */
121  @Override
122  @Interruptible
123  public final ImmortalSpace getVMSpace() {
124    if (bootSpace == null) {
125      bootSpace = new ImmortalSpace("boot", VMRequest.fixedSize(BOOT_SEGMENT_MB));
126    }
127    return bootSpace;
128  }
129
130  @Override
131  public final void globalPrepareVMSpace() {
132    bootSpace.prepare();
133  }
134
135  @Override
136  public final void collectorPrepareVMSpace() {}
137
138  @Override
139  public final void collectorReleaseVMSpace() {}
140
141  @Override
142  public final void globalReleaseVMSpace() {
143    bootSpace.release();
144  }
145
146  @Override
147  public final void setHeapRange(int id, Address start, Address end) {
148    BootRecord.the_boot_record.setHeapRange(id, start, end);
149  }
150
151  @Override
152  public final int dzmmap(Address start, int size) {
153    Address result = org.jikesrvm.runtime.Memory.dzmmap(start, Extent.fromIntZeroExtend(size));
154    if (result.EQ(start)) return 0;
155    if (result.GT(Address.fromIntZeroExtend(127))) {
156      VM.sysWrite("demand zero mmap with MAP_FIXED on ", start);
157      VM.sysWriteln(" returned some other address", result);
158      VM.sysFail("mmap with MAP_FIXED has unexpected behavior");
159    }
160    return result.toInt();
161  }
162
163  @Override
164  public final boolean mprotect(Address start, int size) {
165    return org.jikesrvm.runtime.Memory.mprotect(start, Extent.fromIntZeroExtend(size),
166                                                   org.jikesrvm.runtime.Memory.PROT_NONE);
167  }
168
169  @Override
170  public final boolean munprotect(Address start, int size) {
171    return org.jikesrvm.runtime.Memory.mprotect(start, Extent.fromIntZeroExtend(size),
172                                                   org.jikesrvm.runtime.Memory.PROT_READ |
173                                                   org.jikesrvm.runtime.Memory.PROT_WRITE |
174                                                   org.jikesrvm.runtime.Memory.PROT_EXEC);
175  }
176
177  @Override
178  public final void zero(boolean useNT, Address start, Extent len) {
179    org.jikesrvm.runtime.Memory.zero(useNT, start,len);
180  }
181
182  @Override
183  public final void dumpMemory(Address start, int beforeBytes,
184                                int afterBytes) {
185    org.jikesrvm.runtime.Memory.dumpMemory(start,beforeBytes,afterBytes);
186  }
187
188  /*
189   * Utilities from the VM class
190   */
191
192  @Override
193  @Inline
194  public final void sync() {
195    Magic.sync();
196  }
197
198  @Override
199  @Inline
200  public final void isync() {
201    Magic.isync();
202  }
203}