aboutsummaryrefslogtreecommitdiff
path: root/src/share
diff options
context:
space:
mode:
authornever <none@none>2011-05-02 18:53:37 -0700
committernever <none@none>2011-05-02 18:53:37 -0700
commit81bee76dcb7c4a57fa21cb0692672fe2310754f6 (patch)
tree29fb538b4d292d2dddf5a0d7b9e8949cbffe9206 /src/share
parent89494cf4ded68cf30fc20e772e36016f269dd3d0 (diff)
7009361: JSR 292 Invalid value on stack on solaris-sparc with -Xcomp
Reviewed-by: kvn, twisti
Diffstat (limited to 'src/share')
-rw-r--r--src/share/vm/opto/loopPredicate.cpp23
-rw-r--r--src/share/vm/runtime/deoptimization.cpp26
-rw-r--r--src/share/vm/runtime/frame.cpp134
-rw-r--r--src/share/vm/runtime/frame.hpp41
-rw-r--r--src/share/vm/runtime/thread.cpp20
-rw-r--r--src/share/vm/runtime/thread.hpp6
-rw-r--r--src/share/vm/utilities/debug.cpp12
7 files changed, 250 insertions, 12 deletions
diff --git a/src/share/vm/opto/loopPredicate.cpp b/src/share/vm/opto/loopPredicate.cpp
index c5ac2c682..d436a572c 100644
--- a/src/share/vm/opto/loopPredicate.cpp
+++ b/src/share/vm/opto/loopPredicate.cpp
@@ -700,32 +700,35 @@ BoolNode* PhaseIdealLoop::rc_predicate(Node* ctrl,
int scale, Node* offset,
Node* init, Node* limit, Node* stride,
Node* range, bool upper) {
- DEBUG_ONLY(ttyLocker ttyl);
- if (TraceLoopPredicate) tty->print("rc_predicate ");
+ stringStream* predString = NULL;
+ if (TraceLoopPredicate) {
+ predString = new stringStream();
+ predString->print("rc_predicate ");
+ }
Node* max_idx_expr = init;
int stride_con = stride->get_int();
if ((stride_con > 0) == (scale > 0) == upper) {
max_idx_expr = new (C, 3) SubINode(limit, stride);
register_new_node(max_idx_expr, ctrl);
- if (TraceLoopPredicate) tty->print("(limit - stride) ");
+ if (TraceLoopPredicate) predString->print("(limit - stride) ");
} else {
- if (TraceLoopPredicate) tty->print("init ");
+ if (TraceLoopPredicate) predString->print("init ");
}
if (scale != 1) {
ConNode* con_scale = _igvn.intcon(scale);
max_idx_expr = new (C, 3) MulINode(max_idx_expr, con_scale);
register_new_node(max_idx_expr, ctrl);
- if (TraceLoopPredicate) tty->print("* %d ", scale);
+ if (TraceLoopPredicate) predString->print("* %d ", scale);
}
if (offset && (!offset->is_Con() || offset->get_int() != 0)){
max_idx_expr = new (C, 3) AddINode(max_idx_expr, offset);
register_new_node(max_idx_expr, ctrl);
if (TraceLoopPredicate)
- if (offset->is_Con()) tty->print("+ %d ", offset->get_int());
- else tty->print("+ offset ");
+ if (offset->is_Con()) predString->print("+ %d ", offset->get_int());
+ else predString->print("+ offset ");
}
CmpUNode* cmp = new (C, 3) CmpUNode(max_idx_expr, range);
@@ -733,7 +736,10 @@ BoolNode* PhaseIdealLoop::rc_predicate(Node* ctrl,
BoolNode* bol = new (C, 2) BoolNode(cmp, BoolTest::lt);
register_new_node(bol, ctrl);
- if (TraceLoopPredicate) tty->print_cr("<u range");
+ if (TraceLoopPredicate) {
+ predString->print_cr("<u range");
+ tty->print(predString->as_string());
+ }
return bol;
}
@@ -957,4 +963,3 @@ bool IdealLoopTree::loop_predication( PhaseIdealLoop *phase) {
return hoisted;
}
-
diff --git a/src/share/vm/runtime/deoptimization.cpp b/src/share/vm/runtime/deoptimization.cpp
index 3e03486d3..10ebd8364 100644
--- a/src/share/vm/runtime/deoptimization.cpp
+++ b/src/share/vm/runtime/deoptimization.cpp
@@ -189,6 +189,10 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread
assert(thread->deopt_nmethod() == NULL, "Pending deopt!");
thread->set_deopt_nmethod(deoptee.cb()->as_nmethod_or_null());
+ if (VerifyStack) {
+ thread->validate_frame_layout();
+ }
+
// Create a growable array of VFrames where each VFrame represents an inlined
// Java frame. This storage is allocated with the usual system arena.
assert(deoptee.is_compiled_frame(), "Wrong frame type");
@@ -421,6 +425,21 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread
frame deopt_sender = stub_frame.sender(&dummy_map); // First is the deoptee frame
deopt_sender = deopt_sender.sender(&dummy_map); // Now deoptee caller
+ // It's possible that the number of paramters at the call site is
+ // different than number of arguments in the callee when method
+ // handles are used. If the caller is interpreted get the real
+ // value so that the proper amount of space can be added to it's
+ // frame.
+ int sender_callee_parameters = callee_parameters;
+ if (deopt_sender.is_interpreted_frame()) {
+ methodHandle method = deopt_sender.interpreter_frame_method();
+ Bytecode_invoke cur = Bytecode_invoke_check(method,
+ deopt_sender.interpreter_frame_bci());
+ Symbol* signature = method->constants()->signature_ref_at(cur.index());
+ ArgumentSizeComputer asc(signature);
+ sender_callee_parameters = asc.size() + cur.has_receiver() ? 1 : 0;
+ }
+
// Compute the amount the oldest interpreter frame will have to adjust
// its caller's stack by. If the caller is a compiled frame then
// we pretend that the callee has no parameters so that the
@@ -435,14 +454,13 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread
if (deopt_sender.is_compiled_frame()) {
caller_adjustment = last_frame_adjust(0, callee_locals);
- } else if (callee_locals > callee_parameters) {
+ } else if (callee_locals > sender_callee_parameters) {
// The caller frame may need extending to accommodate
// non-parameter locals of the first unpacked interpreted frame.
// Compute that adjustment.
- caller_adjustment = last_frame_adjust(callee_parameters, callee_locals);
+ caller_adjustment = last_frame_adjust(sender_callee_parameters, callee_locals);
}
-
// If the sender is deoptimized the we must retrieve the address of the handler
// since the frame will "magically" show the original pc before the deopt
// and we'd undo the deopt.
@@ -569,6 +587,8 @@ JRT_LEAF(BasicType, Deoptimization::unpack_frames(JavaThread* thread, int exec_m
if (VerifyStack) {
ResourceMark res_mark;
+ thread->validate_frame_layout();
+
// Verify that the just-unpacked frames match the interpreter's
// notions of expression stack and locals
vframeArray* cur_array = thread->vframe_array_last();
diff --git a/src/share/vm/runtime/frame.cpp b/src/share/vm/runtime/frame.cpp
index 5c205501a..b5352fc00 100644
--- a/src/share/vm/runtime/frame.cpp
+++ b/src/share/vm/runtime/frame.cpp
@@ -1308,6 +1308,72 @@ void frame::interpreter_frame_verify_monitor(BasicObjectLock* value) const {
guarantee((current - low_mark) % monitor_size == 0 , "Misaligned bottom of BasicObjectLock*");
guarantee( current >= low_mark , "Current BasicObjectLock* below than low_mark");
}
+
+
+void frame::describe(FrameValues& values, int frame_no) {
+ if (is_entry_frame() || is_compiled_frame() || is_interpreted_frame() || is_native_frame()) {
+ // Label values common to most frames
+ values.describe(-1, unextended_sp(), err_msg("unextended_sp for #%d", frame_no));
+ values.describe(-1, sp(), err_msg("sp for #%d", frame_no));
+ values.describe(-1, fp(), err_msg("fp for #%d", frame_no));
+ }
+ if (is_interpreted_frame()) {
+ methodOop m = interpreter_frame_method();
+ int bci = interpreter_frame_bci();
+
+ // Label the method and current bci
+ values.describe(-1, MAX2(sp(), fp()),
+ FormatBuffer<1024>("#%d method %s @ %d", frame_no, m->name_and_sig_as_C_string(), bci), 2);
+ values.describe(-1, MAX2(sp(), fp()),
+ err_msg("- %d locals %d max stack", m->max_locals(), m->max_stack()), 1);
+ if (m->max_locals() > 0) {
+ intptr_t* l0 = interpreter_frame_local_at(0);
+ intptr_t* ln = interpreter_frame_local_at(m->max_locals() - 1);
+ values.describe(-1, MAX2(l0, ln), err_msg("locals for #%d", frame_no), 1);
+ // Report each local and mark as owned by this frame
+ for (int l = 0; l < m->max_locals(); l++) {
+ intptr_t* l0 = interpreter_frame_local_at(l);
+ values.describe(frame_no, l0, err_msg("local %d", l));
+ }
+ }
+
+ // Compute the actual expression stack size
+ InterpreterOopMap mask;
+ OopMapCache::compute_one_oop_map(m, bci, &mask);
+ intptr_t* tos = NULL;
+ // Report each stack element and mark as owned by this frame
+ for (int e = 0; e < mask.expression_stack_size(); e++) {
+ tos = MAX2(tos, interpreter_frame_expression_stack_at(e));
+ values.describe(frame_no, interpreter_frame_expression_stack_at(e),
+ err_msg("stack %d", e));
+ }
+ if (tos != NULL) {
+ values.describe(-1, tos, err_msg("expression stack for #%d", frame_no), 1);
+ }
+ if (interpreter_frame_monitor_begin() != interpreter_frame_monitor_end()) {
+ values.describe(frame_no, (intptr_t*)interpreter_frame_monitor_begin(), "monitors begin");
+ values.describe(frame_no, (intptr_t*)interpreter_frame_monitor_end(), "monitors end");
+ }
+ } else if (is_entry_frame()) {
+ // For now just label the frame
+ values.describe(-1, MAX2(sp(), fp()), err_msg("#%d entry frame", frame_no), 2);
+ } else if (is_compiled_frame()) {
+ // For now just label the frame
+ nmethod* nm = cb()->as_nmethod_or_null();
+ values.describe(-1, MAX2(sp(), fp()),
+ FormatBuffer<1024>("#%d nmethod " INTPTR_FORMAT " for method %s%s", frame_no,
+ nm, nm->method()->name_and_sig_as_C_string(),
+ is_deoptimized_frame() ? " (deoptimized" : ""), 2);
+ } else if (is_native_frame()) {
+ // For now just label the frame
+ nmethod* nm = cb()->as_nmethod_or_null();
+ values.describe(-1, MAX2(sp(), fp()),
+ FormatBuffer<1024>("#%d nmethod " INTPTR_FORMAT " for native method %s", frame_no,
+ nm, nm->method()->name_and_sig_as_C_string()), 2);
+ }
+ describe_pd(values, frame_no);
+}
+
#endif
@@ -1319,3 +1385,71 @@ StackFrameStream::StackFrameStream(JavaThread *thread, bool update) : _reg_map(t
_fr = thread->last_frame();
_is_done = false;
}
+
+
+#ifdef ASSERT
+
+void FrameValues::describe(int owner, intptr_t* location, const char* description, int priority) {
+ FrameValue fv;
+ fv.location = location;
+ fv.owner = owner;
+ fv.priority = priority;
+ fv.description = NEW_RESOURCE_ARRAY(char, strlen(description) + 1);
+ strcpy(fv.description, description);
+ _values.append(fv);
+}
+
+
+bool FrameValues::validate() {
+ _values.sort(compare);
+ bool error = false;
+ FrameValue prev;
+ prev.owner = -1;
+ for (int i = _values.length() - 1; i >= 0; i--) {
+ FrameValue fv = _values.at(i);
+ if (fv.owner == -1) continue;
+ if (prev.owner == -1) {
+ prev = fv;
+ continue;
+ }
+ if (prev.location == fv.location) {
+ if (fv.owner != prev.owner) {
+ tty->print_cr("overlapping storage");
+ tty->print_cr(" " INTPTR_FORMAT ": " INTPTR_FORMAT " %s", prev.location, *prev.location, prev.description);
+ tty->print_cr(" " INTPTR_FORMAT ": " INTPTR_FORMAT " %s", fv.location, *fv.location, fv.description);
+ error = true;
+ }
+ } else {
+ prev = fv;
+ }
+ }
+ return error;
+}
+
+
+void FrameValues::print() {
+ _values.sort(compare);
+ intptr_t* v0 = _values.at(0).location;
+ intptr_t* v1 = _values.at(_values.length() - 1).location;
+ intptr_t* min = MIN2(v0, v1);
+ intptr_t* max = MAX2(v0, v1);
+ intptr_t* cur = max;
+ intptr_t* last = NULL;
+ for (int i = _values.length() - 1; i >= 0; i--) {
+ FrameValue fv = _values.at(i);
+ while (cur > fv.location) {
+ tty->print_cr(" " INTPTR_FORMAT ": " INTPTR_FORMAT, cur, *cur);
+ cur--;
+ }
+ if (last == fv.location) {
+ const char* spacer = " " LP64_ONLY(" ");
+ tty->print_cr(" %s %s %s", spacer, spacer, fv.description);
+ } else {
+ tty->print_cr(" " INTPTR_FORMAT ": " INTPTR_FORMAT " %s", fv.location, *fv.location, fv.description);
+ last = fv.location;
+ cur--;
+ }
+ }
+}
+
+#endif
diff --git a/src/share/vm/runtime/frame.hpp b/src/share/vm/runtime/frame.hpp
index a48c2af37..66d17a9f7 100644
--- a/src/share/vm/runtime/frame.hpp
+++ b/src/share/vm/runtime/frame.hpp
@@ -60,6 +60,7 @@
typedef class BytecodeInterpreter* interpreterState;
class CodeBlob;
+class FrameValues;
class vframeArray;
@@ -381,6 +382,8 @@ class frame VALUE_OBJ_CLASS_SPEC {
private:
const char* print_name() const;
+ void describe_pd(FrameValues& values, int frame_no);
+
public:
void print_value() const { print_value_on(tty,NULL); }
void print_value_on(outputStream* st, JavaThread *thread) const;
@@ -388,6 +391,9 @@ class frame VALUE_OBJ_CLASS_SPEC {
void interpreter_frame_print_on(outputStream* st) const;
void print_on_error(outputStream* st, char* buf, int buflen, bool verbose = false) const;
+ // Add annotated descriptions of memory locations belonging to this frame to values
+ void describe(FrameValues& values, int frame_no);
+
// Conversion from an VMReg to physical stack location
oop* oopmapreg_to_location(VMReg reg, const RegisterMap* regmap) const;
@@ -472,6 +478,41 @@ class frame VALUE_OBJ_CLASS_SPEC {
};
+#ifdef ASSERT
+// A simple class to describe a location on the stack
+class FrameValue VALUE_OBJ_CLASS_SPEC {
+ public:
+ intptr_t* location;
+ char* description;
+ int owner;
+ int priority;
+};
+
+
+// A collection of described stack values that can print a symbolic
+// description of the stack memory. Interpreter frame values can be
+// in the caller frames so all the values are collected first and then
+// sorted before being printed.
+class FrameValues {
+ private:
+ GrowableArray<FrameValue> _values;
+
+ static int compare(FrameValue* a, FrameValue* b) {
+ if (a->location == b->location) {
+ return a->priority - b->priority;
+ }
+ return a->location - b->location;
+ }
+
+ public:
+ // Used by frame functions to describe locations.
+ void describe(int owner, intptr_t* location, const char* description, int priority = 0);
+
+ bool validate();
+ void print();
+};
+
+#endif
//
// StackFrameStream iterates through the frames of a thread starting from
diff --git a/src/share/vm/runtime/thread.cpp b/src/share/vm/runtime/thread.cpp
index 6cb2deeb4..02f4e7f49 100644
--- a/src/share/vm/runtime/thread.cpp
+++ b/src/share/vm/runtime/thread.cpp
@@ -31,6 +31,7 @@
#include "compiler/compileBroker.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/linkResolver.hpp"
+#include "interpreter/oopMapCache.hpp"
#include "jvmtifiles/jvmtiEnv.hpp"
#include "memory/oopFactory.hpp"
#include "memory/universe.inline.hpp"
@@ -2860,6 +2861,25 @@ void JavaThread::trace_frames() {
}
+// Print or validate the layout of stack frames
+void JavaThread::print_frame_layout(int depth, bool validate_only) {
+ ResourceMark rm;
+ PRESERVE_EXCEPTION_MARK;
+ FrameValues values;
+ int frame_no = 0;
+ for(StackFrameStream fst(this, false); !fst.is_done(); fst.next()) {
+ fst.current()->describe(values, ++frame_no);
+ if (depth == frame_no) break;
+ }
+ if (validate_only) {
+ values.validate();
+ } else {
+ tty->print_cr("[Describe stack layout]");
+ values.print();
+ }
+}
+
+
void JavaThread::trace_stack_from(vframe* start_vf) {
ResourceMark rm;
int vframe_no = 1;
diff --git a/src/share/vm/runtime/thread.hpp b/src/share/vm/runtime/thread.hpp
index 73e0fda02..eefe93bc7 100644
--- a/src/share/vm/runtime/thread.hpp
+++ b/src/share/vm/runtime/thread.hpp
@@ -1380,6 +1380,12 @@ public:
void trace_stack_from(vframe* start_vf) PRODUCT_RETURN;
void trace_frames() PRODUCT_RETURN;
+ // Print an annotated view of the stack frames
+ void print_frame_layout(int depth = 0, bool validate_only = false) PRODUCT_RETURN;
+ void validate_frame_layout() {
+ print_frame_layout(0, true);
+ }
+
// Returns the number of stack frames on the stack
int depth() const;
diff --git a/src/share/vm/utilities/debug.cpp b/src/share/vm/utilities/debug.cpp
index cb5efc08d..27eaea8b4 100644
--- a/src/share/vm/utilities/debug.cpp
+++ b/src/share/vm/utilities/debug.cpp
@@ -469,6 +469,7 @@ extern "C" void verify() {
extern "C" void pp(void* p) {
Command c("pp");
FlagSetting fl(PrintVMMessages, true);
+ FlagSetting f2(DisplayVMOutput, true);
if (Universe::heap()->is_in(p)) {
oop obj = oop(p);
obj->print();
@@ -507,6 +508,17 @@ extern "C" void ps() { // print stack
}
+extern "C" void pfl() {
+ // print frame layout
+ Command c("pfl");
+ JavaThread* p = JavaThread::active();
+ tty->print(" for thread: ");
+ p->print();
+ tty->cr();
+ if (p->has_last_Java_frame()) {
+ p->print_frame_layout();
+ }
+}
extern "C" void psf() { // print stack frames
{