8078521: AARCH64: Add AArch64 SA support
Summary: Add AArch64 SA support
Reviewed-by: dsamersoff, dholmes
--- a/hotspot/agent/make/Makefile Wed Jun 24 11:55:18 2015 +0200
+++ b/hotspot/agent/make/Makefile Fri Jun 12 15:49:55 2015 +0100
@@ -58,6 +58,7 @@
sun.jvm.hotspot.debugger.dummy \
sun.jvm.hotspot.debugger.linux \
sun.jvm.hotspot.debugger.linux.amd64 \
+sun.jvm.hotspot.debugger.linux.aarch64 \
sun.jvm.hotspot.debugger.linux.ppc64 \
sun.jvm.hotspot.debugger.linux.x86 \
sun.jvm.hotspot.debugger.posix \
@@ -65,6 +66,7 @@
sun.jvm.hotspot.debugger.ppc64 \
sun.jvm.hotspot.debugger.proc \
sun.jvm.hotspot.debugger.proc.amd64 \
+sun.jvm.hotspot.debugger.proc.aarch64 \
sun.jvm.hotspot.debugger.proc.ppc64 \
sun.jvm.hotspot.debugger.proc.sparc \
sun.jvm.hotspot.debugger.proc.x86 \
@@ -91,11 +93,13 @@
sun.jvm.hotspot.prims \
sun.jvm.hotspot.runtime \
sun.jvm.hotspot.runtime.amd64 \
+sun.jvm.hotspot.runtime.aarch64 \
sun.jvm.hotspot.runtime.bsd \
sun.jvm.hotspot.runtime.bsd_amd64 \
sun.jvm.hotspot.runtime.bsd_x86 \
sun.jvm.hotspot.runtime.linux \
sun.jvm.hotspot.runtime.linux_amd64 \
+sun.jvm.hotspot.runtime.linux_aarch64 \
sun.jvm.hotspot.runtime.linux_ppc64 \
sun.jvm.hotspot.runtime.linux_sparc \
sun.jvm.hotspot.runtime.linux_x86 \
@@ -149,16 +153,19 @@
sun/jvm/hotspot/debugger/linux/*.java \
sun/jvm/hotspot/debugger/linux/ppc64/*.java \
sun/jvm/hotspot/debugger/linux/x86/*.java \
+sun/jvm/hotspot/debugger/linux/aarch64/*.java \
sun/jvm/hotspot/debugger/posix/*.java \
sun/jvm/hotspot/debugger/posix/elf/*.java \
sun/jvm/hotspot/debugger/ppc64/*.java \
sun/jvm/hotspot/debugger/proc/*.java \
sun/jvm/hotspot/debugger/proc/amd64/*.java \
+sun/jvm/hotspot/debugger/proc/aarch64/*.java \
sun/jvm/hotspot/debugger/proc/ppc64/*.java \
sun/jvm/hotspot/debugger/proc/sparc/*.java \
sun/jvm/hotspot/debugger/proc/x86/*.java \
sun/jvm/hotspot/debugger/remote/*.java \
sun/jvm/hotspot/debugger/remote/amd64/*.java \
+sun/jvm/hotspot/debugger/remote/aarch64/*.java \
sun/jvm/hotspot/debugger/remote/ppc64/*.java \
sun/jvm/hotspot/debugger/remote/sparc/*.java \
sun/jvm/hotspot/debugger/remote/x86/*.java \
@@ -178,11 +185,13 @@
sun/jvm/hotspot/prims/*.java \
sun/jvm/hotspot/runtime/*.java \
sun/jvm/hotspot/runtime/amd64/*.java \
+sun/jvm/hotspot/runtime/aarch64/*.java \
sun/jvm/hotspot/runtime/bsd/*.java \
sun/jvm/hotspot/runtime/bsd_amd64/*.java \
sun/jvm/hotspot/runtime/bsd_x86/*.java \
sun/jvm/hotspot/runtime/linux/*.java \
sun/jvm/hotspot/runtime/linux_amd64/*.java \
+sun/jvm/hotspot/runtime/linux_aarch64/*.java \
sun/jvm/hotspot/runtime/linux_ppc64/*.java \
sun/jvm/hotspot/runtime/linux_sparc/*.java \
sun/jvm/hotspot/runtime/linux_x86/*.java \
--- a/hotspot/agent/src/os/linux/LinuxDebuggerLocal.c Wed Jun 24 11:55:18 2015 +0200
+++ b/hotspot/agent/src/os/linux/LinuxDebuggerLocal.c Fri Jun 12 15:49:55 2015 +0100
@@ -53,6 +53,10 @@
#include "sun_jvm_hotspot_debugger_ppc64_PPC64ThreadContext.h"
#endif
+#ifdef aarch64
+#include "sun_jvm_hotspot_debugger_aarch64_AARCH64ThreadContext.h"
+#endif
+
static jfieldID p_ps_prochandle_ID = 0;
static jfieldID threadList_ID = 0;
static jfieldID loadObjectList_ID = 0;
@@ -368,7 +372,7 @@
#define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG
#endif
#ifdef aarch64
-#define NPRGREG 32
+#define NPRGREG sun_jvm_hotspot_debugger_aarch64_AARCH64ThreadContext_NPRGREG
#endif
#if defined(sparc) || defined(sparcv9)
#define NPRGREG sun_jvm_hotspot_debugger_sparc_SPARCThreadContext_NPRGREG
@@ -473,6 +477,13 @@
#define REG_INDEX(reg) sun_jvm_hotspot_debugger_aarch64_AARCH64ThreadContext_##reg
+ {
+ int i;
+ for (i = 0; i < 31; i++)
+ regs[i] = gregs.regs[i];
+ regs[REG_INDEX(SP)] = gregs.sp;
+ regs[REG_INDEX(PC)] = gregs.pc;
+ }
#endif /* aarch64 */
#ifdef ppc64
--- a/hotspot/agent/src/os/linux/Makefile Wed Jun 24 11:55:18 2015 +0200
+++ b/hotspot/agent/src/os/linux/Makefile Fri Jun 12 15:49:55 2015 +0100
@@ -53,14 +53,15 @@
$(JAVAH) -jni -classpath ../../../build/classes -d $(ARCH) \
sun.jvm.hotspot.debugger.x86.X86ThreadContext \
sun.jvm.hotspot.debugger.sparc.SPARCThreadContext \
- sun.jvm.hotspot.debugger.amd64.AMD64ThreadContext
+ sun.jvm.hotspot.debugger.amd64.AMD64ThreadContext \
+ sun.jvm.hotspot.debugger.aarch64.AARCH64ThreadContext
$(GCC) $(CFLAGS) $< -o $@
$(ARCH)/sadis.o: ../../share/native/sadis.c
$(JAVAH) -jni -classpath ../../../build/classes -d $(ARCH) \
sun.jvm.hotspot.asm.Disassembler
$(GCC) $(CFLAGS) $< -o $@
-
+
$(ARCH)/%.o: %.c
$(GCC) $(CFLAGS) $< -o $@
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/HSDB.java Wed Jun 24 11:55:18 2015 +0200
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/HSDB.java Fri Jun 12 15:49:55 2015 +0100
@@ -983,19 +983,15 @@
curFrame.getFP(),
anno));
} else {
- if (VM.getVM().getCPU().equals("x86") || VM.getVM().getCPU().equals("amd64")) {
- // For C2, which has null frame pointers on x86/amd64
- CodeBlob cb = VM.getVM().getCodeCache().findBlob(curFrame.getPC());
- Address sp = curFrame.getSP();
- if (Assert.ASSERTS_ENABLED) {
- Assert.that(cb.getFrameSize() > 0, "CodeBlob must have non-zero frame size");
- }
- annoPanel.addAnnotation(new Annotation(sp,
- sp.addOffsetTo(cb.getFrameSize()),
- anno));
- } else {
- Assert.that(VM.getVM().getCPU().equals("ia64"), "only ia64 should reach here");
+ // For C2, which has null frame pointers on x86/amd64/aarch64
+ CodeBlob cb = VM.getVM().getCodeCache().findBlob(curFrame.getPC());
+ Address sp = curFrame.getSP();
+ if (Assert.ASSERTS_ENABLED) {
+ Assert.that(cb.getFrameSize() > 0, "CodeBlob must have non-zero frame size");
}
+ annoPanel.addAnnotation(new Annotation(sp,
+ sp.addOffsetTo(cb.getFrameSize()),
+ anno));
}
// Add interpreter frame annotations
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/aarch64/AARCH64ThreadContext.java Fri Jun 12 15:49:55 2015 +0100
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc.
+ * 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 sun.jvm.hotspot.debugger.aarch64;
+
+import java.lang.annotation.Native;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.cdbg.*;
+
+/** Specifies the thread context on aarch64 platforms; only a sub-portion
+ * of the context is guaranteed to be present on all operating
+ * systems. */
+
+public abstract class AARCH64ThreadContext implements ThreadContext {
+ // Taken from /usr/include/asm/sigcontext.h on Linux/AARCH64.
+
+ // NOTE: the indices for the various registers must be maintained as
+ // listed across various operating systems. However, only a small
+ // subset of the registers' values are guaranteed to be present (and
+ // must be present for the SA's stack walking to work)
+
+ // One instance of the Native annotation is enough to trigger header generation
+ // for this file.
+ @Native
+ public static final int R0 = 0;
+ public static final int R1 = 1;
+ public static final int R2 = 2;
+ public static final int R3 = 3;
+ public static final int R4 = 4;
+ public static final int R5 = 5;
+ public static final int R6 = 6;
+ public static final int R7 = 7;
+ public static final int R8 = 8;
+ public static final int R9 = 9;
+ public static final int R10 = 10;
+ public static final int R11 = 11;
+ public static final int R12 = 12;
+ public static final int R13 = 13;
+ public static final int R14 = 14;
+ public static final int R15 = 15;
+ public static final int R16 = 16;
+ public static final int R17 = 17;
+ public static final int R18 = 18;
+ public static final int R19 = 19;
+ public static final int R20 = 20;
+ public static final int R21 = 21;
+ public static final int R22 = 22;
+ public static final int R23 = 23;
+ public static final int R24 = 24;
+ public static final int R25 = 25;
+ public static final int R26 = 26;
+ public static final int R27 = 27;
+ public static final int R28 = 28;
+ public static final int FP = 29;
+ public static final int LR = 30;
+ public static final int SP = 31;
+ public static final int PC = 32;
+
+ public static final int NPRGREG = 33;
+
+ private long[] data;
+
+ public AARCH64ThreadContext() {
+ data = new long[NPRGREG];
+ }
+
+ public int getNumRegisters() {
+ return NPRGREG;
+ }
+
+ public String getRegisterName(int index) {
+ switch (index) {
+ case LR: return "lr";
+ case SP: return "sp";
+ case PC: return "pc";
+ default:
+ return "r" + index;
+ }
+ }
+
+ public void setRegister(int index, long value) {
+ data[index] = value;
+ }
+
+ public long getRegister(int index) {
+ return data[index];
+ }
+
+ public CFrame getTopFrame(Debugger dbg) {
+ return null;
+ }
+
+ /** This can't be implemented in this class since we would have to
+ * tie the implementation to, for example, the debugging system */
+ public abstract void setRegisterAsAddress(int index, Address value);
+
+ /** This can't be implemented in this class since we would have to
+ * tie the implementation to, for example, the debugging system */
+ public abstract Address getRegisterAsAddress(int index);
+}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java Wed Jun 24 11:55:18 2015 +0200
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java Fri Jun 12 15:49:55 2015 +0100
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,12 +32,14 @@
import sun.jvm.hotspot.debugger.cdbg.*;
import sun.jvm.hotspot.debugger.x86.*;
import sun.jvm.hotspot.debugger.amd64.*;
+import sun.jvm.hotspot.debugger.aarch64.*;
import sun.jvm.hotspot.debugger.sparc.*;
import sun.jvm.hotspot.debugger.ppc64.*;
import sun.jvm.hotspot.debugger.linux.x86.*;
import sun.jvm.hotspot.debugger.linux.amd64.*;
import sun.jvm.hotspot.debugger.linux.sparc.*;
import sun.jvm.hotspot.debugger.linux.ppc64.*;
+import sun.jvm.hotspot.debugger.linux.aarch64.*;
import sun.jvm.hotspot.utilities.*;
class LinuxCDebugger implements CDebugger {
@@ -106,6 +109,13 @@
Address pc = context.getRegisterAsAddress(PPC64ThreadContext.PC);
if (pc == null) return null;
return new LinuxPPC64CFrame(dbg, sp, pc, LinuxDebuggerLocal.getAddressSize());
+ } else if (cpu.equals("aarch64")) {
+ AARCH64ThreadContext context = (AARCH64ThreadContext) thread.getContext();
+ Address fp = context.getRegisterAsAddress(AARCH64ThreadContext.FP);
+ if (fp == null) return null;
+ Address pc = context.getRegisterAsAddress(AARCH64ThreadContext.PC);
+ if (pc == null) return null;
+ return new LinuxAARCH64CFrame(dbg, fp, pc);
} else {
// Runtime exception thrown by LinuxThreadContextFactory if unknown cpu
ThreadContext context = (ThreadContext) thread.getContext();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/aarch64/LinuxAARCH64CFrame.java Fri Jun 12 15:49:55 2015 +0100
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc.
+ * 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 sun.jvm.hotspot.debugger.linux.aarch64;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.aarch64.*;
+import sun.jvm.hotspot.debugger.linux.*;
+import sun.jvm.hotspot.debugger.cdbg.*;
+import sun.jvm.hotspot.debugger.cdbg.basic.*;
+
+final public class LinuxAARCH64CFrame extends BasicCFrame {
+ public LinuxAARCH64CFrame(LinuxDebugger dbg, Address fp, Address pc) {
+ super(dbg.getCDebugger());
+ this.fp = fp;
+ this.pc = pc;
+ this.dbg = dbg;
+ }
+
+ // override base class impl to avoid ELF parsing
+ public ClosestSymbol closestSymbolToPC() {
+ // try native lookup in debugger.
+ return dbg.lookup(dbg.getAddressValue(pc()));
+ }
+
+ public Address pc() {
+ return pc;
+ }
+
+ public Address localVariableBase() {
+ return fp;
+ }
+
+ public CFrame sender(ThreadProxy thread) {
+ AARCH64ThreadContext context = (AARCH64ThreadContext) thread.getContext();
+ Address rsp = context.getRegisterAsAddress(AARCH64ThreadContext.SP);
+
+ if ((fp == null) || fp.lessThan(rsp)) {
+ return null;
+ }
+
+ // Check alignment of fp
+ if (dbg.getAddressValue(fp) % (2 * ADDRESS_SIZE) != 0) {
+ return null;
+ }
+
+ Address nextFP = fp.getAddressAt(0 * ADDRESS_SIZE);
+ if (nextFP == null || nextFP.lessThanOrEqual(fp)) {
+ return null;
+ }
+ Address nextPC = fp.getAddressAt(1 * ADDRESS_SIZE);
+ if (nextPC == null) {
+ return null;
+ }
+ return new LinuxAARCH64CFrame(dbg, nextFP, nextPC);
+ }
+
+ // package/class internals only
+ private static final int ADDRESS_SIZE = 8;
+ private Address pc;
+ private Address sp;
+ private Address fp;
+ private LinuxDebugger dbg;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/aarch64/LinuxAARCH64ThreadContext.java Fri Jun 12 15:49:55 2015 +0100
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc.
+ * 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 sun.jvm.hotspot.debugger.linux.aarch64;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.aarch64.*;
+import sun.jvm.hotspot.debugger.linux.*;
+
+public class LinuxAARCH64ThreadContext extends AARCH64ThreadContext {
+ private LinuxDebugger debugger;
+
+ public LinuxAARCH64ThreadContext(LinuxDebugger debugger) {
+ super();
+ this.debugger = debugger;
+ }
+
+ public void setRegisterAsAddress(int index, Address value) {
+ setRegister(index, debugger.getAddressValue(value));
+ }
+
+ public Address getRegisterAsAddress(int index) {
+ return debugger.newAddress(getRegister(index));
+ }
+}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/proc/ProcDebuggerLocal.java Wed Jun 24 11:55:18 2015 +0200
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/proc/ProcDebuggerLocal.java Fri Jun 12 15:49:55 2015 +0100
@@ -31,11 +31,13 @@
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.cdbg.*;
import sun.jvm.hotspot.debugger.proc.amd64.*;
+import sun.jvm.hotspot.debugger.proc.aarch64.*;
import sun.jvm.hotspot.debugger.proc.sparc.*;
import sun.jvm.hotspot.debugger.proc.ppc64.*;
import sun.jvm.hotspot.debugger.proc.x86.*;
import sun.jvm.hotspot.debugger.ppc64.*;
import sun.jvm.hotspot.debugger.amd64.*;
+import sun.jvm.hotspot.debugger.aarch64.*;
import sun.jvm.hotspot.debugger.sparc.*;
import sun.jvm.hotspot.debugger.x86.*;
import sun.jvm.hotspot.utilities.*;
@@ -88,6 +90,10 @@
threadFactory = new ProcAMD64ThreadFactory(this);
pcRegIndex = AMD64ThreadContext.RIP;
fpRegIndex = AMD64ThreadContext.RBP;
+ } else if (cpu.equals("aarch64")) {
+ threadFactory = new ProcAARCH64ThreadFactory(this);
+ pcRegIndex = AARCH64ThreadContext.PC;
+ fpRegIndex = AARCH64ThreadContext.FP;
} else if (cpu.equals("ppc64")) {
threadFactory = new ProcPPC64ThreadFactory(this);
pcRegIndex = PPC64ThreadContext.PC;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/proc/aarch64/ProcAARCH64Thread.java Fri Jun 12 15:49:55 2015 +0100
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc.
+ * 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 sun.jvm.hotspot.debugger.proc.aarch64;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.aarch64.*;
+import sun.jvm.hotspot.debugger.proc.*;
+import sun.jvm.hotspot.utilities.*;
+
+public class ProcAARCH64Thread implements ThreadProxy {
+ private ProcDebugger debugger;
+ private int id;
+
+ public ProcAARCH64Thread(ProcDebugger debugger, Address addr) {
+ this.debugger = debugger;
+
+ // FIXME: the size here should be configurable. However, making it
+ // so would produce a dependency on the "types" package from the
+ // debugger package, which is not desired.
+ this.id = (int) addr.getCIntegerAt(0, 4, true);
+ }
+
+ public ProcAARCH64Thread(ProcDebugger debugger, long id) {
+ this.debugger = debugger;
+ this.id = (int) id;
+ }
+
+ public ThreadContext getContext() throws IllegalThreadStateException {
+ ProcAARCH64ThreadContext context = new ProcAARCH64ThreadContext(debugger);
+ long[] regs = debugger.getThreadIntegerRegisterSet(id);
+ if (Assert.ASSERTS_ENABLED) {
+ Assert.that(regs.length == AARCH64ThreadContext.NPRGREG, "size mismatch");
+ }
+ for (int i = 0; i < regs.length; i++) {
+ context.setRegister(i, regs[i]);
+ }
+ return context;
+ }
+
+ public boolean canSetContext() throws DebuggerException {
+ return false;
+ }
+
+ public void setContext(ThreadContext context)
+ throws IllegalThreadStateException, DebuggerException {
+ throw new DebuggerException("Unimplemented");
+ }
+
+ public String toString() {
+ return "t@" + id;
+ }
+
+ public boolean equals(Object obj) {
+ if ((obj == null) || !(obj instanceof ProcAARCH64Thread)) {
+ return false;
+ }
+
+ return (((ProcAARCH64Thread) obj).id == id);
+ }
+
+ public int hashCode() {
+ return id;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/proc/aarch64/ProcAARCH64ThreadContext.java Fri Jun 12 15:49:55 2015 +0100
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc.
+ * 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 sun.jvm.hotspot.debugger.proc.aarch64;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.aarch64.*;
+import sun.jvm.hotspot.debugger.proc.*;
+
+public class ProcAARCH64ThreadContext extends AARCH64ThreadContext {
+ private ProcDebugger debugger;
+
+ public ProcAARCH64ThreadContext(ProcDebugger debugger) {
+ super();
+ this.debugger = debugger;
+ }
+
+ public void setRegisterAsAddress(int index, Address value) {
+ setRegister(index, debugger.getAddressValue(value));
+ }
+
+ public Address getRegisterAsAddress(int index) {
+ return debugger.newAddress(getRegister(index));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/proc/aarch64/ProcAARCH64ThreadFactory.java Fri Jun 12 15:49:55 2015 +0100
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc.
+ * 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 sun.jvm.hotspot.debugger.proc.aarch64;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.proc.*;
+
+public class ProcAARCH64ThreadFactory implements ProcThreadFactory {
+ private ProcDebugger debugger;
+
+ public ProcAARCH64ThreadFactory(ProcDebugger debugger) {
+ this.debugger = debugger;
+ }
+
+ public ThreadProxy createThreadWrapper(Address threadIdentifierAddr) {
+ return new ProcAARCH64Thread(debugger, threadIdentifierAddr);
+ }
+
+ public ThreadProxy createThreadWrapper(long id) {
+ return new ProcAARCH64Thread(debugger, id);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/aarch64/RemoteAARCH64Thread.java Fri Jun 12 15:49:55 2015 +0100
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc.
+ * 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 sun.jvm.hotspot.debugger.remote.aarch64;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.aarch64.*;
+import sun.jvm.hotspot.debugger.remote.*;
+import sun.jvm.hotspot.utilities.*;
+
+public class RemoteAARCH64Thread extends RemoteThread {
+ public RemoteAARCH64Thread(RemoteDebuggerClient debugger, Address addr) {
+ super(debugger, addr);
+ }
+
+ public RemoteAARCH64Thread(RemoteDebuggerClient debugger, long id) {
+ super(debugger, id);
+ }
+
+ public ThreadContext getContext() throws IllegalThreadStateException {
+ RemoteAARCH64ThreadContext context = new RemoteAARCH64ThreadContext(debugger);
+ long[] regs = (addr != null)? debugger.getThreadIntegerRegisterSet(addr) :
+ debugger.getThreadIntegerRegisterSet(id);
+ if (Assert.ASSERTS_ENABLED) {
+ Assert.that(regs.length == AARCH64ThreadContext.NPRGREG, "size of register set must match");
+ }
+ for (int i = 0; i < regs.length; i++) {
+ context.setRegister(i, regs[i]);
+ }
+ return context;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/aarch64/RemoteAARCH64ThreadContext.java Fri Jun 12 15:49:55 2015 +0100
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc.
+ * 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 sun.jvm.hotspot.debugger.remote.aarch64;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.aarch64.*;
+import sun.jvm.hotspot.debugger.remote.*;
+
+public class RemoteAARCH64ThreadContext extends AARCH64ThreadContext {
+ private RemoteDebuggerClient debugger;
+
+ public RemoteAARCH64ThreadContext(RemoteDebuggerClient debugger) {
+ super();
+ this.debugger = debugger;
+ }
+
+ public void setRegisterAsAddress(int index, Address value) {
+ setRegister(index, debugger.getAddressValue(value));
+ }
+
+ public Address getRegisterAsAddress(int index) {
+ return debugger.newAddress(getRegister(index));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/aarch64/RemoteAARCH64ThreadFactory.java Fri Jun 12 15:49:55 2015 +0100
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc.
+ * 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 sun.jvm.hotspot.debugger.remote.aarch64;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.remote.*;
+
+public class RemoteAARCH64ThreadFactory implements RemoteThreadFactory {
+ private RemoteDebuggerClient debugger;
+
+ public RemoteAARCH64ThreadFactory(RemoteDebuggerClient debugger) {
+ this.debugger = debugger;
+ }
+
+ public ThreadProxy createThreadWrapper(Address threadIdentifierAddr) {
+ return new RemoteAARCH64Thread(debugger, threadIdentifierAddr);
+ }
+
+ public ThreadProxy createThreadWrapper(long id) {
+ return new RemoteAARCH64Thread(debugger, id);
+ }
+}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java Wed Jun 24 11:55:18 2015 +0200
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java Fri Jun 12 15:49:55 2015 +0100
@@ -35,6 +35,7 @@
import sun.jvm.hotspot.runtime.win32_x86.Win32X86JavaThreadPDAccess;
import sun.jvm.hotspot.runtime.linux_x86.LinuxX86JavaThreadPDAccess;
import sun.jvm.hotspot.runtime.linux_amd64.LinuxAMD64JavaThreadPDAccess;
+import sun.jvm.hotspot.runtime.linux_aarch64.LinuxAARCH64JavaThreadPDAccess;
import sun.jvm.hotspot.runtime.linux_ppc64.LinuxPPC64JavaThreadPDAccess;
import sun.jvm.hotspot.runtime.linux_sparc.LinuxSPARCJavaThreadPDAccess;
import sun.jvm.hotspot.runtime.bsd_x86.BsdX86JavaThreadPDAccess;
@@ -91,6 +92,8 @@
access = new LinuxSPARCJavaThreadPDAccess();
} else if (cpu.equals("ppc64")) {
access = new LinuxPPC64JavaThreadPDAccess();
+ } else if (cpu.equals("aarch64")) {
+ access = new LinuxAARCH64JavaThreadPDAccess();
} else {
try {
access = (JavaThreadPDAccess)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64CurrentFrameGuess.java Fri Jun 12 15:49:55 2015 +0100
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc.
+ * 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 sun.jvm.hotspot.runtime.aarch64;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.aarch64.*;
+import sun.jvm.hotspot.code.*;
+import sun.jvm.hotspot.interpreter.*;
+import sun.jvm.hotspot.runtime.*;
+import sun.jvm.hotspot.runtime.aarch64.*;
+
+/** <P> Should be able to be used on all aarch64 platforms we support
+ (Linux/aarch64) to implement JavaThread's "currentFrameGuess()"
+ functionality. Input is an AARCH64ThreadContext; output is SP, FP,
+ and PC for an AARCH64Frame. Instantiation of the AARCH64Frame is
+ left to the caller, since we may need to subclass AARCH64Frame to
+ support signal handler frames on Unix platforms. </P>
+
+ <P> Algorithm is to walk up the stack within a given range (say,
+ 512K at most) looking for a plausible PC and SP for a Java frame,
+ also considering those coming in from the context. If we find a PC
+ that belongs to the VM (i.e., in generated code like the
+ interpreter or CodeCache) then we try to find an associated FP.
+ We repeat this until we either find a complete frame or run out of
+ stack to look at. </P> */
+
+public class AARCH64CurrentFrameGuess {
+ private AARCH64ThreadContext context;
+ private JavaThread thread;
+ private Address spFound;
+ private Address fpFound;
+ private Address pcFound;
+
+ private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.runtime.aarch64.AARCH64Frame.DEBUG")
+ != null;
+
+ public AARCH64CurrentFrameGuess(AARCH64ThreadContext context,
+ JavaThread thread) {
+ this.context = context;
+ this.thread = thread;
+ }
+
+ /** Returns false if not able to find a frame within a reasonable range. */
+ public boolean run(long regionInBytesToSearch) {
+ Address sp = context.getRegisterAsAddress(AARCH64ThreadContext.SP);
+ Address pc = context.getRegisterAsAddress(AARCH64ThreadContext.PC);
+ Address fp = context.getRegisterAsAddress(AARCH64ThreadContext.FP);
+ if (sp == null) {
+ // Bail out if no last java frame either
+ if (thread.getLastJavaSP() != null) {
+ setValues(thread.getLastJavaSP(), thread.getLastJavaFP(), null);
+ return true;
+ }
+ return false;
+ }
+ Address end = sp.addOffsetTo(regionInBytesToSearch);
+ VM vm = VM.getVM();
+
+ setValues(null, null, null); // Assume we're not going to find anything
+
+ if (vm.isJavaPCDbg(pc)) {
+ if (vm.isClientCompiler()) {
+ // If the topmost frame is a Java frame, we are (pretty much)
+ // guaranteed to have a viable FP. We should be more robust
+ // than this (we have the potential for losing entire threads'
+ // stack traces) but need to see how much work we really have
+ // to do here. Searching the stack for an (SP, FP) pair is
+ // hard since it's easy to misinterpret inter-frame stack
+ // pointers as base-of-frame pointers; we also don't know the
+ // sizes of C1 frames (not registered in the nmethod) so can't
+ // derive them from SP.
+
+ setValues(sp, fp, pc);
+ return true;
+ } else {
+ if (vm.getInterpreter().contains(pc)) {
+ if (DEBUG) {
+ System.out.println("CurrentFrameGuess: choosing interpreter frame: sp = " +
+ sp + ", fp = " + fp + ", pc = " + pc);
+ }
+ setValues(sp, fp, pc);
+ return true;
+ }
+
+ // For the server compiler, FP is not guaranteed to be valid
+ // for compiled code. In addition, an earlier attempt at a
+ // non-searching algorithm (see below) failed because the
+ // stack pointer from the thread context was pointing
+ // (considerably) beyond the ostensible end of the stack, into
+ // garbage; walking from the topmost frame back caused a crash.
+ //
+ // This algorithm takes the current PC as a given and tries to
+ // find the correct corresponding SP by walking up the stack
+ // and repeatedly performing stackwalks (very inefficient).
+ //
+ // FIXME: there is something wrong with stackwalking across
+ // adapter frames...this is likely to be the root cause of the
+ // failure with the simpler algorithm below.
+
+ for (long offset = 0;
+ offset < regionInBytesToSearch;
+ offset += vm.getAddressSize()) {
+ try {
+ Address curSP = sp.addOffsetTo(offset);
+ Frame frame = new AARCH64Frame(curSP, null, pc);
+ RegisterMap map = thread.newRegisterMap(false);
+ while (frame != null) {
+ if (frame.isEntryFrame() && frame.entryFrameIsFirst()) {
+ // We were able to traverse all the way to the
+ // bottommost Java frame.
+ // This sp looks good. Keep it.
+ if (DEBUG) {
+ System.out.println("CurrentFrameGuess: Choosing sp = " + curSP + ", pc = " + pc);
+ }
+ setValues(curSP, null, pc);
+ return true;
+ }
+ frame = frame.sender(map);
+ }
+ } catch (Exception e) {
+ if (DEBUG) {
+ System.out.println("CurrentFrameGuess: Exception " + e + " at offset " + offset);
+ }
+ // Bad SP. Try another.
+ }
+ }
+
+ // Were not able to find a plausible SP to go with this PC.
+ // Bail out.
+ return false;
+
+ /*
+ // Original algorithm which does not work because SP was
+ // pointing beyond where it should have:
+
+ // For the server compiler, FP is not guaranteed to be valid
+ // for compiled code. We see whether the PC is in the
+ // interpreter and take care of that, otherwise we run code
+ // (unfortunately) duplicated from AARCH64Frame.senderForCompiledFrame.
+
+ CodeCache cc = vm.getCodeCache();
+ if (cc.contains(pc)) {
+ CodeBlob cb = cc.findBlob(pc);
+
+ // See if we can derive a frame pointer from SP and PC
+ // NOTE: This is the code duplicated from AARCH64Frame
+ Address saved_fp = null;
+ int llink_offset = cb.getLinkOffset();
+ if (llink_offset >= 0) {
+ // Restore base-pointer, since next frame might be an interpreter frame.
+ Address fp_addr = sp.addOffsetTo(VM.getVM().getAddressSize() * llink_offset);
+ saved_fp = fp_addr.getAddressAt(0);
+ }
+
+ setValues(sp, saved_fp, pc);
+ return true;
+ }
+ */
+ }
+ } else {
+ // If the current program counter was not known to us as a Java
+ // PC, we currently assume that we are in the run-time system
+ // and attempt to look to thread-local storage for saved SP and
+ // FP. Note that if these are null (because we were, in fact,
+ // in Java code, i.e., vtable stubs or similar, and the SA
+ // didn't have enough insight into the target VM to understand
+ // that) then we are going to lose the entire stack trace for
+ // the thread, which is sub-optimal. FIXME.
+
+ if (DEBUG) {
+ System.out.println("CurrentFrameGuess: choosing last Java frame: sp = " +
+ thread.getLastJavaSP() + ", fp = " + thread.getLastJavaFP());
+ }
+ if (thread.getLastJavaSP() == null) {
+ return false; // No known Java frames on stack
+ }
+
+ // The runtime has a nasty habit of not saving fp in the frame
+ // anchor, leaving us to grovel about in the stack to find a
+ // plausible address. Fortunately, this only happens in
+ // compiled code; there we always have a valid PC, and we always
+ // push LR and FP onto the stack as a pair, with FP at the lower
+ // address.
+ pc = thread.getLastJavaPC();
+ fp = thread.getLastJavaFP();
+ sp = thread.getLastJavaSP();
+
+ if (fp == null) {
+ CodeCache cc = vm.getCodeCache();
+ if (cc.contains(pc)) {
+ CodeBlob cb = cc.findBlob(pc);
+ if (DEBUG) {
+ System.out.println("FP is null. Found blob frame size " + cb.getFrameSize());
+ }
+ // See if we can derive a frame pointer from SP and PC
+ long link_offset = cb.getFrameSize() - 2 * VM.getVM().getAddressSize();
+ if (link_offset >= 0) {
+ fp = sp.addOffsetTo(link_offset);
+ }
+ }
+ }
+
+ setValues(sp, fp, null);
+
+ return true;
+ }
+ }
+
+ public Address getSP() { return spFound; }
+ public Address getFP() { return fpFound; }
+ /** May be null if getting values from thread-local storage; take
+ care to call the correct AARCH64Frame constructor to recover this if
+ necessary */
+ public Address getPC() { return pcFound; }
+
+ private void setValues(Address sp, Address fp, Address pc) {
+ spFound = sp;
+ fpFound = fp;
+ pcFound = pc;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64Frame.java Fri Jun 12 15:49:55 2015 +0100
@@ -0,0 +1,555 @@
+/*
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc.
+ * 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 sun.jvm.hotspot.runtime.aarch64;
+
+import java.util.*;
+import sun.jvm.hotspot.code.*;
+import sun.jvm.hotspot.compiler.*;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.oops.*;
+import sun.jvm.hotspot.runtime.*;
+import sun.jvm.hotspot.types.*;
+import sun.jvm.hotspot.utilities.*;
+
+/** Specialization of and implementation of abstract methods of the
+ Frame class for the aarch64 family of CPUs. */
+
+public class AARCH64Frame extends Frame {
+ private static final boolean DEBUG;
+ static {
+ DEBUG = System.getProperty("sun.jvm.hotspot.runtime.aarch64.AARCH64Frame.DEBUG") != null;
+ }
+
+ // All frames
+ private static final int LINK_OFFSET = 0;
+ private static final int RETURN_ADDR_OFFSET = 1;
+ private static final int SENDER_SP_OFFSET = 2;
+
+ // Interpreter frames
+ private static final int INTERPRETER_FRAME_MIRROR_OFFSET = 2; // for native calls only
+ private static final int INTERPRETER_FRAME_SENDER_SP_OFFSET = -1;
+ private static final int INTERPRETER_FRAME_LAST_SP_OFFSET = INTERPRETER_FRAME_SENDER_SP_OFFSET - 1;
+ private static final int INTERPRETER_FRAME_METHOD_OFFSET = INTERPRETER_FRAME_LAST_SP_OFFSET - 1;
+ private static int INTERPRETER_FRAME_MDX_OFFSET; // Non-core builds only
+ private static int INTERPRETER_FRAME_CACHE_OFFSET;
+ private static int INTERPRETER_FRAME_LOCALS_OFFSET;
+ private static int INTERPRETER_FRAME_BCX_OFFSET;
+ private static int INTERPRETER_FRAME_INITIAL_SP_OFFSET;
+ private static int INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET;
+ private static int INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET;
+
+ // Entry frames
+ private static int ENTRY_FRAME_CALL_WRAPPER_OFFSET = -8;
+
+ // Native frames
+ private static final int NATIVE_FRAME_INITIAL_PARAM_OFFSET = 2;
+
+ private static VMReg fp = new VMReg(29);
+
+ static {
+ VM.registerVMInitializedObserver(new Observer() {
+ public void update(Observable o, Object data) {
+ initialize(VM.getVM().getTypeDataBase());
+ }
+ });
+ }
+
+ private static synchronized void initialize(TypeDataBase db) {
+ INTERPRETER_FRAME_MDX_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1;
+ INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_MDX_OFFSET - 1;
+ INTERPRETER_FRAME_LOCALS_OFFSET = INTERPRETER_FRAME_CACHE_OFFSET - 1;
+ INTERPRETER_FRAME_BCX_OFFSET = INTERPRETER_FRAME_LOCALS_OFFSET - 1;
+ INTERPRETER_FRAME_INITIAL_SP_OFFSET = INTERPRETER_FRAME_BCX_OFFSET - 1;
+ INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET;
+ INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET;
+ }
+
+
+ // an additional field beyond sp and pc:
+ Address raw_fp; // frame pointer
+ private Address raw_unextendedSP;
+
+ private AARCH64Frame() {
+ }
+
+ private void adjustForDeopt() {
+ if ( pc != null) {
+ // Look for a deopt pc and if it is deopted convert to original pc
+ CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc);
+ if (cb != null && cb.isJavaMethod()) {
+ NMethod nm = (NMethod) cb;
+ if (pc.equals(nm.deoptHandlerBegin())) {
+ if (Assert.ASSERTS_ENABLED) {
+ Assert.that(this.getUnextendedSP() != null, "null SP in Java frame");
+ }
+ // adjust pc if frame is deoptimized.
+ pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset());
+ deoptimized = true;
+ }
+ }
+ }
+ }
+
+ public AARCH64Frame(Address raw_sp, Address raw_fp, Address pc) {
+ this.raw_sp = raw_sp;
+ this.raw_unextendedSP = raw_sp;
+ this.raw_fp = raw_fp;
+ this.pc = pc;
+ adjustUnextendedSP();
+
+ // Frame must be fully constructed before this call
+ adjustForDeopt();
+
+ if (DEBUG) {
+ System.out.println("AARCH64Frame(sp, fp, pc): " + this);
+ dumpStack();
+ }
+ }
+
+ public AARCH64Frame(Address raw_sp, Address raw_fp) {
+ this.raw_sp = raw_sp;
+ this.raw_unextendedSP = raw_sp;
+ this.raw_fp = raw_fp;
+ this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize());
+ adjustUnextendedSP();
+
+ // Frame must be fully constructed before this call
+ adjustForDeopt();
+
+ if (DEBUG) {
+ System.out.println("AARCH64Frame(sp, fp): " + this);
+ dumpStack();
+ }
+ }
+
+ public AARCH64Frame(Address raw_sp, Address raw_unextendedSp, Address raw_fp, Address pc) {
+ this.raw_sp = raw_sp;
+ this.raw_unextendedSP = raw_unextendedSp;
+ this.raw_fp = raw_fp;
+ this.pc = pc;
+ adjustUnextendedSP();
+
+ // Frame must be fully constructed before this call
+ adjustForDeopt();
+
+ if (DEBUG) {
+ System.out.println("AARCH64Frame(sp, unextendedSP, fp, pc): " + this);
+ dumpStack();
+ }
+
+ }
+
+ public Object clone() {
+ AARCH64Frame frame = new AARCH64Frame();
+ frame.raw_sp = raw_sp;
+ frame.raw_unextendedSP = raw_unextendedSP;
+ frame.raw_fp = raw_fp;
+ frame.pc = pc;
+ frame.deoptimized = deoptimized;
+ return frame;
+ }
+
+ public boolean equals(Object arg) {
+ if (arg == null) {
+ return false;
+ }
+
+ if (!(arg instanceof AARCH64Frame)) {
+ return false;
+ }
+
+ AARCH64Frame other = (AARCH64Frame) arg;
+
+ return (AddressOps.equal(getSP(), other.getSP()) &&
+ AddressOps.equal(getUnextendedSP(), other.getUnextendedSP()) &&
+ AddressOps.equal(getFP(), other.getFP()) &&
+ AddressOps.equal(getPC(), other.getPC()));
+ }
+
+ public int hashCode() {
+ if (raw_sp == null) {
+ return 0;
+ }
+
+ return raw_sp.hashCode();
+ }
+
+ public String toString() {
+ return "sp: " + (getSP() == null? "null" : getSP().toString()) +
+ ", unextendedSP: " + (getUnextendedSP() == null? "null" : getUnextendedSP().toString()) +
+ ", fp: " + (getFP() == null? "null" : getFP().toString()) +
+ ", pc: " + (pc == null? "null" : pc.toString());
+ }
+
+ // accessors for the instance variables
+ public Address getFP() { return raw_fp; }
+ public Address getSP() { return raw_sp; }
+ public Address getID() { return raw_sp; }
+
+ // FIXME: not implemented yet
+ public boolean isSignalHandlerFrameDbg() { return false; }
+ public int getSignalNumberDbg() { return 0; }
+ public String getSignalNameDbg() { return null; }
+
+ public boolean isInterpretedFrameValid() {
+ if (Assert.ASSERTS_ENABLED) {
+ Assert.that(isInterpretedFrame(), "Not an interpreted frame");
+ }
+
+ // These are reasonable sanity checks
+ if (getFP() == null || getFP().andWithMask(0x3) != null) {
+ return false;
+ }
+
+ if (getSP() == null || getSP().andWithMask(0x3) != null) {
+ return false;
+ }
+
+ if (getFP().addOffsetTo(INTERPRETER_FRAME_INITIAL_SP_OFFSET * VM.getVM().getAddressSize()).lessThan(getSP())) {
+ return false;
+ }
+
+ // These are hacks to keep us out of trouble.
+ // The problem with these is that they mask other problems
+ if (getFP().lessThanOrEqual(getSP())) {
+ // this attempts to deal with unsigned comparison above
+ return false;
+ }
+
+ if (getFP().minus(getSP()) > 4096 * VM.getVM().getAddressSize()) {
+ // stack frames shouldn't be large.
+ return false;
+ }
+
+ return true;
+ }
+
+ // FIXME: not applicable in current system
+ // void patch_pc(Thread* thread, address pc);
+
+ public Frame sender(RegisterMap regMap, CodeBlob cb) {
+ AARCH64RegisterMap map = (AARCH64RegisterMap) regMap;
+
+ if (Assert.ASSERTS_ENABLED) {
+ Assert.that(map != null, "map must be set");
+ }
+
+ // Default is we done have to follow them. The sender_for_xxx will
+ // update it accordingly
+ map.setIncludeArgumentOops(false);
+
+ if (isEntryFrame()) return senderForEntryFrame(map);
+ if (isInterpretedFrame()) return senderForInterpreterFrame(map);
+
+ if(cb == null) {
+ cb = VM.getVM().getCodeCache().findBlob(getPC());
+ } else {
+ if (Assert.ASSERTS_ENABLED) {
+ Assert.that(cb.equals(VM.getVM().getCodeCache().findBlob(getPC())), "Must be the same");
+ }
+ }
+
+ if (cb != null) {
+ return senderForCompiledFrame(map, cb);
+ }
+
+ // Must be native-compiled frame, i.e. the marshaling code for native
+ // methods that exists in the core system.
+ return new AARCH64Frame(getSenderSP(), getLink(), getSenderPC());
+ }
+
+ private Frame senderForEntryFrame(AARCH64RegisterMap map) {
+ if (DEBUG) {
+ System.out.println("senderForEntryFrame");
+ }
+ if (Assert.ASSERTS_ENABLED) {
+ Assert.that(map != null, "map must be set");
+ }
+ // Java frame called from C; skip all C frames and return top C
+ // frame of that chunk as the sender
+ AARCH64JavaCallWrapper jcw = (AARCH64JavaCallWrapper) getEntryFrameCallWrapper();
+ if (Assert.ASSERTS_ENABLED) {
+ Assert.that(!entryFrameIsFirst(), "next Java fp must be non zero");
+ Assert.that(jcw.getLastJavaSP().greaterThan(getSP()), "must be above this frame on stack");
+ }
+ AARCH64Frame fr;
+ if (jcw.getLastJavaPC() != null) {
+ fr = new AARCH64Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP(), jcw.getLastJavaPC());
+ } else {
+ fr = new AARCH64Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP());
+ }
+ map.clear();
+ if (Assert.ASSERTS_ENABLED) {
+ Assert.that(map.getIncludeArgumentOops(), "should be set by clear");
+ }
+ return fr;
+ }
+
+ //------------------------------------------------------------------------------
+ // frame::adjust_unextended_sp
+ private void adjustUnextendedSP() {
+ // If we are returning to a compiled MethodHandle call site, the
+ // saved_fp will in fact be a saved value of the unextended SP. The
+ // simplest way to tell whether we are returning to such a call site
+ // is as follows:
+
+ CodeBlob cb = cb();
+ NMethod senderNm = (cb == null) ? null : cb.asNMethodOrNull();
+ if (senderNm != null) {
+ // If the sender PC is a deoptimization point, get the original
+ // PC. For MethodHandle call site the unextended_sp is stored in
+ // saved_fp.
+ if (senderNm.isDeoptMhEntry(getPC())) {
+ // DEBUG_ONLY(verifyDeoptMhOriginalPc(senderNm, getFP()));
+ raw_unextendedSP = getFP();
+ }
+ else if (senderNm.isDeoptEntry(getPC())) {
+ // DEBUG_ONLY(verifyDeoptOriginalPc(senderNm, raw_unextendedSp));
+ }
+ else if (senderNm.isMethodHandleReturn(getPC())) {
+ raw_unextendedSP = getFP();
+ }
+ }
+ }
+
+ private Frame senderForInterpreterFrame(AARCH64RegisterMap map) {
+ if (DEBUG) {
+ System.out.println("senderForInterpreterFrame");
+ }
+ Address unextendedSP = addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0);
+ Address sp = addressOfStackSlot(SENDER_SP_OFFSET);
+ // We do not need to update the callee-save register mapping because above
+ // us is either another interpreter frame or a converter-frame, but never
+ // directly a compiled frame.
+ // 11/24/04 SFG. With the removal of adapter frames this is no longer true.
+ // However c2 no longer uses callee save register for java calls so there
+ // are no callee register to find.
+
+ if (map.getUpdateMap())
+ updateMapWithSavedLink(map, addressOfStackSlot(LINK_OFFSET));
+
+ return new AARCH64Frame(sp, unextendedSP, getLink(), getSenderPC());
+ }
+
+ private void updateMapWithSavedLink(RegisterMap map, Address savedFPAddr) {
+ map.setLocation(fp, savedFPAddr);
+ }
+
+ private Frame senderForCompiledFrame(AARCH64RegisterMap map, CodeBlob cb) {
+ if (DEBUG) {
+ System.out.println("senderForCompiledFrame");
+ }
+
+ //
+ // NOTE: some of this code is (unfortunately) duplicated AARCH64CurrentFrameGuess
+ //
+
+ if (Assert.ASSERTS_ENABLED) {
+ Assert.that(map != null, "map must be set");
+ }
+
+ // frame owned by optimizing compiler
+ if (Assert.ASSERTS_ENABLED) {
+ Assert.that(cb.getFrameSize() >= 0, "must have non-zero frame size");
+ }
+ Address senderSP = getUnextendedSP().addOffsetTo(cb.getFrameSize());
+
+ // The return_address is always the word on the stack
+ Address senderPC = senderSP.getAddressAt(-1 * VM.getVM().getAddressSize());
+
+ // This is the saved value of FP which may or may not really be an FP.
+ // It is only an FP if the sender is an interpreter frame.
+ Address savedFPAddr = senderSP.addOffsetTo(- SENDER_SP_OFFSET * VM.getVM().getAddressSize());
+
+ if (map.getUpdateMap()) {
+ // Tell GC to use argument oopmaps for some runtime stubs that need it.
+ // For C1, the runtime stub might not have oop maps, so set this flag
+ // outside of update_register_map.
+ map.setIncludeArgumentOops(cb.callerMustGCArguments());
+
+ if (cb.getOopMaps() != null) {
+ ImmutableOopMapSet.updateRegisterMap(this, cb, map, true);
+ }
+
+ // Since the prolog does the save and restore of FP there is no oopmap
+ // for it so we must fill in its location as if there was an oopmap entry
+ // since if our caller was compiled code there could be live jvm state in it.
+ updateMapWithSavedLink(map, savedFPAddr);
+ }
+
+ return new AARCH64Frame(senderSP, savedFPAddr.getAddressAt(0), senderPC);
+ }
+
+ protected boolean hasSenderPD() {
+ return true;
+ }
+
+ public long frameSize() {
+ return (getSenderSP().minus(getSP()) / VM.getVM().getAddressSize());
+ }
+
+ public Address getLink() {
+ try {
+ if (DEBUG) {
+ System.out.println("Reading link at " + addressOfStackSlot(LINK_OFFSET)
+ + " = " + addressOfStackSlot(LINK_OFFSET).getAddressAt(0));
+ }
+ return addressOfStackSlot(LINK_OFFSET).getAddressAt(0);
+ } catch (Exception e) {
+ if (DEBUG)
+ System.out.println("Returning null");
+ return null;
+ }
+ }
+
+ // FIXME: not implementable yet
+ //inline void frame::set_link(intptr_t* addr) { *(intptr_t **)addr_at(link_offset) = addr; }
+
+ public Address getUnextendedSP() { return raw_unextendedSP; }
+
+ // Return address:
+ public Address getSenderPCAddr() { return addressOfStackSlot(RETURN_ADDR_OFFSET); }
+ public Address getSenderPC() { return getSenderPCAddr().getAddressAt(0); }
+
+ // return address of param, zero origin index.
+ public Address getNativeParamAddr(int idx) {
+ return addressOfStackSlot(NATIVE_FRAME_INITIAL_PARAM_OFFSET + idx);
+ }
+
+ public Address getSenderSP() { return addressOfStackSlot(SENDER_SP_OFFSET); }
+
+ public Address addressOfInterpreterFrameLocals() {
+ return addressOfStackSlot(INTERPRETER_FRAME_LOCALS_OFFSET);
+ }
+
+ private Address addressOfInterpreterFrameBCX() {
+ return addressOfStackSlot(INTERPRETER_FRAME_BCX_OFFSET);
+ }
+
+ public int getInterpreterFrameBCI() {
+ // FIXME: this is not atomic with respect to GC and is unsuitable
+ // for use in a non-debugging, or reflective, system. Need to
+ // figure out how to express this.
+ Address bcp = addressOfInterpreterFrameBCX().getAddressAt(0);
+ Address methodHandle = addressOfInterpreterFrameMethod().getAddressAt(0);
+ Method method = (Method)Metadata.instantiateWrapperFor(methodHandle);
+ return bcpToBci(bcp, method);
+ }
+
+ public Address addressOfInterpreterFrameMDX() {
+ return addressOfStackSlot(INTERPRETER_FRAME_MDX_OFFSET);
+ }
+
+ // FIXME
+ //inline int frame::interpreter_frame_monitor_size() {
+ // return BasicObjectLock::size();
+ //}
+
+ // expression stack
+ // (the max_stack arguments are used by the GC; see class FrameClosure)
+
+ public Address addressOfInterpreterFrameExpressionStack() {
+ Address monitorEnd = interpreterFrameMonitorEnd().address();
+ return monitorEnd.addOffsetTo(-1 * VM.getVM().getAddressSize());
+ }
+
+ public int getInterpreterFrameExpressionStackDirection() { return -1; }
+
+ // top of expression stack
+ public Address addressOfInterpreterFrameTOS() {
+ return getSP();
+ }
+
+ /** Expression stack from top down */
+ public Address addressOfInterpreterFrameTOSAt(int slot) {
+ return addressOfInterpreterFrameTOS().addOffsetTo(slot * VM.getVM().getAddressSize());
+ }
+
+ public Address getInterpreterFrameSenderSP() {
+ if (Assert.ASSERTS_ENABLED) {
+ Assert.that(isInterpretedFrame(), "interpreted frame expected");
+ }
+ return addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0);
+ }
+
+ // Monitors
+ public BasicObjectLock interpreterFrameMonitorBegin() {
+ return new BasicObjectLock(addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET));
+ }
+
+ public BasicObjectLock interpreterFrameMonitorEnd() {
+ Address result = addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET).getAddressAt(0);
+ if (Assert.ASSERTS_ENABLED) {
+ // make sure the pointer points inside the frame
+ Assert.that(AddressOps.gt(getFP(), result), "result must < than frame pointer");
+ Assert.that(AddressOps.lte(getSP(), result), "result must >= than stack pointer");
+ }
+ return new BasicObjectLock(result);
+ }
+
+ public int interpreterFrameMonitorSize() {
+ return BasicObjectLock.size();
+ }
+
+ // Method
+ public Address addressOfInterpreterFrameMethod() {
+ return addressOfStackSlot(INTERPRETER_FRAME_METHOD_OFFSET);
+ }
+
+ // Constant pool cache
+ public Address addressOfInterpreterFrameCPCache() {
+ return addressOfStackSlot(INTERPRETER_FRAME_CACHE_OFFSET);
+ }
+
+ // Entry frames
+ public JavaCallWrapper getEntryFrameCallWrapper() {
+ return new AARCH64JavaCallWrapper(addressOfStackSlot(ENTRY_FRAME_CALL_WRAPPER_OFFSET).getAddressAt(0));
+ }
+
+ protected Address addressOfSavedOopResult() {
+ // offset is 2 for compiler2 and 3 for compiler1
+ return getSP().addOffsetTo((VM.getVM().isClientCompiler() ? 2 : 3) *
+ VM.getVM().getAddressSize());
+ }
+
+ protected Address addressOfSavedReceiver() {
+ return getSP().addOffsetTo(-4 * VM.getVM().getAddressSize());
+ }
+
+ private void dumpStack() {
+ for (Address addr = getSP().addOffsetTo(-4 * VM.getVM().getAddressSize());
+ AddressOps.lt(addr, getSP());
+ addr = addr.addOffsetTo(VM.getVM().getAddressSize())) {
+ System.out.println(addr + ": " + addr.getAddressAt(0));
+ }
+ System.out.println("-----------------------");
+ for (Address addr = getSP();
+ AddressOps.lte(addr, getSP().addOffsetTo(20 * VM.getVM().getAddressSize()));
+ addr = addr.addOffsetTo(VM.getVM().getAddressSize())) {
+ System.out.println(addr + ": " + addr.getAddressAt(0));
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64JavaCallWrapper.java Fri Jun 12 15:49:55 2015 +0100
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc.
+ * 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 sun.jvm.hotspot.runtime.aarch64;
+
+import java.util.*;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.types.*;
+import sun.jvm.hotspot.runtime.*;
+
+public class AARCH64JavaCallWrapper extends JavaCallWrapper {
+ private static AddressField lastJavaFPField;
+
+ static {
+ VM.registerVMInitializedObserver(new Observer() {
+ public void update(Observable o, Object data) {
+ initialize(VM.getVM().getTypeDataBase());
+ }
+ });
+ }
+
+ private static synchronized void initialize(TypeDataBase db) {
+ Type type = db.lookupType("JavaFrameAnchor");
+
+ lastJavaFPField = type.getAddressField("_last_Java_fp");
+ }
+
+ public AARCH64JavaCallWrapper(Address addr) {
+ super(addr);
+ }
+
+ public Address getLastJavaFP() {
+ return lastJavaFPField.getValue(addr.addOffsetTo(anchorField.getOffset()));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64RegisterMap.java Fri Jun 12 15:49:55 2015 +0100
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc.
+ * 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 sun.jvm.hotspot.runtime.aarch64;
+
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.runtime.*;
+
+public class AARCH64RegisterMap extends RegisterMap {
+
+ /** This is the only public constructor */
+ public AARCH64RegisterMap(JavaThread thread, boolean updateMap) {
+ super(thread, updateMap);
+ }
+
+ protected AARCH64RegisterMap(RegisterMap map) {
+ super(map);
+ }
+
+ public Object clone() {
+ AARCH64RegisterMap retval = new AARCH64RegisterMap(this);
+ return retval;
+ }
+
+ // no PD state to clear or copy:
+ protected void clearPD() {}
+ protected void initializePD() {}
+ protected void initializeFromPD(RegisterMap map) {}
+ protected Address getLocationPD(VMReg reg) { return null; }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/linux_aarch64/LinuxAARCH64JavaThreadPDAccess.java Fri Jun 12 15:49:55 2015 +0100
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Red Hat Inc.
+ * 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 sun.jvm.hotspot.runtime.linux_aarch64;
+
+import java.io.*;
+import java.util.*;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.debugger.aarch64.*;
+import sun.jvm.hotspot.runtime.*;
+import sun.jvm.hotspot.runtime.aarch64.*;
+import sun.jvm.hotspot.types.*;
+import sun.jvm.hotspot.utilities.*;
+
+public class LinuxAARCH64JavaThreadPDAccess implements JavaThreadPDAccess {
+ private static AddressField lastJavaFPField;
+ private static AddressField osThreadField;
+
+ // Field from OSThread
+ private static CIntegerField osThreadThreadIDField;
+
+ // This is currently unneeded but is being kept in case we change
+ // the currentFrameGuess algorithm
+ private static final long GUESS_SCAN_RANGE = 128 * 1024;
+
+ static {
+ VM.registerVMInitializedObserver(new Observer() {
+ public void update(Observable o, Object data) {
+ initialize(VM.getVM().getTypeDataBase());
+ }
+ });
+ }
+
+ private static synchronized void initialize(TypeDataBase db) {
+ Type type = db.lookupType("JavaThread");
+ osThreadField = type.getAddressField("_osthread");
+
+ Type anchorType = db.lookupType("JavaFrameAnchor");
+ lastJavaFPField = anchorType.getAddressField("_last_Java_fp");
+
+ Type osThreadType = db.lookupType("OSThread");
+ osThreadThreadIDField = osThreadType.getCIntegerField("_thread_id");
+ }
+
+ public Address getLastJavaFP(Address addr) {
+ return lastJavaFPField.getValue(addr.addOffsetTo(sun.jvm.hotspot.runtime.JavaThread.getAnchorField().getOffset()));
+ }
+
+ public Address getLastJavaPC(Address addr) {
+ return null;
+ }
+
+ public Address getBaseOfStackPointer(Address addr) {
+ return null;
+ }
+
+ public Frame getLastFramePD(JavaThread thread, Address addr) {
+ Address fp = thread.getLastJavaFP();
+ if (fp == null) {
+ return null; // no information
+ }
+ return new AARCH64Frame(thread.getLastJavaSP(), fp);
+ }
+
+ public RegisterMap newRegisterMap(JavaThread thread, boolean updateMap) {
+ return new AARCH64RegisterMap(thread, updateMap);
+ }
+
+ public Frame getCurrentFrameGuess(JavaThread thread, Address addr) {
+ ThreadProxy t = getThreadProxy(addr);
+ AARCH64ThreadContext context = (AARCH64ThreadContext) t.getContext();
+ AARCH64CurrentFrameGuess guesser = new AARCH64CurrentFrameGuess(context, thread);
+ if (!guesser.run(GUESS_SCAN_RANGE)) {
+ return null;
+ }
+ if (guesser.getPC() == null) {
+ return new AARCH64Frame(guesser.getSP(), guesser.getFP());
+ } else {
+ return new AARCH64Frame(guesser.getSP(), guesser.getFP(), guesser.getPC());
+ }
+ }
+
+ public void printThreadIDOn(Address addr, PrintStream tty) {
+ tty.print(getThreadProxy(addr));
+ }
+
+ public void printInfoOn(Address threadAddr, PrintStream tty) {
+ tty.print("Thread id: ");
+ printThreadIDOn(threadAddr, tty);
+// tty.println("\nPostJavaState: " + getPostJavaState(threadAddr));
+ }
+
+ public Address getLastSP(Address addr) {
+ ThreadProxy t = getThreadProxy(addr);
+ AARCH64ThreadContext context = (AARCH64ThreadContext) t.getContext();
+ return context.getRegisterAsAddress(AARCH64ThreadContext.SP);
+ }
+
+ public ThreadProxy getThreadProxy(Address addr) {
+ // Addr is the address of the JavaThread.
+ // Fetch the OSThread (for now and for simplicity, not making a
+ // separate "OSThread" class in this package)
+ Address osThreadAddr = osThreadField.getValue(addr);
+ // Get the address of the _thread_id from the OSThread
+ Address threadIdAddr = osThreadAddr.addOffsetTo(osThreadThreadIDField.getOffset());
+
+ JVMDebugger debugger = VM.getVM().getDebugger();
+ return debugger.getThreadForIdentifierAddress(threadIdAddr);
+ }
+}
--- a/hotspot/make/sa.files Wed Jun 24 11:55:18 2015 +0200
+++ b/hotspot/make/sa.files Fri Jun 12 15:49:55 2015 +0100
@@ -44,6 +44,7 @@
$(AGENT_SRC_DIR)/sun/jvm/hotspot/compiler/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/amd64/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/aarch64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/bsd/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/bsd/amd64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/bsd/x86/*.java \
@@ -55,6 +56,7 @@
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/amd64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/ia64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/ppc64/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/aarch64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/x86/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/sparc/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/posix/*.java \
@@ -63,6 +65,7 @@
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/proc/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/proc/amd64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/proc/ppc64/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/proc/aarch64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/proc/sparc/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/proc/x86/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/remote/*.java \
@@ -70,6 +73,7 @@
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/remote/ppc64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/remote/sparc/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/remote/x86/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/remote/aarch64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/sparc/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/win32/coff/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windbg/*.java \
@@ -92,11 +96,13 @@
$(AGENT_SRC_DIR)/sun/jvm/hotspot/prims/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/amd64/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/aarch64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/bsd/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/bsd_amd64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/bsd_x86/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/linux/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/linux_amd64/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/linux_aarch64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/linux_x86/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/linux_sparc/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/linux_ppc64/*.java \