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 org.mmtk.plan.Phase; 016import org.mmtk.plan.Plan; 017import org.mmtk.plan.SimpleCollector; 018import org.mmtk.plan.TraceLocal; 019import org.mmtk.utility.Log; 020import org.mmtk.utility.options.Options; 021import org.mmtk.vm.VM; 022 023import org.vmmagic.pragma.*; 024 025/** 026 * This class implements <i>per-collector thread</i> behavior 027 * and state for a concurrent collector. 028 */ 029@Uninterruptible 030public abstract class ConcurrentCollector extends SimpleCollector { 031 032 /**************************************************************************** 033 * Instance fields 034 */ 035 036 /**************************************************************************** 037 * Initialization 038 */ 039 040 /**************************************************************************** 041 * 042 * Collection 043 */ 044 045 /** 046 * {@inheritDoc} 047 */ 048 @Override 049 @Unpreemptible 050 public void run() { 051 while (true) { 052 park(); 053 if (Plan.concurrentWorkers.isMember(this)) { 054 concurrentCollect(); 055 } else { 056 collect(); 057 } 058 } 059 } 060 061 private static volatile boolean continueCollecting; 062 063 /** Perform some concurrent garbage collection */ 064 @Unpreemptible 065 public final void concurrentCollect() { 066 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!Plan.gcInProgress()); 067 do { 068 short phaseId = Phase.getConcurrentPhaseId(); 069 concurrentCollectionPhase(phaseId); 070 } while (continueCollecting); 071 } 072 073 @Override 074 public void collect() { 075 if (!Phase.isPhaseStackEmpty()) { 076 Phase.continuePhaseStack(); 077 } else { 078 Phase.beginNewPhaseStack(Phase.scheduleComplex(global().collection)); 079 } 080 } 081 082 @Override 083 @Inline 084 public void collectionPhase(short phaseId, boolean primary) { 085 if (phaseId == Concurrent.FLUSH_COLLECTOR) { 086 getCurrentTrace().processRoots(); 087 getCurrentTrace().flush(); 088 return; 089 } 090 091 super.collectionPhase(phaseId, primary); 092 } 093 094 /** 095 * Perform some concurrent collection work. 096 * 097 * @param phaseId The unique phase identifier 098 */ 099 @Unpreemptible 100 public void concurrentCollectionPhase(short phaseId) { 101 if (phaseId == Concurrent.CONCURRENT_CLOSURE) { 102 if (VM.VERIFY_ASSERTIONS) { 103 VM.assertions._assert(!Plan.gcInProgress()); 104 } 105 TraceLocal trace = getCurrentTrace(); 106 while (!trace.incrementalTrace(100)) { 107 if (group.isAborted()) { 108 trace.flush(); 109 break; 110 } 111 } 112 if (rendezvous() == 0) { 113 continueCollecting = false; 114 if (!group.isAborted()) { 115 /* We are responsible for ensuring termination. */ 116 if (Options.verbose.getValue() >= 2) Log.writeln("< requesting mutator flush >"); 117 VM.collection.requestMutatorFlush(); 118 119 if (Options.verbose.getValue() >= 2) Log.writeln("< mutators flushed >"); 120 121 if (concurrentTraceComplete()) { 122 continueCollecting = Phase.notifyConcurrentPhaseComplete(); 123 } else { 124 continueCollecting = true; 125 Phase.notifyConcurrentPhaseIncomplete(); 126 } 127 } 128 } 129 rendezvous(); 130 return; 131 } 132 133 Log.write("Concurrent phase "); Log.write(Phase.getName(phaseId)); 134 Log.writeln(" not handled."); 135 VM.assertions.fail("Concurrent phase not handled!"); 136 } 137 138 /** 139 * @return whether all work has been completed 140 */ 141 protected abstract boolean concurrentTraceComplete(); 142 143 144 /**************************************************************************** 145 * 146 * Miscellaneous. 147 */ 148 149 /** @return The active global plan as a <code>Concurrent</code> instance. */ 150 @Inline 151 private static Concurrent global() { 152 return (Concurrent) VM.activePlan.global(); 153 } 154}