/* * 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.vm.code; import com.sun.max.unsafe.*; import com.sun.max.vm.compiler.target.*; /** * A concurrency-safe representation of an IP (instruction pointer) that * abstracts away from the IP's nature (native function, or Java method). A native function * IP is stored as a raw {@link Pointer}, while a virtual-machine (VM, Java) IP is represented * by a {@link TargetMethod} and offset. * <p> * This class is useful for storing IPs in fields in a concurrency-safe way. For storing IPs * in local variables, {@link CodePointer}s should be used. */ public class NativeOrVmIP { public static final NativeOrVmIP ZERO = new NativeOrVmIP(); private TargetMethod tm; private int pos; private Pointer nativeIP; /** * The default constructor should be used with extreme care, as it creates an ill-formed * instance of this class. */ public NativeOrVmIP() { tm = null; pos = 0; nativeIP = Pointer.zero(); } /** * Returns a special pointer to code in a method compilation. * Fails if the IP points into native code somewhere and not at a VM method compilation. */ public final CodePointer vmIP() { return tm.codeAt(pos()); } /** * Returns the offset in the target method. * Fails if the IP points into native code somewhere and not at a VM method compilation. */ public final int pos() { assert tm != null : "target method must not be null"; assert nativeIP.isZero() : "raw IP must be zero"; return pos; } /** * Returns an absolute location pointer to code in native code not known to the VM. * Fails if the IP points into a VM method compilation. */ public final Pointer nativeIP() { assert tm == null : "target method must be null"; return nativeIP; } /** * Returns the IP represented by this object as a {@link Pointer}, no matter what kind of * IP is represented. */ public final Pointer asPointer() { if (tm == null) { return nativeIP(); } else { return vmIP().toPointer(); } } /** * Smart setter: determines whether the IP is a native or VM one. */ public final void derive(Pointer ip) { tm = targetMethodFor(ip); if (tm == null) { pos = 0; nativeIP = ip; } else { pos = tm.posFor(CodePointer.from(ip)); nativeIP = Pointer.zero(); } } /** * Primitive setter, accepting values for all three fields. Illegal value combinations are * rejected. */ public final void primitiveSet(TargetMethod tm, int pos, Pointer nativeIP) { assert !(tm != null && !nativeIP.isZero()); this.tm = tm; this.pos = pos; this.nativeIP = nativeIP; } /** * Copy the values from another instance into this one. */ public final void copyFrom(NativeOrVmIP other) { primitiveSet(other.tm, other.pos, other.nativeIP); } public final TargetMethod targetMethod() { return tm; } /** * Gets the {@link TargetMethod}, if any, whose code currently * includes the specified location. * May be overridden for use by the Inspector. */ protected TargetMethod targetMethodFor(Pointer ip) { return Code.codePointerToTargetMethod(ip); } }