Mercurial > hg > graal-compiler
diff src/share/vm/runtime/vframe.cpp @ 20501:c204e2044c29
8038624: interpretedVFrame::expressions() must respect InterpreterOopMap for liveness
Reviewed-by: coleenp, minqi
author | mgronlun |
---|---|
date | Mon, 29 Sep 2014 13:12:48 +0200 |
parents | 4a1062dc52d1 |
children | 7848fc12602b |
line wrap: on
line diff
--- a/src/share/vm/runtime/vframe.cpp Fri Sep 26 03:42:38 2014 -0700 +++ b/src/share/vm/runtime/vframe.cpp Mon Sep 29 13:12:48 2014 +0200 @@ -260,65 +260,156 @@ 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) { + + assert(index >= 0 && + index < oop_mask.number_of_entries(), "invariant"); - 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(); + // 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); +} + +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, + int max_locals, + 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 + max_locals, + 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 == expressions) + * + */ +StackValueCollection* interpretedVFrame::stack_data(bool expressions) const { + InterpreterOopMap oop_mask; + // oopmap for current bci if (TraceDeoptimization && Verbose) { - methodHandle m_h(thread(), method()); + 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, max_locals, 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())(); @@ -328,46 +419,6 @@ } } -StackValueCollection* interpretedVFrame::expressions() const { - int length = fr().interpreter_frame_expression_stack_size(); - if (method()->is_native()) { - // If the method is native, there is no expression stack - length = 0; - } - - int nof_locals = method()->max_locals(); - StackValueCollection* result = new StackValueCollection(length); - - InterpreterOopMap oop_mask; - // Get oopmap describing oops and int for current bci - if (TraceDeoptimization && Verbose) { - methodHandle m_h(method()); - OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask); - } else { - method()->mask_for(bci(), &oop_mask); - } - // 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)