< prev index next >

src/share/vm/runtime/deoptimization.cpp

Print this page

        

*** 211,251 **** // It is not guaranteed that we can get such information here only // by analyzing bytecode in deoptimized frames. This is why this flag // is set during method compilation (see Compile::Process_OopMap_Node()). // If the previous frame was popped or if we are dispatching an exception, // we don't have an oop result. ! bool save_oop_result = chunk->at(0)->scope()->return_oop() && !thread->popframe_forcing_deopt_reexecution() && (exec_mode == Unpack_deopt); ! 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) { ttyLocker ttyl; tty->print_cr("SAVED OOP RESULT " INTPTR_FORMAT " in thread " INTPTR_FORMAT, p2i(result), p2i(thread)); } } ! if (objects != NULL) { bool skip_internal = (cm != NULL) && !cm->is_compiled_by_jvmci(); JRT_BLOCK ! realloc_failures = realloc_objects(thread, &deoptee, objects, THREAD); reassign_fields(&deoptee, &map, objects, realloc_failures, skip_internal, THREAD); JRT_END #ifndef PRODUCT if (TraceDeoptimization) { ttyLocker ttyl; tty->print_cr("REALLOC OBJECTS in thread " INTPTR_FORMAT, p2i(thread)); print_objects(objects, realloc_failures); } #endif } ! if (save_oop_result) { // Restore result. ! deoptee.set_saved_oop_result(&map, return_value()); } #ifndef INCLUDE_JVMCI } if (EliminateLocks) { #endif // INCLUDE_JVMCI --- 211,273 ---- // It is not guaranteed that we can get such information here only // by analyzing bytecode in deoptimized frames. This is why this flag // is set during method compilation (see Compile::Process_OopMap_Node()). // If the previous frame was popped or if we are dispatching an exception, // we don't have an oop result. ! ScopeDesc* scope = chunk->at(0)->scope(); ! bool save_oop_result = scope->return_oop() && !thread->popframe_forcing_deopt_reexecution() && (exec_mode == Unpack_deopt); ! // In case of the return of multiple values, we must take care ! // of all oop return values. ! GrowableArray<Handle> return_oops; ! ValueKlass* vk = NULL; ! if (save_oop_result) { ! if (scope->return_vt()) { ! vk = ValueKlass::returned_value_type(map); ! if (vk != NULL) { ! bool success = vk->save_oop_results(map, return_oops); ! assert(success, "found klass ptr being returned: saving oops can't fail"); ! save_oop_result = false; ! } else { ! vk = NULL; ! } ! } ! } 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_oops.push(Handle(thread, result)); assert(Universe::heap()->is_in_or_null(result), "must be heap pointer"); if (TraceDeoptimization) { ttyLocker ttyl; tty->print_cr("SAVED OOP RESULT " INTPTR_FORMAT " in thread " INTPTR_FORMAT, p2i(result), p2i(thread)); } } ! if (objects != NULL || vk != NULL) { bool skip_internal = (cm != NULL) && !cm->is_compiled_by_jvmci(); JRT_BLOCK ! if (vk != NULL) { ! realloc_failures = realloc_value_type_result(vk, map, return_oops, THREAD); ! } ! if (objects != NULL) { ! realloc_failures = realloc_failures || realloc_objects(thread, &deoptee, objects, THREAD); reassign_fields(&deoptee, &map, objects, realloc_failures, skip_internal, THREAD); + } JRT_END #ifndef PRODUCT if (TraceDeoptimization) { ttyLocker ttyl; tty->print_cr("REALLOC OBJECTS in thread " INTPTR_FORMAT, p2i(thread)); print_objects(objects, realloc_failures); } #endif } ! if (save_oop_result || vk != NULL) { // Restore result. ! assert(return_oops.length() == 1, "no value type"); ! deoptee.set_saved_oop_result(&map, return_oops.pop()()); } #ifndef INCLUDE_JVMCI } if (EliminateLocks) { #endif // INCLUDE_JVMCI
*** 850,859 **** --- 872,901 ---- } return failures; } + // We're deoptimizing at the return of a call, value type fields are + // in registers. When we go back to the interpreter, it will expect a + // reference to a value type instance. Allocate and initialize it from + // the register values here. + bool Deoptimization::realloc_value_type_result(ValueKlass* vk, const RegisterMap& map, GrowableArray<Handle>& return_oops, TRAPS) { + VMRegPair* regs; + int nb_fields; + const GrowableArray<SigEntry>& sig_vk = vk->return_convention(regs, nb_fields); + regs++; + nb_fields--; + oop new_vt = vk->realloc_result(sig_vk, map, regs, return_oops, nb_fields, THREAD); + if (new_vt == NULL) { + CLEAR_PENDING_EXCEPTION; + THROW_OOP_(Universe::out_of_memory_error_realloc_objects(), true); + } + return_oops.clear(); + return_oops.push(Handle(THREAD, new_vt)); + return false; + } + // restore elements of an eliminated type array void Deoptimization::reassign_type_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, typeArrayOop obj, BasicType type) { int index = 0; intptr_t val;
< prev index next >