src/share/vm/opto/graphKit.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File
*** old/src/share/vm/opto/graphKit.cpp	Thu Mar 20 12:32:00 2014
--- new/src/share/vm/opto/graphKit.cpp	Thu Mar 20 12:32:00 2014

*** 610,623 **** --- 610,623 ---- // create the stack trace. // Usual case: Bail to interpreter. // Reserve the right to recompile if we haven't seen anything yet. ! assert(!Deoptimization::reason_is_speculate(reason), "unsupported"); ! ciMethod* m = Deoptimization::reason_is_speculate(reason) ? C->method() : NULL; Deoptimization::DeoptAction action = Deoptimization::Action_maybe_recompile; if (treat_throw_as_hot ! && (method()->method_data()->trap_recompiled_at(bci(), NULL) ! && (method()->method_data()->trap_recompiled_at(bci(), m) || C->too_many_traps(reason))) { // We cannot afford to take more traps here. Suffer in the interpreter. if (C->log() != NULL) C->log()->elem("hot_throw preallocated='0' reason='%s' mcount='%d'", Deoptimization::trap_reason_name(reason),
*** 1168,1178 **** --- 1168,1179 ---- extern int explicit_null_checks_inserted, explicit_null_checks_elided; Node* GraphKit::null_check_common(Node* value, BasicType type, // optional arguments for variations: bool assert_null, ! Node* *null_control) { ! Node* *null_control, + bool speculative) { assert(!assert_null || null_control == NULL, "not both at once"); if (stopped()) return top(); if (!GenerateCompilerNullChecks && !assert_null && null_control == NULL) { // For some performance testing, we may wish to suppress null checking. value = cast_not_null(value); // Make it appear to be non-null (4962416).
*** 1278,1294 **** --- 1279,1295 ---- //----------- // Branch to failure if null float ok_prob = PROB_MAX; // a priori estimate: nulls never happen Deoptimization::DeoptReason reason; ! if (assert_null) { reason = Deoptimization::Reason_null_assert; else if (type == T_OBJECT) ! reason = speculative ? Deoptimization::Reason_speculate_null_check : Deoptimization::Reason_null_check; else + } else if (type == T_OBJECT) { + } else { reason = Deoptimization::Reason_div0_check; + } // %%% Since Reason_unhandled is not recorded on a per-bytecode basis, // ciMethodData::has_trap_at will return a conservative -1 if any // must-be-null assertion has failed. This could cause performance // problems for a method after its first do_null_assert failure. // Consider using 'Reason_class_check' instead?
*** 2107,2131 **** --- 2108,2147 ---- * Record profiling data exact_kls for Node n with the type system so * that it can propagate it (speculation) * * @param n node that the type applies to * @param exact_kls type from profiling + * @param maybe_null did profiling see null? * * @return node with improved type */ ! Node* GraphKit::record_profile_for_speculation(Node* n, ciKlass* exact_kls, bool maybe_null) { const Type* current_type = _gvn.type(n); assert(UseTypeSpeculation, "type speculation must be on"); ! const TypeOopPtr* speculative = current_type->speculative(); ! const TypePtr* speculative = current_type->speculative(); + // Should the klass from the profile be recorded in the speculative type? if (current_type->would_improve_type(exact_kls, jvms()->depth())) { const TypeKlassPtr* tklass = TypeKlassPtr::make(exact_kls); const TypeOopPtr* xtype = tklass->as_instance_type(); assert(xtype->klass_is_exact(), "Should be exact"); + // Any reason to believe n is not null (from this profiling or a previous one)? + const TypePtr* ptr = (maybe_null && current_type->speculative_maybe_null()) ? TypePtr::BOTTOM : TypePtr::NOTNULL; // record the new speculative type's depth ! speculative = xtype->with_inline_depth(jvms()->depth()); ! speculative = xtype->cast_to_ptr_type(ptr->ptr())->is_ptr(); + speculative = speculative->with_inline_depth(jvms()->depth()); + } else if (current_type->would_improve_ptr(maybe_null)) { + // Profiling report that null was never seen so we can change the + // speculative type to non null ptr. + assert(!maybe_null, "nothing to improve"); + if (speculative == NULL) { + speculative = TypePtr::NOTNULL; + } else { + const TypePtr* ptr = TypePtr::NOTNULL; + speculative = speculative->cast_to_ptr_type(ptr->ptr())->is_ptr(); + } } if (speculative != current_type->speculative()) { // Build a type with a speculative type (what we think we know // about the type but will need a guard when we use it)
*** 2154,2164 **** --- 2170,2188 ---- Node* GraphKit::record_profiled_receiver_for_speculation(Node* n) { if (!UseTypeSpeculation) { return n; } ciKlass* exact_kls = profile_has_unique_klass(); ! return record_profile_for_speculation(n, exact_kls); ! bool maybe_null = true; + if (java_bc() == Bytecodes::_checkcast || + java_bc() == Bytecodes::_instanceof || + java_bc() == Bytecodes::_aastore) { + ciProfileData* data = method()->method_data()->bci_to_data(bci()); + bool maybe_null = data == NULL ? true : data->as_BitData()->null_seen(); + } + return record_profile_for_speculation(n, exact_kls, maybe_null); + return n; } /** * Record profiling data from argument profiling at an invoke with the * type system so that it can propagate it (speculation)
*** 2174,2186 **** --- 2198,2211 ---- int nargs = tf->_domain->_cnt - TypeFunc::Parms; int skip = Bytecodes::has_receiver(bc) ? 1 : 0; for (int j = skip, i = 0; j < nargs && i < TypeProfileArgsLimit; j++) { const Type *targ = tf->_domain->field_at(j + TypeFunc::Parms); if (targ->basic_type() == T_OBJECT || targ->basic_type() == T_ARRAY) { ! ciKlass* better_type = method()->argument_profiled_type(bci(), i); if (better_type != NULL) { record_profile_for_speculation(argument(j), better_type); ! bool maybe_null = true; + ciKlass* better_type = NULL; + if (method()->argument_profiled_type(bci(), i, better_type, maybe_null)) { + record_profile_for_speculation(argument(j), better_type, maybe_null); } i++; } } }
*** 2193,2211 **** --- 2218,2255 ---- if (!UseTypeSpeculation) { return; } for (int i = 0, j = 0; i < method()->arg_size() ; i++) { if (_gvn.type(local(i))->isa_oopptr()) { ! ciKlass* better_type = method()->parameter_profiled_type(j); if (better_type != NULL) { record_profile_for_speculation(local(i), better_type); ! bool maybe_null = true; + ciKlass* better_type = NULL; + if (method()->parameter_profiled_type(j, better_type, maybe_null)) { + record_profile_for_speculation(local(i), better_type, maybe_null); } j++; } } } + /** + * Record profiling data from return value profiling at an invoke with + * the type system so that it can propagate it (speculation) + */ + void GraphKit::record_profiled_return_for_speculation() { + if (!UseTypeSpeculation) { + return; + } + bool maybe_null = true; + ciKlass* better_type = NULL; + if (method()->return_profiled_type(bci(), better_type, maybe_null)) { + // If profiling reports a single type for the return value, + // feed it to the type system so it can propagate it as a + // speculative type + record_profile_for_speculation(stack(sp()-1), better_type, maybe_null); + } + } + void GraphKit::round_double_result(ciMethod* dest_method) { // A non-strict method may return a double value which has an extended // exponent, but this must not be visible in a caller which is 'strict' // If a strict caller invokes a non-strict callee, round a double result
*** 2281,2305 **** --- 2325,2352 ---- //------------------------------null_check_oop--------------------------------- // Null check oop. Set null-path control into Region in slot 3. // Make a cast-not-nullness use the other not-null control. Return cast. Node* GraphKit::null_check_oop(Node* value, Node* *null_control, - bool never_see_null, bool safe_for_replace) { + bool safe_for_replace, + bool speculative) { // Initial NULL check taken path (*null_control) = top(); ! Node* cast = null_check_common(value, T_OBJECT, false, null_control, speculative); // Generate uncommon_trap: if (never_see_null && (*null_control) != top()) { // If we see an unexpected null at a check-cast we record it and force a // recompile; the offending check-cast will be compiled to handle NULLs. // If we see more than one offending BCI, then all checkcasts in the // method will be compiled to handle NULLs. PreserveJVMState pjvms(this); set_control(*null_control); replace_in_map(value, null()); uncommon_trap(Deoptimization::Reason_null_check, + Deoptimization::DeoptReason reason = speculative ? Deoptimization::Reason_speculate_null_check : Deoptimization::Reason_null_check; + uncommon_trap(reason, Deoptimization::Action_make_not_entrant); (*null_control) = top(); // NULL path is dead } if ((*null_control) == top() && safe_for_replace) { replace_in_map(value, cast);
*** 2719,2742 **** --- 2766,2795 ---- // Use null_seen information if it is available from the profile. // If we see an unexpected null at a type check we record it and force a // recompile; the offending check will be recompiled to handle NULLs. // If we see several offending BCIs, then all checks in the // method will be recompiled. ! bool GraphKit::seems_never_null(Node* obj, ciProfileData* data, bool& speculating) { + speculating = !_gvn.type(obj)->speculative_maybe_null(); + Deoptimization::DeoptReason reason = speculating ? Deoptimization::Reason_speculate_null_check : Deoptimization::Reason_null_check; if (UncommonNullCast // Cutout for this technique && obj != null() // And not the -Xcomp stupid case? ! && !too_many_traps(Deoptimization::Reason_null_check) ! && !too_many_traps(reason) ) { + if (speculating) { + return true; + } if (data == NULL) // Edge case: no mature data. Be optimistic here. return true; // If the profile has not seen a null, assume it won't happen. assert(java_bc() == Bytecodes::_checkcast || java_bc() == Bytecodes::_instanceof || java_bc() == Bytecodes::_aastore, "MDO must collect null_seen bit here"); return !data->as_BitData()->null_seen(); } + speculating = false; return false; } //------------------------maybe_cast_profiled_receiver------------------------- // If the profile has seen exactly one type, narrow to exactly that type.
*** 2798,2816 **** --- 2851,2869 ---- ciKlass* type, bool not_null) { // type == NULL if profiling tells us this object is always null if (type != NULL) { Deoptimization::DeoptReason class_reason = Deoptimization::Reason_speculate_class_check; ! Deoptimization::DeoptReason null_reason = Deoptimization::Reason_null_check; ! Deoptimization::DeoptReason null_reason = Deoptimization::Reason_speculate_null_check; if (!too_many_traps(null_reason) && !too_many_traps(class_reason)) { Node* not_null_obj = NULL; // not_null is true if we know the object is not null and // there's no need for a null check if (!not_null) { Node* null_ctl = top(); ! not_null_obj = null_check_oop(obj, &null_ctl, true, true); ! not_null_obj = null_check_oop(obj, &null_ctl, true, true, true); assert(null_ctl->is_top(), "no null control here"); } else { not_null_obj = obj; }
*** 2854,2869 **** --- 2907,2923 ---- ciProfileData* data = NULL; if (java_bc() == Bytecodes::_instanceof) { // Only for the bytecode data = method()->method_data()->bci_to_data(bci()); } + bool speculative_not_null = false; bool never_see_null = (ProfileDynamicTypes // aggressive use of profile ! && seems_never_null(obj, data, speculative_not_null)); // Null check; get casted pointer; set region slot 3 Node* null_ctl = top(); ! Node* not_null_obj = null_check_oop(obj, &null_ctl, never_see_null, safe_for_replace, speculative_not_null); // If not_null_obj is dead, only null-path is taken if (stopped()) { // Doing instance-of on a NULL? set_control(null_ctl); return intcon(0);
*** 2982,2997 **** --- 3036,3052 ---- RegionNode* region = new (C) RegionNode(PATH_LIMIT); Node* phi = new (C) PhiNode(region, toop); C->set_has_split_ifs(true); // Has chance for split-if optimization // Use null-cast information if it is available + bool speculative_not_null = false; bool never_see_null = ((failure_control == NULL) // regular case only ! && seems_never_null(obj, data, speculative_not_null)); // Null check; get casted pointer; set region slot 3 Node* null_ctl = top(); ! Node* not_null_obj = null_check_oop(obj, &null_ctl, never_see_null, safe_for_replace, speculative_not_null); // If not_null_obj is dead, only null-path is taken if (stopped()) { // Doing instance-of on a NULL? set_control(null_ctl); return null();

src/share/vm/opto/graphKit.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File