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 }