While debugging my latest DataValue PR under 2.11, I came across what I believe
to be a compiler bug.
Recall that we have source code along the lines of:
...
@inline implicit def toDataValue(v: DFDLTime): DataValueTime = new
DataValue(v)
@inline implicit def toDataValue(v: Array[Byte]): DataValueByteArray = new
DataValue(v)
@inline implicit def toDataValue(v: JBoolean): DataValueBool = new
DataValue(v)
@inline implicit def toDataValue(v: JNumber): DataValueNumber = new
DataValue(v)
...
Under 2.11, this gets compiled to:
...
public org.apache.daffodil.calendar.DFDLDate
toDataValue(org.apache.daffodil.calendar.DFDLDate);
Code:
0: aload_1
1: areturn
public org.apache.daffodil.calendar.DFDLTime
toDataValue(org.apache.daffodil.calendar.DFDLTime);
Code:
0: aload_1
1: areturn
public byte[] toDataValue(byte[]);
Code:
0: getstatic #35 // Field
scala/runtime/ScalaRunTime$.MODULE$:Lscala/runtime/ScalaRunTime$;
3: aload_1
4: invokevirtual #39 // Method
scala/runtime/ScalaRunTime$.toObjectArray:(Ljava/lang/Object;)[Ljava/lang/Object;
7: checkcast #41 // class "[Ljava/lang/Byte;"
10: areturn
public java.lang.Boolean toDataValue(java.lang.Boolean);
Code:
0: aload_1
1: areturn
public java.lang.Number toDataValue(java.lang.Number);
Code:
0: aload_1
1: areturn
...
Note that for every instant accept byte[], the function compiles to a simple
identity function.
When compiled under 2.12, the byte[] instance gets compiled to identity as well:
public byte[] toDataValue(byte[]);
Code:
0: aload_1
1: areturn
The 2.11 version is not just inefficient; it is also wrong. It first converts
to an array of Objects (which implies boxing), before attempting to cast said
array to an array of (boxed) Bytes. This case fails , as Object[] does not
extends Byte[].
Even if this cast were to succeed, the function would then be attempting to
return an array of boxed java.lang.Byte, while its signature indicates it
should be returning an array of unboxed bytes.
(As an asside, at the callpoint I looked at in 2.12 optimizes this function out
entirely; the 2.11 version makes a standard function call to toDataValue)
I'm at a bit of a loss as to how to proceed. This bug seems fatal to the idea
of having an AnyVal DataValue class, and we do not have much wiggle-room to
tweak our source code to avoid triggering it.
Thoughts?
Brandon T. Sloane
Associate, Services
[email protected] | tresys.com