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 */ 013package org.mmtk.plan.stickyimmix; 014 015import org.mmtk.plan.*; 016import org.mmtk.plan.immix.ImmixMutator; 017 018import org.mmtk.utility.HeaderByte; 019import org.mmtk.utility.deque.ObjectReferenceDeque; 020import org.mmtk.vm.VM; 021 022import org.vmmagic.pragma.*; 023import org.vmmagic.unboxed.*; 024 025/** 026 * This class implements <i>per-mutator thread</i> behavior 027 * and state for the <i>StickyImmix</i> plan, which implements a 028 * generational mark-sweep collector.<p> 029 * 030 * Specifically, this class defines <i>MS</i> mutator-time allocation 031 * and per-mutator thread collection semantics (flushing and restoring 032 * per-mutator allocator state).<p> 033 * * 034 * @see StickyImmix 035 * @see StickyImmixCollector 036 * @see MutatorContext 037 * @see Phase 038 */ 039@Uninterruptible 040public class StickyImmixMutator extends ImmixMutator { 041 042 /**************************************************************************** 043 * Instance fields 044 */ 045 046 /** 047 * 048 */ 049 private final ObjectReferenceDeque modBuffer; 050 051 /**************************************************************************** 052 * 053 * Initialization 054 */ 055 056 /** 057 * Constructor 058 */ 059 public StickyImmixMutator() { 060 super(); 061 modBuffer = new ObjectReferenceDeque("mod buf", global().modPool); 062 } 063 064 /**************************************************************************** 065 * 066 * Barriers 067 */ 068 069 /** 070 * {@inheritDoc}<p> 071 * 072 * In this case, we remember the address of the source of the 073 * pointer if the new reference points into the nursery from 074 * non-nursery space. 075 */ 076 @Override 077 @Inline 078 public final void objectReferenceWrite(ObjectReference src, Address slot, 079 ObjectReference tgt, Word metaDataA, Word metaDataB, int mode) { 080 if (HeaderByte.isUnlogged(src)) 081 logSource(src); 082 VM.barriers.objectReferenceWrite(src, tgt, metaDataA, metaDataB, mode); 083 } 084 085 /** 086 * {@inheritDoc}<p> 087 * 088 * In this case, we remember the mutated source address range and 089 * will scan that address range at GC time. 090 * 091 * @param src The source of the values to copied 092 * @param srcOffset The offset of the first source address, in 093 * bytes, relative to <code>src</code> (in principle, this could be 094 * negative). 095 * @param dst The mutated object, i.e. the destination of the copy. 096 * @param dstOffset The offset of the first destination address, in 097 * bytes relative to <code>tgt</code> (in principle, this could be 098 * negative). 099 * @param bytes The size of the region being copied, in bytes. 100 * @return True if the update was performed by the barrier, false if 101 * left to the caller (always false in this case). 102 */ 103 @Override 104 @Inline 105 public final boolean objectReferenceBulkCopy(ObjectReference src, Offset srcOffset, 106 ObjectReference dst, Offset dstOffset, int bytes) { 107 if (HeaderByte.isUnlogged(src)) 108 logSource(src); 109 return false; 110 } 111 112 @Override 113 @Inline 114 public boolean objectReferenceTryCompareAndSwap(ObjectReference src, Address slot, 115 ObjectReference old, ObjectReference tgt, Word metaDataA, 116 Word metaDataB, int mode) { 117 if (HeaderByte.isUnlogged(src)) 118 logSource(src); 119 return VM.barriers.objectReferenceTryCompareAndSwap(src,old,tgt,metaDataA,metaDataB,mode); 120 } 121 122 /** 123 * Add an object to the modified objects buffer and mark the 124 * object has having been logged. Since duplicate entries do 125 * not raise any correctness issues, we do <i>not</i> worry 126 * about synchronization and allow threads to race to log the 127 * object, potentially including it twice (unlike reference 128 * counting where duplicates would lead to incorrect reference 129 * counts). 130 * 131 * @param src The object to be logged 132 */ 133 private void logSource(ObjectReference src) { 134 HeaderByte.markAsLogged(src); 135 modBuffer.push(src); 136 } 137 138 @Override 139 public final void flushRememberedSets() { 140 modBuffer.flushLocal(); 141 assertRemsetFlushed(); 142 } 143 144 public final void assertRemsetFlushed() { 145 if (VM.VERIFY_ASSERTIONS) { 146 VM.assertions._assert(modBuffer.isFlushed()); 147 } 148 } 149 150 151 /**************************************************************************** 152 * 153 * Collection 154 */ 155 156 /** 157 * {@inheritDoc} 158 */ 159 @Override 160 @Inline 161 public final void collectionPhase(short phaseId, boolean primary) { 162 if (phaseId == StickyImmix.PREPARE) { 163 flushRememberedSets(); 164 } 165 if (phaseId == StickyImmix.RELEASE) { 166 assertRemsetFlushed(); 167 } 168 169 if (!global().collectWholeHeap) { 170 if (phaseId == StickyImmix.PREPARE) { 171 immix.prepare(); 172 return; 173 } 174 175 if (phaseId == StickyImmix.RELEASE) { 176 immix.release(); 177 return; 178 } 179 } 180 181 super.collectionPhase(phaseId, primary); 182 } 183 184 /**************************************************************************** 185 * 186 * Miscellaneous 187 */ 188 189 /** @return The active global plan as an <code>MSGen</code> instance. */ 190 @Inline 191 private static StickyImmix global() { 192 return (StickyImmix) VM.activePlan.global(); 193 } 194}