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.marksweep; 014 015import org.mmtk.plan.*; 016import org.mmtk.plan.concurrent.ConcurrentMutator; 017import org.mmtk.policy.MarkSweepLocal; 018import org.mmtk.policy.Space; 019 020import org.mmtk.utility.alloc.Allocator; 021import org.mmtk.vm.VM; 022 023import org.vmmagic.pragma.*; 024import 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 043public class CMSMutator extends ConcurrentMutator { 044 045 /**************************************************************************** 046 * Instance fields 047 */ 048 049 /** 050 * 051 */ 052 private final MarkSweepLocal ms; 053 private final 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}