/*
* 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.compilers.opt;
import java.util.Iterator;
import org.jikesrvm.classloader.VM_Method;
import org.jikesrvm.util.VM_HashMap;
import org.jikesrvm.util.VM_HashSet;
/**
* Database to store multiple specialized versions for a given method.
*
* <p> The overall design is very similar to that of the
* InvalidationDatabase (see OPT_InvalidationDatabase.java)
* In this database, the key is the VM_Method object of the source method
* and the value is a method set. The method set is a list of
* specialized versions of the method pointed by the key. Specialized
* versions are represented by using the OPT_SpecializedMethod class.
* There is no provision for removing/deleting method versions as classes
* are never unloaded and the ClassLoader.compiledMethods[] is never cleaned.
*/
public final class OPT_SpecializationDatabase {
/**
* Drain the queue of methods waiting for specialized code
* generation.
*/
static synchronized void doDeferredSpecializations() {
// prevent recursive entry to this method
if (specializationInProgress) {
return;
}
specializationInProgress = true;
Iterator<OPT_SpecializedMethod> methods = deferredMethods.iterator();
while (methods.hasNext()) {
OPT_SpecializedMethod m = methods.next();
if (m.getCompiledMethod() == null) {
m.compile();
registerCompiledMethod(m);
}
deferredMethods.remove(m);
// since we modified the set, reset the iterator.
// TODO: use a better abstraction
// (ModifiableSetIterator of some kind?)
methods = deferredMethods.iterator();
}
specializationInProgress = false;
}
private static boolean specializationInProgress;
private static VM_HashSet<OPT_SpecializedMethod> deferredMethods = new VM_HashSet<OPT_SpecializedMethod>();
// write the new compiled method in the specialized method pool
private static void registerCompiledMethod(OPT_SpecializedMethod m) {
OPT_SpecializedMethodPool.registerCompiledMethod(m);
}
/**
* Return an iteration of OPT_SpecializedMethods that represents
* specialied compiled versions of the method pointed by VM_Method
* @return null if no specialized versions
*/
static synchronized Iterator<OPT_SpecializedMethod> getSpecialVersions(VM_Method m) {
MethodSet<VM_Method> s = specialVersionsHash.get(m);
if (s == null) {
return null;
} else {
return s.iterator();
}
}
static int getSpecialVersionCount(VM_Method m) {
Iterator<OPT_SpecializedMethod> versions = getSpecialVersions(m);
int count = 0;
if (versions != null) {
while (versions.hasNext() && (versions.next() != null)) {
count++;
}
}
return count;
}
/**
* Record a new specialized method in this database.
* Also remember that this method will need to be compiled later,
* at the next call to <code> doDeferredSpecializations() </code>
*/
static synchronized void registerSpecialVersion(OPT_SpecializedMethod spMethod) {
VM_Method source = spMethod.getMethod();
MethodSet<VM_Method> s = findOrCreateMethodSet(specialVersionsHash, source);
s.add(spMethod);
deferredMethods.add(spMethod);
}
private static VM_HashMap<VM_Method, MethodSet<VM_Method>> specialVersionsHash =
new VM_HashMap<VM_Method, MethodSet<VM_Method>>();
/**
* Look up the MethodSet corresponding to a given key in the database
* If none found, create one.
*/
private static <T> MethodSet<T> findOrCreateMethodSet(VM_HashMap<T, MethodSet<T>> hash, T key) {
MethodSet<T> result = hash.get(key);
if (result == null) {
result = new MethodSet<T>(key);
hash.put(key, result);
}
return result;
}
/**
* The following defines a set of methods that share a common "key"
*/
static class MethodSet<T> {
final T key;
/**
* a set of OPT_SpecializedMethod
*/
VM_HashSet<OPT_SpecializedMethod> methods = new VM_HashSet<OPT_SpecializedMethod>();
MethodSet(T key) {
this.key = key;
}
void add(OPT_SpecializedMethod spMethod) {
methods.add(spMethod);
}
public Iterator<OPT_SpecializedMethod> iterator() {
return methods.iterator();
}
}
}