/*
* This file is part of the Jikes RVM project (http://jikesrvm.org).
*
* This file is licensed to You under the Common Public License (CPL);
* You may not use this file except in compliance with the License. You
* may obtain a copy of the License at
*
* http://www.opensource.org/licenses/cpl1.0.php
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
package org.jikesrvm.adaptive.measurements.organizers;
import org.jikesrvm.VM;
import org.jikesrvm.adaptive.controller.VM_Controller;
import org.jikesrvm.adaptive.controller.VM_HotMethodRecompilationEvent;
import org.jikesrvm.adaptive.measurements.VM_RuntimeMeasurements;
import org.jikesrvm.adaptive.measurements.listeners.VM_MethodListener;
import org.jikesrvm.adaptive.util.VM_AOSLogging;
import org.jikesrvm.compilers.common.VM_CompiledMethod;
import org.jikesrvm.compilers.common.VM_CompiledMethods;
import org.jikesrvm.compilers.opt.VM_OptCompiledMethod;
import org.jikesrvm.scheduler.greenthreads.VM_GreenScheduler;
/**
* An organizer for method listener information.
* <p>
* This organizer is designed to work well with non-decayed
* cumulative method samples. The basic idea is that each time
* the sampling threshold is reached we update the accumulated method
* sample data with the new data and then notify the controller of all
* methods that were sampled in the current window.
*/
public final class VM_MethodSampleOrganizer extends VM_Organizer {
/**
* Filter out all opt-compiled methods that were compiled
* at this level or higher.
*/
private int filterOptLevel;
/**
* @param filterOptLevel filter out all opt-compiled methods that
* were compiled at this level or higher
*/
public VM_MethodSampleOrganizer(int filterOptLevel) {
this.filterOptLevel = filterOptLevel;
makeDaemon(true);
}
/**
* Initialization: set up data structures and sampling objects.
*/
@Override
public void initialize() {
VM_AOSLogging.methodSampleOrganizerThreadStarted(filterOptLevel);
int numSamples = VM_Controller.options.METHOD_SAMPLE_SIZE * VM_GreenScheduler.numProcessors;
if (VM_Controller.options.mlCBS()) {
numSamples *= VM.CBSMethodSamplesPerTick;
}
VM_MethodListener methodListener = new VM_MethodListener(numSamples);
listener = methodListener;
listener.setOrganizer(this);
if (VM_Controller.options.mlTimer()) {
VM_RuntimeMeasurements.installTimerMethodListener(methodListener);
} else if (VM_Controller.options.mlCBS()) {
VM_RuntimeMeasurements.installCBSMethodListener(methodListener);
} else {
if (VM.VerifyAssertions) VM._assert(false, "Unexpected value of method_listener_trigger");
}
}
/**
* Method that is called when the sampling threshold is reached
*/
void thresholdReached() {
VM_AOSLogging.organizerThresholdReached();
int numSamples = ((VM_MethodListener) listener).getNumSamples();
int[] samples = ((VM_MethodListener) listener).getSamples();
// (1) Update the global (cumulative) sample data
VM_Controller.methodSamples.update(samples, numSamples);
// (2) Remove duplicates from samples buffer.
// NOTE: This is a dirty trick and may be ill-advised.
// Rather than copying the unique samples into a different buffer
// we treat samples as if it was a scratch buffer.
// NOTE: This is worse case O(numSamples^2) but we expect a
// significant number of duplicates, so it's probably better than
// the other obvious alternative (sorting samples).
int uniqueIdx = 1;
outer:
for (int i = 1; i < numSamples; i++) {
int cur = samples[i];
for (int j = 0; j < uniqueIdx; j++) {
if (cur == samples[j]) continue outer;
}
samples[uniqueIdx++] = cur;
}
// (3) For all samples in 0...uniqueIdx, if the method represented by
// the sample is compiled at an opt level below filterOptLevel
// then report it to the controller.
for (int i = 0; i < uniqueIdx; i++) {
int cmid = samples[i];
double ns = VM_Controller.methodSamples.getData(cmid);
VM_CompiledMethod cm = VM_CompiledMethods.getCompiledMethod(cmid);
if (cm != null) { // not already obsoleted
int compilerType = cm.getCompilerType();
// Enqueue it unless it's either a trap method or already opt
// compiled at filterOptLevel or higher.
if (!(compilerType == VM_CompiledMethod.TRAP ||
(compilerType == VM_CompiledMethod.OPT &&
(((VM_OptCompiledMethod) cm).getOptLevel() >= filterOptLevel)))) {
VM_HotMethodRecompilationEvent event = new VM_HotMethodRecompilationEvent(cm, ns);
VM_Controller.controllerInputQueue.insert(ns, event);
VM_AOSLogging.controllerNotifiedForHotness(cm, ns);
}
}
}
}
}