/* * 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 org.jikesrvm.VM; import org.jikesrvm.classloader.VM_Class; import org.jikesrvm.classloader.VM_Field; import org.jikesrvm.classloader.VM_Method; import org.jikesrvm.classloader.VM_TypeReference; import org.jikesrvm.util.VM_HashMap; /** * database to hold field-level information * this is a mapping from VM_Field -> FieldDatabaseEntry */ final class OPT_FieldDatabase extends VM_HashMap<VM_Field, OPT_FieldDatabase.FieldDatabaseEntry> { private static final boolean DEBUG = false; FieldDatabaseEntry findOrCreateEntry(VM_Field f) { FieldDatabaseEntry e = get(f); if (e == null) { e = new FieldDatabaseEntry(f); put(f, e); } return e; } /** * return the concrete type of a field, or null if none determined */ public VM_TypeReference getConcreteType(VM_Field f) { FieldDatabaseEntry e = get(f); if (e == null) return null; if (e.allMethodsAreAnalyzed()) { return e.getConcreteType(); } return null; } // a data structure holding information about a field final class FieldDatabaseEntry { private VM_HashMap<VM_Method, FieldWriterInfo> summaries; boolean cachedAllAnalyzed; // have we already determined all methods are analyzed? VM_TypeReference cachedConcreteType; // cache a copy of the concrete type already determined for this field FieldWriterInfo findMethodInfo(VM_Method m) { return summaries.get(m); } // are all methods that may write this field analyzed already? boolean allMethodsAreAnalyzed() { if (cachedAllAnalyzed) return true; for (FieldWriterInfo info : summaries.values()) { if (!info.isAnalyzed()) return false; } cachedAllAnalyzed = true; return true; } // return the concrete type of the field; null if no consistent // concrete type has yet been determined. VM_TypeReference getConcreteType() { if (cachedConcreteType != null) return cachedConcreteType; VM_TypeReference result = null; for (FieldWriterInfo info : summaries.values()) { if (!info.isAnalyzed()) return null; if (info.isBottom()) return null; VM_TypeReference t = info.concreteType; if (result != null) { // make sure that all methods set the same concrete type. if (result != t) return null; } else { result = info.concreteType; } } // found a concrete type. cache it and return it. cachedConcreteType = result; return result; } // create a new FieldDatabaseEntry, with a FieldWriterInfo // for each method that may write this field FieldDatabaseEntry(VM_Field f) { if (VM.VerifyAssertions) VM._assert(f.isPrivate()); VM_Class klass = f.getDeclaringClass(); summaries = new VM_HashMap<VM_Method, FieldWriterInfo>(1); // walk thru each method of the declaring class. // If a method m may write to f, then create a FieldWriterInfo for m for (VM_Method m : klass.getDeclaredMethods()) { if (m.mayWrite(f)) { FieldWriterInfo info = new FieldWriterInfo(); if (DEBUG) debug("New summary METHOD " + m + " FIELD " + f + " INFO " + info); summaries.put(m, info); } } } } // class FieldDatabaseEntry // a data structure holding information about a particular <method,field> // combination, where the method may write the field final class FieldWriterInfo { static final int BOTTOM = 0x1; static final int ANALYZED = 0x2; int status; VM_TypeReference concreteType; void setBottom() { status |= BOTTOM; } void setAnalyzed() { status |= ANALYZED; } boolean isBottom() { return (status & BOTTOM) != 0; } boolean isAnalyzed() { return (status & ANALYZED) != 0; } } // print a debug message private static void debug(String s) { if (DEBUG) VM.sysWrite(s + " \n"); } }