#1666 Native types in Fantom

DanielFath Thu 6 Oct 2011

So I want to create native types in Fantom that fill the role of short, int and byte. However go4 told me such types wouldn't benefit from JVM autoboxing since they are basically wrapper and not the primitive types themselves.

I looked at FanInt.java and all it does is use static methods that pass the values around (when corresponding methods are non-static). But I can't do that since my native classes can't have static methods for plus, minus... Is there any way to implement such types without changing compiler?

Speaking of native types there is one problem with exceptions:

//Int32.java
class Int32
{
   private long  data;

   public something(){
       //I found some error
       throw new Int32OutOfBoundsErr //this doesn't work since it is defined as a Fantom class
   }
} 

Is there any way I can throw my own Err in my native classes? If so, how?

andy Thu 6 Oct 2011

Is there any way I can throw my own Err in my native classes? If so, how?

Err.java extends RuntimeException - so you can throw them - but need to use the static make method:

throw IndexErr.make(index)

brian Thu 6 Oct 2011

Daniel,

Int, Float, and Bool are special "value" types that are handled by the compiler and runtime very specially to optimize how they are passed around (to avoid boxing unless required). You aren't going to be achieve that level of performance.

I'm not sure what exactly you want to accomplish. But byte and short don't actually exist per se in the JVM. Everything is designed to work on the stack as a 32-bit or 64-bit int/float. Byte and short only have value in arrays to achieve better memory savings. In the case of byte[], this is essentially what Buf is.

32-bit ints potentially have some performance over 64 when working on 32-bit processors, but not to the extend that having both 32-bit and 64-bit integers is a worth tradeoff. Plus I think the in long run, everything will move to 64-bit just like everything moved from 16-bit to 32-bit.

Also remember that you can already use byte, short, int, and float with the Java FFI.

DanielFath Thu 6 Oct 2011

Didn't know that. Oh, well it's good to have been warned in advance. I know people wanted optimized collections and numbers but I guess there ain't much point in making them(numbers) anyway.

brian Thu 6 Oct 2011

I think the only real performance booster that is worth it, would be to create a specialized list/array for various integers 16, 32, 64. That would have significant advantages b/c using Int[] requires boxing all the longs into Long. And if you have a big list, then using the more compact bit count might be worth it.

In fact I came across a place last week where I decided for performance to drop down and use a Java int[]. So I was thinking this might be something worth while to add to maybe util pod. I was thinking something like this:

class IntArray
{
  static IntArray make16(Int size)
  static IntArray make32(Int size)
  static IntArray make64(Int size)

  Int get(Int index)
  Void set(Int index, Int val)
  Int size()
}

We could also create a peer FloatArray class.

go4 Fri 7 Oct 2011

I think many people have done this work. For your reference: array1 and array2

DanielFath Fri 7 Oct 2011

Tnx. I was never aware of masalov's work.

brian Sat 8 Oct 2011

I think enough people are doing something like this to warrant putting directly into the core. I was originally holding off hoping we could just optimize sys::List itself, but it is vastly complicated to write the generic get/sets to avoid boxing issues for just special cases.

So I went ahead and created a simple, but optimized util::IntArray class. Not feature rich, but think I got the basics:

native class IntArray
{
  static IntArray makeS1(Int size)
  static IntArray makeU1(Int size)
  static IntArray makeS2(Int size)
  static IntArray makeU2(Int size)
  static IntArray makeS4(Int size)
  static IntArray makeU4(Int size)
  static IntArray makeS8(Int size)

  Int size()
  @Operator Int get(Int index)
  @Operator Void set(Int index, Int val)
  This copyFrom(IntArray that, Range? thatRange := null, Int thisOffset := 0)
  This fill(Int val, Range? range := null)
}

We can add new methods and maybe eventually add FloatArray as things come up.

MoOm Sun 9 Oct 2011

Why not having arrays and extra native value-types directly in the language instead? The problem with IntArray and FloatArray is that, in the end, you still do all your computations with 64-bit ints and floats, which is an unwanted overhead if just want an array of Int32 for example. Furthermore, everytime you set/get a value from an array, there is an unneeded long->int conversion plus a method call that should not be necessary. If what I really want is a Int32 array, I probably care about perfs and in this regard, IntArray/FloatArray are probably not optimized enough.

Here is what I'd really like to have in the language:

  1. 8/16/32 bit native-types
  2. built-in array support. I propose the following syntax: Int32![] array := Int32![1, 2 3, 4]. Arrays would only have a few methods, would not be covariant/contravariant, and get/set would be translated directly into the corresponding VM opcode.

With the two previous points and with generics, many classes of sys could be rewritten directly in Fantom (List, Map, Str, StrBuf, Buf, Uri, Zip...) which would be great for maintainability among the different platforms.

brian Sun 9 Oct 2011

The tradeoff is pretty clear: adding a bunch of private and array types is a massive complication to a language and its type system. And probably 99.99% of software written today doesn't need the performance. So I think the tradeoff we've made is correct for the language, and when you need the performance drop down to Java (or really if you care that much, drop down to C).

Login or Signup to reply.