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