/** * Notify that the concurrent phase has completed successfully. This must only be called by a * single thread after it has determined that the phase has been completed successfully. */ public static void notifyConcurrentPhaseComplete() { if (Options.verbose.getValue() >= 2) { Log.write("< Concurrent phase "); Log.write(getName(concurrentPhaseId)); Log.writeln(" complete >"); } /* Concurrent phase is complete*/ concurrentPhaseId = 0; /* Remove it from the stack */ popScheduledPhase(); /* Pop the next phase off the stack */ int nextScheduledPhase = getNextPhase(); if (nextScheduledPhase > 0) { short schedule = getSchedule(nextScheduledPhase); /* A concurrent phase, lets wake up and do it all again */ if (schedule == SCHEDULE_CONCURRENT) { concurrentPhaseId = getPhaseId(nextScheduledPhase); scheduleConcurrentWorkers(); return; } /* Push phase back on and resume atomic collection */ pushScheduledPhase(nextScheduledPhase); VM.collection.triggerAsyncCollection(Collection.INTERNAL_PHASE_GC_TRIGGER); } }
/** * Pull the next scheduled phase off the stack. This may involve processing several complex phases * and skipping placeholders, etc. * * @return The next phase to run, or -1 if no phases are left. */ private static int getNextPhase() { boolean allowConcurrentPhase = Plan.collectionTrigger == Collection.INTERNAL_PHASE_GC_TRIGGER; while (phaseStackPointer >= 0) { int scheduledPhase = peekScheduledPhase(); short schedule = getSchedule(scheduledPhase); short phaseId = getPhaseId(scheduledPhase); switch (schedule) { case SCHEDULE_PLACEHOLDER: { /* Placeholders are ignored and we continue looking */ popScheduledPhase(); continue; } case SCHEDULE_GLOBAL: case SCHEDULE_COLLECTOR: case SCHEDULE_MUTATOR: { /* Simple phases are just popped off the stack and executed */ popScheduledPhase(); return scheduledPhase; } case SCHEDULE_CONCURRENT: { /* Concurrent phases are either popped off or we forward to * an associated non-concurrent phase. */ if (!allowConcurrentPhase) { popScheduledPhase(); ConcurrentPhase cp = (ConcurrentPhase) getPhase(phaseId); int alternateScheduledPhase = cp.getAtomicScheduledPhase(); if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(getSchedule(alternateScheduledPhase) != SCHEDULE_CONCURRENT); pushScheduledPhase(alternateScheduledPhase); continue; } if (VM.VERIFY_ASSERTIONS) { /* Concurrent phases can not have a timer */ VM.assertions._assert(getPhase(getPhaseId(scheduledPhase)).timer == null); } return scheduledPhase; } case SCHEDULE_COMPLEX: { /* A complex phase may either be a newly pushed complex phase, * or a complex phase we are in the process of executing in * which case we move to the next subphase. */ ComplexPhase p = (ComplexPhase) getPhase(phaseId); int cursor = incrementComplexPhaseCursor(); if (cursor == 0 && p.timer != null) { /* Tell the primary thread to start the timer after the next sync. */ startComplexTimer = phaseId; } if (cursor < p.count()) { /* There are more entries, we push the next one and continue */ pushScheduledPhase(p.get(cursor)); continue; } /* We have finished this complex phase */ popScheduledPhase(); if (p.timer != null) { /* Tell the primary thread to stop the timer after the next sync. */ stopComplexTimer = phaseId; } continue; } default: { VM.assertions.fail("Invalid phase type encountered"); } } } return -1; }