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