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.runtime;
014    
015    import static org.jikesrvm.SizeConstants.BYTES_IN_ADDRESS;
016    import static org.jikesrvm.SizeConstants.BYTES_IN_INT;
017    import static org.jikesrvm.SizeConstants.LOG_BYTES_IN_DOUBLE;
018    import static org.jikesrvm.SizeConstants.LOG_BYTES_IN_INT;
019    import static org.jikesrvm.SizeConstants.LOG_BYTES_IN_SHORT;
020    
021    import org.jikesrvm.VM;
022    import org.vmmagic.pragma.Inline;
023    import org.vmmagic.pragma.Uninterruptible;
024    import org.vmmagic.unboxed.Address;
025    import org.vmmagic.unboxed.Extent;
026    import org.vmmagic.unboxed.Offset;
027    import org.vmmagic.unboxed.Word;
028    
029    /**
030     * Low level memory management functions.
031     *
032     * Note that this class is "uninterruptible" - calling its methods will never
033     * cause the current thread to yield the cpu to another thread (one that
034     * might cause a gc, for example).
035     */
036    @Uninterruptible
037    public class Memory {
038    
039      ////////////////////////
040      // (1) Utilities for copying/filling/zeroing memory
041      ////////////////////////
042    
043      /**
044       * How many bytes is considered large enough to justify the transition to
045       * C code to use memcpy?
046       */
047      private static final int NATIVE_THRESHOLD = 512;
048    
049      /**
050       * Allow the use of C based memcpy
051       */
052      private static final boolean USE_NATIVE = true;
053    
054      /**
055       * Number of bytes used when copying larger chunks of memory. Normally 8 bytes
056       * except on x87 Intel
057       */
058      private static final int BYTES_IN_COPY = VM.BuildForIA32 && !VM.BuildForSSE2 ? 4 : 8;
059    
060      @Inline
061      private static void copy8Bytes(Address dstPtr, Address srcPtr) {
062        if (BYTES_IN_COPY == 8) {
063          if (VM.BuildForIA32) {
064            dstPtr.store(srcPtr.loadLong());
065          } else {
066            dstPtr.store(srcPtr.loadDouble());
067          }
068        } else {
069          copy4Bytes(dstPtr, srcPtr);
070          copy4Bytes(dstPtr.plus(4), srcPtr.plus(4));
071        }
072      }
073      @Inline
074      private static void copy4Bytes(Address dstPtr, Address srcPtr) {
075        dstPtr.store(srcPtr.loadInt());
076      }
077      @Inline
078      private static void copy2Bytes(Address dstPtr, Address srcPtr) {
079        dstPtr.store(srcPtr.loadChar());
080      }
081      @Inline
082      private static void copy1Bytes(Address dstPtr, Address srcPtr) {
083        dstPtr.store(srcPtr.loadByte());
084      }
085      /**
086       * Low level copy of len elements from src[srcPos] to dst[dstPos].
087       *
088       * Assumptions: <code> src != dst || (scrPos >= dstPos + 4) </code>
089       *              and src and dst are 8Bit arrays.
090       * @param src     the source array
091       * @param srcPos  index in the source array to begin copy
092       * @param dst     the destination array
093       * @param dstPos  index in the destination array to being copy
094       * @param len     number of array elements to copy
095       */
096      public static void arraycopy8Bit(Object src, int srcPos, Object dst, int dstPos, int len) {
097        Address srcPtr = Magic.objectAsAddress(src).plus(srcPos);
098        Address dstPtr = Magic.objectAsAddress(dst).plus(dstPos);
099        arraycopy8Bit(srcPtr, dstPtr, len);
100      }
101    
102      /**
103       * Low level copy of <code>copyBytes</code> bytes from <code>src[srcPos]</code> to <code>dst[dstPos]</code>.
104       *
105       * Assumption <code>src != dst || (srcPos >= dstPos)</code> and element size is 4 bytes.
106       *
107       * @param srcPtr The source start address
108       * @param dstPtr The destination start address
109       * @param copyBytes The number of bytes to be copied
110       */
111      public static void arraycopy8Bit(Address srcPtr, Address dstPtr , int copyBytes) {
112        if (USE_NATIVE && copyBytes > NATIVE_THRESHOLD) {
113          memcopy(dstPtr, srcPtr, copyBytes);
114        } else {
115          if (copyBytes >= BYTES_IN_COPY &&
116              (srcPtr.toWord().and(Word.fromIntZeroExtend(BYTES_IN_COPY - 1)) ==
117              (dstPtr.toWord().and(Word.fromIntZeroExtend(BYTES_IN_COPY - 1))))) {
118            // relative alignment is the same
119            Address endPtr = srcPtr.plus(copyBytes);
120            Address wordEndPtr = endPtr.toWord().and(Word.fromIntZeroExtend(BYTES_IN_COPY-1).not()).toAddress();
121    
122            if (BYTES_IN_COPY == 8) {
123              if (srcPtr.toWord().and(Word.fromIntZeroExtend(1)).NE(Word.zero())) {
124                copy1Bytes(dstPtr, srcPtr);
125                srcPtr = srcPtr.plus(1);
126                dstPtr = dstPtr.plus(1);
127              }
128              if (srcPtr.toWord().and(Word.fromIntZeroExtend(2)).NE(Word.zero())) {
129                copy2Bytes(dstPtr, srcPtr);
130                srcPtr = srcPtr.plus(2);
131                dstPtr = dstPtr.plus(2);
132              }
133              if (srcPtr.toWord().and(Word.fromIntZeroExtend(4)).NE(Word.zero())) {
134                copy4Bytes(dstPtr, srcPtr);
135                srcPtr = srcPtr.plus(4);
136                dstPtr = dstPtr.plus(4);
137              }
138            } else {
139              if (srcPtr.toWord().and(Word.fromIntZeroExtend(1)).NE(Word.zero())) {
140                copy1Bytes(dstPtr, srcPtr);
141                srcPtr = srcPtr.plus(1);
142                dstPtr = dstPtr.plus(1);
143              }
144              if (srcPtr.toWord().and(Word.fromIntZeroExtend(2)).NE(Word.zero())) {
145                copy2Bytes(dstPtr, srcPtr);
146                srcPtr = srcPtr.plus(2);
147                dstPtr = dstPtr.plus(2);
148              }
149            }
150            while (srcPtr.LT(wordEndPtr)) {
151              if (BYTES_IN_COPY == 8) {
152                copy8Bytes(dstPtr, srcPtr);
153              } else {
154                copy4Bytes(dstPtr, srcPtr);
155              }
156              srcPtr = srcPtr.plus(BYTES_IN_COPY);
157              dstPtr = dstPtr.plus(BYTES_IN_COPY);
158            }
159            // if(VM.VerifyAssertions) VM._assert(wordEndPtr.EQ(srcPtr));
160            if (BYTES_IN_COPY == 8) {
161              if (endPtr.toWord().and(Word.fromIntZeroExtend(4)).NE(Word.zero())) {
162                copy4Bytes(dstPtr, srcPtr);
163                srcPtr = srcPtr.plus(4);
164                dstPtr = dstPtr.plus(4);
165              }
166              if (endPtr.toWord().and(Word.fromIntZeroExtend(2)).NE(Word.zero())) {
167                copy2Bytes(dstPtr, srcPtr);
168                srcPtr = srcPtr.plus(2);
169                dstPtr = dstPtr.plus(2);
170              }
171              if (endPtr.toWord().and(Word.fromIntZeroExtend(1)).NE(Word.zero())) {
172                copy1Bytes(dstPtr, srcPtr);
173              }
174            } else {
175              if (endPtr.toWord().and(Word.fromIntZeroExtend(2)).NE(Word.zero())) {
176                copy2Bytes(dstPtr, srcPtr);
177                srcPtr = srcPtr.plus(2);
178                dstPtr = dstPtr.plus(2);
179              }
180              if (endPtr.toWord().and(Word.fromIntZeroExtend(1)).NE(Word.zero())) {
181                copy1Bytes(dstPtr, srcPtr);
182              }
183            }
184          } else {
185            Address endPtr = srcPtr.plus(copyBytes);
186            while (srcPtr.LT(endPtr)) {
187              dstPtr.store(srcPtr.loadByte());
188              srcPtr = srcPtr.plus(1);
189              dstPtr = dstPtr.plus(1);
190            }
191          }
192        }
193      }
194    
195      /**
196       * Low level copy of len elements from src[srcPos] to dst[dstPos].
197       *
198       * Assumption src != dst || (srcPos >= dstPos + 2).
199       *
200       * @param src     the source array
201       * @param srcPos  index in the source array to begin copy
202       * @param dst     the destination array
203       * @param dstPos  index in the destination array to being copy
204       * @param len     number of array elements to copy
205       */
206      public static void arraycopy16Bit(Object src, int srcPos, Object dst, int dstPos, int len) {
207        Address srcPtr = Magic.objectAsAddress(src).plus(srcPos << LOG_BYTES_IN_SHORT);
208        Address dstPtr = Magic.objectAsAddress(dst).plus(dstPos << LOG_BYTES_IN_SHORT);
209        int copyBytes = len << LOG_BYTES_IN_SHORT;
210        arraycopy16Bit(srcPtr, dstPtr, copyBytes);
211      }
212      /**
213       * Low level copy of <code>copyBytes</code> bytes from <code>src[srcPos]</code> to <code>dst[dstPos]</code>.
214       *
215       * Assumption <code>src != dst || (srcPos >= dstPos)</code> and element size is 2 bytes.
216       *
217       * @param srcPtr The source start address
218       * @param dstPtr The destination start address
219       * @param copyBytes The number of bytes to be copied
220       */
221      public static void arraycopy16Bit(Address srcPtr, Address dstPtr , int copyBytes) {
222        if (USE_NATIVE && copyBytes > NATIVE_THRESHOLD) {
223          memcopy(dstPtr, srcPtr, copyBytes);
224        } else {
225          if (copyBytes >= BYTES_IN_COPY &&
226              (srcPtr.toWord().and(Word.fromIntZeroExtend(BYTES_IN_COPY - 1)) ==
227              (dstPtr.toWord().and(Word.fromIntZeroExtend(BYTES_IN_COPY - 1))))) {
228            // relative alignment is the same
229            Address endPtr = srcPtr.plus(copyBytes);
230            Address wordEndPtr = endPtr.toWord().and(Word.fromIntZeroExtend(BYTES_IN_COPY-1).not()).toAddress();
231    
232            if (BYTES_IN_COPY == 8) {
233              if (srcPtr.toWord().and(Word.fromIntZeroExtend(2)).NE(Word.zero())) {
234                copy2Bytes(dstPtr, srcPtr);
235                srcPtr = srcPtr.plus(2);
236                dstPtr = dstPtr.plus(2);
237              }
238              if (srcPtr.toWord().and(Word.fromIntZeroExtend(4)).NE(Word.zero())) {
239                copy4Bytes(dstPtr, srcPtr);
240                srcPtr = srcPtr.plus(4);
241                dstPtr = dstPtr.plus(4);
242              }
243            } else {
244              if (srcPtr.toWord().and(Word.fromIntZeroExtend(2)).NE(Word.zero())) {
245                copy2Bytes(dstPtr, srcPtr);
246                srcPtr = srcPtr.plus(2);
247                dstPtr = dstPtr.plus(2);
248              }
249            }
250            while (srcPtr.LT(wordEndPtr)) {
251              if (BYTES_IN_COPY == 8) {
252                copy8Bytes(dstPtr, srcPtr);
253              } else {
254                copy4Bytes(dstPtr, srcPtr);
255              }
256              srcPtr = srcPtr.plus(BYTES_IN_COPY);
257              dstPtr = dstPtr.plus(BYTES_IN_COPY);
258            }
259            // if(VM.VerifyAssertions) VM._assert(wordEndPtr.EQ(srcPtr));
260            if (BYTES_IN_COPY == 8) {
261              if (endPtr.toWord().and(Word.fromIntZeroExtend(4)).NE(Word.zero())) {
262                copy4Bytes(dstPtr, srcPtr);
263                srcPtr = srcPtr.plus(4);
264                dstPtr = dstPtr.plus(4);
265              }
266              if (endPtr.toWord().and(Word.fromIntZeroExtend(2)).NE(Word.zero())) {
267                copy2Bytes(dstPtr, srcPtr);
268              }
269            } else {
270              if (endPtr.toWord().and(Word.fromIntZeroExtend(2)).NE(Word.zero())) {
271                copy2Bytes(dstPtr, srcPtr);
272              }
273            }
274          } else {
275            Address endPtr = srcPtr.plus(copyBytes);
276            while (srcPtr.LT(endPtr)) {
277              copy2Bytes(dstPtr, srcPtr);
278              srcPtr = srcPtr.plus(2);
279              dstPtr = dstPtr.plus(2);
280            }
281          }
282        }
283      }
284    
285      /**
286       * Low level copy of <code>len</code> elements from <code>src[srcPos]</code> to <code>dst[dstPos]</code>.
287       *
288       * Assumption: <code>src != dst || (srcPos >= dstPos)</code> and element size is 4 bytes.
289       *
290       * @param src     the source array
291       * @param srcIdx  index in the source array to begin copy
292       * @param dst     the destination array
293       * @param dstIdx  index in the destination array to being copy
294       * @param len     number of array elements to copy
295       */
296      public static void arraycopy32Bit(Object src, int srcIdx, Object dst, int dstIdx, int len) {
297        Address srcPtr = Magic.objectAsAddress(src).plus(srcIdx << LOG_BYTES_IN_INT);
298        Address dstPtr = Magic.objectAsAddress(dst).plus(dstIdx << LOG_BYTES_IN_INT);
299        int copyBytes = len << LOG_BYTES_IN_INT;
300        arraycopy32Bit(srcPtr, dstPtr, copyBytes);
301      }
302    
303      /**
304       * Low level copy of <code>copyBytes</code> bytes from <code>src[srcPos]</code> to <code>dst[dstPos]</code>.
305       *
306       * Assumption <code>src != dst || (srcPos >= dstPos)</code> and element size is 4 bytes.
307       *
308       * @param srcPtr The source start address
309       * @param dstPtr The destination start address
310       * @param copyBytes The number of bytes to be copied
311       */
312      public static void arraycopy32Bit(Address srcPtr, Address dstPtr , int copyBytes) {
313        if (USE_NATIVE && copyBytes > NATIVE_THRESHOLD) {
314          memcopy(dstPtr, srcPtr, copyBytes);
315        } else {
316          // The elements of int[] and float[] are always 32 bit aligned
317          // therefore we can do 32 bit load/stores without worrying about alignment.
318          // TODO: optimize to use 64bit copies. Suspected problem in _202_jess with overlapping arrays
319          //aligned32Copy(dstPtr, srcPtr, Offset.fromIntSignExtend(len << LOG_BYTES_IN_INT));
320          Address endPtr = srcPtr.plus(copyBytes);
321          while (srcPtr.LT(endPtr)) {
322            dstPtr.store(srcPtr.loadInt());
323            srcPtr = srcPtr.plus(4);
324            dstPtr = dstPtr.plus(4);
325          }
326        }
327      }
328      /**
329       * Low level copy of <code>len</code> elements from <code>src[srcPos]</code> to <code>dst[dstPos]</code>.
330       *
331       * Assumption <code>src != dst || (srcPos >= dstPos)</code> and element size is 8 bytes.
332       *
333       * @param src     the source array
334       * @param srcIdx  index in the source array to begin copy
335       * @param dst     the destination array
336       * @param dstIdx  index in the destination array to being copy
337       * @param len     number of array elements to copy
338       */
339      public static void arraycopy64Bit(Object src, int srcIdx, Object dst, int dstIdx, int len) {
340        Offset srcOffset = Offset.fromIntZeroExtend(srcIdx << LOG_BYTES_IN_DOUBLE);
341        Offset dstOffset = Offset.fromIntZeroExtend(dstIdx << LOG_BYTES_IN_DOUBLE);
342        int copyBytes = len << LOG_BYTES_IN_DOUBLE;
343        arraycopy64Bit(Magic.objectAsAddress(src).plus(srcOffset), Magic.objectAsAddress(dst).plus(dstOffset), copyBytes);
344      }
345    
346      /**
347       * Low level copy of <code>copyBytes</code> bytes from <code>src[srcPos]</code> to <code>dst[dstPos]</code>.
348       *
349       * Assumption <code>src != dst || (srcPos >= dstPos)</code> and element size is 8 bytes.
350       *
351       * @param srcPtr The source start address
352       * @param dstPtr The destination start address
353       * @param copyBytes The number of bytes to be copied
354       */
355      public static void arraycopy64Bit(Address srcPtr, Address dstPtr , int copyBytes) {
356        if (USE_NATIVE && copyBytes > NATIVE_THRESHOLD) {
357          memcopy(dstPtr, srcPtr, copyBytes);
358        } else {
359          // The elements of long[] and double[] are always doubleword aligned
360          // therefore we can do 64 bit load/stores without worrying about alignment.
361          Address endPtr = srcPtr.plus(copyBytes);
362          while (srcPtr.LT(endPtr)) {
363            copy8Bytes(dstPtr, srcPtr);
364            srcPtr = srcPtr.plus(8);
365            dstPtr = dstPtr.plus(8);
366          }
367        }
368      }
369    
370    
371      /**
372       * Copy numbytes from src to dst.
373       * Assumption either the ranges are non overlapping, or src >= dst + 4.
374       * Also, src and dst are 4 byte aligned and numBytes is a multiple of 4.
375       * @param dst the destination addr
376       * @param src the source addr
377       * @param numBytes the number of bytes top copy
378       */
379      public static void aligned32Copy(Address dst, Address src, Offset numBytes) {
380        if (USE_NATIVE && numBytes.sGT(Offset.fromIntSignExtend(NATIVE_THRESHOLD))) {
381          memcopy(dst, src, numBytes.toWord().toExtent());
382        } else {
383          if (BYTES_IN_COPY == 8) {
384            Word wordMask = Word.fromIntZeroExtend(BYTES_IN_COPY-1);
385            Word srcAlignment = src.toWord().and(wordMask);
386            if (srcAlignment.EQ(dst.toWord().and(wordMask))) {
387              Offset i = Offset.zero();
388              if (srcAlignment.EQ(Word.fromIntZeroExtend(BYTES_IN_INT))) {
389                copy4Bytes(dst.plus(i), src.plus(i));
390                i = i.plus(BYTES_IN_INT);
391              }
392              Word endAlignment = srcAlignment.plus(numBytes).and(wordMask);
393              numBytes = numBytes.minus(endAlignment.toOffset());
394              for (; i.sLT(numBytes); i = i.plus(BYTES_IN_COPY)) {
395                copy8Bytes(dst.plus(i), src.plus(i));
396              }
397              if (!endAlignment.isZero()) {
398                copy4Bytes(dst.plus(i), src.plus(i));
399              }
400              return;
401            }
402          }
403          //normal case: 32 bit or (64 bit not aligned)
404          for (Offset i = Offset.zero(); i.sLT(numBytes); i = i.plus(BYTES_IN_INT)) {
405            copy4Bytes(dst.plus(i), src.plus(i));
406          }
407        }
408      }
409    
410      public static void aligned32Copy(Address dst, Address src, int numBytes) {
411        aligned32Copy(dst, src, Offset.fromIntSignExtend(numBytes));
412      }
413    
414      /**
415       * Copy numbytes from src to dst.
416       * Assumption either the ranges are non overlapping, or src >= dst + BYTES_IN_ADDRESS.
417       * Also, src and dst are word aligned and numBytes is a multiple of BYTES_IN_ADDRESS.
418       * @param dst the destination addr
419       * @param src the source addr
420       * @param numBytes the number of bytes top copy
421       */
422      public static void alignedWordCopy(Address dst, Address src, int numBytes) {
423        if (USE_NATIVE && numBytes > NATIVE_THRESHOLD) {
424          memcopy(dst, src, numBytes);
425        } else {
426          internalAlignedWordCopy(dst, src, numBytes);
427        }
428      }
429    
430      /**
431       * Copy <code>numbytes</code> from <code>src</code> to <code>dst</code>.
432       * Assumption either the ranges are non overlapping, or <code>src >= dst + BYTES_IN_ADDRESS</code>.
433       * @param dst     The destination addr
434       * @param src     The source addr
435       * @param numBytes The number of bytes to copy
436       */
437      private static void internalAlignedWordCopy(Address dst, Address src, int numBytes) {
438        Address end = src.plus(numBytes);
439        while (src.LT(end)) {
440          dst.store(src.loadWord());
441          src = src.plus(BYTES_IN_ADDRESS);
442          dst = dst.plus(BYTES_IN_ADDRESS);
443        }
444      }
445    
446      /**
447       * Copy a region of memory.
448       * @param dst   Destination address
449       * @param src   Source address
450       * @param cnt   Number of bytes to copy
451       * Assumption: source and destination regions do not overlap
452       */
453      public static void memcopy(Address dst, Address src, Extent cnt) {
454        SysCall.sysCall.sysCopy(dst, src, cnt);
455      }
456    
457      public static void memcopy(Address dst, Address src, int cnt) {
458        SysCall.sysCall.sysCopy(dst, src, Extent.fromIntSignExtend(cnt));
459      }
460    
461      /**
462       * Zero a region of memory.
463       * @param start of address range (inclusive)
464       * @param len extent to zero.
465       */
466      public static void zero(Address start, Extent len) {
467        SysCall.sysCall.sysZero(start, len);
468      }
469    
470      /**
471       * Zero a range of pages of memory.
472       * @param start Starting address       (must be a page address)
473       * @param len   Number of bytes     (must be multiple of page size)
474       */
475      public static void zeroPages(Address start, int len) {
476        if (VM.VerifyAssertions) VM._assert(isPageAligned(start) && isPageMultiple(len));
477        SysCall.sysCall.sysZeroPages(start, len);
478      }
479    
480      ////////////////////////
481      // (2) Cache management
482      ////////////////////////
483    
484      /**
485       * Synchronize a region of memory: force data in dcache to be written out to main
486       * memory so that it will be seen by icache when instructions are fetched back.
487       * @param address  Start of address range
488       * @param size     Size of address range (bytes)
489       */
490      public static void sync(Address address, int size) {
491        SysCall.sysCall.sysSyncCache(address, size);
492      }
493    
494      ////////////////////////
495      // (3) MMap
496      ////////////////////////
497    
498      // constants for protection and mapping calls
499      public static final int PROT_NONE = 0;
500      public static final int PROT_READ = 1;
501      public static final int PROT_WRITE = 2;
502      public static final int PROT_EXEC = 4;
503    
504      public static final int MAP_PRIVATE = 2;
505      public static final int MAP_FIXED     = (VM.BuildForLinux) ? 16 : (VM.BuildForOsx) ?     16 : (VM.BuildForSolaris) ? 0x10 :256;
506      public static final int MAP_ANONYMOUS = (VM.BuildForLinux) ? 32 : (VM.BuildForOsx) ? 0x1000 : (VM.BuildForSolaris) ? 0x100 : 16;
507    
508      public static boolean isPageMultiple(int val) {
509        int pagesizeMask = getPagesize() - 1;
510        return ((val & pagesizeMask) == 0);
511      }
512    
513      public static boolean isPageMultiple(Extent val) {
514        Word pagesizeMask = Word.fromIntZeroExtend(getPagesize() - 1);
515        return val.toWord().and(pagesizeMask).isZero();
516      }
517    
518      public static boolean isPageMultiple(Offset val) {
519        Word pagesizeMask = Word.fromIntZeroExtend(getPagesize() - 1);
520        return val.toWord().and(pagesizeMask).isZero();
521      }
522    
523      public static boolean isPageAligned(Address addr) {
524        Word pagesizeMask = Word.fromIntZeroExtend(getPagesize() - 1);
525        return addr.toWord().and(pagesizeMask).isZero();
526      }
527    
528      /**
529       * Do generic mmap non-file memory mapping call
530       * @param address  Start of address range (Address)
531       * @param size    Size of address range
532       * @param prot    Protection (int)
533       * @param flags (int)
534       * @return Address (of region) if successful; errno (1 to 127) otherwise
535       */
536      public static Address mmap(Address address, Extent size, int prot, int flags) {
537        if (VM.VerifyAssertions) {
538          VM._assert(isPageAligned(address) && isPageMultiple(size));
539        }
540        return SysCall.sysCall.sysMMapErrno(address, size, prot, flags, -1, Offset.zero());
541      }
542    
543      /**
544       * Do mmap demand zero fixed address memory mapping call
545       * @param address  Start of address range
546       * @param size     Size of address range
547       * @return Address (of region) if successful; errno (1 to 127) otherwise
548       */
549      public static Address dzmmap(Address address, Extent size) {
550        if (VM.VerifyAssertions) {
551          VM._assert(isPageAligned(address) && isPageMultiple(size));
552        }
553        int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
554        int flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED;
555        return mmap(address, size, prot, flags);
556      }
557    
558      /**
559       * Do mprotect system call
560       * @param address Start of address range (Address)
561       * @param size Size of address range
562       * @param prot Protection (int)
563       * @return true iff success
564       */
565      public static boolean mprotect(Address address, Extent size, int prot) {
566        if (VM.VerifyAssertions) {
567          VM._assert(isPageAligned(address) && isPageMultiple(size));
568        }
569        return SysCall.sysCall.sysMProtect(address, size, prot) == 0;
570      }
571    
572      private static int pagesize = -1;
573      private static int pagesizeLog = -1;
574    
575      /**
576       * Do getpagesize call
577       * @return page size
578       */
579      public static int getPagesize() {
580        if (pagesize == -1) {
581          pagesize = SysCall.sysCall.sysGetPageSize();
582          pagesizeLog = -1;
583          int temp = pagesize;
584          while (temp > 0) {
585            temp >>>= 1;
586            pagesizeLog++;
587          }
588          if (VM.VerifyAssertions) VM._assert((1 << pagesizeLog) == pagesize);
589        }
590        return pagesize;
591      }
592    
593      public static void dumpMemory(Address start, int beforeBytes, int afterBytes) {
594    
595        beforeBytes = alignDown(beforeBytes, BYTES_IN_ADDRESS);
596        afterBytes = alignUp(afterBytes, BYTES_IN_ADDRESS);
597        VM.sysWrite("---- Dumping memory from ");
598        VM.sysWrite(start.minus(beforeBytes));
599        VM.sysWrite(" to ");
600        VM.sysWrite(start.plus(afterBytes));
601        VM.sysWrite(" ----\n");
602        for (int i = -beforeBytes; i < afterBytes; i += BYTES_IN_ADDRESS) {
603          VM.sysWrite(i, ": ");
604          VM.sysWrite(start.plus(i));
605          Word value = start.plus(i).loadWord();
606          VM.sysWriteln("  ", value);
607        }
608      }
609    
610      @Inline
611      public static Address alignUp(Address address, int alignment) {
612        return address.plus(alignment - 1).toWord().and(Word.fromIntSignExtend(~(alignment - 1))).toAddress();
613      }
614    
615      @Inline
616      public static Address alignDown(Address address, int alignment) {
617        return address.toWord().and(Word.fromIntSignExtend(~(alignment - 1))).toAddress();
618      }
619    
620      // These versions are here to accommodate the boot image writer
621      @Inline
622      public static int alignUp(int address, int alignment) {
623        return ((address + alignment - 1) & ~(alignment - 1));
624      }
625    
626      @Inline
627      public static int alignDown(int address, int alignment) {
628        return (address & ~(alignment - 1));
629      }
630    }