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.compilers.opt.specialization; 014 015 import java.util.Iterator; 016 017 import org.jikesrvm.classloader.RVMMethod; 018 import org.jikesrvm.util.ImmutableEntryHashMapRVM; 019 import org.jikesrvm.util.HashSetRVM; 020 021 /** 022 * Database to store multiple specialized versions for a given method. 023 * 024 * <p> The overall design is very similar to that of the 025 * InvalidationDatabase (see InvalidationDatabase.java) 026 * In this database, the key is the RVMMethod object of the source method 027 * and the value is a method set. The method set is a list of 028 * specialized versions of the method pointed by the key. Specialized 029 * versions are represented by using the SpecializedMethod class. 030 * There is no provision for removing/deleting method versions as classes 031 * are never unloaded and the ClassLoader.compiledMethods[] is never cleaned. 032 */ 033 public final class SpecializationDatabase { 034 035 private static boolean specializationInProgress; 036 037 private static final HashSetRVM<SpecializedMethod> deferredMethods = 038 new HashSetRVM<SpecializedMethod>(); 039 040 private static final ImmutableEntryHashMapRVM<RVMMethod, MethodSet<RVMMethod>> specialVersionsHash = 041 new ImmutableEntryHashMapRVM<RVMMethod, MethodSet<RVMMethod>>(); 042 043 /** 044 * Drain the queue of methods waiting for specialized code 045 * generation. 046 */ 047 public static synchronized void doDeferredSpecializations() { 048 // prevent recursive entry to this method 049 if (specializationInProgress) { 050 return; 051 } 052 specializationInProgress = true; 053 Iterator<SpecializedMethod> methods = deferredMethods.iterator(); 054 while (methods.hasNext()) { 055 SpecializedMethod m = methods.next(); 056 if (m.getCompiledMethod() == null) { 057 m.compile(); 058 registerCompiledMethod(m); 059 } 060 deferredMethods.remove(m); 061 // since we modified the set, reset the iterator. 062 // TODO: use a better abstraction 063 // (ModifiableSetIterator of some kind?) 064 methods = deferredMethods.iterator(); 065 } 066 specializationInProgress = false; 067 } 068 069 // write the new compiled method in the specialized method pool 070 private static void registerCompiledMethod(SpecializedMethod m) { 071 SpecializedMethodPool.registerCompiledMethod(m); 072 } 073 074 /** 075 * Return an iteration of SpecializedMethods that represents 076 * specialized compiled versions of the method pointed by RVMMethod 077 * @return null if no specialized versions 078 */ 079 static synchronized Iterator<SpecializedMethod> getSpecialVersions(RVMMethod m) { 080 MethodSet<RVMMethod> s = specialVersionsHash.get(m); 081 if (s == null) { 082 return null; 083 } else { 084 return s.iterator(); 085 } 086 } 087 088 static int getSpecialVersionCount(RVMMethod m) { 089 Iterator<SpecializedMethod> versions = getSpecialVersions(m); 090 int count = 0; 091 if (versions != null) { 092 while (versions.hasNext() && (versions.next() != null)) { 093 count++; 094 } 095 } 096 return count; 097 } 098 099 /** 100 * Record a new specialized method in this database. 101 * Also remember that this method will need to be compiled later, 102 * at the next call to <code> doDeferredSpecializations() </code> 103 */ 104 static synchronized void registerSpecialVersion(SpecializedMethod spMethod) { 105 RVMMethod source = spMethod.getMethod(); 106 MethodSet<RVMMethod> s = findOrCreateMethodSet(specialVersionsHash, source); 107 s.add(spMethod); 108 deferredMethods.add(spMethod); 109 } 110 111 /** 112 * Look up the MethodSet corresponding to a given key in the database 113 * If none found, create one. 114 */ 115 private static <T> MethodSet<T> findOrCreateMethodSet(ImmutableEntryHashMapRVM<T, MethodSet<T>> hash, T key) { 116 MethodSet<T> result = hash.get(key); 117 if (result == null) { 118 result = new MethodSet<T>(key); 119 hash.put(key, result); 120 } 121 return result; 122 } 123 124 /** 125 * The following defines a set of methods that share a common "key" 126 */ 127 static class MethodSet<T> { 128 final T key; 129 130 /** 131 * a set of SpecializedMethod 132 */ 133 final HashSetRVM<SpecializedMethod> methods = new HashSetRVM<SpecializedMethod>(); 134 135 MethodSet(T key) { 136 this.key = key; 137 } 138 139 void add(SpecializedMethod spMethod) { 140 methods.add(spMethod); 141 } 142 143 public Iterator<SpecializedMethod> iterator() { 144 return methods.iterator(); 145 } 146 } 147 }