src/share/vm/c1/c1_LIRGenerator.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hotspot Cdiff src/share/vm/c1/c1_LIRGenerator.cpp

src/share/vm/c1/c1_LIRGenerator.cpp

Print this page
rev 5462 : 8026251: New type profiling points: parameters to methods
Summary: x86 interpreter and c1 type profiling for parameters on method entries
Reviewed-by:

*** 2641,2650 **** --- 2641,2683 ---- __ profile_type(new LIR_Address(mdp, md_offset, T_METADATA), value.result(), exact_klass, profiled_k, new_pointer_register(), not_null, exact_signature_k != NULL); return result; } + // profile parameters on entry to the root of the compilation + void LIRGenerator::profile_parameters(Base* x) { + if (compilation()->profile_parameters()) { + CallingConvention* args = compilation()->frame_map()->incoming_arguments(); + ciMethodData* md = scope()->method()->method_data_or_null(); + assert(md != NULL, "Sanity"); + + if (md->parameters_type_data() != NULL) { + ciParametersTypeData* parameters_type_data = md->parameters_type_data(); + ciTypeStackSlotEntries* parameters = parameters_type_data->parameters(); + LIR_Opr mdp = LIR_OprFact::illegalOpr; + for (int java_index = 0, i = 0, j = 0; j < parameters_type_data->number_of_parameters(); i++) { + LIR_Opr src = args->at(i); + assert(!src->is_illegal(), "check"); + BasicType t = src->type(); + if (t == T_OBJECT || t == T_ARRAY) { + intptr_t profiled_k = parameters->type(j); + Local* local = x->state()->local_at(java_index)->as_Local(); + ciKlass* exact = profile_arg_type(md, md->byte_offset_of_slot(parameters_type_data, ParametersTypeData::type_offset(0)), + in_bytes(ParametersTypeData::type_offset(j)) - in_bytes(ParametersTypeData::type_offset(0)), + profiled_k, local, mdp, false, local->declared_type()->as_klass()); + // If the profile is known statically set it once for all and do not emit any code + if (exact != NULL) { + md->set_parameter_type(j, exact); + } + j++; + } + java_index += type2size[t]; + } + } + } + } + void LIRGenerator::do_Base(Base* x) { __ std_entry(LIR_OprFact::illegalOpr); // Emit moves from physical registers / stack slots to virtual registers CallingConvention* args = compilation()->frame_map()->incoming_arguments(); IRScope* irScope = compilation()->hir()->top_scope();
*** 2716,2725 **** --- 2749,2759 ---- } } // increment invocation counters if needed if (!method()->is_accessor()) { // Accessors do not have MDOs, so no counting. + profile_parameters(x); CodeEmitInfo* info = new CodeEmitInfo(scope()->start()->state()->copy(ValueStack::StateBefore, SynchronizationEntryBCI), NULL, false); increment_invocation_counter(info); } // all blocks with a successor must end with an unconditional jump
*** 3075,3089 **** default: ShouldNotReachHere(); break; } } void LIRGenerator::profile_arguments(ProfileCall* x) { ! if (MethodData::profile_arguments()) { int bci = x->bci_of_invoke(); ciMethodData* md = x->method()->method_data_or_null(); ciProfileData* data = md->bci_to_data(bci); ! if (data->is_CallTypeData() || data->is_VirtualCallTypeData()) { ByteSize extra = data->is_CallTypeData() ? CallTypeData::args_data_offset() : VirtualCallTypeData::args_data_offset(); int base_offset = md->byte_offset_of_slot(data, extra); LIR_Opr mdp = LIR_OprFact::illegalOpr; ciTypeStackSlotEntries* args = data->is_CallTypeData() ? ((ciCallTypeData*)data)->args() : ((ciVirtualCallTypeData*)data)->args(); --- 3109,3124 ---- default: ShouldNotReachHere(); break; } } void LIRGenerator::profile_arguments(ProfileCall* x) { ! if (compilation()->profile_arguments()) { int bci = x->bci_of_invoke(); ciMethodData* md = x->method()->method_data_or_null(); ciProfileData* data = md->bci_to_data(bci); ! if ((data->is_CallTypeData() && data->as_CallTypeData()->has_arguments()) || ! (data->is_VirtualCallTypeData() && data->as_VirtualCallTypeData()->has_arguments())) { ByteSize extra = data->is_CallTypeData() ? CallTypeData::args_data_offset() : VirtualCallTypeData::args_data_offset(); int base_offset = md->byte_offset_of_slot(data, extra); LIR_Opr mdp = LIR_OprFact::illegalOpr; ciTypeStackSlotEntries* args = data->is_CallTypeData() ? ((ciCallTypeData*)data)->args() : ((ciVirtualCallTypeData*)data)->args();
*** 3105,3114 **** --- 3140,3214 ---- !x->arg_needs_null_check(i+start), sig_stream.next_klass()); if (exact != NULL) { md->set_argument_type(bci, i, exact); } } + } else { + #ifdef ASSERT + Bytecodes::Code code = x->method()->raw_code_at_bci(x->bci_of_invoke()); + int n = x->nb_profiled_args(); + assert(MethodData::profile_parameters() && x->inlined() && + ((code == Bytecodes::_invokedynamic && n <= 1) || (code == Bytecodes::_invokehandle && n <= 2)), + "only at JSR292 bytecodes"); + #endif + } + } + } + + // profile parameters on entry to an inlined method + void LIRGenerator::profile_parameters_at_call(ProfileCall* x) { + if (compilation()->profile_parameters() && x->inlined()) { + ciMethodData* md = x->callee()->method_data_or_null(); + if (md != NULL) { + ciParametersTypeData* parameters_type_data = md->parameters_type_data(); + if (parameters_type_data != NULL) { + ciTypeStackSlotEntries* parameters = parameters_type_data->parameters(); + LIR_Opr mdp = LIR_OprFact::illegalOpr; + bool has_receiver = !x->callee()->is_static(); + ciSignature* sig = x->callee()->signature(); + ciSignatureStream sig_stream(sig, has_receiver ? x->callee()->holder() : NULL); + int i = 0; // to iterate on the Instructions + Value arg = x->recv(); + bool not_null = false; + int bci = x->bci_of_invoke(); + Bytecodes::Code bc = x->method()->java_code_at_bci(bci); + // The first parameter is the receiver so that's what we start + // with if it exists. On exception if method handle call to + // virtual method has receiver in the args list + if (arg == NULL || !Bytecodes::has_receiver(bc)) { + i = 1; + arg = x->profiled_arg_at(0); + not_null = !x->arg_needs_null_check(0); + } + int k = 0; // to iterate on the profile data + for (;;) { + intptr_t profiled_k = parameters->type(k); + ciKlass* exact = profile_arg_type(md, md->byte_offset_of_slot(parameters_type_data, ParametersTypeData::type_offset(0)), + in_bytes(ParametersTypeData::type_offset(k)) - in_bytes(ParametersTypeData::type_offset(0)), + profiled_k, arg, mdp, not_null, sig_stream.next_klass()); + // If the profile is known statically set it once for all and do not emit any code + if (exact != NULL) { + md->set_parameter_type(k, exact); + } + k++; + if (k >= parameters_type_data->number_of_parameters()) { + #ifdef ASSERT + int extra = 0; + if (MethodData::profile_arguments() && TypeProfileParmsLimit != -1 && + x->nb_profiled_args() >= TypeProfileParmsLimit && + x->recv() != NULL && Bytecodes::has_receiver(bc)) { + extra += 1; + } + assert(i == x->nb_profiled_args() - extra || (TypeProfileParmsLimit != -1 && TypeProfileArgsLimit > TypeProfileParmsLimit), "unused parameters?"); + #endif + break; + } + arg = x->profiled_arg_at(i); + not_null = !x->arg_needs_null_check(i); + i++; + } + } } } } void LIRGenerator::do_ProfileCall(ProfileCall* x) {
*** 3120,3129 **** --- 3220,3234 ---- if (x->nb_profiled_args() > 0) { profile_arguments(x); } + // profile parameters on inlined method entry including receiver + if (x->recv() != NULL || x->nb_profiled_args() > 0) { + profile_parameters_at_call(x); + } + if (x->recv() != NULL) { LIRItem value(x->recv(), this); value.load_item(); recv = new_register(T_OBJECT); __ move(value.result(), recv);
src/share/vm/c1/c1_LIRGenerator.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File