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.mmtk.utility;
014    
015    import org.mmtk.utility.heap.*;
016    
017    import org.mmtk.vm.VM;
018    
019    import org.vmmagic.unboxed.*;
020    import org.vmmagic.pragma.*;
021    
022    /*
023     import org.jikesrvm.Offset;
024     * Conversions between different units.
025     */
026    @Uninterruptible public class Conversions implements Constants {
027    
028      // public static Address roundDownVM(Address addr) {
029      //   return roundDown(addr.toWord(), VMResource.LOG_BYTES_IN_REGION).toAddress();
030      // }
031    
032      // public static Extent roundDownVM(Extent bytes) {
033      //   return roundDown(bytes.toWord(), VMResource.LOG_BYTES_IN_REGION).toExtent();
034      // }
035    
036      public static Address roundDownMB(Address addr) {
037        return roundDown(addr.toWord(), LOG_BYTES_IN_MBYTE).toAddress();
038      }
039    
040      public static Extent roundDownMB(Extent bytes) {
041        return roundDown(bytes.toWord(), LOG_BYTES_IN_MBYTE).toExtent();
042      }
043    
044      private static Word roundDown(Word value, int logBase) {
045        Word mask = Word.one().lsh(logBase).minus(Word.one()).not();
046        return value.and(mask);
047      }
048    
049      public static int roundDown(int value, int alignment) {
050        return value & ~(alignment - 1);
051      }
052    
053      // Round up (if necessary)
054      //
055      public static int MBToPages(int megs) {
056        if (LOG_BYTES_IN_PAGE <= LOG_BYTES_IN_MBYTE)
057          return (megs << (LOG_BYTES_IN_MBYTE - LOG_BYTES_IN_PAGE));
058        else
059          return (megs + ((BYTES_IN_PAGE >>> LOG_BYTES_IN_MBYTE) - 1)) >>> (LOG_BYTES_IN_PAGE - LOG_BYTES_IN_MBYTE);
060      }
061    
062      public static int bytesToMmapChunksUp(Extent bytes) {
063        return bytes.plus(Mmapper.MMAP_CHUNK_BYTES - 1).toWord().rshl(Mmapper.LOG_MMAP_CHUNK_BYTES).toInt();
064      }
065    
066      public static int pagesToMmapChunksUp(int pages) {
067        return bytesToMmapChunksUp(pagesToBytes(pages));
068      }
069    
070      public static int addressToMmapChunksDown(Address addr) {
071        Word chunk = addr.toWord().rshl(Mmapper.LOG_MMAP_CHUNK_BYTES);
072        return chunk.toInt();
073      }
074    
075      public static int addressToPagesDown(Address addr) {
076        Word chunk = addr.toWord().rshl(LOG_BYTES_IN_PAGE);
077        return chunk.toInt();
078      }
079    
080      public static int addressToPages(Address addr) {
081        int page = addressToPagesDown(addr);
082        if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(pagesToAddress(page).EQ(addr));
083        return page;
084      }
085    
086      public static Address pagesToAddress(int pages) {
087        return Word.fromIntZeroExtend(pages).lsh(LOG_BYTES_IN_PAGE).toAddress();
088      }
089    
090      public static int addressToMmapChunksUp(Address addr) {
091        Word chunk = addr.plus(Mmapper.MMAP_CHUNK_BYTES - 1).toWord().rshl(Mmapper.LOG_MMAP_CHUNK_BYTES);
092        return chunk.toInt();
093      }
094    
095      public static Extent pagesToBytes(int pages) {
096        return Word.fromIntZeroExtend(pages).lsh(LOG_BYTES_IN_PAGE).toExtent();
097      }
098    
099      public static int pagesToMBytes(int pages) {
100        return pages >> (LOG_BYTES_IN_MBYTE - LOG_BYTES_IN_PAGE);
101      }
102    
103      public static int pagesToKBytes(int pages) {
104        return pages << (LOG_BYTES_IN_PAGE - LOG_BYTES_IN_KBYTE);
105      }
106    
107      /**
108        @deprecated : use int bytesToPagesUp(Extent bytes) if possible
109       */
110      @Deprecated
111      public static int bytesToPagesUp(int bytes) {
112        return bytesToPagesUp(Extent.fromIntZeroExtend(bytes));
113      }
114    
115      /**
116        @deprecated : use int bytesToPagesUp(Extent bytes) if possible
117       */
118      @Deprecated
119      public static int bytesToPages(int bytes) {
120        return bytesToPages(Extent.fromIntZeroExtend(bytes));
121      }
122    
123      public static int bytesToPagesUp(Extent bytes) {
124        return bytes.plus(BYTES_IN_PAGE-1).toWord().rshl(LOG_BYTES_IN_PAGE).toInt();
125      }
126    
127      public static int bytesToPages(Extent bytes) {
128        int pages = bytesToPagesUp(bytes);
129        if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(pagesToAddress(pages).toWord().toExtent().EQ(bytes));
130        return pages;
131      }
132    
133      public static int bytesToPages(Offset bytes) {
134        if (VM.VERIFY_ASSERTIONS) {
135          long val = bytes.toLong();
136          VM.assertions._assert(val >= MIN_INT && val <= MAX_INT);
137        }
138        if (bytes.sGE(Offset.zero()))
139          return bytesToPagesUp(Extent.fromIntSignExtend(bytes.toInt()));
140        else
141          return -bytesToPagesUp(Extent.fromIntSignExtend(-bytes.toInt()));
142      }
143    
144      public static Address mmapChunksToAddress(int chunk) {
145        return Word.fromIntZeroExtend(chunk).lsh(Mmapper.LOG_MMAP_CHUNK_BYTES).toAddress();
146      }
147    
148      public static Address pageAlign(Address address) {
149        return address.toWord().rshl(LOG_BYTES_IN_PAGE).lsh(LOG_BYTES_IN_PAGE).toAddress();
150      }
151    
152      public static int pageAlign(int value) {
153        return (value>>LOG_BYTES_IN_PAGE)<<LOG_BYTES_IN_PAGE;
154      }
155    
156      public static boolean isPageAligned(Address address) {
157        return pageAlign(address).EQ(address);
158      }
159    
160      public static boolean isPageAligned(int value) {
161        return pageAlign(value) == value;
162      }
163    }