--- old/src/share/vm/code/debugInfoRec.cpp Mon Feb 8 11:00:30 2010 +++ new/src/share/vm/code/debugInfoRec.cpp Mon Feb 8 11:00:30 2010 @@ -282,6 +282,7 @@ int bci, bool reexecute, bool is_method_handle_invoke, + bool return_oop, DebugToken* locals, DebugToken* expressions, DebugToken* monitors) { @@ -296,6 +297,7 @@ // Record flags into pcDesc. last_pd->set_should_reexecute(reexecute); last_pd->set_is_method_handle_invoke(is_method_handle_invoke); + last_pd->set_return_oop(return_oop); // serialize sender stream offest stream()->write_int(sender_stream_offset); --- old/src/share/vm/code/debugInfoRec.hpp Mon Feb 8 11:00:31 2010 +++ new/src/share/vm/code/debugInfoRec.hpp Mon Feb 8 11:00:30 2010 @@ -89,6 +89,7 @@ int bci, bool reexecute, bool is_method_handle_invoke = false, + bool return_oop = false, DebugToken* locals = NULL, DebugToken* expressions = NULL, DebugToken* monitors = NULL); --- old/src/share/vm/code/nmethod.cpp Mon Feb 8 11:00:31 2010 +++ new/src/share/vm/code/nmethod.cpp Mon Feb 8 11:00:31 2010 @@ -988,7 +988,8 @@ PcDesc* pd = pc_desc_at(pc); guarantee(pd != NULL, "scope must be present"); return new ScopeDesc(this, pd->scope_decode_offset(), - pd->obj_decode_offset(), pd->should_reexecute()); + pd->obj_decode_offset(), pd->should_reexecute(), + pd->return_oop()); } @@ -2159,7 +2160,8 @@ PcDesc* pd = pc_desc_at(ic->end_of_call()); assert(pd != NULL, "PcDesc must exist"); for (ScopeDesc* sd = new ScopeDesc(this, pd->scope_decode_offset(), - pd->obj_decode_offset(), pd->should_reexecute()); + pd->obj_decode_offset(), pd->should_reexecute(), + pd->return_oop()); !sd->is_top(); sd = sd->sender()) { sd->verify(); } @@ -2424,7 +2426,8 @@ PcDesc* p = pc_desc_near(begin+1); if (p != NULL && p->real_pc(this) <= end) { return new ScopeDesc(this, p->scope_decode_offset(), - p->obj_decode_offset(), p->should_reexecute()); + p->obj_decode_offset(), p->should_reexecute(), + p->return_oop()); } return NULL; } --- old/src/share/vm/code/pcDesc.cpp Mon Feb 8 11:00:32 2010 +++ new/src/share/vm/code/pcDesc.cpp Mon Feb 8 11:00:31 2010 @@ -52,7 +52,10 @@ tty->print(" "); sd->method()->print_short_name(tty); tty->print(" @%d", sd->bci()); - tty->print(" reexecute=%s", sd->should_reexecute()?"true":"false"); + if (sd->should_reexecute()) + tty->print(" reexecute=true"); + if (sd->return_oop()) + tty->print(" return_oop=true"); tty->cr(); } #endif --- old/src/share/vm/code/pcDesc.hpp Mon Feb 8 11:00:32 2010 +++ new/src/share/vm/code/pcDesc.hpp Mon Feb 8 11:00:32 2010 @@ -39,6 +39,7 @@ struct { unsigned int reexecute: 1; unsigned int is_method_handle_invoke: 1; + unsigned int return_oop: 1; } bits; bool operator ==(const PcDescFlags& other) { return word == other.word; } } _flags; @@ -76,6 +77,9 @@ bool is_method_handle_invoke() const { return _flags.bits.is_method_handle_invoke; } void set_is_method_handle_invoke(bool z) { _flags.bits.is_method_handle_invoke = z; } + bool return_oop() const { return _flags.bits.return_oop; } + void set_return_oop(bool z) { _flags.bits.return_oop = z; } + // Returns the real pc address real_pc(const nmethod* code) const; --- old/src/share/vm/code/scopeDesc.cpp Mon Feb 8 11:00:32 2010 +++ new/src/share/vm/code/scopeDesc.cpp Mon Feb 8 11:00:32 2010 @@ -26,19 +26,21 @@ # include "incls/_scopeDesc.cpp.incl" -ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute) { +ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute, bool return_oop) { _code = code; _decode_offset = decode_offset; _objects = decode_object_values(obj_decode_offset); _reexecute = reexecute; + _return_oop = return_oop; decode_body(); } -ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, bool reexecute) { +ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, bool reexecute, bool return_oop) { _code = code; _decode_offset = decode_offset; _objects = decode_object_values(DebugInformationRecorder::serialized_null); _reexecute = reexecute; + _return_oop = return_oop; decode_body(); } @@ -48,6 +50,7 @@ _decode_offset = parent->_sender_decode_offset; _objects = parent->_objects; _reexecute = false; //reexecute only applies to the first scope + _return_oop = false; decode_body(); } @@ -175,6 +178,7 @@ st->print_cr(" offset: %d", _decode_offset); st->print_cr(" bci: %d", bci()); st->print_cr(" reexecute: %s", should_reexecute() ? "true" : "false"); + st->print_cr(" return_oop: %s", return_oop() ? "true" : "false"); st->print_cr(" locals: %d", _locals_decode_offset); st->print_cr(" stack: %d", _expressions_decode_offset); st->print_cr(" monitor: %d", _monitors_decode_offset); --- old/src/share/vm/code/scopeDesc.hpp Mon Feb 8 11:00:33 2010 +++ new/src/share/vm/code/scopeDesc.hpp Mon Feb 8 11:00:33 2010 @@ -52,17 +52,18 @@ class ScopeDesc : public ResourceObj { public: // Constructor - ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute); + ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute, bool return_oop); // Calls above, giving default value of "serialized_null" to the // "obj_decode_offset" argument. (We don't use a default argument to // avoid a .hpp-.hpp dependency.) - ScopeDesc(const nmethod* code, int decode_offset, bool reexecute); + ScopeDesc(const nmethod* code, int decode_offset, bool reexecute, bool return_oop); // JVM state methodHandle method() const { return _method; } int bci() const { return _bci; } bool should_reexecute() const { return _reexecute; } + bool return_oop() const { return _return_oop; } GrowableArray* locals(); GrowableArray* expressions(); @@ -88,6 +89,7 @@ methodHandle _method; int _bci; bool _reexecute; + bool _return_oop; // Decoding offsets int _decode_offset; --- old/src/share/vm/opto/output.cpp Mon Feb 8 11:00:33 2010 +++ new/src/share/vm/opto/output.cpp Mon Feb 8 11:00:33 2010 @@ -795,6 +795,7 @@ int safepoint_pc_offset = current_offset; bool is_method_handle_invoke = false; + bool return_oop = false; // Add the safepoint in the DebugInfoRecorder if( !mach->is_MachCall() ) { @@ -807,6 +808,11 @@ if (mcall->is_MachCallJava()) is_method_handle_invoke = mcall->as_MachCallJava()->_method_handle_invoke; + // Check if a call returns an object. + if (mcall->return_value_is_used() && + mcall->tf()->range()->field_at(TypeFunc::Parms)->isa_ptr()) { + return_oop = true; + } safepoint_pc_offset += mcall->ret_addr_offset(); debug_info()->add_safepoint(safepoint_pc_offset, mcall->_oop_map); } @@ -919,7 +925,7 @@ assert(jvms->bci() >= InvocationEntryBci && jvms->bci() <= 0x10000, "must be a valid or entry BCI"); assert(!jvms->should_reexecute() || depth == max_depth, "reexecute allowed only for the youngest"); // Now we can describe the scope. - debug_info()->describe_scope(safepoint_pc_offset, scope_method, jvms->bci(), jvms->should_reexecute(), is_method_handle_invoke, locvals, expvals, monvals); + debug_info()->describe_scope(safepoint_pc_offset, scope_method, jvms->bci(), jvms->should_reexecute(), is_method_handle_invoke, return_oop, locvals, expvals, monvals); } // End jvms loop // Mark the end of the scope set. --- old/src/share/vm/prims/jvmtiCodeBlobEvents.cpp Mon Feb 8 11:00:34 2010 +++ new/src/share/vm/prims/jvmtiCodeBlobEvents.cpp Mon Feb 8 11:00:34 2010 @@ -402,7 +402,7 @@ address scopes_data = nm->scopes_data_begin(); for( pcd = nm->scopes_pcs_begin(); pcd < nm->scopes_pcs_end(); ++pcd ) { - ScopeDesc sc0(nm, pcd->scope_decode_offset(), pcd->should_reexecute()); + ScopeDesc sc0(nm, pcd->scope_decode_offset(), pcd->should_reexecute(), pcd->return_oop()); ScopeDesc *sd = &sc0; while( !sd->is_top() ) { sd = sd->sender(); } int bci = sd->bci(); --- old/src/share/vm/runtime/deoptimization.cpp Mon Feb 8 11:00:34 2010 +++ new/src/share/vm/runtime/deoptimization.cpp Mon Feb 8 11:00:34 2010 @@ -145,6 +145,19 @@ if (EliminateAllocations) { assert (chunk->at(0)->scope() != NULL,"expect only compiled java frames"); GrowableArray* objects = chunk->at(0)->scope()->objects(); + bool save_oop_result = chunk->at(0)->scope()->return_oop(); + Handle return_value; + if (save_oop_result) { + // Reallocation may trigger GC. If deoptimization happened on return from + // call which returns oop we need to save it since it is not in oopmap. + oop result = deoptee.saved_oop_result(&map); + assert(result == NULL || result->is_oop(), "must be oop"); + return_value = Handle(thread, result); + assert(Universe::heap()->is_in_or_null(result), "must be heap pointer"); + if (TraceDeoptimization) { + tty->print_cr("SAVED OOP RESULT " INTPTR_FORMAT " in thread " INTPTR_FORMAT, result, thread); + } + } bool reallocated = false; if (objects != NULL) { JRT_BLOCK @@ -158,9 +171,13 @@ ttyLocker ttyl; tty->print_cr("REALLOC OBJECTS in thread " INTPTR_FORMAT, thread); print_objects(objects); - } + } #endif } + if (save_oop_result) { + // Restore result. + deoptee.set_saved_oop_result(&map, return_value()); + } } if (EliminateLocks) { #ifndef PRODUCT