Simn / genjvm

13 stars 1 forks source link

NativeArray wrapping #14

Closed Simn closed 5 years ago

Simn commented 5 years ago

We currently always create java.NativeArray (should move that btw...) as a reference type and wrap the values, mostly because "that's easy". We should use the array specializations for basic types here and generate the instructions accordingly.

The problem with this is that Haxe's type system is retarded and allow this kind of stuff:

class Main {
    static public function main() {
        var ia = new java.NativeArray<Int>(1);
        var fa = new java.NativeArray<Float>(1);
        var da = new java.NativeArray<Dynamic>(1);
        da = ia;
        da = fa;
        f(ia);
        f(fa);
    }

    static function f<T>(_:java.NativeArray<T>) { }
}

I think we have three options:

  1. Introduce some @:absolutelyNoVariance metadata in Haxe core which does not allow this. That's somewhat straightforward for the assignment to Dynamic, but could be a huge mess for type parameters. I think we would basically have to disable type inference for this, like for the old @:generic implementation.
  2. Generate reference arrays by default (like now), but do some escape analysis to detect if the array is never assigned and aliased. In these cases we can safely use the unwrapped types. This is quite similar to the inline constructor analysis, but less local because it should work for fields as well.
  3. Don't care and simply let the JVM verifier fail.

We'll start with 3 either way, but the question is how much nicer we can/should make this and with what priority...

Simn commented 5 years ago

Actually maybe 2. shouldn't be an option. If the type is NativeArray<Int> (explicit or implicit), it should not silently become a reference array.

Simn commented 5 years ago

I can't be arsed to write a manual detection for this. If you use native arrays you better know what you're doing, and if you don't you should at least not complain about getting ClassCastExceptions at run-time.