/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Eclipse Public License (EPL); * 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/eclipse-1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.mmtk.harness.sanity; import java.util.Collections; import java.util.HashSet; import java.util.Set; import org.mmtk.harness.vm.ObjectModel; import org.vmmagic.unboxed.Address; import org.vmmagic.unboxed.ObjectReference; /** * An entry in the heap snapshot. */ public class HeapEntry implements Comparable<HeapEntry> { /* Immutable fields */ /** A reference to the object */ private final ObjectReference object; /** */ private final int id; /* Mutable fields */ /** */ private boolean rootReachable = false; /** */ private int refCount = 0; private final Set<ObjectReference> referrers = new HashSet<ObjectReference>(); HeapEntry(ObjectReference object, int id) { this.object = object; this.id = id; } /** * Create an entry from an object reference - the constructor * inspects the object for any fields it wants to record. * @param object The object */ HeapEntry(ObjectReference object) { this(object,ObjectModel.getId(object)); } /** @return The ObjectReference */ public ObjectReference getObject() { return object; } /** @return The object id */ public int getId() { return id; } /** @return Is the object root reachable */ public boolean isRootReachable() { return rootReachable; } /** @return the object reference count */ public int getRefCount() { return refCount; } /** Increment the object reference count */ public void incRefCount() { refCount++; } /** Set the object to be root reachable */ public void setRootReachable() { this.rootReachable = true; } /** * Register an incoming pointer * @param referrer The object that points to this one * */ public void addReferrer(ObjectReference referrer) { referrers.add(referrer); } /** @return the set of objects that point to this one */ public Set<ObjectReference> getReferrers() { return Collections.unmodifiableSet(referrers); } /** Eclipse-generated hashcode based on object and id */ @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + id; result = prime * result + ((object == null) ? 0 : object.hashCode()); return result; } /** Eclipse-generated equals */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; HeapEntry other = (HeapEntry) obj; if (id != other.id) return false; if (!object.equals(other.object)) return false; return true; } /** * @see Comparable#compareTo(Object) */ @Override public int compareTo(HeapEntry o) { if (o == null) return -1; if (Integer.valueOf(id).compareTo(o.id) == 0) { Address address = object.toAddress(); Address oAddress = o.object.toAddress(); return address.LT(oAddress) ? -1 : address.EQ(oAddress) ? 0 : 1; } return 1; } /** * @see java.lang.Object#toString() */ @Override public String toString() { String result = String.format("Heap entry: id=%s, ",id,ObjectModel.getString(object)); result += String.format("incoming pointers: %n"); for (ObjectReference ref : getReferrers()) { result += String.format(" %s%n",ref); } return result; } }