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