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

Christian Thalinger christian.thalinger at oracle.com
Thu Oct 3 12:38:02 PDT 2013


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.

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.

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

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:

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

src/share/vm/ci/ciMethodData.hpp:

+   // If the compiler finds a profiled type is known statically for

"type that is known"

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

+   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().

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

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

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.

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

src/share/vm/runtime/globals.hpp:

+   develop(bool, PrintMethodDataStats, false,                                \

Most of these flags are named *Statistics.

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

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