/* * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.max.tele.reference; import java.util.concurrent.atomic.*; import com.sun.max.tele.*; import com.sun.max.tele.object.*; import com.sun.max.unsafe.*; import com.sun.max.vm.actor.holder.*; import com.sun.max.vm.actor.member.*; import com.sun.max.vm.heap.*; import com.sun.max.vm.layout.*; import com.sun.max.vm.reference.*; import com.sun.max.vm.type.*; import com.sun.max.vm.value.*; /** * Special implementations of VM {@link Reference}s to objects that permit reuse of many VM classes and schemas in the * context of non-local VM heap inspection. * * @see VmReferenceManager */ public abstract class RemoteReference extends Reference { private final TeleVM vm; private long refOID = 0; private static final AtomicLong nextOID = new AtomicLong(1); protected RemoteReference(TeleVM vm) { this.vm = vm; } public TeleVM vm() { return vm; } /** * @return a non-zero integer uniquely identifying the referred-to object in the VM, assigned lazily */ public synchronized long makeOID() { if (refOID == 0) { refOID = nextOID.incrementAndGet(); } return refOID; } /** * @return the status of the object representation in memory to which this instance refers: * {@linkplain ObjectStatus#LIVE LIVE}, {@linkplain ObjectStatus#DEAD DEAD}, or one of the {@linkplain ObjectStatus#isQuasi() quasi states}. */ public abstract ObjectStatus status(); /** * Gets the previous status of the object; this is interesting mainly when the the current {@link #status()} is {@linkplain ObjectStatus#DEAD DEAD}. * @return the status of the object representation prior to the one reported by {@link #status()}, {@code null} if there was none. */ public abstract ObjectStatus priorStatus(); /** * Gets the absolute location of the object's <em>origin</em> in VM memory. This may or may not be the same as the * beginning of the object's storage, depending on the {@link LayoutScheme} being used. * <p> * When an object is <em>forwarded</em> during the {@linkplain HeapPhase#ANALYZING ANALYZING} phase of a GC, this is * the location of the new copy. The location of the old copy is available during that phase via the * {@link #forwardedFrom()} method. * <p> * Returns the last valid origin when the object has become <em>unreachable</em> and its status is * {@linkplain ObjectStatus#DEAD DEAD}. * * @return the VM memory location of the object */ public abstract Address origin(); /** * Reads the {@link Hub} word from the object's header field in VM memory. * * @return contents of the object's hub field */ public Word readHubAsWord() { return vm.referenceScheme().readHubAsWord(this); } /** * Reads from this object in VM memory the reference to the object's {@link Hub}, traversing a forwarder if * necessary to locate the live Hub; returns {@link RemoteReference#zero()} if the hub field in the object header * does not point at a live object. * * @return the value of the object's hub field in VM memory interpreted as a reference, unless it refers to a forwarder * in which case the reference returned refers to the destination of the forwarder. */ public final RemoteReference readHubAsRemoteReference() { return vm.referenceScheme().readHubAsRemoteReference(this); } /** * Reads from this tuple or hybrid object in VM memory the reference presumed to be held in a field at the specified * offset, traversing a forwarder if necessary; returns {@link RemoteReference#zero()} if the field's value does not * point at a live object. No checking is performed to ensure that the offset identifies a reference field, or even * whether the offset is contained within the object. * * @param fieldActor field description, including the offset in bytes from the presumed object's origin at which to read the field * @return the value of the instance field in VM memory interpreted as a reference, unless it refers to a forwarder * in which case the reference returned refers to the destination of the forwarder. */ public final RemoteReference readFieldAsRemoteReference(FieldActor fieldActor) { return vm.referenceScheme().readFieldAsRemoteReference(this, fieldActor); } /** * Reads from this array in VM memory the reference presumed to be held in an at the specified index, traversing a * forwarder if necessary; returns {@link RemoteReference#zero()} if the element's value does not point at a live * object. No checking is performed to ensure that this is an array or that it hold references or that the index is * within the array bounds. * * @param index the index into the presumed array of references at which to read * @return the value of the array element in VM memory interpreted as a reference, unless it refers to a forwarder * in which case the reference returned refers to the destination of the forwarder. */ public final RemoteReference readArrayAsRemoteReference(int index) { return vm.referenceScheme().readArrayAsRemoteReference(this, index); } /** * Read a VM array element as a generic boxed value. Does not check that there is a valid array of the specified * kind at the specified location, or whether the index is in bounds. * * @param kind identifies one of the basic VM value types * @param index offset into the array * @return a generic boxed value based on the contents of the array element in VM memory. */ public final Value readArrayAsValue(Kind kind, int index) { return vm.referenceScheme().readArrayAsValue(kind, this, index); } /** * Returns the location of the <em>old</em> copy of the object in VM memory during any period of time when the * object is being <em>forwarded</em>. This is available <em>only</em> when the heap phase is * {@linkplain HeapPhase#ANALYZING ANALYZING} <em>and</em> the object has been copied to a new location. In all * other situations returns {@link Address#zero()}. * * @return the former address of an object while it is being <em>forwarded</em>. */ public abstract Address forwardedFrom(); /** * Returns the location of the <em>new</em> copy of the object in VM memory during any period of time when the * object is being <em>forwarded</em> and a new live copy created elsewhere. This can happen <em>only</em> when the * heap phase is {@linkplain HeapPhase#ANALYZING ANALYZING} <em>and</em> the status is * {@link ObjectStatus#FORWARDER}. In all other situations returns {@link Address#zero()}. * * @return the former address of an object while it is being <em>forwarded</em>. */ public abstract Address forwardedTo(); /** * Returns {@code this} unless the reference status is {@link ObjectStatus#FORWARDER}, in which case a reference is * returned to the new, live copy created elsewhere. This can happen <em>only</em> when the heap phase is * {@linkplain HeapPhase#ANALYZING ANALYZING}. * * @return a reference to the actual location of the object, possibly following a forwarder to a new copy. */ final public RemoteReference followIfForwarded() { if (status().isForwarder()) { return vm.referenceManager().makeReference(forwardedTo()); } return this; } /** * Generates a string describing the status of the object in VM memory with respect to memory management, designed * to provide useful information to a person: information that the Inspector can't already deduce from the standard * interfaces. For example, the Inspector can identify the region into which the reference points and the basic * status of the object's {@linkplain ObjectStatus status}. * * @return an optional string with information useful to a person, null if unavailable. */ public abstract String gcDescription(); /** * @return is this reference a special temporary {@linkplain ObjectStatus#DEAD DEAD} reference that should not be * allowed to persist past any VM execution? */ public boolean isTemporary() { return false; } /** * @return is this reference a special temporary {@linkplain ObjectStatus#LIVE LIVE} reference that appears to refer * to an object that is not in any known VM memory region? */ public boolean isProvisional() { return false; } /** * @return is this reference a local value dressed up to look like a remote reference */ public boolean isLocal() { return false; } }