RFR(L): 8023657: New type profiling points: arguments to call

Roland Westrelin roland.westrelin at oracle.com
Fri Oct 4 08:28:46 PDT 2013


Thanks Chris for taking a look at this.

On Oct 3, 2013, at 9:38 PM, Christian Thalinger <christian.thalinger at oracle.com> wrote:

> src/share/vm/c1/c1_GraphBuilder.cpp:
> 
> + Values* GraphBuilder::args_list_for_profiling(ciMethod* target, int& start, bool may_have_receiver) {
> + Values* GraphBuilder::collect_args_for_profiling(Values* args, ciMethod* target, bool may_have_receiver) {
> 
> Both methods take a target as argument but never use it.

It's used in a subsequent patch. Thanks for spotting that. I'll remove it.

> src/share/vm/c1/c1_Instruction.hpp:
> 
> +     bool arg_needs_null_check(int i) const {
> +       if (i >= 0 && i < (int)sizeof(_nonnull_state) * BitsPerByte) {
> 
> This means that arguments after the 32nd position always need a null check.  Can you add a comment to these methods explaining that as we do for Java API methods?  Maybe use Doxygen style.

Ok.

> 
> +   virtual void input_values_do(ValueVisitor* f)   {
> +     if (_recv != NULL) f->visit(&_recv);
> +     for (int i = 0; i < nb_profiled_args(); i++) f->visit(_obj_args->adr_at(i));
> +   }
> 
> Can you use some line breaks and curly braces here too?

Ok.

> src/share/vm/c1/c1_LIR.hpp:
> 
> +   intptr_t     _current_klass; // what the profiling currently reports
> 
> Why is the type intptr_t?  Can't we use a more specific type here?  Hmm, you tag klass pointers:

Indeed.

> 
> +  static intptr_t with_status(intptr_t k, intptr_t in) {
> +    return k | (in & status_bits);
> +  }
> 
> src/share/vm/c1/c1_LIRGenerator.cpp:
> 
> + static ciKlass* sig_next_klass(ciSignature* sig, ciKlass*& first_sig_k, int& j) {
> 
> We should move this method into ciSignature.  Or better ciSignatureStream.

I thought about it but figured it was too specific to be useful to anything else. Anyway, I can make that change.

> 
> src/share/vm/ci/ciMethodData.hpp:
> 
> +   // If the compiler finds a profiled type is known statically for
> 
> "type that is known"

Ok.

> 
> src/share/vm/oops/methodData.cpp:
> 
> +   SignatureStream ss(inv.signature());
> +   int args_count = 0;
> +   for ( ; !ss.at_return_type(); ss.next()) {
> +     if (ss.is_object() || ss.is_array()) {
> +       args_count++;
> +       if (args_count >= max) {
> +         break;
> +       }
> +     }
> +   }
> 
> This would be a nice utility method in SignatureStream (sans the >= max part).  Maybe reference_parameter_count().  Oh, btw., arrays are treated as objects:
> 
> bool SignatureStream::is_object() const {
>  return _type == T_OBJECT
>      || _type == T_ARRAY;
> }
> 
> It could be reused here right away:
> 
> + #ifdef ASSERT
> +   int count = 0;
> +   for (SignatureStream ss(inv.signature()); !ss.at_return_type(); ss.next()) {
> +     if (ss.is_object() || ss.is_array()) {
> +       count++;

Ok, I'll see what I can do.

> 
> +   Bytecodes::Code bc = m->code_at(bci);
> +   assert(Bytecodes::is_invoke(m->java_code_at(bci)), "arguments only make sense at call");
> + 
> +   return bc == Bytecodes::_invokedynamic || bc == Bytecodes::_invokehandle;
> 
> Instead of this code you can use Bytecode_invoke and then query inv.is_invokedynamic() || inv.is_invokehandle().

Sure.

> 
> + int MethodData::profile_arguments_flag() {
> +   return TypeProfile % 10;
> + }
> 
> Why 10?

That's also something that leaked from a subsequent patch. I intend to use TypeProfile=xyz, with x,y,z in {0,1,2} to select the level of profiling for each of arguments, parameters, return value. I welcome other suggestions. I'll remove the % 10.

> 
> + bool MethodData::profile_arguments() {
> +   return profile_arguments_flag() > 0 && profile_arguments_flag() <= 2;
> + }
> + 
> + bool MethodData::profile_arguments_jsr292_only() {
> +   return profile_arguments_flag() == 1;
> + }
> + 
> + bool MethodData::profile_all_arguments() {
> +   return profile_arguments_flag() == 2;
> + }
> 
> I think you should have an enum for all of these constants.

Ok.

> 
> src/share/vm/oops/methodData.hpp:
> 
> +   void set_int_at_unchecked(int index, int value) {
> +     data()->set_cell_at(index, (intptr_t) value);
> +   }
> 
> This method is not used.

Well you're much better than I am at spotting unused stuff. I'll remove it.

> 
> +     return _args.set_type(i, TypeEntries::with_status((intptr_t)k, current));
> 
> Maybe you should add another with_status method that takes a Klass* and do the cast there.

Ok.

> 
> src/share/vm/runtime/globals.hpp:
> 
> +   develop(bool, PrintMethodDataStats, false,                                \
> 
> Most of these flags are named *Statistics.

I'll make the change.

> 
> +   product_pd(uintx, TypeProfile,                                            \
> +           "Type profiling of arguments at call:"                            \
> +           "0->off ; 1->js292 only; 2->all methods")                         \
> +   product(intx, TypeProfileArgsLimit,     2,                                \
> +           "max number of call arguments to consider for type profiling")    \
> +                                                                             \
> 
> Empty line missing between.

I'll add the missing like.

> 
> On Oct 2, 2013, at 10:02 AM, Roland Westrelin <roland.westrelin at oracle.com> wrote:
> 
>> Here is a new webrev for the new profiling points, only profiling of arguments at calls this time. This one includes tiered support on 32bit and 64bit x86.
>> 
>> http://cr.openjdk.java.net/~roland/8023657/webrev.01/
>> 
>> The output of -XX:+PrintMethodData is:
>> 
>> 6 invokevirtual 2 <TestProfiling.m2(LTestProfiling$C;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;>
>> 0   bci: 6    VirtualCallData     count(0) entries(1)
>>                                   'TestProfiling'(4746 1.00)
>>               argument types      0: stack(1) 'TestProfiling$C'
>>                                   1: stack(2) unknown (null seen)
>> 
>> Profiling can either be off, on only for jsr292 related calls (invokedynamic, invokehandle or all invokes in a lambda form) or on for all methods and invokes. -XX:TypeProfile={0,1,2} is used to pick a level of profiling.
>> Once all profiling is in (arguments, parameters, return value), in order to limit the number of options my plan is to use TypeProfile=xyz, with x,y,z in {0,1,2} to select the level of profiling for each. TypeProfile=111, Typeprofile=222 etc.
>> Profiling is by default on only for jsr292 related calls in order to not impact startup/footprint of standard java apps.
>> 
>> Roland.
>> 
>> 
> 



More information about the hotspot-compiler-dev mailing list