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.concurrent; 014 015import static org.mmtk.utility.Constants.*; 016 017import org.mmtk.plan.*; 018 019import org.mmtk.vm.VM; 020 021import org.vmmagic.pragma.*; 022import org.vmmagic.unboxed.*; 023 024/** 025 * This class implements <i>per-mutator thread</i> behavior 026 * and state for a simple whole-heap concurrent collector. 027 * 028 * @see Concurrent 029 * @see ConcurrentCollector 030 * @see StopTheWorldMutator 031 * @see MutatorContext 032 */ 033@Uninterruptible 034public abstract class ConcurrentMutator extends SimpleMutator { 035 036 /**************************************************************************** 037 * Instance fields 038 */ 039 040 /** 041 * 042 */ 043 public static boolean newMutatorBarrierActive = false; 044 protected volatile boolean barrierActive = false; 045 046 protected ConcurrentMutator() { 047 barrierActive = newMutatorBarrierActive; 048 } 049 050 /**************************************************************************** 051 * 052 * Collection 053 */ 054 055 /** 056 * Perform a per-mutator collection phase. 057 */ 058 @Override 059 @Inline 060 public void collectionPhase(short phaseId, boolean primary) { 061 if (phaseId == Concurrent.SET_BARRIER_ACTIVE) { 062 barrierActive = true; 063 return; 064 } 065 066 if (phaseId == Concurrent.CLEAR_BARRIER_ACTIVE) { 067 barrierActive = false; 068 return; 069 } 070 071 if (phaseId == Concurrent.FLUSH_MUTATOR) { 072 flush(); 073 return; 074 } 075 076 super.collectionPhase(phaseId, primary); 077 } 078 079 /**************************************************************************** 080 * 081 * Write and read barriers. 082 */ 083 084 /** 085 * {@inheritDoc}<p> 086 * 087 * <b>In this case we employ a Yuasa style snapshot barrier.</b> 088 * 089 */ 090 @Inline 091 @Override 092 public void objectReferenceWrite(ObjectReference src, Address slot, ObjectReference tgt, Word metaDataA, Word metaDataB, int mode) { 093 if (barrierActive) checkAndEnqueueReference(slot.loadObjectReference()); 094 VM.barriers.objectReferenceWrite(src, tgt, metaDataA, metaDataB, mode); 095 } 096 097 @Inline 098 @Override 099 public boolean objectReferenceTryCompareAndSwap(ObjectReference src, Address slot, ObjectReference old, 100 ObjectReference tgt, Word metaDataA, Word metaDataB, int mode) { 101 boolean result = VM.barriers.objectReferenceTryCompareAndSwap(src, old, tgt, metaDataA, metaDataB, mode); 102 if (barrierActive) checkAndEnqueueReference(old); 103 return result; 104 } 105 106 /** 107 * {@inheritDoc} 108 * 109 * @param src The source of the values to be copied 110 * @param srcOffset The offset of the first source address, in 111 * bytes, relative to <code>src</code> (in principle, this could be 112 * negative). 113 * @param dst The mutated object, i.e. the destination of the copy. 114 * @param dstOffset The offset of the first destination address, in 115 * bytes relative to <code>tgt</code> (in principle, this could be 116 * negative). 117 * @param bytes The size of the region being copied, in bytes. 118 */ 119 @Inline 120 @Override 121 public boolean objectReferenceBulkCopy(ObjectReference src, Offset srcOffset, ObjectReference dst, Offset dstOffset, int bytes) { 122 Address cursor = dst.toAddress().plus(dstOffset); 123 Address limit = cursor.plus(bytes); 124 while (cursor.LT(limit)) { 125 ObjectReference ref = cursor.loadObjectReference(); 126 if (barrierActive) checkAndEnqueueReference(ref); 127 cursor = cursor.plus(BYTES_IN_ADDRESS); 128 } 129 return false; 130 } 131 132 @Inline 133 @Override 134 public ObjectReference javaLangReferenceReadBarrier(ObjectReference ref) { 135 if (barrierActive) checkAndEnqueueReference(ref); 136 return ref; 137 } 138 139 /** 140 * Process a reference that may require being enqueued as part of a concurrent 141 * collection. 142 * 143 * @param ref The reference to check. 144 */ 145 protected abstract void checkAndEnqueueReference(ObjectReference ref); 146}