/** * Check whether profiling provides a type for the argument i to the * call at bci bci * * @param bci bci of the call * @param i argument number * @return profiled type * * If the profile reports that the argument may be null, return false * at least for now. */ ciKlass* ciMethod::argument_profiled_type(int bci, int i) { if (MethodData::profile_parameters() && method_data() != NULL && method_data()->is_mature()) { ciProfileData* data = method_data()->bci_to_data(bci); if (data != NULL) { if (data->is_VirtualCallTypeData()) { assert_virtual_call_type_ok(bci); ciVirtualCallTypeData* call = (ciVirtualCallTypeData*)data->as_VirtualCallTypeData(); if (i >= call->number_of_arguments()) { return NULL; } ciKlass* type = call->valid_argument_type(i); if (type != NULL && !call->argument_maybe_null(i)) { return type; } } else if (data->is_CallTypeData()) { assert_call_type_ok(bci); ciCallTypeData* call = (ciCallTypeData*)data->as_CallTypeData(); if (i >= call->number_of_arguments()) { return NULL; } ciKlass* type = call->valid_argument_type(i); if (type != NULL && !call->argument_maybe_null(i)) { return type; } } } } return NULL; }
// ------------------------------------------------------------------ // ciMethod::call_profile_at_bci // // Get the ciCallProfile for the invocation of this method. // Also reports receiver types for non-call type checks (if TypeProfileCasts). ciCallProfile ciMethod::call_profile_at_bci(int bci) { ResourceMark rm; ciCallProfile result; if (method_data() != NULL && method_data()->is_mature()) { ciProfileData* data = method_data()->bci_to_data(bci); if (data != NULL && data->is_CounterData()) { // Every profiled call site has a counter. int count = data->as_CounterData()->count(); if (!data->is_ReceiverTypeData()) { result._receiver_count[0] = 0; // that's a definite zero } else { // ReceiverTypeData is a subclass of CounterData ciReceiverTypeData* call = (ciReceiverTypeData*)data->as_ReceiverTypeData(); // In addition, virtual call sites have receiver type information int receivers_count_total = 0; int morphism = 0; for (uint i = 0; i < call->row_limit(); i++) { ciKlass* receiver = call->receiver(i); if (receiver == NULL) continue; morphism += 1; int rcount = call->receiver_count(i); if (rcount == 0) rcount = 1; // Should be valid value receivers_count_total += rcount; // Add the receiver to result data. result.add_receiver(receiver, rcount); // If we extend profiling to record methods, // we will set result._method also. } // Determine call site's morphism. // The call site count is 0 with known morphism (onlt 1 or 2 receivers) // or < 0 in the case of a type check failured for checkcast, aastore, instanceof. // The call site count is > 0 in the case of a polymorphic virtual call. if (morphism > 0 && morphism == result._limit) { // The morphism <= MorphismLimit. if ((morphism < ciCallProfile::MorphismLimit) || (morphism == ciCallProfile::MorphismLimit && count == 0)) { #ifdef ASSERT if (count > 0) { this->print_short_name(tty); tty->print_cr(" @ bci:%d", bci); this->print_codes(); assert(false, "this call site should not be polymorphic"); } #endif result._morphism = morphism; } } // Make the count consistent if this is a call profile. If count is // zero or less, presume that this is a typecheck profile and // do nothing. Otherwise, increase count to be the sum of all // receiver's counts. if (count >= 0) { count += receivers_count_total; } } result._count = count; } } return result; }
// ------------------------------------------------------------------ // ciMethod::call_profile_at_bci // // Get the ciCallProfile for the invocation of this method. // Also reports receiver types for non-call type checks (if TypeProfileCasts). ciCallProfile ciMethod::call_profile_at_bci(int bci) { ResourceMark rm; ciCallProfile result; if (method_data() != NULL && method_data()->is_mature()) { ciProfileData* data = method_data()->bci_to_data(bci); if (data != NULL && data->is_CounterData()) { // Every profiled call site has a counter. int count = data->as_CounterData()->count(); if (!data->is_ReceiverTypeData()) { result._receiver_count[0] = 0; // that's a definite zero } else { // ReceiverTypeData is a subclass of CounterData ciReceiverTypeData* call = (ciReceiverTypeData*)data->as_ReceiverTypeData(); // In addition, virtual call sites have receiver type information int receivers_count_total = 0; int morphism = 0; for (uint i = 0; i < call->row_limit(); i++) { ciKlass* receiver = call->receiver(i); if (receiver == NULL) continue; morphism += 1; int rcount = call->receiver_count(i); if (rcount == 0) rcount = 1; // Should be valid value receivers_count_total += rcount; // Add the receiver to result data. result.add_receiver(receiver, rcount); // If we extend profiling to record methods, // we will set result._method also. } // Determine call site's morphism. // The call site count could be == (receivers_count_total + 1) // not only in the case of a polymorphic call but also in the case // when a method data snapshot is taken after the site count was updated // but before receivers counters were updated. if (morphism == result._limit) { // There were no array klasses and morphism <= MorphismLimit. if (morphism < ciCallProfile::MorphismLimit || morphism == ciCallProfile::MorphismLimit && (receivers_count_total+1) >= count) { result._morphism = morphism; } } // Make the count consistent if this is a call profile. If count is // zero or less, presume that this is a typecheck profile and // do nothing. Otherwise, increase count to be the sum of all // receiver's counts. if (count > 0) { if (count < receivers_count_total) { count = receivers_count_total; } } } result._count = count; } } return result; }
// ------------------------------------------------------------------ // ciMethod::interpreter_call_site_count int ciMethod::interpreter_call_site_count(int bci) { if (method_data() != NULL) { ResourceMark rm; ciProfileData* data = method_data()->bci_to_data(bci); if (data != NULL && data->is_CounterData()) { return scale_count(data->as_CounterData()->count()); } } return -1; // unknown }
/** * Check whether profiling provides a type for the parameter i * * @param [in]i parameter number * @param [out]type profiled type of parameter, NULL if none * @param [out]maybe_null true if null was seen for parameter * @return true if profiling exists * */ bool ciMethod::parameter_profiled_type(int i, ciKlass*& type, bool& maybe_null) { if (MethodData::profile_parameters() && method_data() != NULL && method_data()->is_mature()) { ciParametersTypeData* parameters = method_data()->parameters_type_data(); if (parameters != NULL && i < parameters->number_of_parameters()) { type = parameters->valid_parameter_type(i); maybe_null = parameters->parameter_maybe_null(i); return true; } } return false; }
/** * Check whether profiling provides a type for the parameter i * * @param i parameter number * @return profiled type * * If the profile reports that the argument may be null, return false * at least for now. */ ciKlass* ciMethod::parameter_profiled_type(int i) { if (MethodData::profile_parameters() && method_data() != NULL && method_data()->is_mature()) { ciParametersTypeData* parameters = method_data()->parameters_type_data(); if (parameters != NULL && i < parameters->number_of_parameters()) { ciKlass* type = parameters->valid_parameter_type(i); if (type != NULL && !parameters->parameter_maybe_null(i)) { return type; } } } return NULL; }
// ------------------------------------------------------------------ // Adjust a CounterData count to be commensurate with // interpreter_invocation_count. If the MDO exists for // only 25% of the time the method exists, then the // counts in the MDO should be scaled by 4X, so that // they can be usefully and stably compared against the // invocation counts in methods. int ciMethod::scale_count(int count, float prof_factor) { if (count > 0 && method_data() != NULL) { int current_mileage = method_data()->current_mileage(); int creation_mileage = method_data()->creation_mileage(); int counter_life = current_mileage - creation_mileage; int method_life = interpreter_invocation_count(); // counter_life due to backedge_counter could be > method_life if (counter_life > method_life) counter_life = method_life; if (0 < counter_life && counter_life <= method_life) { count = (int)((double)count * prof_factor * method_life / counter_life + 0.5); count = (count > 0) ? count : 1; } } return count; }
/** * Check whether profiling provides a type for the return value from * the call at bci bci * * @param [in]bci bci of the call * @param [out]type profiled type of argument, NULL if none * @param [out]maybe_null true if null was seen for argument * @return true if profiling exists * */ bool ciMethod::return_profiled_type(int bci, ciKlass*& type, bool& maybe_null) { if (MethodData::profile_return() && method_data() != NULL && method_data()->is_mature()) { ciProfileData* data = method_data()->bci_to_data(bci); if (data != NULL) { if (data->is_VirtualCallTypeData()) { assert_virtual_call_type_ok(bci); ciVirtualCallTypeData* call = (ciVirtualCallTypeData*)data->as_VirtualCallTypeData(); type = call->valid_return_type(); maybe_null = call->return_maybe_null(); return true; } else if (data->is_CallTypeData()) { assert_call_type_ok(bci); ciCallTypeData* call = (ciCallTypeData*)data->as_CallTypeData(); type = call->valid_return_type(); maybe_null = call->return_maybe_null(); return true; } } } return false; }
// ------------------------------------------------------------------ // Adjust a CounterData count to be commensurate with // interpreter_invocation_count. If the MDO exists for // only 25% of the time the method exists, then the // counts in the MDO should be scaled by 4X, so that // they can be usefully and stably compared against the // invocation counts in methods. int ciMethod::scale_count(int count, float prof_factor) { if (count > 0 && method_data() != NULL) { int counter_life; int method_life = interpreter_invocation_count(); if (TieredCompilation) { // In tiered the MDO's life is measured directly, so just use the snapshotted counters counter_life = MAX2(method_data()->invocation_count(), method_data()->backedge_count()); } else { int current_mileage = method_data()->current_mileage(); int creation_mileage = method_data()->creation_mileage(); counter_life = current_mileage - creation_mileage; } // counter_life due to backedge_counter could be > method_life if (counter_life > method_life) counter_life = method_life; if (0 < counter_life && counter_life <= method_life) { count = (int)((double)count * prof_factor * method_life / counter_life + 0.5); count = (count > 0) ? count : 1; } } return count; }
/** * Check whether profiling provides a type for the return value from * the call at bci bci * * @param bci bci of the call * @return profiled type * * If the profile reports that the argument may be null, return false * at least for now. */ ciKlass* ciMethod::return_profiled_type(int bci) { if (MethodData::profile_return() && method_data() != NULL && method_data()->is_mature()) { ciProfileData* data = method_data()->bci_to_data(bci); if (data != NULL) { if (data->is_VirtualCallTypeData()) { assert_virtual_call_type_ok(bci); ciVirtualCallTypeData* call = (ciVirtualCallTypeData*)data->as_VirtualCallTypeData(); ciKlass* type = call->valid_return_type(); if (type != NULL && !call->return_maybe_null()) { return type; } } else if (data->is_CallTypeData()) { assert_call_type_ok(bci); ciCallTypeData* call = (ciCallTypeData*)data->as_CallTypeData(); ciKlass* type = call->valid_return_type(); if (type != NULL && !call->return_maybe_null()) { return type; } } } } return NULL; }