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.jikesrvm.adaptive.measurements.organizers; 014 015import org.jikesrvm.VM; 016import org.jikesrvm.adaptive.controller.Controller; 017import org.jikesrvm.adaptive.controller.HotMethodRecompilationEvent; 018import org.jikesrvm.adaptive.measurements.RuntimeMeasurements; 019import org.jikesrvm.adaptive.measurements.listeners.MethodListener; 020import org.jikesrvm.adaptive.util.AOSLogging; 021import org.jikesrvm.compilers.common.CompiledMethod; 022import org.jikesrvm.compilers.common.CompiledMethods; 023import org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod; 024import org.jikesrvm.scheduler.RVMThread; 025import org.vmmagic.pragma.NonMoving; 026 027/** 028 * An organizer for method listener information. 029 * <p> 030 * This organizer is designed to work well with non-decayed 031 * cumulative method samples. The basic idea is that each time 032 * the sampling threshold is reached we update the accumulated method 033 * sample data with the new data and then notify the controller of all 034 * methods that were sampled in the current window. 035 */ 036@NonMoving 037public final class MethodSampleOrganizer extends Organizer { 038 039 /** 040 * Filter out all opt-compiled methods that were compiled 041 * at this level or higher. 042 */ 043 private final int filterOptLevel; 044 045 /** 046 * @param filterOptLevel filter out all opt-compiled methods that 047 * were compiled at this level or higher 048 */ 049 public MethodSampleOrganizer(int filterOptLevel) { 050 this.filterOptLevel = filterOptLevel; 051 } 052 053 /** 054 * Initialization: set up data structures and sampling objects. 055 * <p> 056 * Uses either timer based sampling or counter based sampling, 057 * depending on {@link Controller#options}. 058 */ 059 @Override 060 public void initialize() { 061 int numSamples = Controller.options.METHOD_SAMPLE_SIZE * RVMThread.availableProcessors; 062 if (Controller.options.mlCBS()) { 063 numSamples *= VM.CBSMethodSamplesPerTick; 064 } 065 MethodListener methodListener = new MethodListener(numSamples); 066 listener = methodListener; 067 listener.setOrganizer(this); 068 069 if (Controller.options.mlTimer()) { 070 RuntimeMeasurements.installTimerMethodListener(methodListener); 071 } else if (Controller.options.mlCBS()) { 072 RuntimeMeasurements.installCBSMethodListener(methodListener); 073 } else { 074 if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED, "Unexpected value of method_listener_trigger"); 075 } 076 } 077 078 @Override 079 void thresholdReached() { 080 AOSLogging.logger.organizerThresholdReached(); 081 082 int numSamples = ((MethodListener) listener).getNumSamples(); 083 int[] samples = ((MethodListener) listener).getSamples(); 084 085 // (1) Update the global (cumulative) sample data 086 Controller.methodSamples.update(samples, numSamples); 087 088 // (2) Remove duplicates from samples buffer. 089 // NOTE: This is a dirty trick and may be ill-advised. 090 // Rather than copying the unique samples into a different buffer 091 // we treat samples as if it was a scratch buffer. 092 // NOTE: This is worse case O(numSamples^2) but we expect a 093 // significant number of duplicates, so it's probably better than 094 // the other obvious alternative (sorting samples). 095 int uniqueIdx = 1; 096 outer: 097 for (int i = 1; i < numSamples; i++) { 098 int cur = samples[i]; 099 for (int j = 0; j < uniqueIdx; j++) { 100 if (cur == samples[j]) continue outer; 101 } 102 samples[uniqueIdx++] = cur; 103 } 104 105 // (3) For all samples in 0...uniqueIdx, if the method represented by 106 // the sample is compiled at an opt level below filterOptLevel 107 // then report it to the controller. 108 for (int i = 0; i < uniqueIdx; i++) { 109 int cmid = samples[i]; 110 double ns = Controller.methodSamples.getData(cmid); 111 CompiledMethod cm = CompiledMethods.getCompiledMethod(cmid); 112 if (cm != null) { // not already obsoleted 113 int compilerType = cm.getCompilerType(); 114 115 // Enqueue it unless it's either a trap method or already opt 116 // compiled at filterOptLevel or higher. 117 if (!(compilerType == CompiledMethod.TRAP || 118 (compilerType == CompiledMethod.OPT && 119 (((OptCompiledMethod) cm).getOptLevel() >= filterOptLevel)))) { 120 HotMethodRecompilationEvent event = new HotMethodRecompilationEvent(cm, ns); 121 Controller.controllerInputQueue.insert(ns, event); 122 AOSLogging.logger.controllerNotifiedForHotness(cm, ns); 123 } 124 } 125 } 126 } 127}