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.heap;
014
015 import org.mmtk.policy.Space;
016 import org.mmtk.utility.Constants;
017
018 import org.mmtk.vm.VM;
019
020 import org.vmmagic.pragma.*;
021 import org.vmmagic.unboxed.*;
022
023 /**
024 * This class manages the encoding and decoding of space descriptors.<p>
025 *
026 * Space descriptors are integers that encode a space's mapping into
027 * virtual memory. For discontiguous spaces, they indicate
028 * discontiguity and mapping must be done by consulting the space map.
029 * For contiguous spaces, the space's address range is encoded into
030 * the integer (using a fixed point notation).<p>
031 *
032 * The purpose of this class is to allow <code>static final int</code>
033 * space descriptors to exist for each space, which can then be used
034 * in tests to determine whether an object is in a space. A good
035 * compiler can perform this decoding at compile time and produce
036 * optimal code for the test.
037 */
038 @Uninterruptible public class SpaceDescriptor implements Constants {
039
040 /****************************************************************************
041 *
042 * Class variables
043 */
044
045 /**
046 *
047 */
048 private static final int TYPE_BITS = 2;
049 private static final int TYPE_SHARED = 0;
050 private static final int TYPE_CONTIGUOUS = 1;
051 private static final int TYPE_CONTIGUOUS_HI = 3;
052 private static final int TYPE_MASK = (1 << TYPE_BITS) - 1;
053 private static final int SIZE_SHIFT = TYPE_BITS;
054 private static final int SIZE_BITS = 10;
055 private static final int SIZE_MASK = ((1 << SIZE_BITS) - 1) << SIZE_SHIFT;
056 private static final int EXPONENT_SHIFT = SIZE_SHIFT + SIZE_BITS;
057 private static final int EXPONENT_BITS = 5;
058 private static final int EXPONENT_MASK = ((1 << EXPONENT_BITS) - 1) << EXPONENT_SHIFT;
059 private static final int MANTISSA_SHIFT = EXPONENT_SHIFT + EXPONENT_BITS;
060 private static final int MANTISSA_BITS = 14;
061 private static final int BASE_EXPONENT = BITS_IN_INT - MANTISSA_BITS;
062
063 private static int discontiguousSpaceIndex = 0;
064 private static final int DISCONTIG_INDEX_INCREMENT = 1<<TYPE_BITS;
065
066 /****************************************************************************
067 *
068 * Descriptor creation
069 */
070
071 /**
072 * Create a descriptor for a <i>contiguous</i> space
073 *
074 * @param start The start address of the space
075 * @param end The end address of the space
076 * @return An integer descriptor encoding the region of virtual
077 * memory occupied by the space
078 */
079 public static int createDescriptor(Address start, Address end) {
080 int chunks = end.diff(start).toWord().rshl(Space.LOG_BYTES_IN_CHUNK).toInt();
081 if (VM.VERIFY_ASSERTIONS)
082 VM.assertions._assert(!start.isZero() && chunks > 0 && chunks < (1 << SIZE_BITS));
083 boolean top = end.EQ(Space.HEAP_END);
084 Word tmp = start.toWord();
085 tmp = tmp.rshl(BASE_EXPONENT);
086 int exponent = 0;
087 while (!tmp.isZero() && tmp.and(Word.one()).isZero()) {
088 tmp = tmp.rshl(1);
089 exponent++;
090 }
091 int mantissa = tmp.toInt();
092 if (VM.VERIFY_ASSERTIONS)
093 VM.assertions._assert(tmp.lsh(BASE_EXPONENT + exponent).EQ(start.toWord()));
094 return (mantissa<<MANTISSA_SHIFT) |
095 (exponent<<EXPONENT_SHIFT) |
096 (chunks << SIZE_SHIFT) |
097 ((top) ? TYPE_CONTIGUOUS_HI : TYPE_CONTIGUOUS);
098 }
099
100 /**
101 * Create a descriptor for a <i>dis-contiguous</i> (shared) space
102 *
103 * @return An integer descriptor reflecting the fact that this space
104 * is shared (and thus discontiguous and so must be established via
105 * maps).
106 */
107 public static int createDescriptor() {
108 discontiguousSpaceIndex += DISCONTIG_INDEX_INCREMENT;
109 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((discontiguousSpaceIndex & TYPE_CONTIGUOUS) != TYPE_CONTIGUOUS);
110 return discontiguousSpaceIndex;
111 }
112
113 /****************************************************************************
114 *
115 * Descriptor interrogation
116 */
117
118 /**
119 * Return true if this descriptor describes a contiguous space
120 *
121 * @param descriptor
122 * @return {@code true} if this descriptor describes a contiguous space
123 */
124 @Inline
125 public static boolean isContiguous(int descriptor) {
126 return ((descriptor & TYPE_CONTIGUOUS) == TYPE_CONTIGUOUS);
127 }
128
129 /**
130 * Return true if this descriptor describes a contiguous space that
131 * is at the top of the virtual address space
132 *
133 * @param descriptor
134 * @return {@code true} if this descriptor describes a contiguous space that
135 * is at the top of the virtual address space
136 */
137 @Inline
138 public static boolean isContiguousHi(int descriptor) {
139 return ((descriptor & TYPE_MASK) == TYPE_CONTIGUOUS_HI);
140 }
141
142 /**
143 * Return the start of this region of memory encoded in this descriptor
144 *
145 * @param descriptor
146 * @return The start of this region of memory encoded in this descriptor
147 */
148 @Inline
149 public static Address getStart(int descriptor) {
150 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isContiguous(descriptor));
151 Word mantissa = Word.fromIntSignExtend(descriptor >>> MANTISSA_SHIFT);
152 int exponent = (descriptor & EXPONENT_MASK) >>> EXPONENT_SHIFT;
153 return mantissa.lsh(BASE_EXPONENT + exponent).toAddress();
154 }
155
156 /**
157 * Return the size of the region of memory encoded in this
158 * descriptor, in chunks
159 *
160 * @param descriptor
161 * @return The size of the region of memory encoded in this
162 * descriptor, in chunks
163 */
164 @Inline
165 public static int getChunks(int descriptor) {
166 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isContiguous(descriptor));
167 return (descriptor & SIZE_MASK) >>> SIZE_SHIFT;
168 }
169 }