/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/eclipse-1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.jikesrvm.mm.mminterface; import static org.jikesrvm.objectmodel.JavaHeaderConstants.ALIGNMENT_VALUE; import static org.jikesrvm.runtime.UnboxedSizeConstants.LOG_BYTES_IN_ADDRESS; import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_INT; import org.jikesrvm.VM; import org.jikesrvm.objectmodel.JavaHeader; import org.jikesrvm.objectmodel.ObjectModel; import org.jikesrvm.runtime.Magic; import org.vmmagic.pragma.Inline; import org.vmmagic.pragma.Uninterruptible; import org.vmmagic.unboxed.Address; import org.vmmagic.unboxed.ObjectReference; /** * Support for encoding a small amount of metadata in the alignment of * a TIB. We choose the alignment of the TIB so that the pointer * looks like * <pre> * 31 24 16 8 0 * +-------+-------+-------+-------+ * xxxxxxxxxxxxxxxxxxxxxxxxxxxxfff00 * </pre> * where the natural alignment of the object is preserved (the low-order bits * are zero), and the next least significant <i>n</i> bits contain the * encoded metadata. * <p> * With the cooperation of MemoryManager, the idea is that we allocate 2^n * additional words of memory, then offset the object within the allocated * region so that the value of <i>fff</i> is encoded. * <p> * The current implementation specifically encodes the TIB pointer, because this * is the only pointer field where this technique can give a speedup that * makes it worthwhile. */ public class AlignmentEncoding { public static final int ALIGN_CODE_NONE = -1; /** Bits of metadata that we encode */ static final int FIELD_WIDTH = 3; /** Maximum distance (in words) that we shift an object */ private static final int MAX_ALIGN_WORDS = 1 << FIELD_WIDTH; /** First bit of the encoded field */ private static final int FIELD_SHIFT = LOG_BYTES_IN_ADDRESS; /** How far do we need to shift the object to increment the encoded field by 1 */ private static final int ALIGNMENT_INCREMENT = 1 << FIELD_SHIFT; /** Bit-mask to select out the encoded field */ private static final int TIB_ALIGN_MASK = (MAX_ALIGN_WORDS - 1) << FIELD_SHIFT; private static final boolean VERBOSE = false; /** * Assert that a prospective encoded value is sane * @param alignCode Prospective encoded value */ static void assertSanity(int alignCode) { if (VM.VerifyAssertions) { VM._assert(alignCode == ALIGN_CODE_NONE || (alignCode >= 0 && alignCode < MAX_ALIGN_WORDS)); } } /** * Number of padding bytes required. * @param alignCode Prospective encoded value. * @return the number of padding bytes required */ public static int padding(int alignCode) { if (alignCode == ALIGN_CODE_NONE) return 0; return (MAX_ALIGN_WORDS << FIELD_SHIFT); } /** * Adjust a region address so that the object pointer of an object that starts at this address * will be aligned so as to encode the specified value. * * @param alignCode Value to encode * @param region The initial region * @return the aligned address */ public static Address adjustRegion(int alignCode, Address region) { assertSanity(alignCode); if (alignCode == ALIGN_CODE_NONE) return region; // Now fake the region address to encode our data final Address limit = region.plus(padding(alignCode)); if (VERBOSE) { VM.sysWrite("Allocating TIB: region = ",region," tib code = ",getTibCodeForRegion(region)); VM.sysWriteln(", requested = ",alignCode); } while (getTibCodeForRegion(region) != alignCode) { Address next = region.plus(ALIGNMENT_INCREMENT); // Hack to allow alignment, but no alignment filling during boot while (region.LT(next)) { if (VM.runningVM) { region.store(ALIGNMENT_VALUE); } region = region.plus(BYTES_IN_INT); } if (region.GT(limit)) { VM.sysFail("Tib alignment fail"); } } if (VERBOSE) { VM.sysWrite(" TIB: region = ",region," tib code = ",getTibCodeForRegion(region)); VM.sysWriteln(", requested = ",alignCode); } return region; } private static int getTibCodeForRegion(Address region) { return extractTibCode(region.plus(JavaHeader.OBJECT_REF_OFFSET)); } /** * Extract the encoded value from a TIB pointer, * represented as a raw address. * @param address the TIB's address * @return the encoded value from a TIB pointer */ @Uninterruptible @Inline public static int extractTibCode(Address address) { return (address.toInt() & TIB_ALIGN_MASK) >> FIELD_SHIFT; } /** * Extract the encoded value from an object's TIB pointer * @param object the object * @return the encoded value from a TIB pointer */ @Uninterruptible @Inline public static int getTibCode(ObjectReference object) { int tibCode = extractTibCode(Magic.objectAsAddress(ObjectModel.getTIB(object))); return tibCode; } }