Zero stack printer changes
Gary Benson
gbenson at redhat.com
Wed Sep 9 02:00:56 PDT 2009
Hi all,
This patch rearranges the stack printer code in Zero so that it slots
in better with HotSpot's existing frame walker and therefore requires
less modification to vmError.cpp as requested by Tom Rodriguez.
Cheers,
Gary
--
http://gbenson.net/
-------------- next part --------------
diff -r 175266c8ad02 ChangeLog
--- a/ChangeLog Tue Sep 08 11:47:14 2009 +0100
+++ b/ChangeLog Wed Sep 09 04:44:36 2009 -0400
@@ -1,3 +1,50 @@
+2009-09-09 Gary Benson <gbenson at redhat.com>
+
+ * ports/hotspot/src/cpu/zero/vm/stack_zero.hpp
+ (ZeroFrame::identify_word): New method.
+ (ZeroFrame::identify_vp_word): Likewise.
+
+ * ports/hotspot/src/cpu/zero/vm/entryFrame_zero.hpp
+ (EntryFrame::identify_word): New method.
+ * ports/hotspot/src/cpu/zero/vm/interpreterFrame_zero.hpp
+ (InterpreterFrame::identify_word): New method.
+ * ports/hotspot/src/cpu/zero/vm/sharkFrame_zero.hpp
+ (SharkFrame::identify_word): New method.
+ * ports/hotspot/src/cpu/zero/vm/deoptimizerFrame_zero.hpp
+ (DeoptimizerFrame::identify_word): Likewise.
+
+ * ports/hotspot/src/cpu/zero/vm/frame_zero.hpp
+ (frame::frame): Added frame pointer argument.
+ (frame::_fp): New field.
+ (frame::fp): Return the above, instead of a dummy value.
+ (frame::zero_print_on_error): New method.
+ * ports/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp
+ (frame::frame): Initialize frame pointer.
+ * ports/hotspot/src/cpu/zero/vm/frame_zero.cpp
+ (frame::sender_for_entry_frame): Pass frame pointer.
+ (frame::sender_for_interpreter_frame): Likewise.
+ (frame::sender_for_compiled_frame): Likewise.
+ (frame::sender_for_deoptimizer_frame): Likewise.
+ (frame::zero_print_on_error): New method.
+ (ZeroFrame::identify_word): Likewise.
+ (EntryFrame::identify_word): Likewise.
+ (InterpreterFrame::identify_word): Likewise.
+ (SharkFrame::identify_word): Likewise.
+ (ZeroFrame::identify_vp_word): Likewise.
+ (DeoptimizerFrame::identify_word): Likewise.
+
+ * ports/hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp
+ (JavaThread::pd_last_frame): Pass frame pointer.
+
+ * ports/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp
+ (os::current_frame): Implemented.
+
+ * patches/icedtea-zero.patch
+ (VMError::report): Replace stack printer code.
+ (hotspot/src/share/vm/includeDB_core): Updated.
+
+ * ports/hotspot/src/cpu/zero/vm/stackPrinter_zero.hpp: Removed.
+
2009-09-08 Gary Benson <gbenson at redhat.com>
* ports/hotspot/src/cpu/zero/vm/stack_zero.hpp: Whitespace changes.
diff -r 175266c8ad02 patches/icedtea-zero.patch
--- a/patches/icedtea-zero.patch Tue Sep 08 11:47:14 2009 +0100
+++ b/patches/icedtea-zero.patch Wed Sep 09 04:44:36 2009 -0400
@@ -144,43 +144,48 @@
--- openjdk/hotspot/src/share/vm/utilities/vmError.cpp.orig 2008-07-27 08:37:02.000000000 +0000
+++ openjdk/hotspot/src/share/vm/utilities/vmError.cpp 2008-07-27 08:38:13.000000000 +0000
-@@ -25,6 +25,10 @@
- # include "incls/_precompiled.incl"
- # include "incls/_vmError.cpp.incl"
-
-+# ifdef ZERO
-+# include <stackPrinter_zero.hpp>
-+# endif // ZERO
-+
- // List of environment variables that should be reported in error log file.
- const char *env_list[] = {
- // All platforms
-@@ -392,6 +397,7 @@
- st->cr();
- }
-
-+#ifndef ZERO
- STEP(110, "(printing stack bounds)" )
-
- if (_verbose) {
-@@ -449,11 +455,16 @@
- st->cr();
- }
- }
-+#endif // !ZERO
-
- STEP(130, "(printing Java stack)" )
+@@ -462,6 +462,40 @@
if (_verbose && _thread && _thread->is_Java_thread()) {
JavaThread* jt = (JavaThread*)_thread;
+#ifdef ZERO
-+ st->print_cr("Java stack:");
-+ ZeroStackPrinter(st, buf, sizeof(buf)).print(jt);
++ if (jt->zero_stack()->sp() && jt->top_zero_frame()) {
++ // StackFrameStream uses the frame anchor, which may not have
++ // been set up. This can be done at any time in Zero, however,
++ // so if it hasn't been set up then we just set it up now and
++ // clear it again when we're done.
++ bool has_last_Java_frame = jt->has_last_Java_frame();
++ if (!has_last_Java_frame)
++ jt->set_last_Java_frame();
++ st->print("Java frames:");
++
++ // If the top frame is a Shark frame and the frame anchor isn't
++ // set up then it's possible that the information in the frame
++ // is garbage: it could be from a previous decache, or it could
++ // simply have never been written. So we print a warning...
++ StackFrameStream sfs(jt);
++ if (!has_last_Java_frame && !sfs.is_done()) {
++ if (sfs.current()->zeroframe()->is_shark_frame()) {
++ st->print(" (TOP FRAME MAY BE JUNK)");
++ }
++ }
++ st->cr();
++
++ // Print the frames
++ for(int i = 0; !sfs.is_done(); sfs.next(), i++) {
++ sfs.current()->zero_print_on_error(i, st, buf, sizeof(buf));
++ st->cr();
++ }
++
++ // Reset the frame anchor if necessary
++ if (!has_last_Java_frame)
++ jt->reset_last_Java_frame();
++ }
+#else
if (jt->has_last_Java_frame()) {
st->print_cr("Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)");
for(StackFrameStream sfs(jt); !sfs.is_done(); sfs.next()) {
-@@ -461,6 +472,7 @@
+@@ -469,6 +503,7 @@
st->cr();
}
}
@@ -188,21 +193,7 @@
}
STEP(140, "(printing VM operation)" )
-@@ -472,6 +484,14 @@ void VMError::report(outputStream* st) {
- op->print_on_error(st);
- st->cr();
- st->cr();
-+#ifdef ZERO
-+ if (op->calling_thread()->is_Java_thread()) {
-+ st->print_cr("Calling thread's Java stack:");
-+ ZeroStackPrinter(st, buf, sizeof(buf)).print(
-+ (JavaThread *) op->calling_thread());
-+ st->cr();
-+ }
-+#endif // ZERO
- }
- }
-
+
Index: openjdk/hotspot/src/share/vm/runtime/jniHandles.cpp
===================================================================
--- openjdk/hotspot/src/share/vm/runtime/jniHandles.cpp.orig 2009-06-10 11:30:46.000000000 +0200
@@ -219,3 +210,20 @@
}
+--- openjdk/hotspot/src/share/vm/includeDB_core 2009-09-08 13:22:25.000000000 +0100
++++ openjdk/hotspot/src/share/vm/includeDB_core 2009-09-08 13:41:57.000000000 +0100
+@@ -1655,12 +1655,14 @@
+ frame_<arch>.cpp frame.inline.hpp
+ frame_<arch>.cpp handles.inline.hpp
+ frame_<arch>.cpp interpreter.hpp
++frame_<arch>.cpp interpreterRuntime.hpp
+ frame_<arch>.cpp javaCalls.hpp
+ frame_<arch>.cpp markOop.hpp
+ frame_<arch>.cpp methodOop.hpp
+ frame_<arch>.cpp monitorChunk.hpp
+ frame_<arch>.cpp oop.inline.hpp
+ frame_<arch>.cpp resourceArea.hpp
++frame_<arch>.cpp scopeDesc.hpp
+ frame_<arch>.cpp signature.hpp
+ frame_<arch>.cpp stubCodeGenerator.hpp
+ frame_<arch>.cpp stubRoutines.hpp
diff -r 175266c8ad02 ports/hotspot/src/cpu/zero/vm/deoptimizerFrame_zero.hpp
--- a/ports/hotspot/src/cpu/zero/vm/deoptimizerFrame_zero.hpp Tue Sep 08 11:47:14 2009 +0100
+++ b/ports/hotspot/src/cpu/zero/vm/deoptimizerFrame_zero.hpp Wed Sep 09 04:44:36 2009 -0400
@@ -45,4 +45,11 @@
public:
static DeoptimizerFrame *build(ZeroStack* stack);
+
+ public:
+ void identify_word(int frame_index,
+ int offset,
+ char* fieldbuf,
+ char* valuebuf,
+ int buflen) const;
};
diff -r 175266c8ad02 ports/hotspot/src/cpu/zero/vm/entryFrame_zero.hpp
--- a/ports/hotspot/src/cpu/zero/vm/entryFrame_zero.hpp Tue Sep 08 11:47:14 2009 +0100
+++ b/ports/hotspot/src/cpu/zero/vm/entryFrame_zero.hpp Wed Sep 09 04:44:36 2009 -0400
@@ -57,4 +57,11 @@
JavaCallWrapper *call_wrapper() const {
return (JavaCallWrapper *) value_of_word(call_wrapper_off);
}
+
+ public:
+ void identify_word(int frame_index,
+ int offset,
+ char* fieldbuf,
+ char* valuebuf,
+ int buflen) const;
};
diff -r 175266c8ad02 ports/hotspot/src/cpu/zero/vm/frame_zero.cpp
--- a/ports/hotspot/src/cpu/zero/vm/frame_zero.cpp Tue Sep 08 11:47:14 2009 +0100
+++ b/ports/hotspot/src/cpu/zero/vm/frame_zero.cpp Wed Sep 09 04:44:36 2009 -0400
@@ -1,6 +1,6 @@
/*
* Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright 2007, 2008 Red Hat, Inc.
+ * Copyright 2007, 2008, 2009 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
@@ -47,19 +47,19 @@
"sender should be next Java frame");
map->clear();
assert(map->include_argument_oops(), "should be set by clear");
- return frame(sender_sp());
+ return frame(sender_sp(), sp() + 1);
}
frame frame::sender_for_interpreter_frame(RegisterMap *map) const {
- return frame(sender_sp());
+ return frame(sender_sp(), sp() + 1);
}
frame frame::sender_for_compiled_frame(RegisterMap *map) const {
- return frame(sender_sp());
+ return frame(sender_sp(), sp() + 1);
}
frame frame::sender_for_deoptimizer_frame(RegisterMap *map) const {
- return frame(sender_sp());
+ return frame(sender_sp(), sp() + 1);
}
frame frame::sender(RegisterMap* map) const {
@@ -180,3 +180,243 @@
int index = (Interpreter::expr_offset_in_bytes(offset) / wordSize);
return &interpreter_frame_tos_address()[index];
}
+
+void frame::zero_print_on_error(int frame_index,
+ outputStream* st,
+ char* buf,
+ int buflen) const {
+ // Divide the buffer between the field and the value
+ buflen >>= 1;
+ char *fieldbuf = buf;
+ char *valuebuf = buf + buflen;
+
+ // Print each word of the frame
+ for (intptr_t *addr = fp(); addr <= sp(); addr++) {
+ int offset = sp() - addr;
+
+ // Fill in default values, then try and improve them
+ snprintf(fieldbuf, buflen, "word[%d]", offset);
+ snprintf(valuebuf, buflen, PTR_FORMAT, *addr);
+ zeroframe()->identify_word(frame_index, offset, fieldbuf, valuebuf, buflen);
+ fieldbuf[buflen - 1] = '\0';
+ valuebuf[buflen - 1] = '\0';
+
+ // Print the result
+ st->print_cr(" " PTR_FORMAT ": %-21s = %s", addr, fieldbuf, valuebuf);
+ }
+}
+
+void ZeroFrame::identify_word(int frame_index,
+ int offset,
+ char* fieldbuf,
+ char* valuebuf,
+ int buflen) const {
+ switch (offset) {
+ case next_frame_off:
+ strncpy(fieldbuf, "next_frame", buflen);
+ break;
+
+ case frame_type_off:
+ strncpy(fieldbuf, "frame_type", buflen);
+ if (is_entry_frame())
+ strncpy(valuebuf, "ENTRY_FRAME", buflen);
+ else if (is_interpreter_frame())
+ strncpy(valuebuf, "INTERPRETER_FRAME", buflen);
+ else if (is_shark_frame())
+ strncpy(valuebuf, "SHARK_FRAME", buflen);
+ else if (is_deoptimizer_frame())
+ strncpy(valuebuf, "DEOPTIMIZER_FRAME", buflen);
+ break;
+
+ default:
+ if (is_entry_frame()) {
+ as_entry_frame()->identify_word(
+ frame_index, offset, fieldbuf, valuebuf, buflen);
+ }
+ else if (is_interpreter_frame()) {
+ as_interpreter_frame()->identify_word(
+ frame_index, offset, fieldbuf, valuebuf, buflen);
+ }
+ else if (is_shark_frame()) {
+ as_shark_frame()->identify_word(
+ frame_index, offset, fieldbuf, valuebuf, buflen);
+ }
+ else if (is_deoptimizer_frame()) {
+ as_deoptimizer_frame()->identify_word(
+ frame_index, offset, fieldbuf, valuebuf, buflen);
+ }
+ }
+}
+
+void EntryFrame::identify_word(int frame_index,
+ int offset,
+ char* fieldbuf,
+ char* valuebuf,
+ int buflen) const {
+ switch (offset) {
+ case call_wrapper_off:
+ strncpy(fieldbuf, "call_wrapper", buflen);
+ break;
+
+ default:
+ snprintf(fieldbuf, buflen, "local[%d]", offset - 3);
+ }
+}
+
+void InterpreterFrame::identify_word(int frame_index,
+ int offset,
+ char* fieldbuf,
+ char* valuebuf,
+ int buflen) const {
+ interpreterState istate = interpreter_state();
+ bool is_valid = istate->self_link() == istate;
+ intptr_t *addr = addr_of_word(offset);
+
+ // Fixed part
+ if (addr >= (intptr_t *) istate) {
+ const char *field = istate->name_of_field_at_address((address) addr);
+ if (field) {
+ if (is_valid && !strcmp(field, "_method")) {
+ istate->method()->name_and_sig_as_C_string(valuebuf, buflen);
+ }
+ else if (is_valid && !strcmp(field, "_bcp") && istate->bcp()) {
+ snprintf(valuebuf, buflen, PTR_FORMAT " (bci %d)",
+ istate->bcp(), istate->method()->bci_from(istate->bcp()));
+ }
+ snprintf(fieldbuf, buflen, "%sistate->%s",
+ field[strlen(field) - 1] == ')' ? "(": "", field);
+ }
+ else if (addr == (intptr_t *) istate) {
+ strncpy(fieldbuf, "(vtable for istate)", buflen);
+ }
+ return;
+ }
+
+ // Variable part
+ if (!is_valid)
+ return;
+
+ // JNI stuff
+ if (istate->method()->is_native() && addr < istate->stack_base()) {
+ address hA = istate->method()->signature_handler();
+ if (hA != NULL) {
+ if (hA != (address) InterpreterRuntime::slow_signature_handler) {
+ InterpreterRuntime::SignatureHandler *handler =
+ InterpreterRuntime::SignatureHandler::from_handlerAddr(hA);
+
+ intptr_t *params = istate->stack_base() - handler->argument_count();
+ if (addr >= params) {
+ int param = addr - params;
+ const char *desc = "";
+ if (param == 0)
+ desc = " (JNIEnv)";
+ else if (param == 1) {
+ if (istate->method()->is_static())
+ desc = " (mirror)";
+ else
+ desc = " (this)";
+ }
+ snprintf(fieldbuf, buflen, "parameter[%d]%s", param, desc);
+ return;
+ }
+
+ for (int i = 0; i < handler->argument_count(); i++) {
+ if (params[i] == (intptr_t) addr) {
+ snprintf(fieldbuf, buflen, "unboxed parameter[%d]", i);
+ return;
+ }
+ }
+ }
+ }
+ return;
+ }
+
+ // Monitors and stack
+ identify_vp_word(frame_index, addr,
+ (intptr_t *) istate->monitor_base(),
+ istate->stack_base(),
+ fieldbuf, buflen);
+}
+
+void SharkFrame::identify_word(int frame_index,
+ int offset,
+ char* fieldbuf,
+ char* valuebuf,
+ int buflen) const {
+ // Fixed part
+ switch (offset) {
+ case pc_off:
+ strncpy(fieldbuf, "pc", buflen);
+ if (method()->is_oop()) {
+ nmethod *code = method()->code();
+ if (code && code->pc_desc_at(pc())) {
+ SimpleScopeDesc ssd(code, pc());
+ snprintf(valuebuf, buflen, PTR_FORMAT " (bci %d)", pc(), ssd.bci());
+ }
+ }
+ return;
+
+ case unextended_sp_off:
+ strncpy(fieldbuf, "unextended_sp", buflen);
+ return;
+
+ case method_off:
+ strncpy(fieldbuf, "method", buflen);
+ if (method()->is_oop()) {
+ method()->name_and_sig_as_C_string(valuebuf, buflen);
+ }
+ return;
+
+ case oop_tmp_off:
+ strncpy(fieldbuf, "oop_tmp", buflen);
+ return;
+ }
+
+ // Variable part
+ if (method()->is_oop()) {
+ identify_vp_word(frame_index, addr_of_word(offset),
+ addr_of_word(header_words + 1),
+ unextended_sp() + method()->max_stack(),
+ fieldbuf, buflen);
+ }
+}
+
+void ZeroFrame::identify_vp_word(int frame_index,
+ intptr_t* addr,
+ intptr_t* monitor_base,
+ intptr_t* stack_base,
+ char* fieldbuf,
+ int buflen) const {
+ // Monitors
+ if (addr >= stack_base && addr < monitor_base) {
+ int monitor_size = frame::interpreter_frame_monitor_size();
+ int last_index = (monitor_base - stack_base) / monitor_size - 1;
+ int index = last_index - (addr - stack_base) / monitor_size;
+ intptr_t monitor = (intptr_t) (
+ (BasicObjectLock *) monitor_base - 1 - index);
+ intptr_t offset = (intptr_t) addr - monitor;
+
+ if (offset == BasicObjectLock::obj_offset_in_bytes())
+ snprintf(fieldbuf, buflen, "monitor[%d]->_obj", index);
+ else if (offset == BasicObjectLock::lock_offset_in_bytes())
+ snprintf(fieldbuf, buflen, "monitor[%d]->_lock", index);
+
+ return;
+ }
+
+ // Expression stack
+ if (addr < stack_base) {
+ snprintf(fieldbuf, buflen, "%s[%d]",
+ frame_index == 0 ? "stack_word" : "local",
+ (int) (stack_base - addr - 1));
+ return;
+ }
+}
+
+void DeoptimizerFrame::identify_word(int frame_index,
+ int offset,
+ char* fieldbuf,
+ char* valuebuf,
+ int buflen) const {
+ // Deoptimizer frames have no extra words to identify
+}
diff -r 175266c8ad02 ports/hotspot/src/cpu/zero/vm/frame_zero.hpp
--- a/ports/hotspot/src/cpu/zero/vm/frame_zero.hpp Tue Sep 08 11:47:14 2009 +0100
+++ b/ports/hotspot/src/cpu/zero/vm/frame_zero.hpp Wed Sep 09 04:44:36 2009 -0400
@@ -23,24 +23,26 @@
*
*/
-// A frame represents a physical stack frame (an activation). Frames
-// can be C or Java frames, and the Java frames can be interpreted or
-// compiled. In contrast, vframes represent source-level activations,
-// so that one physical frame can correspond to multiple source level
-// frames because of inlining. A frame is comprised of {pc, sp}
+// A frame represents a physical stack frame on the Zero stack.
public:
enum {
pc_return_offset = 0
};
+ // Constructor
public:
- // Constructors
- frame(intptr_t* sp);
+ frame(intptr_t* sp, intptr_t* fp);
- // accessors for the instance variables
+ // The sp of a Zero frame is the address of the highest word in
+ // that frame. We keep track of the lowest address too, so the
+ // boundaries of the frame are available for debug printing.
+ private:
+ intptr_t* _fp;
+
+ public:
intptr_t* fp() const {
- return (intptr_t *) -1;
+ return _fp;
}
#ifdef CC_INTERP
@@ -67,3 +69,9 @@
public:
frame sender_for_deoptimizer_frame(RegisterMap* map) const;
+
+ public:
+ void zero_print_on_error(int index,
+ outputStream* st,
+ char* buf,
+ int buflen) const;
diff -r 175266c8ad02 ports/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp
--- a/ports/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp Tue Sep 08 11:47:14 2009 +0100
+++ b/ports/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp Wed Sep 09 04:44:36 2009 -0400
@@ -1,6 +1,6 @@
/*
* Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright 2007, 2008 Red Hat, Inc.
+ * Copyright 2007, 2008, 2009 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
@@ -32,13 +32,15 @@
inline frame::frame() {
_sp = NULL;
+ _fp = NULL;
_pc = NULL;
_cb = NULL;
_deopt_state = unknown;
}
-inline frame::frame(intptr_t* sp) {
+inline frame::frame(intptr_t* sp, intptr_t* fp) {
_sp = sp;
+ _fp = fp;
switch (zeroframe()->type()) {
case ZeroFrame::ENTRY_FRAME:
_pc = StubRoutines::call_stub_return_pc();
diff -r 175266c8ad02 ports/hotspot/src/cpu/zero/vm/interpreterFrame_zero.hpp
--- a/ports/hotspot/src/cpu/zero/vm/interpreterFrame_zero.hpp Tue Sep 08 11:47:14 2009 +0100
+++ b/ports/hotspot/src/cpu/zero/vm/interpreterFrame_zero.hpp Wed Sep 09 04:44:36 2009 -0400
@@ -65,5 +65,12 @@
interpreterState interpreter_state() const {
return (interpreterState) addr_of_word(istate_off);
}
+
+ public:
+ void identify_word(int frame_index,
+ int offset,
+ char* fieldbuf,
+ char* valuebuf,
+ int buflen) const;
};
#endif // CC_INTERP
diff -r 175266c8ad02 ports/hotspot/src/cpu/zero/vm/sharkFrame_zero.hpp
--- a/ports/hotspot/src/cpu/zero/vm/sharkFrame_zero.hpp Tue Sep 08 11:47:14 2009 +0100
+++ b/ports/hotspot/src/cpu/zero/vm/sharkFrame_zero.hpp Wed Sep 09 04:44:36 2009 -0400
@@ -70,4 +70,11 @@
methodOop method() const {
return (methodOop) value_of_word(method_off);
}
+
+ public:
+ void identify_word(int frame_index,
+ int offset,
+ char* fieldbuf,
+ char* valuebuf,
+ int buflen) const;
};
diff -r 175266c8ad02 ports/hotspot/src/cpu/zero/vm/stackPrinter_zero.hpp
--- a/ports/hotspot/src/cpu/zero/vm/stackPrinter_zero.hpp Tue Sep 08 11:47:14 2009 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,291 +0,0 @@
-/*
- * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright 2008, 2009 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- */
-
-#include <interpreterRuntime.hpp>
-#include <scopeDesc.hpp>
-
-class ZeroStackPrinter {
- private:
- outputStream* _st;
- char* _buf;
- int _buflen;
-
- public:
- ZeroStackPrinter(outputStream *st, char *buf, int buflen)
- : _st(st), _buf(buf), _buflen(buflen) {}
-
- void print(JavaThread *thread) {
- intptr_t *lo_addr = thread->zero_stack()->sp();
- if (!lo_addr) {
- _st->print_cr(" stack not set up");
- return;
- }
-
- intptr_t *hi_addr = (intptr_t *) thread->top_zero_frame();
- if (!hi_addr) {
- _st->print_cr("no frames pushed");
- return;
- }
- assert(hi_addr >= lo_addr, "corrupted stack");
-
- bool top_frame = true;
- while (hi_addr) {
- if (!top_frame)
- _st->cr();
- ZeroFrame *frame = (ZeroFrame *) hi_addr;
- for (intptr_t *addr = lo_addr; addr <= hi_addr; addr++)
- print_word(frame, addr, top_frame);
- lo_addr = hi_addr + 1;
- hi_addr = *(intptr_t **) hi_addr;
- top_frame = false;
- }
- }
-
- private:
- void print_word(ZeroFrame *frame, intptr_t *addr, bool top_frame) {
- const char *field = NULL;
- const char *value = NULL;
-
- int word = (intptr_t *) frame - addr;
- switch (word) {
- case ZeroFrame::next_frame_off:
- field = "next_frame";
- break;
- case ZeroFrame::frame_type_off:
- field = "frame_type";
- switch (*addr) {
- case ZeroFrame::ENTRY_FRAME:
- value = "ENTRY_FRAME";
- break;
- case ZeroFrame::INTERPRETER_FRAME:
- value = "INTERPRETER_FRAME";
- break;
- case ZeroFrame::SHARK_FRAME:
- value = "SHARK_FRAME";
- break;
- case ZeroFrame::DEOPTIMIZER_FRAME:
- value = "DEOPTIMIZER_FRAME";
- break;
- }
- break;
- }
-
- if (!field) {
- if (frame->is_entry_frame()) {
- if (word == EntryFrame::call_wrapper_off) {
- field = "call_wrapper";
- }
- else {
- snprintf(_buf, _buflen, "local[%d]", word - 3);
- field = _buf;
- }
- }
- if (frame->is_interpreter_frame()) {
- interpreterState istate =
- ((InterpreterFrame *) frame)->interpreter_state();
- bool is_valid = istate->self_link() == istate;
-
- if (addr >= (intptr_t *) istate) {
- field = istate->name_of_field_at_address((address) addr);
- if (field) {
- if (is_valid && !strcmp(field, "_method")) {
- value = istate->method()->name_and_sig_as_C_string(_buf,_buflen);
- field = "istate->_method";
- }
- else if (is_valid && !strcmp(field, "_bcp") && istate->bcp()) {
- snprintf(_buf, _buflen, PTR_FORMAT " (bci %d)", istate->bcp(),
- istate->method()->bci_from(istate->bcp()));
- value = _buf;
- field = "istate->_bcp";
- }
- else {
- snprintf(_buf, _buflen, "%sistate->%s",
- field[strlen(field) - 1] == ')' ? "(": "", field);
- field = _buf;
- }
- }
- else if (addr == (intptr_t *) istate) {
- field = "(vtable for istate)";
- }
- }
- else if (is_valid) {
- intptr_t *monitor_base = (intptr_t *) istate->monitor_base();
- if (addr >= istate->stack_base() && addr < monitor_base) {
- int monitor_size = frame::interpreter_frame_monitor_size();
- int last_index =
- (monitor_base - istate->stack_base()) / monitor_size - 1;
- int index =
- last_index - (addr - istate->stack_base()) / monitor_size;
- intptr_t monitor = (intptr_t) (istate->monitor_base() - 1 - index);
- intptr_t offset = (intptr_t) addr - monitor;
-
- if (offset == BasicObjectLock::obj_offset_in_bytes()) {
- snprintf(_buf, _buflen, "monitor[%d]->_obj", index);
- field = _buf;
- }
- else if (offset == BasicObjectLock::lock_offset_in_bytes()) {
- snprintf(_buf, _buflen, "monitor[%d]->_lock", index);
- field = _buf;
- }
- }
- else if (addr < istate->stack_base()) {
- if (istate->method()->is_native()) {
- address hA = istate->method()->signature_handler();
- if (hA != NULL) {
- if (hA != (address)InterpreterRuntime::slow_signature_handler){
- InterpreterRuntime::SignatureHandler *handler =
- InterpreterRuntime::SignatureHandler::from_handlerAddr(hA);
-
- intptr_t *params =
- istate->stack_base() - handler->argument_count();
-
- if (addr >= params) {
- int param = addr - params;
- const char *desc = "";
- if (param == 0)
- desc = " (JNIEnv)";
- else if (param == 1) {
- if (istate->method()->is_static())
- desc = " (mirror)";
- else
- desc = " (this)";
- }
- snprintf(_buf, _buflen, "parameter[%d]%s", param, desc);
- field = _buf;
- }
- else {
- for (int i = 0; i < handler->argument_count(); i++) {
- if (params[i] == (intptr_t) addr) {
- snprintf(_buf, _buflen, "unboxed parameter[%d]", i);
- field = _buf;
- break;
- }
- }
- }
- }
- }
- }
- else {
- snprintf(_buf, _buflen, "%s[" INTPTR_FORMAT "]",
- top_frame ? "stack_word" : "local",
- istate->stack_base() - addr - 1);
- field = _buf;
- }
- }
- }
- }
- if (frame->is_shark_frame()) {
- SharkFrame *sf = frame->as_shark_frame();
- methodOop method = sf->method();
-
- if (word == SharkFrame::pc_off) {
- field = "pc";
- if (method->is_oop()) {
- nmethod *code = method->code();
- address pc = sf->pc();
- if (code->pc_desc_at(pc)) {
- SimpleScopeDesc ssd(code, pc);
- snprintf(_buf, _buflen, PTR_FORMAT " (bci %d)", pc, ssd.bci());
- value = _buf;
- }
- }
- }
- else if (word == SharkFrame::unextended_sp_off) {
- field = "unextended_sp";
- }
- else if (word == SharkFrame::method_off) {
- field = "method";
- if (method->is_oop())
- value = method->name_and_sig_as_C_string(_buf, _buflen);
- }
- else if (word == SharkFrame::oop_tmp_off) {
- field = "oop_tmp";
- }
- else {
- SharkFrame *sf = (SharkFrame *) frame;
- intptr_t *monitor_base =
- (intptr_t *) frame - SharkFrame::header_words + 1;
- intptr_t *stack_base =
- sf->unextended_sp() + sf->method()->max_stack();
-
- if (addr >= stack_base && addr < monitor_base) {
- int monitor_size = frame::interpreter_frame_monitor_size();
- int last_index = (monitor_base - stack_base) / monitor_size - 1;
- int index = last_index - (addr - stack_base) / monitor_size;
- intptr_t monitor =
- (intptr_t) ((BasicObjectLock *) monitor_base - 1 - index);
- intptr_t offset = (intptr_t) addr - monitor;
-
- if (offset == BasicObjectLock::obj_offset_in_bytes()) {
- snprintf(_buf, _buflen, "monitor[%d]->_obj", index);
- field = _buf;
- }
- else if (offset == BasicObjectLock::lock_offset_in_bytes()) {
- snprintf(_buf, _buflen, "monitor[%d]->_lock", index);
- field = _buf;
- }
- }
- else {
- snprintf(_buf, _buflen, "%s[" INTPTR_FORMAT "]",
- top_frame ? "stack_word" : "local",
- stack_base - addr - 1);
- field = _buf;
- }
- }
- }
- }
-
- if (!field) {
- snprintf(_buf, _buflen, "word[%d]", word);
- field = _buf;
- }
- _st->print(" %p: %-21s = ", addr, field);
- if (value)
- _st->print_cr("%s", value);
- else
- _st->print_cr(PTR_FORMAT, *addr);
- }
-};
-
-#ifndef PRODUCT
-extern "C" {
- void print_zero_threads() {
- char buf[O_BUFLEN];
- ZeroStackPrinter zsp(tty, buf, sizeof(buf));
-
- for (JavaThread *t = Threads::first(); t; t = t->next()) {
- tty->print(PTR_FORMAT, t);
- tty->print(" ");
- t->print_on_error(tty, buf, sizeof(buf));
- tty->cr();
- tty->cr();
-
- zsp.print(t);
- if (t->next())
- tty->cr();
- }
- }
-}
-#endif // !PRODUCT
diff -r 175266c8ad02 ports/hotspot/src/cpu/zero/vm/stack_zero.hpp
--- a/ports/hotspot/src/cpu/zero/vm/stack_zero.hpp Tue Sep 08 11:47:14 2009 +0100
+++ b/ports/hotspot/src/cpu/zero/vm/stack_zero.hpp Wed Sep 09 04:44:36 2009 -0400
@@ -179,4 +179,19 @@
assert(is_deoptimizer_frame(), "should be");
return (DeoptimizerFrame *) this;
}
+
+ public:
+ void identify_word(int frame_index,
+ int offset,
+ char* fieldbuf,
+ char* valuebuf,
+ int buflen) const;
+
+ protected:
+ void identify_vp_word(int frame_index,
+ intptr_t* addr,
+ intptr_t* monitor_base,
+ intptr_t* stack_base,
+ char* fieldbuf,
+ int buflen) const;
};
diff -r 175266c8ad02 ports/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp
--- a/ports/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp Tue Sep 08 11:47:14 2009 +0100
+++ b/ports/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp Wed Sep 09 04:44:36 2009 -0400
@@ -36,7 +36,18 @@
}
frame os::current_frame() {
- Unimplemented();
+ // The only thing that calls this is the stack printing code in
+ // VMError::report:
+ // - Step 110 (printing stack bounds) uses the sp in the frame
+ // to determine the amount of free space on the stack. We
+ // set the sp to a close approximation of the real value in
+ // order to allow this step to complete.
+ // - Step 120 (printing native stack) tries to walk the stack.
+ // The frame we create has a NULL pc, which is ignored as an
+ // invalid frame.
+ frame dummy = frame();
+ dummy.set_sp((intptr_t *) current_stack_pointer());
+ return dummy;
}
char* os::non_memory_address_word() {
diff -r 175266c8ad02 ports/hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp
--- a/ports/hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp Tue Sep 08 11:47:14 2009 +0100
+++ b/ports/hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp Wed Sep 09 04:44:36 2009 -0400
@@ -79,7 +79,7 @@
private:
frame pd_last_frame() {
assert(has_last_Java_frame(), "must have last_Java_sp() when suspended");
- return frame(last_Java_sp());
+ return frame(last_Java_sp(), zero_stack()->sp());
}
public:
More information about the distro-pkg-dev
mailing list