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.plan.semispace.gctrace;
014
015 import org.mmtk.plan.semispace.SSMutator;
016 import org.mmtk.plan.*;
017 import org.mmtk.utility.TraceGenerator;
018 import org.mmtk.vm.VM;
019
020 import org.vmmagic.unboxed.*;
021 import org.vmmagic.pragma.*;
022
023 /**
024 * This class implements <i>per-mutator thread</i> behavior and state for the
025 * <i>GCTrace</i> plan, which implements a GC tracing algorithm.<p>
026 *
027 * Specifically, this class defines <i>SS</i> mutator-time allocation, write
028 * barriers, and per-mutator collection semantics.<p>
029 *
030 * See {@link GCTrace} for an overview of the GC trace algorithm.<p>
031 *
032 * @see SSMutator
033 * @see GCTrace
034 * @see GCTraceCollector
035 * @see org.mmtk.plan.StopTheWorldMutator
036 * @see org.mmtk.plan.MutatorContext
037 */
038 @Uninterruptible public class GCTraceMutator extends SSMutator {
039
040 /****************************************************************************
041 *
042 * Mutator-time allocation
043 */
044
045 /**
046 * Perform post-allocation actions. For many allocators none are
047 * required.
048 *
049 * @param object The newly allocated object
050 * @param typeRef the type reference for the instance being created
051 * @param bytes The size of the space to be allocated (in bytes)
052 * @param allocator The allocator number to be used for this allocation
053 */
054 @Inline
055 public final void postAlloc(ObjectReference object, ObjectReference typeRef,
056 int bytes, int allocator) {
057 /* Make the trace generator aware of the new object. */
058 TraceGenerator.addTraceObject(object, allocator);
059
060 super.postAlloc(object, typeRef, bytes, allocator);
061
062 /* Now have the trace process aware of the new allocation. */
063 GCTrace.traceInducedGC = TraceGenerator.MERLIN_ANALYSIS;
064 TraceGenerator.traceAlloc(allocator == GCTrace.ALLOC_IMMORTAL, object, typeRef, bytes);
065 GCTrace.traceInducedGC = false;
066 }
067
068
069 /****************************************************************************
070 *
071 * Write barrier.
072 */
073
074 /**
075 * A new reference is about to be created. Take appropriate write
076 * barrier actions.<p>
077 *
078 * In this case, we remember the address of the source of the
079 * pointer if the new reference points into the nursery from
080 * non-nursery space.
081 *
082 * @param src The object into which the new reference will be stored
083 * @param slot The address into which the new reference will be
084 * stored.
085 * @param tgt The target of the new reference
086 * @param metaDataA A value that assists the host VM in creating a store
087 * @param metaDataB A value that assists the host VM in creating a store
088 * being modified
089 * @param mode The mode of the store (eg putfield, putstatic etc)
090 */
091 @Inline
092 public final void objectReferenceWrite(ObjectReference src, Address slot,
093 ObjectReference tgt, Word metaDataA,
094 Word metaDataB, int mode) {
095 TraceGenerator.processPointerUpdate(mode == INSTANCE_FIELD,
096 src, slot, tgt);
097 VM.barriers.objectReferenceWrite(src, tgt, metaDataA, metaDataB, mode);
098 }
099
100 /**
101 * Attempt to atomically exchange the value in the given slot
102 * with the passed replacement value. If a new reference is
103 * created, we must then take appropriate write barrier actions.<p>
104 *
105 * <b>By default do nothing, override if appropriate.</b>
106 *
107 * @param src The object into which the new reference will be stored
108 * @param slot The address into which the new reference will be
109 * stored.
110 * @param old The old reference to be swapped out
111 * @param tgt The target of the new reference
112 * @param metaDataA A value that assists the host VM in creating a store
113 * @param metaDataB A value that assists the host VM in creating a store
114 * @param mode The context in which the store occured
115 * @return True if the swap was successful.
116 */
117 @Inline
118 public boolean objectReferenceTryCompareAndSwap(ObjectReference src, Address slot,
119 ObjectReference old, ObjectReference tgt, Word metaDataA,
120 Word metaDataB, int mode) {
121 boolean result = VM.barriers.objectReferenceTryCompareAndSwap(src, old, tgt, metaDataA, metaDataB, mode);
122 if (result) {
123 TraceGenerator.processPointerUpdate(mode == INSTANCE_FIELD, src, slot, tgt);
124 }
125 return result;
126 }
127
128 /**
129 * A number of references are about to be copied from object
130 * <code>src</code> to object <code>dst</code> (as in an array
131 * copy). Thus, <code>dst</code> is the mutated object. Take
132 * appropriate write barrier actions.<p>
133 *
134 * @param src The source of the values to be copied
135 * @param srcOffset The offset of the first source address, in
136 * bytes, relative to <code>src</code> (in principle, this could be
137 * negative).
138 * @param dst The mutated object, i.e. the destination of the copy.
139 * @param dstOffset The offset of the first destination address, in
140 * bytes relative to <code>tgt</code> (in principle, this could be
141 * negative).
142 * @param bytes The size of the region being copied, in bytes.
143 * @return True if the update was performed by the barrier, false if
144 * left to the caller (always false in this case).
145 */
146 public boolean objectReferenceBulkCopy(ObjectReference src, Offset srcOffset,
147 ObjectReference dst, Offset dstOffset, int bytes) {
148 /* These names seem backwards, but are defined to be compatable with the
149 * previous writeBarrier method. */
150 Address slot = dst.toAddress().plus(dstOffset);
151 Address tgtLoc = src.toAddress().plus(srcOffset);
152 for (int i = 0; i < bytes; i += BYTES_IN_ADDRESS) {
153 ObjectReference tgt = tgtLoc.loadObjectReference();
154 TraceGenerator.processPointerUpdate(false, dst, slot, tgt);
155 slot = slot.plus(BYTES_IN_ADDRESS);
156 tgtLoc = tgtLoc.plus(BYTES_IN_ADDRESS);
157 }
158 return false;
159 }
160
161 /****************************************************************************
162 *
163 * Collection
164 */
165
166 /**
167 * Perform a per-mutator collection phase.
168 *
169 * @param phaseId The collection phase to perform
170 * @param primary perform any single-threaded local activities.
171 */
172 public void collectionPhase(short phaseId, boolean primary) {
173 if (!GCTrace.traceInducedGC ||
174 (phaseId != StopTheWorld.PREPARE) &&
175 (phaseId != StopTheWorld.RELEASE)) {
176 // Delegate up.
177 super.collectionPhase(phaseId, primary);
178 }
179 }
180 }