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.jikesrvm.adaptive.util; 014 015 import org.jikesrvm.classloader.MethodReference; 016 017 /** 018 * A collection of weighted call targets. In some case we can't resolve a 019 * class too early in the process. So we recorded it as unresolved and 020 * resolve the method when the method is being compiled. 021 */ 022 public abstract class UnResolvedWeightedCallTargets { 023 024 /** 025 * Iterate over all of the targets, evaluating the argument function on each edge. 026 * NOTE: We guarantee that the targets will be iterated in monotonically decreasing 027 * edge weight. This simplifies the coding of the inlining clients that consume 028 * this information. 029 * @param func the function to evaluate on each target 030 */ 031 public abstract void visitTargets(Visitor func); 032 033 /** 034 * Augment the weight associated with the argument method by 1. 035 * NOTE: This method may change the representation of the target 036 * method. The caller must be sure to update their backing store of 037 * UnResolvedWeightedCallTargets accordingly to avoid losing the update. 038 */ 039 public final UnResolvedWeightedCallTargets incrementCount(MethodReference target) { 040 return augmentCount(target, 1); 041 } 042 043 /** 044 * Augment the weight associated with the argument method by the argument amount. 045 * NOTE: This method may change the representation of the target 046 * method. The caller must be sure to update their backing store of 047 * UnResolvedWeightedCallTargets accordingly to avoid losing the update. 048 */ 049 public abstract UnResolvedWeightedCallTargets augmentCount(MethodReference target, double amount); 050 051 /** 052 * Decay the weights of all call targets by the specified amount 053 * @param rate the value to decay by 054 */ 055 public abstract void decay(double rate); 056 057 /** 058 * totalWeight of all call targets 059 */ 060 public abstract double totalWeight(); 061 062 /** 063 * @param goal MethodReference that is the only statically possible target 064 * @return the filtered call targets or null if no such target exists 065 */ 066 public abstract UnResolvedWeightedCallTargets filter(MethodReference goal); 067 068 public static UnResolvedWeightedCallTargets create(MethodReference target, double weight) { 069 return new UnResolvedSingleTarget(target, weight); 070 } 071 072 /** 073 * Used by visitTargets 074 */ 075 public interface Visitor { 076 void visit(MethodReference target, double weight); 077 } 078 079 /** 080 * An implementation for storing a call site distribution that has a single target. 081 */ 082 private static final class UnResolvedSingleTarget extends UnResolvedWeightedCallTargets { 083 private final MethodReference target; 084 private float weight; 085 086 UnResolvedSingleTarget(MethodReference t, double w) { 087 target = t; 088 weight = (float) w; 089 } 090 091 @Override 092 public void visitTargets(Visitor func) { 093 func.visit(target, weight); 094 } 095 096 @Override 097 public UnResolvedWeightedCallTargets augmentCount(MethodReference t, double v) { 098 if (target.equals(t)) { 099 weight += v; 100 return this; 101 } else { 102 UnResolvedMultiTarget ms = new UnResolvedMultiTarget(); 103 ms.augmentCount(target, weight); 104 ms.augmentCount(t, v); 105 return ms; 106 } 107 } 108 109 @Override 110 public void decay(double rate) { 111 weight /= rate; 112 } 113 114 @Override 115 public double totalWeight() { return weight; } 116 117 @Override 118 public UnResolvedWeightedCallTargets filter(MethodReference goal) { 119 return (goal.equals(target)) ? this : null; 120 } 121 } 122 123 /** 124 * An implementation for storing a call site distribution that has multiple targets. 125 */ 126 private static final class UnResolvedMultiTarget extends UnResolvedWeightedCallTargets { 127 MethodReference[] methods = new MethodReference[5]; 128 float[] weights = new float[5]; 129 130 @Override 131 public synchronized void visitTargets(Visitor func) { 132 // Typically expect elements to be "almost" sorted due to previous sorting operations. 133 // When this is true, expected time for insertion sort is O(n). 134 for (int i = 1; i < methods.length; i++) { 135 MethodReference m = methods[i]; 136 if (m != null) { 137 float w = weights[i]; 138 int j = i; 139 while (j > 0 && weights[j - 1] < w) { 140 methods[j] = methods[j - 1]; 141 weights[j] = weights[j - 1]; 142 j--; 143 } 144 methods[j] = m; 145 weights[j] = w; 146 } 147 } 148 149 for (int i = 0; i < methods.length; i++) { 150 if (methods[i] != null) { 151 func.visit(methods[i], weights[i]); 152 } 153 } 154 } 155 156 @Override 157 public synchronized UnResolvedWeightedCallTargets augmentCount(MethodReference t, double v) { 158 int empty = -1; 159 for (int i = 0; i < methods.length; i++) { 160 if (methods[i] != null) { 161 if (methods[i].equals(t)) { 162 weights[i] += v; 163 return this; 164 } 165 } else { 166 if (empty == -1) { empty = i; } 167 } 168 } 169 170 // New target must be added 171 if (empty == -1) { 172 // must grow arrays 173 empty = methods.length; 174 MethodReference[] newM = new MethodReference[methods.length * 2]; 175 System.arraycopy(methods, 0, newM, 0, methods.length); 176 methods = newM; 177 float[] newW = new float[weights.length * 2]; 178 System.arraycopy(weights, 0, newW, 0, weights.length); 179 weights = newW; 180 } 181 182 methods[empty] = t; 183 weights[empty] = (float) v; 184 return this; 185 } 186 187 @Override 188 public synchronized void decay(double rate) { 189 for (int i = 0; i < weights.length; i++) { 190 weights[i] /= rate; 191 } 192 } 193 194 @Override 195 public synchronized double totalWeight() { 196 double sum = 0; 197 for (float weight : weights) { 198 sum += weight; 199 } 200 return sum; 201 } 202 203 @Override 204 public synchronized UnResolvedWeightedCallTargets filter(MethodReference goal) { 205 for (int i = 0; i < methods.length; i++) { 206 if (goal.equals(methods[i])) { 207 return UnResolvedWeightedCallTargets.create(methods[i], weights[i]); 208 } 209 } 210 return null; 211 } 212 } 213 }