inline void unpack_first_frame(char* ¤t_pc, frame ¤t, CodeIterator &c) { // first vframe in the array if (nlr_through_unpacking) { // NLR is comming through unpacked vframes current_pc = c.interpreter_return_point(); // current_pc points to a normal return point in the interpreter. // To find the nlr return point we first compute the nlr offset. current_pc = ic_info_at(current_pc)->NLR_target(); current.set_hp(c.next_hp()); } else if (redo_the_send) { // Deoptimizing uncommon trap current_pc = Interpreter::redo_bytecode_after_deoptimization(); current.set_hp(c.next_hp()); redo_send_offset = c.next_hp() - c.hp(); redo_the_send = false; } else { // Normal case current_pc = c.interpreter_return_point(true); current.set_hp(c.next_hp()); if (c.is_message_send()) { number_of_arguments_through_unpacking = c.ic()->nof_arguments(); } else if (c.is_primitive_call()) { number_of_arguments_through_unpacking = c.prim_cache()->number_of_parameters(); } else if (c.is_dll_call()) { // The callee should not pop the argument since a DLL call is like a c function call. // The continuation code for the DLL call will pop the arguments! number_of_arguments_through_unpacking = 0; } } }
// Called from assembler in unpack_unoptimized_frames. // Based on the statics (old_sp, old_fp, and frame_array) this function unpacks // the array into interpreter frames. // Returning from this function should activate the most recent deoptimized frame. extern "C" void unpack_frame_array() { BlockScavenge bs; ResourceMark rm; int* pc_addr = (int*) new_sp - 1; assert(*pc_addr = -1, "just checking"); if (TraceDeoptimization) { std->print("[Unpacking]"); if (nlr_through_unpacking) { std->print(" NLR %s", (nlr_home == (int) cur_fp) ? "inside" : "outside"); } std->cr(); std->print(" - array "); frame_array->print_value(); std->print_cr(" @ 0x%lx", old_fp); } bool must_find_nlr_target = nlr_through_unpacking && nlr_home == (int) cur_fp; bool nlr_target_found = false; // For verification // link for the current frame int* link_addr = (int*) new_sp - 2; oop* current_sp = new_sp; int pos = 3; int length = frame_array->length(); bool first = true; frame current; // unpack one frame at at time from most recent to least recent do { oop receiver = frame_array->obj_at(pos++); methodOop method = methodOop(frame_array->obj_at(pos++)); assert(method->is_method(), "expecting method"); smiOop bci_obj = smiOop(frame_array->obj_at(pos++)); assert(bci_obj->is_smi(), "expecting smi"); int bci = bci_obj->value(); smiOop locals_obj = smiOop(frame_array->obj_at(pos++)); assert(locals_obj->is_smi(), "expecting smi"); int locals = locals_obj->value(); current = frame(current_sp, (int*) current_sp + locals + 2); // fill in the locals for (int index = 0; index < locals; index++) { current.set_temp(index, frame_array->obj_at(pos++)); } CodeIterator c(method, bci); char* current_pc; if (first) { // first vframe in the array if (nlr_through_unpacking) { // NLR is comming through unpacked vframes current_pc = c.interpreter_return_point(); // current_pc points to a normal return point in the interpreter. // To find the nlr return point we first compute the nlr offset. current_pc = ic_info_at(current_pc)->NLR_target(); current.set_hp(c.next_hp()); } else if (redo_the_send) { // Deoptimizing uncommon trap current_pc = (char*) redo_bytecode_after_deoptimization; current.set_hp(c.next_hp()); redo_send_offset = c.next_hp() - c.hp(); redo_the_send = false; } else { // Normal case current_pc = c.interpreter_return_point(true); current.set_hp(c.next_hp()); if (c.is_message_send()) { number_of_arguments_through_unpacking = c.ic()->nof_arguments(); } else if (c.is_primitive_call()) { number_of_arguments_through_unpacking = c.prim_cache()->number_of_parameters(); } else if (c.is_dll_call()) { // The callee should not pop the argument since a DLL call is like a c function call. // The continuation code for the DLL call will pop the arguments! number_of_arguments_through_unpacking = 0; } } } else { current_pc = c.interpreter_return_point(); current.set_hp(c.next_hp()); } current.set_receiver(receiver); current.patch_pc(current_pc); current.patch_fp(current.fp()); // Revive the contexts if (!method->is_blockMethod() && method->activation_has_context()) { contextOop con = contextOop(current.temp(0)); assert(con->is_context(), "must be context"); oop frame_oop = oop(current.fp()); con->set_parent(frame_oop); if (nlr_through_unpacking && nlr_home == (int) cur_fp) { if (nlr_home_context == con) { // This frame is the target of the NLR // set nlr_home to frame pointer of current frame nlr_home = (int) current.fp(); // compute number of arguments to pop nlr_home_id = ~method->number_of_arguments(); nlr_target_found = true; // std->print("target frame for NLR (%d, 0x%lx):",method->number_of_arguments(), nlr_home_id); } } } if (TraceDeoptimization) { frame v(current_sp, current.fp(), current_pc); v.print_for_deoptimization(std); } first = false; // Next pc current_sp += frame::interpreter_frame_size(locals); } while (pos <= length); if (must_find_nlr_target && !nlr_target_found) { fatal("Target for NLR not found when unpacking frame"); } assert (current_sp == old_sp, "We have not reached the end"); current.set_link(old_fp); }