src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File
*** old/src/cpu/sparc/vm/templateInterpreter_sparc.cpp	Thu Dec  3 14:02:26 2015
--- new/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp	Thu Dec  3 14:02:25 2015

*** 1400,1655 **** --- 1400,1409 ---- return entry; } static int size_activation_helper(int callee_extra_locals, int max_stack, int monitor_size) { // Figure out the size of an interpreter frame (in words) given that we have a fully allocated // expression stack, the callee will have callee_extra_locals (so we can account for // frame extension) and monitor_size for monitors. Basically we need to calculate // this exactly like generate_fixed_frame/generate_compute_interpreter_state. // // // The big complicating thing here is that we must ensure that the stack stays properly // aligned. This would be even uglier if monitor size wasn't modulo what the stack // needs to be aligned for). We are given that the sp (fp) is already aligned by // the caller so we must ensure that it is properly aligned for our callee. // const int rounded_vm_local_words = round_to(frame::interpreter_frame_vm_local_words,WordsPerLong); // callee_locals and max_stack are counts, not the size in frame. const int locals_size = round_to(callee_extra_locals * Interpreter::stackElementWords, WordsPerLong); const int max_stack_words = max_stack * Interpreter::stackElementWords; return (round_to((max_stack_words + rounded_vm_local_words + frame::memory_parameter_word_sp_offset), WordsPerLong) // already rounded + locals_size + monitor_size); } // How much stack a method top interpreter activation needs in words. int AbstractInterpreter::size_top_interpreter_activation(Method* method) { // See call_stub code int call_stub_size = round_to(7 + frame::memory_parameter_word_sp_offset, WordsPerLong); // 7 + register save area // Save space for one monitor to get into the interpreted method in case // the method is synchronized int monitor_size = method->is_synchronized() ? 1*frame::interpreter_frame_monitor_size() : 0; return size_activation_helper(method->max_locals(), method->max_stack(), monitor_size) + call_stub_size; } int AbstractInterpreter::size_activation(int max_stack, int temps, int extra_args, int monitors, int callee_params, int callee_locals, bool is_top_frame) { // Note: This calculation must exactly parallel the frame setup // in InterpreterGenerator::generate_fixed_frame. int monitor_size = monitors * frame::interpreter_frame_monitor_size(); assert(monitor_size == round_to(monitor_size, WordsPerLong), "must align"); // // Note: if you look closely this appears to be doing something much different // than generate_fixed_frame. What is happening is this. On sparc we have to do // this dance with interpreter_sp_adjustment because the window save area would // appear just below the bottom (tos) of the caller's java expression stack. Because // the interpreter want to have the locals completely contiguous generate_fixed_frame // will adjust the caller's sp for the "extra locals" (max_locals - parameter_size). // Now in generate_fixed_frame the extension of the caller's sp happens in the callee. // In this code the opposite occurs the caller adjusts it's own stack base on the callee. // This is mostly ok but it does cause a problem when we get to the initial frame (the oldest) // because the oldest frame would have adjust its callers frame and yet that frame // already exists and isn't part of this array of frames we are unpacking. So at first // glance this would seem to mess up that frame. However Deoptimization::fetch_unroll_info_helper() // will after it calculates all of the frame's on_stack_size()'s will then figure out the // amount to adjust the caller of the initial (oldest) frame and the calculation will all // add up. It does seem like it simpler to account for the adjustment here (and remove the // callee... parameters here). However this would mean that this routine would have to take // the caller frame as input so we could adjust its sp (and set it's interpreter_sp_adjustment) // and run the calling loop in the reverse order. This would also would appear to mean making // this code aware of what the interactions are when that initial caller fram was an osr or // other adapter frame. deoptimization is complicated enough and hard enough to debug that // there is no sense in messing working code. // int rounded_cls = round_to((callee_locals - callee_params), WordsPerLong); assert(rounded_cls == round_to(rounded_cls, WordsPerLong), "must align"); int raw_frame_size = size_activation_helper(rounded_cls, max_stack, monitor_size); return raw_frame_size; } void AbstractInterpreter::layout_activation(Method* method, int tempcount, int popframe_extra_args, int moncount, int caller_actual_parameters, int callee_param_count, int callee_local_count, frame* caller, frame* interpreter_frame, bool is_top_frame, bool is_bottom_frame) { // Set up the following variables: // - Lmethod // - Llocals // - Lmonitors (to the indicated number of monitors) // - Lesp (to the indicated number of temps) // The frame caller on entry is a description of the caller of the // frame we are about to layout. We are guaranteed that we will be // able to fill in a new interpreter frame as its callee (i.e. the // stack space is allocated and the amount was determined by an // earlier call to the size_activation() method). On return caller // while describe the interpreter frame we just layed out. // The skeleton frame must already look like an interpreter frame // even if not fully filled out. assert(interpreter_frame->is_interpreted_frame(), "Must be interpreted frame"); int rounded_vm_local_words = round_to(frame::interpreter_frame_vm_local_words,WordsPerLong); int monitor_size = moncount * frame::interpreter_frame_monitor_size(); assert(monitor_size == round_to(monitor_size, WordsPerLong), "must align"); intptr_t* fp = interpreter_frame->fp(); JavaThread* thread = JavaThread::current(); RegisterMap map(thread, false); // More verification that skeleton frame is properly walkable assert(fp == caller->sp(), "fp must match"); intptr_t* montop = fp - rounded_vm_local_words; // preallocate monitors (cf. __ add_monitor_to_stack) intptr_t* monitors = montop - monitor_size; // preallocate stack space intptr_t* esp = monitors - 1 - (tempcount * Interpreter::stackElementWords) - popframe_extra_args; int local_words = method->max_locals() * Interpreter::stackElementWords; NEEDS_CLEANUP; intptr_t* locals; if (caller->is_interpreted_frame()) { // Can force the locals area to end up properly overlapping the top of the expression stack. intptr_t* Lesp_ptr = caller->interpreter_frame_tos_address() - 1; // Note that this computation means we replace size_of_parameters() values from the caller // interpreter frame's expression stack with our argument locals int parm_words = caller_actual_parameters * Interpreter::stackElementWords; locals = Lesp_ptr + parm_words; int delta = local_words - parm_words; int computed_sp_adjustment = (delta > 0) ? round_to(delta, WordsPerLong) : 0; *interpreter_frame->register_addr(I5_savedSP) = (intptr_t) (fp + computed_sp_adjustment) - STACK_BIAS; if (!is_bottom_frame) { // Llast_SP is set below for the current frame to SP (with the // extra space for the callee's locals). Here we adjust // Llast_SP for the caller's frame, removing the extra space // for the current method's locals. *caller->register_addr(Llast_SP) = *interpreter_frame->register_addr(I5_savedSP); } else { assert(*caller->register_addr(Llast_SP) >= *interpreter_frame->register_addr(I5_savedSP), "strange Llast_SP"); } } else { assert(caller->is_compiled_frame() || caller->is_entry_frame(), "only possible cases"); // Don't have Lesp available; lay out locals block in the caller // adjacent to the register window save area. // // Compiled frames do not allocate a varargs area which is why this if // statement is needed. // if (caller->is_compiled_frame()) { locals = fp + frame::register_save_words + local_words - 1; } else { locals = fp + frame::memory_parameter_word_sp_offset + local_words - 1; } if (!caller->is_entry_frame()) { // Caller wants his own SP back int caller_frame_size = caller->cb()->frame_size(); *interpreter_frame->register_addr(I5_savedSP) = (intptr_t)(caller->fp() - caller_frame_size) - STACK_BIAS; } } if (TraceDeoptimization) { if (caller->is_entry_frame()) { // make sure I5_savedSP and the entry frames notion of saved SP // agree. This assertion duplicate a check in entry frame code // but catches the failure earlier. assert(*caller->register_addr(Lscratch) == *interpreter_frame->register_addr(I5_savedSP), "would change callers SP"); } if (caller->is_entry_frame()) { tty->print("entry "); } if (caller->is_compiled_frame()) { tty->print("compiled "); if (caller->is_deoptimized_frame()) { tty->print("(deopt) "); } } if (caller->is_interpreted_frame()) { tty->print("interpreted "); } tty->print_cr("caller fp=" INTPTR_FORMAT " sp=" INTPTR_FORMAT, p2i(caller->fp()), p2i(caller->sp())); tty->print_cr("save area = " INTPTR_FORMAT ", " INTPTR_FORMAT, p2i(caller->sp()), p2i(caller->sp() + 16)); tty->print_cr("save area = " INTPTR_FORMAT ", " INTPTR_FORMAT, p2i(caller->fp()), p2i(caller->fp() + 16)); tty->print_cr("interpreter fp=" INTPTR_FORMAT ", " INTPTR_FORMAT, p2i(interpreter_frame->fp()), p2i(interpreter_frame->sp())); tty->print_cr("save area = " INTPTR_FORMAT ", " INTPTR_FORMAT, p2i(interpreter_frame->sp()), p2i(interpreter_frame->sp() + 16)); tty->print_cr("save area = " INTPTR_FORMAT ", " INTPTR_FORMAT, p2i(interpreter_frame->fp()), p2i(interpreter_frame->fp() + 16)); tty->print_cr("Llocals = " INTPTR_FORMAT, p2i(locals)); tty->print_cr("Lesp = " INTPTR_FORMAT, p2i(esp)); tty->print_cr("Lmonitors = " INTPTR_FORMAT, p2i(monitors)); } if (method->max_locals() > 0) { assert(locals < caller->sp() || locals >= (caller->sp() + 16), "locals in save area"); assert(locals < caller->fp() || locals > (caller->fp() + 16), "locals in save area"); assert(locals < interpreter_frame->sp() || locals > (interpreter_frame->sp() + 16), "locals in save area"); assert(locals < interpreter_frame->fp() || locals >= (interpreter_frame->fp() + 16), "locals in save area"); } #ifdef _LP64 assert(*interpreter_frame->register_addr(I5_savedSP) & 1, "must be odd"); #endif *interpreter_frame->register_addr(Lmethod) = (intptr_t) method; *interpreter_frame->register_addr(Llocals) = (intptr_t) locals; *interpreter_frame->register_addr(Lmonitors) = (intptr_t) monitors; *interpreter_frame->register_addr(Lesp) = (intptr_t) esp; // Llast_SP will be same as SP as there is no adapter space *interpreter_frame->register_addr(Llast_SP) = (intptr_t) interpreter_frame->sp() - STACK_BIAS; *interpreter_frame->register_addr(LcpoolCache) = (intptr_t) method->constants()->cache(); #ifdef FAST_DISPATCH *interpreter_frame->register_addr(IdispatchTables) = (intptr_t) Interpreter::dispatch_table(); #endif #ifdef ASSERT BasicObjectLock* mp = (BasicObjectLock*)monitors; assert(interpreter_frame->interpreter_frame_method() == method, "method matches"); assert(interpreter_frame->interpreter_frame_local_at(9) == (intptr_t *)((intptr_t)locals - (9 * Interpreter::stackElementSize)), "locals match"); assert(interpreter_frame->interpreter_frame_monitor_end() == mp, "monitor_end matches"); assert(((intptr_t *)interpreter_frame->interpreter_frame_monitor_begin()) == ((intptr_t *)mp)+monitor_size, "monitor_begin matches"); assert(interpreter_frame->interpreter_frame_tos_address()-1 == esp, "esp matches"); // check bounds intptr_t* lo = interpreter_frame->sp() + (frame::memory_parameter_word_sp_offset - 1); intptr_t* hi = interpreter_frame->fp() - rounded_vm_local_words; assert(lo < monitors && montop <= hi, "monitors in bounds"); assert(lo <= esp && esp < monitors, "esp in bounds"); #endif // ASSERT } //---------------------------------------------------------------------------------------------------- // Exceptions void TemplateInterpreterGenerator::generate_throw_exception() { // Entry point in previous activation (i.e., if the caller was interpreted)

src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File