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.jikesrvm.mm.mminterface; 014 015import static org.jikesrvm.objectmodel.JavaHeaderConstants.ALIGNMENT_VALUE; 016import static org.jikesrvm.runtime.UnboxedSizeConstants.LOG_BYTES_IN_ADDRESS; 017 018import org.jikesrvm.VM; 019import org.jikesrvm.objectmodel.JavaHeader; 020import org.jikesrvm.objectmodel.ObjectModel; 021import org.jikesrvm.runtime.Magic; 022import org.vmmagic.pragma.Inline; 023import org.vmmagic.pragma.Uninterruptible; 024import org.vmmagic.unboxed.Address; 025import org.vmmagic.unboxed.ObjectReference; 026import org.vmmagic.unboxed.Word; 027 028/** 029 * Support for encoding a small amount of metadata in the alignment of 030 * a TIB. We choose the alignment of the TIB so that the pointer 031 * looks like 032 * <pre> 033 * 31 24 16 8 0 034 * +-------+-------+-------+-------+ 035 * xxxxxxxxxxxxxxxxxxxxxxxxxxxxfff00 036 * </pre> 037 * where the natural alignment of the object is preserved (the low-order bits 038 * are zero), and the next least significant <i>n</i> bits contain the 039 * encoded metadata. 040 * <p> 041 * With the cooperation of MemoryManager, the idea is that we allocate 2^n 042 * additional words of memory, then offset the object within the allocated 043 * region so that the value of <i>fff</i> is encoded. 044 * <p> 045 * The current implementation specifically encodes the TIB pointer, because this 046 * is the only pointer field where this technique can give a speedup that 047 * makes it worthwhile. 048 */ 049public class AlignmentEncoding { 050 051 public static final int ALIGN_CODE_NONE = -1; 052 053 /** Bits of metadata that we encode */ 054 static final int FIELD_WIDTH = 3; 055 056 /** Maximum distance (in words) that we shift an object */ 057 private static final int MAX_ALIGN_WORDS = 1 << FIELD_WIDTH; 058 059 /** First bit of the encoded field */ 060 private static final int FIELD_SHIFT = LOG_BYTES_IN_ADDRESS; 061 062 /** How far do we need to shift the object to increment the encoded field by 1 */ 063 private static final int ALIGNMENT_INCREMENT = 1 << FIELD_SHIFT; 064 065 /** Bit-mask to select out the encoded field */ 066 private static final int TIB_ALIGN_MASK = (MAX_ALIGN_WORDS - 1) << FIELD_SHIFT; 067 068 private static final boolean VERBOSE = false; 069 070 /** 071 * Assert that a prospective encoded value is sane 072 * @param alignCode Prospective encoded value 073 */ 074 static void assertSanity(int alignCode) { 075 if (VM.VerifyAssertions) { 076 VM._assert(alignCode == ALIGN_CODE_NONE || (alignCode >= 0 && alignCode < MAX_ALIGN_WORDS)); 077 } 078 } 079 080 /** 081 * Number of padding bytes required. 082 * @param alignCode Prospective encoded value. 083 * @return the number of padding bytes required 084 */ 085 public static int padding(int alignCode) { 086 if (alignCode == ALIGN_CODE_NONE) 087 return 0; 088 return (MAX_ALIGN_WORDS << FIELD_SHIFT); 089 } 090 091 /** 092 * Adjust a region address so that the object pointer of an object that starts at this address 093 * will be aligned so as to encode the specified value. 094 * 095 * @param alignCode Value to encode 096 * @param region The initial region 097 * @return the aligned address 098 */ 099 public static Address adjustRegion(int alignCode, Address region) { 100 assertSanity(alignCode); 101 if (alignCode == ALIGN_CODE_NONE) 102 return region; 103 // Now fake the region address to encode our data 104 final Address limit = region.plus(padding(alignCode)); 105 if (VERBOSE) { 106 VM.sysWrite("Allocating TIB: region = ",region," tib code = ",getTibCodeForRegion(region)); 107 VM.sysWriteln(", requested = ",alignCode); 108 } 109 while (getTibCodeForRegion(region) != alignCode) { 110 if (VM.runningVM) { 111 // Hack to allow alignment, but no alignment filling during boot 112 region.store(Word.fromIntZeroExtend(ALIGNMENT_VALUE)); 113 } 114 region = region.plus(ALIGNMENT_INCREMENT); 115 if (region.GT(limit)) { 116 VM.sysFail("Tib alignment fail"); 117 } 118 } 119 if (VERBOSE) { 120 VM.sysWrite(" TIB: region = ",region," tib code = ",getTibCodeForRegion(region)); 121 VM.sysWriteln(", requested = ",alignCode); 122 } 123 return region; 124 } 125 126 127 private static int getTibCodeForRegion(Address region) { 128 return extractTibCode(region.plus(JavaHeader.OBJECT_REF_OFFSET)); 129 } 130 131 /** 132 * Extract the encoded value from a TIB pointer, 133 * represented as a raw address. 134 * @param address the TIB's address 135 * @return the encoded value from a TIB pointer 136 */ 137 @Uninterruptible 138 @Inline 139 public static int extractTibCode(Address address) { 140 return (address.toInt() & TIB_ALIGN_MASK) >> FIELD_SHIFT; 141 } 142 143 /** 144 * Extract the encoded value from an object's TIB pointer 145 * @param object the object 146 * @return the encoded value from a TIB pointer 147 */ 148 @Uninterruptible 149 @Inline 150 public static int getTibCode(ObjectReference object) { 151 int tibCode = extractTibCode(Magic.objectAsAddress(ObjectModel.getTIB(object))); 152 return tibCode; 153 } 154 155}