Team-CC-Corp / JVML-JIT

A continuation of JVML which JITs Java bytecode to Lua bytecode rather than interpreting.
MIT License
30 stars 4 forks source link

Lua Tables #45

Closed ghost closed 9 years ago

ghost commented 9 years ago

JVML seems to be missing the ability to bind a "native object" (i.e:a Lua table,a file handle,etc.) to a Java object. This is rather crippling,as file IO calls (and a few mod peripherals) generally work around said native objects. Hence,I've written a wrapper around Lua tables and functions. This should also make it possible to pull the Modem peripheral wrapper,as it converts tables into wrapped LuaTable objects. Currently,it stores handles/objects/whatever in the object's table,under the name "native_data".

The following functions are added to the global namespace: ToJTable:Converts a lua table into a LuaTable object. This LuaTable object is directly linked to the lua table. ToLTable:Gets the lua table from a LuaTable object. ToJFunction:This converts a lua function into a LuaFunction object. ToLFunction:This converts a LuaFunction object into a lua function. Class descriptions: NativeObject: Handles the basic operations of a native object,like redirecting toString,and making hashCode into toString().hashCode(). LuaTable: Interface to a table. Allows iterating through key/value pairs,and getting/setting keys. Can be created using new LuaTable(),which creates a new nice empty table.The global table is at Computer.getGlobalTable(). LuaFunction: Interface to a function. Can be created with new LuaFunction(code),where code is a string containing Lua code.

Yevano commented 9 years ago

This would be useful, but I'm not sure about a few parts of it.

  1. Do we even need this in the standard library? All the native binding can be done without resorting to direct object wrapping. As well, proxying like this is slower than just calling native methods to handle things like this. For some reason, I see this being more useful as a stand-alone library.
  2. NATIVE_handle is a field, but it has no actual JVM value. There is, therefore, no reason for it to be a field at all. It might make more sense to attach the handle in some other way. You could have, for example, a pool of native objects which you can index. So the proxy objects would just contain the index to the pool instead of the actual object. Alternatively, you could write the object directly to an unused index on the object, but if we start doing that, collisions will start to happen if other libraries try doing the same thing.
  3. I don't really think LuaFunction.call is done right. Instead of implicitly converting to Lua objects, they should have to be explicitly converted. This is useful if I actually want my Java objects to go through to the Lua function unconverted, instead of being converted.

Also, you need to change your tabs to be consistent. The convention in this repo is 4 spaces per indent, no tab characters.

ElvishJerricco commented 9 years ago

Personally, I just don't think I like the idea of Java having a direct view of Lua. I think the APIs should feel as java-only as possible. Stuff like file IO should use other means of relating native data to an object.

ghost commented 9 years ago

@Yevano

  1. I'd agree-but the problem remains of how to use handles without a similar system(just without the Java side of the interface,but that's only really there to make the objects usable(EDIT:Just forgot to mention this:Although you won't need to automatically box tables,you'll still need to hold native values somehow.)) 2.NATIVE_handle is there because I needed to find some way of transferring lua values alongside objects. Using "object pool"-style systems would work fine until the memory leak. Really,the whole thing's a kludge since there's no decent way to keep a direct reference to a native handle around. This way,as insane as it is,should hopefully work with Lua's garbage collection. 3.Not sure how that would be useful outside of the JVM,or libraries written with it in mind-but then again,similar applies to LuaFunction

And sorry about the inconsistency with tabs. I should probably get a editor which just magically transforms tabs into 4 spaces no matter what.Or write simple automatic conversion into the "build and copy into save folder" script.

ElvishJerricco commented 9 years ago

Most of the things you would want to hold native handles for can use reference counting to accommodate for the memory leak. Each object that holds a native item can be closeable, and on close they can decrement a reference count to the native item. When a native item's reference count is 0, nil it out.

Yevano commented 9 years ago

@ElvishJerricco Yeah, I think reference counting would work fine.

@gamemanj Now that you mention it, I see that we do need to be able to reference objects for things like file IO. The reference counting + object pool model would work well for this, I think. So let's say we want to implement FileInputStream. When you open the stream, it would (natively) call fs.open and allocate the handle onto the native object pool. This would give it back an index, which it would store in a private field. Whenever we want to read some bytes of the stream, the index would be used to get back the handle and do whatever operation we needed to do with it. Finally, when we close the input stream, it should close the file handle and decrement the reference counter for the handle (which would in normal cases delete the handle as well since nobody else should normally be holding onto that handle).

ghost commented 9 years ago

For native objects,maybe an API like this: nativeObject_allocate() : allocates a native object slot,setting reference count to 1. nativeObject[id] : Your native object slot. nativeObject_incref(id) : Increments the reference count. nativeObject_decref(id) : Decrements the reference count-frees the native object if it goes to 0. Anyway,you can deny the pull request,seeing as a better plan now exists.