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.policy.immix; 014 015 import static org.mmtk.policy.immix.ImmixConstants.*; 016 017 import org.mmtk.utility.Constants; 018 import org.mmtk.vm.VM; 019 020 import org.vmmagic.pragma.Inline; 021 import org.vmmagic.pragma.Uninterruptible; 022 import org.vmmagic.unboxed.Address; 023 import org.vmmagic.unboxed.ObjectReference; 024 import org.vmmagic.unboxed.Offset; 025 026 @Uninterruptible 027 public class Line implements Constants { 028 029 public static Address align(Address ptr) { 030 return ptr.toWord().and(LINE_MASK.not()).toAddress(); 031 } 032 033 public static boolean isAligned(Address address) { 034 return address.EQ(align(address)); 035 } 036 037 static int getChunkIndex(Address line) { 038 return line.toWord().and(CHUNK_MASK).rshl(LOG_BYTES_IN_LINE).toInt(); 039 } 040 041 /*************************************************************************** 042 * Line marking 043 */ 044 045 /** 046 * 047 */ 048 static void mark(Address address, final byte markValue) { 049 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!Block.isUnused(Block.align(address))); 050 getMarkAddress(address).store(markValue); 051 } 052 053 static void markMultiLine(Address start, ObjectReference object, final byte markValue) { 054 /* endLine is the address of the last (highest) line touched by this object */ 055 Address endLine = Line.align(VM.objectModel.getObjectEndAddress(object).minus(1)); 056 Address line = Line.align(start.plus(BYTES_IN_LINE)); 057 while (line.LT(endLine)) { 058 if (VM.VERIFY_ASSERTIONS) 059 VM.assertions._assert(Block.align(start).EQ(Block.align(line))); 060 mark(line, markValue); 061 line = line.plus(BYTES_IN_LINE); 062 } 063 } 064 065 /*************************************************************************** 066 * Scanning through avail lines 067 */ 068 069 /** 070 * 071 */ 072 public static Address getChunkMarkTable(Address chunk) { 073 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Chunk.isAligned(chunk)); 074 return getMarkAddress(chunk); 075 } 076 077 public static Address getBlockMarkTable(Address block) { 078 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Block.isAligned(block)); 079 return getMarkAddress(block); 080 } 081 082 @Inline 083 public static int getNextUnavailable(Address baseLineAvailAddress, int line, final byte unavailableState) { 084 while (line < LINES_IN_BLOCK && 085 baseLineAvailAddress.loadByte(Offset.fromIntZeroExtend(line<<Line.LOG_BYTES_IN_LINE_STATUS)) < unavailableState) 086 line++; 087 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(line >= 0 && line <= LINES_IN_BLOCK); 088 return line; 089 } 090 091 @Inline 092 public static int getNextAvailable(Address baseLineAvailAddress, int line, final byte unavailableState) { 093 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(line >= 0 && line < LINES_IN_BLOCK); 094 byte last = baseLineAvailAddress.loadByte(Offset.fromIntZeroExtend(line<<Line.LOG_BYTES_IN_LINE_STATUS)); 095 byte thisline; 096 line++; 097 while (line < LINES_IN_BLOCK) { 098 thisline = baseLineAvailAddress.loadByte(Offset.fromIntZeroExtend(line<<Line.LOG_BYTES_IN_LINE_STATUS)); 099 if (thisline < unavailableState && last < unavailableState) 100 break; 101 last = thisline; 102 line++; 103 } 104 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(line >= 0 && line <= LINES_IN_BLOCK); 105 return line; 106 } 107 108 private static Address getMetaAddress(Address address, final int tableOffset) { 109 Address chunk = Chunk.align(address); 110 int index = getChunkIndex(address); 111 Address rtn = chunk.plus(tableOffset + (index<<LOG_BYTES_IN_LINE_STATUS)); 112 if (VM.VERIFY_ASSERTIONS) { 113 Address line = chunk.plus(index<<LOG_BYTES_IN_LINE); 114 VM.assertions._assert(isAligned(line)); 115 VM.assertions._assert(align(address).EQ(line)); 116 boolean valid = rtn.GE(chunk.plus(tableOffset)) && rtn.LT(chunk.plus(tableOffset + LINE_MARK_TABLE_BYTES)); 117 VM.assertions._assert(valid); 118 } 119 return rtn; 120 } 121 122 private static Address getMarkAddress(Address address) { 123 return getMetaAddress(address, Chunk.LINE_MARK_TABLE_OFFSET); 124 } 125 126 /* per-line mark bytes */ 127 128 static final int LOG_BYTES_IN_LINE_STATUS = 0; 129 static final int BYTES_IN_LINE_STATUS = 1<<LOG_BYTES_IN_LINE_STATUS; 130 131 static final int LINE_MARK_TABLE_BYTES = LINES_IN_CHUNK<<LOG_BYTES_IN_LINE_STATUS; 132 static final int LOG_LINE_MARK_BYTES_PER_BLOCK = LOG_LINES_IN_BLOCK+LOG_BYTES_IN_LINE_STATUS; 133 static final int LINE_MARK_BYTES_PER_BLOCK = (1<<LOG_LINE_MARK_BYTES_PER_BLOCK); 134 }