/* * Copyright (c) 2009, 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.stack; import static com.sun.max.vm.thread.VmThreadLocal.*; import java.util.*; import com.sun.max.annotate.*; import com.sun.max.unsafe.*; import com.sun.max.vm.*; import com.sun.max.vm.thread.*; /** * A Java frame anchor is a stack-allocated block of memory in the frame of a Java * method that makes a transition between the 'in Java' and 'in native' states for a thread. * The anchor records the {@linkplain #PC instruction}, {@linkplain #SP stack} and {@linkplain #FP frame} * pointers of an execution point in a Java frame. Each anchor also points to the anchor further * (logically) down the stack of the closest caller that made a thread state transition. * * The head of the list of frame anchors for a thread is maintained in {@link VmThreadLocal#LAST_JAVA_FRAME_ANCHOR}. */ public enum JavaFrameAnchor { PREVIOUS, PC, SP, FP; /** * The offset of this field within an anchor. */ public final int offset = Word.size() * ordinal(); /** * Gets the value of this field. * * @param anchor the anchor from which to read the value * @return the value of this field within {@code anchor} */ @INLINE public final Pointer get(Pointer anchor) { return anchor.readWord(offset).asPointer(); } /** * Sets the value of this field. * * @param anchor the anchor in which to set the value * @param value the new value of this field in {@code anchor} */ @INLINE public final void set(Pointer anchor, Word value) { anchor.writeWord(offset, value); } /** * Determines if a given anchor indicates a frame that transitioned into Java code. * That is, a frame in a {@linkplain VM_ENTRY_POINT VM entry point}. * This will return true if the {@link #PC} is zero. * * @param anchor the anchor to test * @return {@code true} if {@code anchor} is zero or {@code PC} is zero in {@code anchor} */ public static boolean inJava(Pointer anchor) { return !anchor.isZero() && JavaFrameAnchor.PC.get(anchor).isZero(); } /** * Gets the current anchor (which may be null) for a given thread. * * @param tla the thread locals for a thread * @return the Java frame anchor recorded for the thread denoted by {@code tla} */ public static Pointer from(Pointer tla) { Pointer etla = ETLA.load(tla); return LAST_JAVA_FRAME_ANCHOR.load(etla); } /** * Prints a given list of anchors to the VM's {@linkplain Log log} stream. * * @param anchor the head of the anchor list to be printed */ public static void log(Pointer anchor) { boolean lockDisabledSafepoints = Log.lock(); while (!anchor.isZero()) { Log.print(anchor); Log.print("@{pc="); Log.print(PC.get(anchor)); Log.print(", fp="); Log.print(FP.get(anchor)); Log.print(", sp="); Log.print(SP.get(anchor)); Log.print("} -> "); anchor = PREVIOUS.get(anchor); } Log.print(" null"); Log.unlock(lockDisabledSafepoints); } public static final List<JavaFrameAnchor> VALUES = Arrays.asList(values()); /** * Gets the storage size of a {@link JavaFrameAnchor}. */ @FOLD public static int size() { return VALUES.size() * Word.size(); } /** * Creates an anchor in the frame of the caller (hence the {@link INLINE} annotation). */ @INLINE public static Pointer create(Word sp, Word fp, CodePointer ip, Word previousAnchor) { Pointer anchor = Intrinsics.alloca(size(), false); FP.set(anchor, fp); SP.set(anchor, sp); PC.set(anchor, ip.toAddress()); PREVIOUS.set(anchor, previousAnchor); return anchor; } }