blob: 984bc60a8a13a64d2582c0ae9facd1835d72d23e [file] [log] [blame]
/*
* 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.mmtk.policy.immix;
import static org.mmtk.policy.immix.ImmixConstants.*;
import org.mmtk.utility.Constants;
import org.mmtk.vm.VM;
import org.vmmagic.pragma.Inline;
import org.vmmagic.pragma.Uninterruptible;
import org.vmmagic.unboxed.Address;
import org.vmmagic.unboxed.ObjectReference;
import org.vmmagic.unboxed.Offset;
@Uninterruptible
public class Line implements Constants {
public static Address align(Address ptr) {
return ptr.toWord().and(LINE_MASK.not()).toAddress();
}
public static boolean isAligned(Address address) {
return address.EQ(align(address));
}
static int getChunkIndex(Address line) {
return line.toWord().and(CHUNK_MASK).rshl(LOG_BYTES_IN_LINE).toInt();
}
/***************************************************************************
* Line marking
*/
static void mark(Address address, final byte markValue) {
if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!Block.isUnused(Block.align(address)));
getMarkAddress(address).store(markValue);
}
static void markMultiLine(Address start, ObjectReference object, final byte markValue) {
/* endLine is the address of the last (highest) line touched by this object */
Address endLine = Line.align(VM.objectModel.getObjectEndAddress(object).minus(1));
Address line = Line.align(start.plus(BYTES_IN_LINE));
while (line.LT(endLine)) {
if (VM.VERIFY_ASSERTIONS)
VM.assertions._assert(Block.align(start).EQ(Block.align(line)));
mark(line, markValue);
line = line.plus(BYTES_IN_LINE);
}
}
/***************************************************************************
* Scanning through avail lines
*/
public static Address getChunkMarkTable(Address chunk) {
if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Chunk.isAligned(chunk));
return getMarkAddress(chunk);
}
public static Address getBlockMarkTable(Address block) {
if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Block.isAligned(block));
return getMarkAddress(block);
}
@Inline
public static int getNextUnavailable(Address baseLineAvailAddress, int line, final byte unavailableState) {
while (line < LINES_IN_BLOCK &&
baseLineAvailAddress.loadByte(Offset.fromIntZeroExtend(line<<Line.LOG_BYTES_IN_LINE_STATUS)) < unavailableState)
line++;
if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(line >= 0 && line <= LINES_IN_BLOCK);
return line;
}
@Inline
public static int getNextAvailable(Address baseLineAvailAddress, int line, final byte unavailableState) {
if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(line >= 0 && line < LINES_IN_BLOCK);
byte last = baseLineAvailAddress.loadByte(Offset.fromIntZeroExtend(line<<Line.LOG_BYTES_IN_LINE_STATUS));
byte thisline;
line++;
while (line < LINES_IN_BLOCK) {
thisline = baseLineAvailAddress.loadByte(Offset.fromIntZeroExtend(line<<Line.LOG_BYTES_IN_LINE_STATUS));
if (thisline < unavailableState && last < unavailableState)
break;
last = thisline;
line++;
}
if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(line >= 0 && line <= LINES_IN_BLOCK);
return line;
}
private static Address getMetaAddress(Address address, final int tableOffset) {
Address chunk = Chunk.align(address);
int index = getChunkIndex(address);
Address rtn = chunk.plus(tableOffset + (index<<LOG_BYTES_IN_LINE_STATUS));
if (VM.VERIFY_ASSERTIONS) {
Address line = chunk.plus(index<<LOG_BYTES_IN_LINE);
VM.assertions._assert(isAligned(line));
VM.assertions._assert(align(address).EQ(line));
boolean valid = rtn.GE(chunk.plus(tableOffset)) && rtn.LT(chunk.plus(tableOffset + LINE_MARK_TABLE_BYTES));
VM.assertions._assert(valid);
}
return rtn;
}
private static Address getMarkAddress(Address address) {
return getMetaAddress(address, Chunk.LINE_MARK_TABLE_OFFSET);
}
/* per-line mark bytes */
static final int LOG_BYTES_IN_LINE_STATUS = 0;
static final int BYTES_IN_LINE_STATUS = 1<<LOG_BYTES_IN_LINE_STATUS;
static final int LINE_MARK_TABLE_BYTES = LINES_IN_CHUNK<<LOG_BYTES_IN_LINE_STATUS;
static final int LOG_LINE_MARK_BYTES_PER_BLOCK = LOG_LINES_IN_BLOCK+LOG_BYTES_IN_LINE_STATUS;
static final int LINE_MARK_BYTES_PER_BLOCK = (1<<LOG_LINE_MARK_BYTES_PER_BLOCK);
}