__WhereRef/WhereVal peeling, #ifdef and related proposals
Thomas W
twhitmore.nz at gmail.com
Sun Jan 18 04:41:34 UTC 2015
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