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 }