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     */
013    package org.jikesrvm.mm.mmtk;
014    
015    import org.mmtk.plan.Plan;
016    import org.mmtk.policy.ImmortalSpace;
017    import org.mmtk.utility.Constants;
018    import org.mmtk.utility.heap.VMRequest;
019    
020    import org.jikesrvm.VM;
021    import org.jikesrvm.runtime.BootRecord;
022    import org.jikesrvm.HeapLayoutConstants;
023    import org.jikesrvm.runtime.Magic;
024    import org.jikesrvm.objectmodel.JavaHeader;
025    import org.jikesrvm.SizeConstants;
026    
027    import org.vmmagic.unboxed.*;
028    import org.vmmagic.pragma.*;
029    
030    @Uninterruptible public class Memory extends org.mmtk.vm.Memory
031      implements Constants, HeapLayoutConstants, SizeConstants {
032    
033      protected final Address getHeapStartConstant() { return BOOT_IMAGE_DATA_START; }
034      protected final Address getHeapEndConstant() { return MAXIMUM_MAPPABLE; }
035      protected final Address getAvailableStartConstant() { return BOOT_IMAGE_CODE_END; }
036      protected final Address getAvailableEndConstant() { return MAXIMUM_MAPPABLE; }
037      protected final byte getLogBytesInAddressConstant() { return SizeConstants.LOG_BYTES_IN_ADDRESS; }
038      protected final byte getLogBytesInWordConstant() { return SizeConstants.LOG_BYTES_IN_WORD; }
039      protected final byte getLogBytesInPageConstant() { return SizeConstants.LOG_BYTES_IN_PAGE; }
040      protected final byte getLogMinAlignmentConstant() { return JavaHeader.LOG_MIN_ALIGNMENT;}
041      protected final int getMaxBytesPaddingConstant() { return SizeConstants.BYTES_IN_DOUBLE; }
042      protected final int getAlignmentValueConstant() { return JavaHeader.ALIGNMENT_VALUE;}
043    
044      /* On Intel we align code to 16 bytes as recommended in the optimization manual */
045      protected final byte getMaxAlignmentShiftConstant() { return (VM.BuildForIA32 ? 1 : 0) + SizeConstants.LOG_BYTES_IN_LONG - SizeConstants.LOG_BYTES_IN_INT; }
046    
047      private static ImmortalSpace bootSpace;
048    
049      /* FIXME the following was established via trial and error :-( */
050      //  private static int BOOT_SEGMENT_MB = 4+(BOOT_IMAGE_SIZE.toInt()>>LOG_BYTES_IN_MBYTE);
051      private static int BOOT_SEGMENT_MB = (0x10000000>>LOG_BYTES_IN_MBYTE);
052    
053      /**
054       * Return the space associated with/reserved for the VM.  In the
055       * case of Jikes RVM this is the boot image space.<p>
056       *
057       * The boot image space must be mapped at the start of available
058       * virtual memory, hence we use the constructor that requests the
059       * lowest address in the address space.  The address space awarded
060       * to this space depends on the order in which the request is made.
061       * If this request is not the first request for virtual memory then
062       * the Space allocator will die with an error stating that the
063       * request could not be satisfied.  The remedy is to ensure it is
064       * initialized first.
065       *
066       * @return The space managed by the virtual machine.  In this case,
067       * the boot image space is returned.
068       */
069      @Interruptible
070      public final ImmortalSpace getVMSpace() {
071        if (bootSpace == null) {
072          bootSpace = new ImmortalSpace("boot", Plan.DEFAULT_POLL_FREQUENCY, VMRequest.create(BOOT_SEGMENT_MB));
073        }
074        return bootSpace;
075      }
076    
077      /** Global preparation for a collection. */
078      public final void globalPrepareVMSpace() { bootSpace.prepare(); }
079    
080      /** Per-collector preparation for a collection. */
081      public final void collectorPrepareVMSpace() {}
082    
083      /** Per-collector post-collection work. */
084      public final void collectorReleaseVMSpace() {}
085    
086      /** Global post-collection work. */
087      public final void globalReleaseVMSpace() { bootSpace.release(); }
088    
089      /**
090       * Sets the range of addresses associated with a heap.
091       *
092       * @param id the heap identifier
093       * @param start the address of the start of the heap
094       * @param end the address of the end of the heap
095       */
096      public final void setHeapRange(int id, Address start, Address end) {
097        BootRecord.the_boot_record.setHeapRange(id, start, end);
098      }
099    
100     /**
101       * Demand zero mmaps an area of virtual memory.
102       *
103       * @param start the address of the start of the area to be mapped
104       * @param size the size, in bytes, of the area to be mapped
105       * @return 0 if successful, otherwise the system errno
106       */
107      public final int dzmmap(Address start, int size) {
108        Address result = org.jikesrvm.runtime.Memory.dzmmap(start, Extent.fromIntZeroExtend(size));
109        if (result.EQ(start)) return 0;
110        if (result.GT(Address.fromIntZeroExtend(127))) {
111          VM.sysWrite("demand zero mmap with MAP_FIXED on ", start);
112          VM.sysWriteln(" returned some other address", result);
113          VM.sysFail("mmap with MAP_FIXED has unexpected behavior");
114        }
115        return result.toInt();
116      }
117    
118      /**
119       * Protects access to an area of virtual memory.
120       *
121       * @param start the address of the start of the area to be mapped
122       * @param size the size, in bytes, of the area to be mapped
123       * @return <code>true</code> if successful, otherwise
124       * <code>false</code>
125       */
126      public final boolean mprotect(Address start, int size) {
127        return org.jikesrvm.runtime.Memory.mprotect(start, Extent.fromIntZeroExtend(size),
128                                                       org.jikesrvm.runtime.Memory.PROT_NONE);
129      }
130    
131      /**
132       * Allows access to an area of virtual memory.
133       *
134       * @param start the address of the start of the area to be mapped
135       * @param size the size, in bytes, of the area to be mapped
136       * @return <code>true</code> if successful, otherwise
137       * <code>false</code>
138       */
139      public final boolean munprotect(Address start, int size) {
140        return org.jikesrvm.runtime.Memory.mprotect(start, Extent.fromIntZeroExtend(size),
141                                                       org.jikesrvm.runtime.Memory.PROT_READ |
142                                                       org.jikesrvm.runtime.Memory.PROT_WRITE |
143                                                       org.jikesrvm.runtime.Memory.PROT_EXEC);
144      }
145    
146      /**
147       * Zero a region of memory.
148       * @param start Start of address range (inclusive)
149       * @param len Length in bytes of range to zero
150       * Returned: nothing
151       */
152      public final void zero(Address start, Extent len) {
153        org.jikesrvm.runtime.Memory.zero(start,len);
154      }
155    
156      /**
157       * Zero a range of pages of memory.
158       * @param start Start of address range (must be a page address)
159       * @param len Length in bytes of range (must be multiple of page size)
160       */
161      public final void zeroPages(Address start, int len) {
162          /* AJG: Add assertions to check conditions documented above. */
163        org.jikesrvm.runtime.Memory.zeroPages(start,len);
164      }
165    
166      /**
167       * Logs the contents of an address and the surrounding memory to the
168       * error output.
169       *
170       * @param start the address of the memory to be dumped
171       * @param beforeBytes the number of bytes before the address to be
172       * included
173       * @param afterBytes the number of bytes after the address to be
174       * included
175       */
176      public final void dumpMemory(Address start, int beforeBytes,
177                                    int afterBytes) {
178        org.jikesrvm.runtime.Memory.dumpMemory(start,beforeBytes,afterBytes);
179      }
180    
181      /*
182       * Utilities from the VM class
183       */
184    
185      @Inline
186      public final void sync() {
187        Magic.sync();
188      }
189    
190      @Inline
191      public final void isync() {
192        Magic.isync();
193      }
194    }