__WhereRef/WhereVal peeling, #ifdef and related proposals

Brian Goetz brian.goetz at oracle.com
Sun Jan 18 16:35:45 UTC 2015


Please do not characterize the strawman __WhereRef syntax as any sort of 
"proposal" (as you do in your message title.)  Such things have a 
tendency to get out of hand, and before you know it, you get news 
article like this one:

   http://sdtimes.com/javas-generics-getting-generic/

which seriously thought we were "proposing" to make Java developers 
append "*T" to class names to get specialization.  (You can't make this 
stuff up, but you reduce the degree to which you feed it.)


If your point was "OMG I hope they're not considering a lexical 
preprocessor", hopefully you'll sleep better knowing that this has 
always been off the table.

There are many ways to slice type-casing; your example shows one (though 
you need a "meet rule" when you get to the multiple-tvar case), but 
there are others.  We'll consider syntax when we have a clearer grasp on 
the model we've settled on.



On 1/17/2015 11:41 PM, Thomas W wrote:
> Maurizio's "peeling" patch is interesting. As he noted, his proposal is not
> a real syntax.. just a hack to take experimentation further.
>
> "Peeling" -- as he has titled it -- is programmatic manual specialization.
> This is method specific, in that different methods may depend on a
> different subset of the class's type arguments.
>
> We should be thinking about this in terms of methods having a
> "multi-dimensional space" in which they are specialized; with 1 dimension
> for each type on which the method is specialized.
>
> Note that some method codes may not be manually specialized at all, some
> may only depend on only one of the generic type arguments, others may
> depend on more..
>
> A signature-based illustration (in reality, implementations might tend to
> suck in V but we need to start sketching somewhere):
>
>      public class CountMap <any K, any V> {
>          public void clear();   // not manually specialized
>          public void increment (K key);    // manually specialize on K;
> possibly also on V?
>          public void add (K key, V value);    // manually specialize on K, V
>          public V get (K key);    // manually specialize on K, V
>
>          static private V valueInc (V value);    // manually specialize just
> on V
>      }
>
>
> Correct output bytecode should completely cover (either by explicit code
> sections, by defaulting mechanism, or by automatically specializable code)
> the entire space of specializations which could be requested.
>
> Since we required a well-structured output, completely covering a
> well-defined output space, I would tend to avoid low-level constructs as
> #ifdef. These allow arbitrary spatial patchworks to be created, of high
> complexity but not great for covering the output space in a simple &
> reliable way.
>
> Case statement, as standard, is only one-dimensional.
>
> A multi-dimensional "specialization case" statement could, however, be
> ideal;  it can be defined to have useful rules of matching (most-specific
> wins?) and can fairly easily be checked to prove it correctly covers all
> output space.
>
> Let's have a look at CountMap.increment();  specializing on K.
>
>      public void increment (K key) {
>          int hash = specialize (K) {
>              case (ref) :  (key != null) ? key.hashCode() : 0;
>              case (val) :  key.hashCode();
>              case (int) :  key;
>          };
>          //.. etc
>
> And to specialize on two dimensions:
>
>      public void someMethod (K key, V value) {
>          specialize (K, V) {
>              case (ref, any) :   etc1();
>              case (val, any) :   etc2();
>              case (val, int) :     etc3();
>          }
>          //.. etc
>
> Taking this further, such blocks could be nested;  and/or mixed with normal
> code. The outermost case would not need to contain all dimensions;
> dimensionality of the method overall would be the product of
> dimensionalities of all such 'specialization case' statements within it.
>
> Syntactically, it might possibly (probably?) help to be able to have a
> _result value_ and for this 'specialization case' to actually be an
> expression. I've exemplified this above.
> --------------
>
> I'm not actually arguing for the "manual specialization of methods"
> concept, here -- I've yet to reach a decision on that.
>
> In some ways, the increment() code I've written above illustrates the same
> point I was making with "EQ" -- how being able to code that is portable &
> efficient, at the logical level, between valtype/ reftype/ primitives would
> be mostly superior to manual specialization. HashCode above is an example
> of this issue.
>
> In the one counter-example I've heard -- packing of booleans to bits, eg
> List<boolean> -- I think that *classes* are exactly the mechanism we should
> use!  I would much prefer to have a manually written BooleanArrayList than
> "magic" specialization of storage layouts below the byte-level.
>
> However, in terms of 'manual specialization' syntax I would like us to have
> a high-level view of the problem & express it at this level. C's #ifdef
> syntax is far too ugly & dangerous -- most possible permutations are wrong,
> so I'm dead against it.
>
>
> Regards,
> Thomas
>


More information about the valhalla-dev mailing list