Hi,
On 11/03/2017 02:17 PM, Alan Bateman wrote:
On 03/11/2017 08:11, Christoph Dreis wrote:
Hi John,
this has a bigger impact on the overall footprint of
Method/Executable objects. What are your thoughts on this?
The footprint is probably about the same. Small List.of values
do not contain arrays, and may be smaller than arrays with the
same number of elements, since they do not have a length field.
And, indeed, methods typically have a small number of parameters.
Ah, so you would remove the current array field completely and
replace it with the immutable List, right?
In that case I said nothing. I was thinking of a field on top.
The VM creates Method objects and sets the fields, including
parameterTypes, directly so I think removing it would require more
work than it initially looks. If you add a field then it does increase
the footprint a bit. Alternatively, have the method could use a
ImmutableCollection.ListN like implementation that is backed by the
array and doesn't scan it for nulls at create time, this wouldn't be
completely allocation free of course.
What if the work was done in 2 phases.
Phase 1: Array typed fields are changed to be of type Object, then for
example Method could use the following implementation, VM code has no
changes:
private Object parameterTypes;
public List<Class<?>> parameterTypes() {
return (List<Class<?>>) parameterTypes;
}
public Class<?>[] getParameterTypes() {
return parameterTypes().toArray(new Class<?>[0]);
}
...etc.
The "root" Method objects are never used directly. Their methods are
never called. When "root" Method objects are copied, the arrays would be
swapped for lists:
/**
* Package-private routine (exposed to java.lang.Class via
* ReflectAccess) which returns a copy of this Method. The copy's
* "root" field points to this Method.
*/
Method copy() {
// This routine enables sharing of MethodAccessor objects
// among Method objects which refer to the same underlying
// method in the VM. (All of this contortion is only necessary
// because of the "accessibility" bit in AccessibleObject,
// which implicitly requires that new java.lang.reflect
// objects be fabricated for each reflective call on Class
// objects.)
if (this.root != null)
throw new IllegalArgumentException("Can not copy a non-root
Method");
Object _ptypes = parameterTypes;
if (_ptypes instanceof Class<?>[]) {
parameterTypes = _ptypes = List.ofShared((Class<?>[]) _ptypes);
}
Object _etypes = exceptionTypes;
if (_etypes instanceof Class<?>[]) {
exceptionTypes = _etypes = List.ofShared((Class<?>[]) _etypes);
}
Method res = new Method(clazz, name, _ptypes, returnType,
_etypes, modifiers, slot, signature,
annotations, parameterAnnotations,
annotationDefault);
res.root = this;
// Might as well eagerly propagate this if already present
res.methodAccessor = methodAccessor;
return res;
}
Phase 2: VM is changed to inject List(s) instead of arrays and fields ca
be changed to be of type List with swap-conversions removed.
Regards, Peter