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

bslo...@tresys.com | tresys.com

Reply via email to