/** Process the phase stack. This method is called by multiple threads. */ private static boolean processPhaseStack(boolean resume) { int order = VM.collection.rendezvous(1001); final boolean primary = order == 1; boolean log = Options.verbose.getValue() >= 6; boolean logDetails = Options.verbose.getValue() >= 7; if (primary && resume) { if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!Phase.isPhaseStackEmpty()); if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!Plan.gcInProgress()); Plan.setGCStatus(Plan.GC_PROPER); } /* In order to reduce the need for synchronization, we keep an odd or even * counter for the number of phases processed. As each phase has a single * rendezvous it is only possible to be out by one so the odd or even counter * protects us. */ boolean isEvenPhase = true; if (primary) { /* First phase will be even, so we say we are odd here so that the next phase set is even*/ setNextPhase(false, getNextPhase(), false); } /* Make sure everyone sees the first phase */ VM.collection.rendezvous(1002); /* Global and Collector instances used in phases */ Plan plan = VM.activePlan.global(); CollectorContext collector = VM.activePlan.collector(); /* The main phase execution loop */ int scheduledPhase; while ((scheduledPhase = getCurrentPhase(isEvenPhase)) > 0) { short schedule = getSchedule(scheduledPhase); short phaseId = getPhaseId(scheduledPhase); Phase p = getPhase(phaseId); /* Start the timer(s) */ if (primary) { if (resume) { resumeComplexTimers(); } if (p.timer != null) p.timer.start(); if (startComplexTimer > 0) { Phase.getPhase(startComplexTimer).timer.start(); startComplexTimer = 0; } } if (log) { Log.write("Execute "); p.logPhase(); } /* Execute a single simple scheduled phase */ switch (schedule) { /* Global phase */ case SCHEDULE_GLOBAL: { if (logDetails) Log.writeln(" as Global..."); if (primary) plan.collectionPhase(phaseId); break; } /* Collector phase */ case SCHEDULE_COLLECTOR: { if (logDetails) Log.writeln(" as Collector..."); collector.collectionPhase(phaseId, primary); break; } /* Mutator phase */ case SCHEDULE_MUTATOR: { if (logDetails) Log.writeln(" as Mutator..."); /* Iterate through all mutator contexts */ MutatorContext mutator; while ((mutator = VM.activePlan.getNextMutator()) != null) { mutator.collectionPhase(phaseId, primary); } break; } /* Concurrent phase */ case SCHEDULE_CONCURRENT: { /* We are yielding to a concurrent collection phase */ if (logDetails) Log.writeln(" as Concurrent, yielding..."); if (primary) { concurrentPhaseId = phaseId; scheduleConcurrentWorkers(); /* Concurrent phase, we need to stop gc */ Plan.setGCStatus(Plan.NOT_IN_GC); } VM.collection.rendezvous(1003); if (primary) { pauseComplexTimers(); } return false; } default: { /* getNextPhase has done the wrong thing */ VM.assertions.fail("Invalid schedule in Phase.processPhaseStack"); break; } } if (primary) { /* Set the next phase by processing the stack */ int next = getNextPhase(); boolean needsResetRendezvous = (next > 0) && (schedule == SCHEDULE_MUTATOR && getSchedule(next) == SCHEDULE_MUTATOR); setNextPhase(isEvenPhase, next, needsResetRendezvous); } /* Sync point after execution of a phase */ VM.collection.rendezvous(1004); /* Mutator phase reset */ if (primary && schedule == SCHEDULE_MUTATOR) { VM.activePlan.resetMutatorIterator(); } /* At this point, in the case of consecutive phases with mutator * scheduling, we have to double-synchronize to ensure all * collector threads see the reset mutator counter. */ if (needsMutatorResetRendezvous(isEvenPhase)) { VM.collection.rendezvous(1005); } /* Stop the timer(s) */ if (primary) { if (p.timer != null) p.timer.stop(); if (stopComplexTimer > 0) { Phase.getPhase(stopComplexTimer).timer.stop(); stopComplexTimer = 0; } } /* Flip the even / odd phase sense */ isEvenPhase = !isEvenPhase; resume = false; } /* Phase stack exhausted so we return true */ return true; }
/** * Take the passed phase and return an encoded phase to run that phase in a mutator context; * * @param phaseId The phase to run on mutators * @return The encoded phase value. */ public static int schedulePlaceholder(short phaseId) { if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Phase.getPhase(phaseId) instanceof SimplePhase); return (SCHEDULE_PLACEHOLDER << 16) + phaseId; }
/** * Take the passed phase and return an encoded phase to run that phase in a mutator context; * * @param phaseId The phase to run on mutators * @return The encoded phase value. */ public static int scheduleMutator(short phaseId) { if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Phase.getPhase(phaseId) instanceof SimplePhase); return (SCHEDULE_MUTATOR << 16) + phaseId; }
/** * Take the passed phase and return an encoded phase to run that phase in a global context; * * @param phaseId The phase to run globally * @return The encoded phase value. */ public static int scheduleGlobal(short phaseId) { if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Phase.getPhase(phaseId) instanceof SimplePhase); return (SCHEDULE_GLOBAL << 16) + phaseId; }
/** * Take the passed phase and return an encoded phase to run that phase as a concurrent phase. * * @param phaseId The phase to run as concurrent * @return The encoded phase value. */ public static int scheduleConcurrent(short phaseId) { if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Phase.getPhase(phaseId) instanceof ConcurrentPhase); return (SCHEDULE_CONCURRENT << 16) + phaseId; }
/** * Take the passed phase and return an encoded phase to run that phase as a complex phase. * * @param phaseId The phase to run as complex * @return The encoded phase value. */ public static int scheduleComplex(short phaseId) { if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Phase.getPhase(phaseId) instanceof ComplexPhase); return (SCHEDULE_COMPLEX << 16) + phaseId; }