< prev index next >

src/share/vm/opto/graphKit.cpp

Print this page

        

*** 813,842 **** return true; } #endif //ASSERT - // Helper function for enforcing certain bytecodes to reexecute if - // deoptimization happens - static bool should_reexecute_implied_by_bytecode(JVMState *jvms, bool is_anewarray) { - ciMethod* cur_method = jvms->method(); - int cur_bci = jvms->bci(); - if (cur_method != NULL && cur_bci != InvocationEntryBci) { - Bytecodes::Code code = cur_method->java_code_at_bci(cur_bci); - return Interpreter::bytecode_should_reexecute(code) || - is_anewarray && code == Bytecodes::_multianewarray; - // Reexecute _multianewarray bytecode which was replaced with - // sequence of [a]newarray. See Parse::do_multianewarray(). - // - // Note: interpreter should not have it set since this optimization - // is limited by dimensions and guarded by flag so in some cases - // multianewarray() runtime calls will be generated and - // the bytecode should not be reexecutes (stack will not be reset). - } else - return false; - } - // Helper function for adding JVMState and debug information to node void GraphKit::add_safepoint_edges(SafePointNode* call, bool must_throw) { // Add the safepoint edges to the call (or other safepoint). // Make sure dead locals are set to top. This --- 813,822 ----
*** 876,1000 **** // then require an immediate deoptimization. can_prune_locals = false; // do not prune locals stack_slots_not_pruned = 0; } ! // do not scribble on the input jvms ! JVMState* out_jvms = youngest_jvms->clone_deep(C); ! call->set_jvms(out_jvms); // Start jvms list for call node ! ! // For a known set of bytecodes, the interpreter should reexecute them if ! // deoptimization happens. We set the reexecute state for them here ! if (out_jvms->is_reexecute_undefined() && //don't change if already specified ! should_reexecute_implied_by_bytecode(out_jvms, call->is_AllocateArray())) { ! out_jvms->set_should_reexecute(true); //NOTE: youngest_jvms not changed ! } ! ! // Presize the call: ! DEBUG_ONLY(uint non_debug_edges = call->req()); ! call->add_req_batch(top(), youngest_jvms->debug_depth()); ! assert(call->req() == non_debug_edges + youngest_jvms->debug_depth(), ""); ! ! // Set up edges so that the call looks like this: ! // Call [state:] ctl io mem fptr retadr ! // [parms:] parm0 ... parmN ! // [root:] loc0 ... locN stk0 ... stkSP mon0 obj0 ... monN objN ! // [...mid:] loc0 ... locN stk0 ... stkSP mon0 obj0 ... monN objN [...] ! // [young:] loc0 ... locN stk0 ... stkSP mon0 obj0 ... monN objN ! // Note that caller debug info precedes callee debug info. ! ! // Fill pointer walks backwards from "young:" to "root:" in the diagram above: ! uint debug_ptr = call->req(); ! ! // Loop over the map input edges associated with jvms, add them ! // to the call node, & reset all offsets to match call node array. ! for (JVMState* in_jvms = youngest_jvms; in_jvms != NULL; ) { ! uint debug_end = debug_ptr; ! uint debug_start = debug_ptr - in_jvms->debug_size(); ! debug_ptr = debug_start; // back up the ptr ! ! uint p = debug_start; // walks forward in [debug_start, debug_end) ! uint j, k, l; ! SafePointNode* in_map = in_jvms->map(); ! out_jvms->set_map(call); ! ! if (can_prune_locals) { ! assert(in_jvms->method() == out_jvms->method(), "sanity"); ! // If the current throw can reach an exception handler in this JVMS, ! // then we must keep everything live that can reach that handler. ! // As a quick and dirty approximation, we look for any handlers at all. ! if (in_jvms->method()->has_exception_handlers()) { ! can_prune_locals = false; ! } ! } ! ! // Add the Locals ! k = in_jvms->locoff(); ! l = in_jvms->loc_size(); ! out_jvms->set_locoff(p); ! if (!can_prune_locals) { ! for (j = 0; j < l; j++) ! call->set_req(p++, in_map->in(k+j)); ! } else { ! p += l; // already set to top above by add_req_batch ! } ! ! // Add the Expression Stack ! k = in_jvms->stkoff(); ! l = in_jvms->sp(); ! out_jvms->set_stkoff(p); ! if (!can_prune_locals) { ! for (j = 0; j < l; j++) ! call->set_req(p++, in_map->in(k+j)); ! } else if (can_prune_locals && stack_slots_not_pruned != 0) { ! // Divide stack into {S0,...,S1}, where S0 is set to top. ! uint s1 = stack_slots_not_pruned; ! stack_slots_not_pruned = 0; // for next iteration ! if (s1 > l) s1 = l; ! uint s0 = l - s1; ! p += s0; // skip the tops preinstalled by add_req_batch ! for (j = s0; j < l; j++) ! call->set_req(p++, in_map->in(k+j)); ! } else { ! p += l; // already set to top above by add_req_batch ! } ! ! // Add the Monitors ! k = in_jvms->monoff(); ! l = in_jvms->mon_size(); ! out_jvms->set_monoff(p); ! for (j = 0; j < l; j++) ! call->set_req(p++, in_map->in(k+j)); ! ! // Copy any scalar object fields. ! k = in_jvms->scloff(); ! l = in_jvms->scl_size(); ! out_jvms->set_scloff(p); ! for (j = 0; j < l; j++) ! call->set_req(p++, in_map->in(k+j)); ! ! // Finish the new jvms. ! out_jvms->set_endoff(p); ! ! assert(out_jvms->endoff() == debug_end, "fill ptr must match"); ! assert(out_jvms->depth() == in_jvms->depth(), "depth must match"); ! assert(out_jvms->loc_size() == in_jvms->loc_size(), "size must match"); ! assert(out_jvms->mon_size() == in_jvms->mon_size(), "size must match"); ! assert(out_jvms->scl_size() == in_jvms->scl_size(), "size must match"); ! assert(out_jvms->debug_size() == in_jvms->debug_size(), "size must match"); ! ! // Update the two tail pointers in parallel. ! out_jvms = out_jvms->caller(); ! in_jvms = in_jvms->caller(); ! } ! ! assert(debug_ptr == non_debug_edges, "debug info must fit exactly"); ! ! // Test the correctness of JVMState::debug_xxx accessors: ! assert(call->jvms()->debug_start() == non_debug_edges, ""); ! assert(call->jvms()->debug_end() == call->req(), ""); ! assert(call->jvms()->debug_depth() == call->req() - non_debug_edges, ""); } bool GraphKit::compute_stack_effects(int& inputs, int& depth) { Bytecodes::Code code = java_bc(); if (code == Bytecodes::_wide) { --- 856,866 ---- // then require an immediate deoptimization. can_prune_locals = false; // do not prune locals stack_slots_not_pruned = 0; } ! C->add_safepoint_edges(call, youngest_jvms, can_prune_locals, stack_slots_not_pruned); } bool GraphKit::compute_stack_effects(int& inputs, int& depth) { Bytecodes::Code code = java_bc(); if (code == Bytecodes::_wide) {
*** 1729,1739 **** if (arg->is_ValueType()) { ValueTypeNode* vt = arg->as_ValueType(); if (domain->field_at(i)->is_valuetypeptr()->klass() != C->env()->___Value_klass()) { // We don't pass value type arguments by reference but instead // pass each field of the value type ! idx += vt->set_arguments_for_java_call(call, idx, *this); } else { arg = arg->as_ValueType()->store_to_memory(this); call->init_req(idx, arg); idx++; } --- 1595,1605 ---- if (arg->is_ValueType()) { ValueTypeNode* vt = arg->as_ValueType(); if (domain->field_at(i)->is_valuetypeptr()->klass() != C->env()->___Value_klass()) { // We don't pass value type arguments by reference but instead // pass each field of the value type ! idx += vt->pass_fields(call, idx, *this); } else { arg = arg->as_ValueType()->store_to_memory(this); call->init_req(idx, arg); idx++; }
*** 1792,1802 **** // Capture the return value, if any. Node* ret; if (call->method() == NULL || call->method()->return_type()->basic_type() == T_VOID) ret = top(); ! else ret = _gvn.transform(new ProjNode(call, TypeFunc::Parms)); // Note: Since any out-of-line call can produce an exception, // we always insert an I_O projection from the call into the result. make_slow_call_ex(call, env()->Throwable_klass(), separate_io_proj); --- 1658,1681 ---- // Capture the return value, if any. Node* ret; if (call->method() == NULL || call->method()->return_type()->basic_type() == T_VOID) ret = top(); ! else { ! const TypeTuple *range_cc = call->tf()->range_cc(); ! const TypeTuple *range_sig = call->tf()->range_sig(); ! if (range_cc == range_sig) { ! ret = _gvn.transform(new ProjNode(call, TypeFunc::Parms)); ! } else { ! // Return of multiple values (value type fields): we create a ! // ValueType node, each field is a projection from the call. ! const Type* t = range_sig->field_at(TypeFunc::Parms); ! assert(t->isa_valuetypeptr(), "only value types for multiple return values"); ! ciValueKlass* vk = t->is_valuetypeptr()->value_type()->value_klass(); ! ret = C->create_vt_node(call, vk, vk, 0, TypeFunc::Parms+1, false); ! } ! } // Note: Since any out-of-line call can produce an exception, // we always insert an I_O projection from the call into the result. make_slow_call_ex(call, env()->Throwable_klass(), separate_io_proj);
< prev index next >