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.generational.immix; 014 015import org.mmtk.plan.Plan; 016import org.mmtk.plan.TraceLocal; 017import org.mmtk.plan.generational.*; 018import org.mmtk.policy.Space; 019import org.mmtk.utility.HeaderByte; 020import org.mmtk.utility.alloc.Allocator; 021import org.mmtk.utility.alloc.ImmixAllocator; 022import org.mmtk.utility.statistics.Stats; 023 024import org.mmtk.vm.VM; 025 026import org.vmmagic.pragma.*; 027import org.vmmagic.unboxed.*; 028 029/** 030 * This class implements <i>per-collector thread</i> behavior and state for 031 * the <code>GenImmix</code> two-generational copying collector.<p> 032 * 033 * Specifically, this class defines semantics specific to the collection of 034 * the copy generation (<code>GenCollector</code> defines nursery semantics). 035 * In particular the copy space allocator is defined (for collection-time 036 * allocation into the copy space), and the copy space per-collector thread 037 * collection time semantics are defined.<p> 038 * 039 * @see GenImmix for a description of the <code>GenImmix</code> algorithm. 040 * 041 * @see GenImmix 042 * @see GenImmixMutator 043 * @see GenCollector 044 * @see org.mmtk.plan.StopTheWorldCollector 045 * @see org.mmtk.plan.CollectorContext 046 */ 047@Uninterruptible 048public class GenImmixCollector extends GenCollector { 049 050 /***************************************************************************** 051 * 052 * Instance fields 053 */ 054 055 /** 056 * 057 */ 058 private final GenImmixMatureTraceLocal matureTrace = new GenImmixMatureTraceLocal(global().matureTrace, this); 059 private final GenImmixMatureDefragTraceLocal defragTrace = new GenImmixMatureDefragTraceLocal(global().matureTrace, this); 060 061 private final org.mmtk.policy.immix.CollectorLocal immix = new org.mmtk.policy.immix.CollectorLocal(GenImmix.immixSpace); 062 063 private final ImmixAllocator copy = new ImmixAllocator(GenImmix.immixSpace, true, false); 064 private final ImmixAllocator defragCopy = new ImmixAllocator(GenImmix.immixSpace, true, true); 065 066 /**************************************************************************** 067 * 068 * Collection-time allocation 069 */ 070 071 /** 072 * {@inheritDoc} 073 */ 074 @Override 075 @Inline 076 public final Address allocCopy(ObjectReference original, int bytes, 077 int align, int offset, int allocator) { 078 079 if (Stats.GATHER_MARK_CONS_STATS) { 080 if (Space.isInSpace(GenImmix.NURSERY, original)) GenImmix.nurseryMark.inc(bytes); 081 } 082 if (allocator == Plan.ALLOC_LOS) { 083 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Allocator.getMaximumAlignedSize(bytes, align) > Plan.MAX_NON_LOS_COPY_BYTES); 084 return los.alloc(bytes, align, offset); 085 } else { 086 if (VM.VERIFY_ASSERTIONS) { 087 VM.assertions._assert(bytes <= Plan.MAX_NON_LOS_COPY_BYTES); 088 if (GenImmix.immixSpace.inImmixCollection()) 089 VM.assertions._assert(allocator == GenImmix.ALLOC_MATURE_MAJORGC); 090 else 091 VM.assertions._assert(allocator == GenImmix.ALLOC_MATURE_MINORGC); 092 } 093 if (GenImmix.immixSpace.inImmixDefragCollection()) { 094 return defragCopy.alloc(bytes, align, offset); 095 } else 096 return copy.alloc(bytes, align, offset); 097 } 098 } 099 100 @Override 101 @Inline 102 public final void postCopy(ObjectReference object, ObjectReference typeRef, 103 int bytes, int allocator) { 104 if (allocator == Plan.ALLOC_LOS) 105 Plan.loSpace.initializeHeader(object, false); 106 else { 107 if (VM.VERIFY_ASSERTIONS) { 108 VM.assertions._assert((!GenImmix.immixSpace.inImmixCollection() && allocator == GenImmix.ALLOC_MATURE_MINORGC) || 109 (GenImmix.immixSpace.inImmixCollection() && allocator == GenImmix.ALLOC_MATURE_MAJORGC)); 110 } 111 GenImmix.immixSpace.postCopy(object, bytes, allocator == GenImmix.ALLOC_MATURE_MAJORGC); 112 } 113 if (Gen.USE_OBJECT_BARRIER) 114 HeaderByte.markAsUnlogged(object); 115 } 116 117 /***************************************************************************** 118 * 119 * Collection 120 */ 121 122 /** 123 * {@inheritDoc} 124 */ 125 @Override 126 @Inline 127 public void collectionPhase(short phaseId, boolean primary) { 128 TraceLocal trace = GenImmix.immixSpace.inImmixDefragCollection() ? defragTrace : matureTrace; 129 130 if (global().traceFullHeap()) { 131 if (phaseId == GenImmix.PREPARE) { 132 super.collectionPhase(phaseId, primary); 133 trace.prepare(); 134 copy.reset(); 135 if (global().gcFullHeap) { 136 immix.prepare(true); 137 defragCopy.reset(); 138 } 139 return; 140 } 141 142 if (phaseId == GenImmix.CLOSURE) { 143 trace.completeTrace(); 144 return; 145 } 146 147 if (phaseId == GenImmix.RELEASE) { 148 trace.release(); 149 if (global().gcFullHeap) { 150 immix.release(true); 151 copy.reset(); 152 } 153 super.collectionPhase(phaseId, primary); 154 return; 155 } 156 } 157 158 super.collectionPhase(phaseId, primary); 159 } 160 161 @Override 162 @Inline 163 public final TraceLocal getFullHeapTrace() { 164 return GenImmix.immixSpace.inImmixDefragCollection() ? defragTrace : matureTrace; 165 } 166 167 /**************************************************************************** 168 * 169 * Miscellaneous 170 */ 171 172 /** @return The active global plan as a <code>GenImmix</code> instance. */ 173 @Inline 174 private static GenImmix global() { 175 return (GenImmix) VM.activePlan.global(); 176 } 177}