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;
014
015 import org.mmtk.plan.Phase;
016 import org.mmtk.plan.Simple;
017 import org.mmtk.utility.Log;
018 import org.mmtk.utility.options.ConcurrentTrigger;
019 import org.mmtk.utility.options.Options;
020
021 import org.vmmagic.pragma.*;
022
023 /**
024 * This class implements the global state of a concurrent collector.
025 */
026 @Uninterruptible
027 public abstract class Concurrent extends Simple {
028
029 /****************************************************************************
030 * Constants
031 */
032
033 /****************************************************************************
034 * Class variables
035 */
036
037 /**
038 *
039 */
040 public static final short FLUSH_MUTATOR = Phase.createSimple("flush-mutator", null);
041 public static final short SET_BARRIER_ACTIVE = Phase.createSimple("set-barrier", null);
042 public static final short FLUSH_COLLECTOR = Phase.createSimple("flush-collector", null);
043 public static final short CLEAR_BARRIER_ACTIVE = Phase.createSimple("clear-barrier", null);
044
045 // CHECKSTYLE:OFF
046
047 /**
048 * When we preempt a concurrent marking phase we must flush mutators and then continue the closure.
049 */
050 protected static final short preemptConcurrentClosure = Phase.createComplex("preeempt-concurrent-trace", null,
051 Phase.scheduleMutator (FLUSH_MUTATOR),
052 Phase.scheduleCollector(CLOSURE));
053
054 public static final short CONCURRENT_CLOSURE = Phase.createConcurrent("concurrent-closure",
055 Phase.scheduleComplex(preemptConcurrentClosure));
056
057 /**
058 * Perform the initial determination of liveness from the roots.
059 */
060 protected static final short concurrentClosure = Phase.createComplex("concurrent-mark", null,
061 Phase.scheduleGlobal (SET_BARRIER_ACTIVE),
062 Phase.scheduleMutator (SET_BARRIER_ACTIVE),
063 Phase.scheduleCollector (FLUSH_COLLECTOR),
064 Phase.scheduleConcurrent(CONCURRENT_CLOSURE),
065 Phase.scheduleGlobal (CLEAR_BARRIER_ACTIVE),
066 Phase.scheduleMutator (CLEAR_BARRIER_ACTIVE));
067
068 /** Build, validate and then build another sanity table */
069 protected static final short preSanityPhase = Phase.createComplex("sanity", null,
070 Phase.scheduleComplex (sanityBuildPhase),
071 Phase.scheduleGlobal (SANITY_SET_PREGC),
072 Phase.scheduleComplex (sanityCheckPhase),
073 Phase.scheduleComplex (sanityBuildPhase));
074
075 /** Validate, build and validate the second sanity table */
076 protected static final short postSanityPhase = Phase.createComplex("sanity", null,
077 Phase.scheduleGlobal (SANITY_SET_POSTGC),
078 Phase.scheduleComplex (sanityCheckPhase),
079 Phase.scheduleComplex (sanityBuildPhase),
080 Phase.scheduleGlobal (SANITY_SET_PREGC),
081 Phase.scheduleComplex (sanityCheckPhase));
082
083 // CHECKSTYLE:OFF
084
085 /****************************************************************************
086 * Instance variables
087 */
088
089 /****************************************************************************
090 * Constructor.
091 */
092 public Concurrent() {
093 Options.concurrentTrigger = new ConcurrentTrigger();
094 }
095
096 /*****************************************************************************
097 *
098 * Collection
099 */
100
101 /**
102 * {@inheritDoc}
103 */
104 @Override
105 @Interruptible
106 public void processOptions() {
107 super.processOptions();
108
109 /* Set up the concurrent marking phase */
110 replacePhase(Phase.scheduleCollector(CLOSURE), Phase.scheduleComplex(concurrentClosure));
111
112 if (Options.sanityCheck.getValue()) {
113 Log.writeln("Collection sanity checking enabled.");
114 replacePhase(Phase.schedulePlaceholder(PRE_SANITY_PLACEHOLDER), Phase.scheduleComplex(preSanityPhase));
115 replacePhase(Phase.schedulePlaceholder(POST_SANITY_PLACEHOLDER), Phase.scheduleComplex(postSanityPhase));
116 }
117 }
118
119 /****************************************************************************
120 *
121 * Collection
122 */
123
124 /**
125 *
126 */
127 private boolean inConcurrentCollection = false;
128
129 @Override
130 @Inline
131 public void collectionPhase(short phaseId) {
132 if (phaseId == SET_BARRIER_ACTIVE) {
133 ConcurrentMutator.newMutatorBarrierActive = true;
134 return;
135 }
136 if (phaseId == CLEAR_BARRIER_ACTIVE) {
137 ConcurrentMutator.newMutatorBarrierActive = false;
138 return;
139 }
140 if (phaseId == CLOSURE) {
141 return;
142 }
143 if (phaseId == PREPARE) {
144 inConcurrentCollection = true;
145 }
146 if (phaseId == RELEASE) {
147 inConcurrentCollection = false;
148 }
149 super.collectionPhase(phaseId);
150 }
151
152 @Override
153 protected boolean concurrentCollectionRequired() {
154 return !Phase.concurrentPhaseActive() &&
155 ((getPagesReserved() * 100) / getTotalPages()) > Options.concurrentTrigger.getValue();
156 }
157
158 @Override
159 public boolean lastCollectionFullHeap() {
160 // TODO: Why this?
161 return !inConcurrentCollection;
162 }
163
164 /*****************************************************************************
165 *
166 * Accounting
167 */
168 }