--- a/hotspot/src/share/vm/runtime/vframe.cpp Thu Jul 03 11:07:51 2014 -0700
+++ b/hotspot/src/share/vm/runtime/vframe.cpp Thu Jul 03 21:37:31 2014 +0200
@@ -260,66 +260,148 @@
return fr().interpreter_frame_method();
}
-StackValueCollection* interpretedVFrame::locals() const {
- int length = method()->max_locals();
+static StackValue* create_stack_value_from_oop_map(const InterpreterOopMap& oop_mask,
+ int index,
+ const intptr_t* const addr) {
+ // categorize using oop_mask
+ if (oop_mask.is_oop(index)) {
+ // reference (oop) "r"
+ Handle h(addr != NULL ? (*(oop*)addr) : (oop)NULL);
+ return new StackValue(h);
+ }
+ // value (integer) "v"
+ return new StackValue(addr != NULL ? *addr : 0);
+}
- if (method()->is_native()) {
- // If the method is native, max_locals is not telling the truth.
- // maxlocals then equals the size of parameters
- length = method()->size_of_parameters();
+static bool is_in_expression_stack(const frame& fr, const intptr_t* const addr) {
+ assert(addr != NULL, "invariant");
+
+ // Ensure to be 'inside' the expresion stack (i.e., addr >= sp for Intel).
+ // In case of exceptions, the expression stack is invalid and the sp
+ // will be reset to express this condition.
+ if (frame::interpreter_frame_expression_stack_direction() > 0) {
+ return addr <= fr.interpreter_frame_tos_address();
}
- StackValueCollection* result = new StackValueCollection(length);
+ return addr >= fr.interpreter_frame_tos_address();
+}
+
+static void stack_locals(StackValueCollection* result,
+ int length,
+ const InterpreterOopMap& oop_mask,
+ const frame& fr) {
+
+ assert(result != NULL, "invariant");
+
+ for (int i = 0; i < length; ++i) {
+ const intptr_t* const addr = fr.interpreter_frame_local_at(i);
+ assert(addr != NULL, "invariant");
+ assert(addr >= fr.sp(), "must be inside the frame");
+
+ StackValue* const sv = create_stack_value_from_oop_map(oop_mask, i, addr);
+ assert(sv != NULL, "sanity check");
+
+ result->add(sv);
+ }
+}
+
+static void stack_expressions(StackValueCollection* result,
+ int length,
+ const InterpreterOopMap& oop_mask,
+ const frame& fr) {
+
+ assert(result != NULL, "invariant");
- // Get oopmap describing oops and int for current bci
+ for (int i = 0; i < length; ++i) {
+ const intptr_t* addr = fr.interpreter_frame_expression_stack_at(i);
+ assert(addr != NULL, "invariant");
+ if (!is_in_expression_stack(fr, addr)) {
+ // Need to ensure no bogus escapes.
+ addr = NULL;
+ }
+ StackValue* const sv = create_stack_value_from_oop_map(oop_mask, i, addr);
+ assert(sv != NULL, "sanity check");
+
+ result->add(sv);
+ }
+}
+
+StackValueCollection* interpretedVFrame::locals() const {
+ return stack_data(false);
+}
+
+StackValueCollection* interpretedVFrame::expressions() const {
+ return stack_data(true);
+}
+
+/*
+ * Worker routine for fetching references and/or values
+ * for a particular bci in the interpretedVFrame.
+ *
+ * Returns data for either "locals" or "expressions",
+ * using bci relative oop_map (oop_mask) information.
+ *
+ * @param expressions bool switch controlling what data to return
+ (false == locals / true == expression)
+ *
+ */
+StackValueCollection* interpretedVFrame::stack_data(bool expressions) const {
+
InterpreterOopMap oop_mask;
+ // oopmap for current bci
if (TraceDeoptimization && Verbose) {
- // need the current JavaThread and not thread()
methodHandle m_h(Thread::current(), method());
OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask);
} else {
method()->mask_for(bci(), &oop_mask);
}
- // handle locals
- for(int i=0; i < length; i++) {
- // Find stack location
- intptr_t *addr = locals_addr_at(i);
+
+ const int mask_len = oop_mask.number_of_entries();
+
+ // If the method is native, method()->max_locals() is not telling the truth.
+ // For our purposes, max locals instead equals the size of parameters.
+ const int max_locals = method()->is_native() ?
+ method()->size_of_parameters() : method()->max_locals();
+
+ assert(mask_len >= max_locals, "invariant");
+
+ const int length = expressions ? mask_len - max_locals : max_locals;
+ assert(length >= 0, "invariant");
- // Depending on oop/int put it in the right package
- StackValue *sv;
- if (oop_mask.is_oop(i)) {
- // oop value
- Handle h(*(oop *)addr);
- sv = new StackValue(h);
- } else {
- // integer
- sv = new StackValue(*addr);
- }
- assert(sv != NULL, "sanity check");
- result->add(sv);
+ StackValueCollection* const result = new StackValueCollection(length);
+
+ if (0 == length) {
+ return result;
}
+
+ if (expressions) {
+ stack_expressions(result, length, oop_mask, fr());
+ } else {
+ stack_locals(result, length, oop_mask, fr());
+ }
+
+ assert(length == result->size(), "invariant");
+
return result;
}
void interpretedVFrame::set_locals(StackValueCollection* values) const {
if (values == NULL || values->size() == 0) return;
- int length = method()->max_locals();
- if (method()->is_native()) {
- // If the method is native, max_locals is not telling the truth.
- // maxlocals then equals the size of parameters
- length = method()->size_of_parameters();
- }
+ // If the method is native, max_locals is not telling the truth.
+ // maxlocals then equals the size of parameters
+ const int max_locals = method()->is_native() ?
+ method()->size_of_parameters() : method()->max_locals();
- assert(length == values->size(), "Mismatch between actual stack format and supplied data");
+ assert(max_locals == values->size(), "Mismatch between actual stack format and supplied data");
// handle locals
- for (int i = 0; i < length; i++) {
+ for (int i = 0; i < max_locals; i++) {
// Find stack location
intptr_t *addr = locals_addr_at(i);
// Depending on oop/int put it in the right package
- StackValue *sv = values->at(i);
+ const StackValue* const sv = values->at(i);
assert(sv != NULL, "sanity check");
if (sv->type() == T_OBJECT) {
*(oop *) addr = (sv->get_obj())();
@@ -329,61 +411,6 @@
}
}
-StackValueCollection* interpretedVFrame::expressions() const {
-
- InterpreterOopMap oop_mask;
-
- if (!method()->is_native()) {
- // Get oopmap describing oops and int for current bci
- if (TraceDeoptimization && Verbose) {
- // need the current JavaThread and not thread()
- methodHandle m_h(Thread::current(), method());
- OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask);
- } else {
- method()->mask_for(bci(), &oop_mask);
- }
- }
-
- // If the bci is a call instruction, i.e. any of the invoke* instructions,
- // the InterpreterOopMap does not include expression/operand stack liveness
- // info in the oop_mask/bit_mask. This can lead to a discrepancy of what
- // is actually on the expression stack compared to what is given by the
- // oop_map. We need to use the length reported in the oop_map.
- int length = oop_mask.expression_stack_size();
-
- assert(fr().interpreter_frame_expression_stack_size() >= length,
- "error in expression stack!");
-
- StackValueCollection* result = new StackValueCollection(length);
-
- if (0 == length) {
- return result;
- }
-
- int nof_locals = method()->max_locals();
-
- // handle expressions
- for(int i=0; i < length; i++) {
- // Find stack location
- intptr_t *addr = fr().interpreter_frame_expression_stack_at(i);
-
- // Depending on oop/int put it in the right package
- StackValue *sv;
- if (oop_mask.is_oop(i + nof_locals)) {
- // oop value
- Handle h(*(oop *)addr);
- sv = new StackValue(h);
- } else {
- // integer
- sv = new StackValue(*addr);
- }
- assert(sv != NULL, "sanity check");
- result->add(sv);
- }
- return result;
-}
-
-
// ------------- cChunk --------------
entryVFrame::entryVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread)