changeset 1696:97bab225c4d6

2009-09-09 Gary Benson <gbenson@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.
author Gary Benson <gbenson@redhat.com>
date Wed, 09 Sep 2009 04:45:17 -0400
parents 175266c8ad02
children 6aed937c788b
files ChangeLog patches/icedtea-zero.patch ports/hotspot/src/cpu/zero/vm/deoptimizerFrame_zero.hpp ports/hotspot/src/cpu/zero/vm/entryFrame_zero.hpp ports/hotspot/src/cpu/zero/vm/frame_zero.cpp ports/hotspot/src/cpu/zero/vm/frame_zero.hpp ports/hotspot/src/cpu/zero/vm/frame_zero.inline.hpp ports/hotspot/src/cpu/zero/vm/interpreterFrame_zero.hpp ports/hotspot/src/cpu/zero/vm/sharkFrame_zero.hpp ports/hotspot/src/cpu/zero/vm/stackPrinter_zero.hpp ports/hotspot/src/cpu/zero/vm/stack_zero.hpp ports/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp ports/hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp
diffstat 13 files changed, 421 insertions(+), 353 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Tue Sep 08 11:47:14 2009 +0100
+++ b/ChangeLog	Wed Sep 09 04:45:17 2009 -0400
@@ -1,3 +1,50 @@
+2009-09-09  Gary Benson  <gbenson@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@redhat.com>
 
 	* ports/hotspot/src/cpu/zero/vm/stack_zero.hpp: Whitespace changes.
--- a/patches/icedtea-zero.patch	Tue Sep 08 11:47:14 2009 +0100
+++ b/patches/icedtea-zero.patch	Wed Sep 09 04:45:17 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
--- 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:45:17 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;
 };
--- 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:45:17 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;
 };
--- 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:45:17 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
+}
--- 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:45:17 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;
--- 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:45:17 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();
--- 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:45:17 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
--- 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:45:17 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;
 };
--- 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
--- 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:45:17 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;
 };
--- 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:45:17 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() {
--- 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:45:17 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: