< 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 >