RFR/RFC calling convention change for value types in compiled code

Zoltán Majó zoltan.majo at oracle.com
Thu Nov 24 14:16:30 UTC 2016


Hi Roland,


On 11/24/2016 11:25 AM, Roland Westrelin wrote:
> http://cr.openjdk.java.net/~roland/valhalla/callingconvention/webrev.00/
>
> This patch implements a new compiled code calling convention for methods
> that take value type arguments: instead of passing a reference to the
> value type as an argument, the method is passed each field of the value
> type in registers/stack slots.
>
> The interpreter continues to use references at calls so when going to
> compiled from the interpreter (i2c adapter), value type fields are
> loaded from the value type object and the value type object is
> discarded. When going from compiled code to the interpreter (c2i
> adapter), value type objects for every arguments need to be allocated
> and initialized with the field values passed by the compiler.

the change looks good to me in general. Please find some minor comments 
below:

= src/cpu/x86/vm/sharedRuntime_x86_64.cpp

Don't we have one T_VOID too much here?

561         // flattened so, for instance: T_VALUETYPE T_INT T_VALUETYPE
562         // T_INT T_LONG T_VOID T_VOID T_VOID is a value type with a


2 minor typos.

563         // int field an a value type field that itself has 2 fields, a
564         // int and a long

=>

563         // int field and a value type field that itself has 2 fields, an
564         // int and a long


Maybe it's better to have a more precise condition here:

692     if (i != sig.length()) {

=>

692     if (i < sig.length()) {


Can you maybe find more suggestive names for j and k (and maybe i) in 
gen_c2i_adapter_helper()?

766   for (int i = 0, ignored = 0, j = 0, k = 0; i < sig.length(); i++) {

Maybe next_vt_arg_comp for j, next_arg_int for k and next_arg_comp for 
k? These are long variable names, I agree, but it would be helpful if 
the code indicated which variable represents the interpreter's and which 
the compiler's point of view.

The same could be applied to gen_i2c_adapter()

1029   for (int i = 0, ignored = 0, k = 0; i < sig.length(); i++) {


Can we maybe change the method name to reflect that the number of 
arguments computed is from the point of view of the interpreter?

  552 static int compute_total_args_passed_int(const 
GrowableArray<SigEntry>& sig) {

Maybe it would be also good to change the argument name to sig_extended 
or sig_cc so that it's more obvious that this is the signature used by 
the calling convention (and not the declared signature).

So in SharedRuntime::gen_i2c_adapter, you could change

1018   int total_args_passed = compute_total_args_passed(sig);

to

1018   int total_args_passed_int = 
compute_total_args_passed_int(sig_extended);


= src/share/vm/opto/type.hpp

1536   const TypeTuple* const _domain_sig;     // Domain of inputs
1537   const TypeTuple* const _domain_cc;  // Domain of inputs

Could you please add a comment to explain what the difference between 
_domain_sig and _domain_cc is? I see that 'cc' refers to calling 
convention, but that was not obvious on the first sight. Or maybe you 
can use _domain_sig_extended instead. (Whatever you may pick, it would 
be great if it stayed consistent with the terms you use at other places, 
e.g., in the adapter generation).

The comment in src/share/vm/opto/type.cpp describes very well what is 
happening, maybe you can reuse part of that text.


1558   static const TypeFunc *make(const TypeTuple* domain, const 
TypeTuple* domain_cc, const TypeTuple* range);

You could add a version of the make method that takes only one domain 
argument for the case domain_sig and domain_sig_extended are the same. 
(There are more than 30 places where the two are equal and only one 
place where they are not.)


652   static const TypeTuple *make_domain(ciInstanceKlass* recv, 
ciSignature *sig, bool is_cc = false);

Could you please give a more suggestive name to the 'is_cc'? You don't 
actually check that we have a calling convention but rather if the 
special calling convention for VT fields is enabled. Maybe 
vt_fields_as_args_enabled could work.


= src/share/vm/opto/type.cpp

Could you please move the extra_value_fields() and 
collect_value_fields() functions to ciValueKlass? Both functions operate 
on a ciValueKlass instance and maybe we want to use them later in some 
other context. Maybe add a short comment summarizing what those 
functions do.


= src/share/vm/opto/callGenerator.cpp

  375   // FIXME: late inlining of methods that take value type arguments is
  376   // broken: arguments at the call are set up so fields of value type
  377   // arguments are passed but code here expects a single argument per
  378   // value type (a ValueTypeNode) instead.

How difficult do you think it will be to fix late inlining later on? 
It's fine to do the fix later -- I'm just wondering if there is anything 
here that would cause a large difficulty for us later on (most likely 
not, but better to ask).


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

4183   experimental(bool, ValueTypePassFieldsAsArgs, 
true,                       \
4184           "Pass each field as an argument at 
calls")                        \

Can you please correct the indentation in the second line?

Thank you!

Best regards,


Zoltan

>
> Roland.



More information about the valhalla-dev mailing list