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.concurrent.marksweep;
014
015 import org.mmtk.plan.*;
016 import org.mmtk.plan.concurrent.ConcurrentMutator;
017 import org.mmtk.policy.MarkSweepLocal;
018 import org.mmtk.policy.Space;
019
020 import org.mmtk.utility.alloc.Allocator;
021 import org.mmtk.vm.VM;
022
023 import org.vmmagic.pragma.*;
024 import org.vmmagic.unboxed.*;
025
026 /**
027 * This class implements <i>per-mutator thread</i> behavior
028 * and state for the <i>CMS</i> plan, which implements a full-heap
029 * concurrent mark-sweep collector.<p>
030 *
031 * FIXME The SegregatedFreeList class (and its descendants such as
032 * MarkSweepLocal) does not properly separate mutator and collector
033 * behaviors, so the ms field below should really not exist in
034 * this class as there is no collection-time allocation in this
035 * collector.
036 *
037 * @see CMS
038 * @see CMSCollector
039 * @see StopTheWorldMutator
040 * @see MutatorContext
041 */
042 @Uninterruptible
043 public class CMSMutator extends ConcurrentMutator {
044
045 /****************************************************************************
046 * Instance fields
047 */
048
049 /**
050 *
051 */
052 private MarkSweepLocal ms;
053 private TraceWriteBuffer remset;
054
055 /****************************************************************************
056 *
057 * Initialization
058 */
059
060 /**
061 * Constructor
062 */
063 public CMSMutator() {
064 ms = new MarkSweepLocal(CMS.msSpace);
065 remset = new TraceWriteBuffer(global().msTrace);
066 }
067
068 /****************************************************************************
069 *
070 * Mutator-time allocation
071 */
072
073 /**
074 * {@inheritDoc}<p>
075 *
076 * This class handles the default allocator from the mark sweep space, and
077 * delegates everything else to the superclass.
078 */
079 @Inline
080 @Override
081 public Address alloc(int bytes, int align, int offset, int allocator, int site) {
082 if (allocator == CMS.ALLOC_DEFAULT) {
083 return ms.alloc(bytes, align, offset);
084 }
085 return super.alloc(bytes, align, offset, allocator, site);
086 }
087
088 /**
089 * {@inheritDoc}<p>
090 *
091 * Initialize the object header for objects in the mark-sweep space,
092 * and delegate to the superclass for other objects.
093 */
094 @NoInline
095 @Override
096 public void postAlloc(ObjectReference ref, ObjectReference typeRef,
097 int bytes, int allocator) {
098 switch (allocator) {
099 case CMS.ALLOC_DEFAULT: CMS.msSpace.initializeHeader(ref, true); break;
100 default:
101 super.postAlloc(ref, typeRef, bytes, allocator);
102 break;
103 }
104 }
105
106 @Override
107 public Allocator getAllocatorFromSpace(Space space) {
108 if (space == CMS.msSpace) return ms;
109 return super.getAllocatorFromSpace(space);
110 }
111
112 /****************************************************************************
113 *
114 * Collection
115 */
116
117 /**
118 * {@inheritDoc}
119 */
120 @Override
121 @Inline
122 public void collectionPhase(short phaseId, boolean primary) {
123 if (phaseId == CMS.PREPARE) {
124 super.collectionPhase(phaseId, primary);
125 ms.prepare();
126 return;
127 }
128
129 if (phaseId == CMS.RELEASE) {
130 ms.release();
131 super.collectionPhase(phaseId, primary);
132 return;
133 }
134
135 super.collectionPhase(phaseId, primary);
136 }
137
138 @Override
139 public void flushRememberedSets() {
140 remset.flush();
141 ms.flush();
142 }
143
144 /****************************************************************************
145 *
146 * Write and read barriers.
147 */
148
149 /**
150 * {@inheritDoc}
151 */
152 @Override
153 protected void checkAndEnqueueReference(ObjectReference ref) {
154 if (ref.isNull()) return;
155 if (barrierActive) {
156 if (!ref.isNull()) {
157 if (Space.isInSpace(CMS.MARK_SWEEP, ref)) CMS.msSpace.traceObject(remset, ref);
158 else if (Space.isInSpace(CMS.IMMORTAL, ref)) CMS.immortalSpace.traceObject(remset, ref);
159 else if (Space.isInSpace(CMS.LOS, ref)) CMS.loSpace.traceObject(remset, ref);
160 else if (Space.isInSpace(CMS.NON_MOVING, ref)) CMS.nonMovingSpace.traceObject(remset, ref);
161 else if (Space.isInSpace(CMS.SMALL_CODE, ref)) CMS.smallCodeSpace.traceObject(remset, ref);
162 else if (Space.isInSpace(CMS.LARGE_CODE, ref)) CMS.largeCodeSpace.traceObject(remset, ref);
163 }
164 }
165
166 if (VM.VERIFY_ASSERTIONS) {
167 if (!ref.isNull() && !Plan.gcInProgress()) {
168 if (Space.isInSpace(CMS.MARK_SWEEP, ref)) VM.assertions._assert(CMS.msSpace.isLive(ref));
169 else if (Space.isInSpace(CMS.IMMORTAL, ref)) VM.assertions._assert(CMS.immortalSpace.isLive(ref));
170 else if (Space.isInSpace(CMS.LOS, ref)) VM.assertions._assert(CMS.loSpace.isLive(ref));
171 else if (Space.isInSpace(CMS.NON_MOVING, ref)) VM.assertions._assert(CMS.nonMovingSpace.isLive(ref));
172 else if (Space.isInSpace(CMS.SMALL_CODE, ref)) VM.assertions._assert(CMS.smallCodeSpace.isLive(ref));
173 else if (Space.isInSpace(CMS.LARGE_CODE, ref)) VM.assertions._assert(CMS.largeCodeSpace.isLive(ref));
174 }
175 }
176 }
177
178 /****************************************************************************
179 *
180 * Miscellaneous
181 */
182
183 /** @return The active global plan as a <code>Gen</code> instance. */
184 @Inline
185 private static CMS global() {
186 return (CMS) VM.activePlan.global();
187 }
188 }