•Runtime upgrade to Java 8 or newer.

•Feature: Support Java 21 VirtualThread
This commit is contained in:
qiaoenxin
2024-11-07 16:16:09 +08:00
parent daf3da94e3
commit 4c25b88076
12 changed files with 307 additions and 192 deletions

View File

@@ -1019,6 +1019,11 @@ and at <a href="http://luaj.sourceforge.net/api/2.0/index.html">http://luaj.sour
<li>Let JsePlatform.luaMain() return values returned by the main chunk.</li> <li>Let JsePlatform.luaMain() return values returned by the main chunk.</li>
<li>Add synchronization to CoerceJavaToLua.COERCIONS map.</li> <li>Add synchronization to CoerceJavaToLua.COERCIONS map.</li>
</ul></td></tr>
<tr valign="top"><td>&nbsp;&nbsp;<b>3.1.0</b></td><td><ul>
<li>Runtime upgrade to Java 8 or newer.</li>
<li>Feature: Support Java 21 VirtualThread</li>
</ul></td></tr> </ul></td></tr>
</table></td></tr></table> </table></td></tr></table>

View File

@@ -14,7 +14,7 @@
<attribute name="jars" default="**/*.jar"/> <attribute name="jars" default="**/*.jar"/>
<sequential> <sequential>
<mkdir dir="lib"/> <mkdir dir="lib"/>
<get src="http://luaj.sourceforge.net/lib/@{zipname}.tar.gz" <get src="https://luaj.sourceforge.net/lib/@{zipname}.tar.gz"
dest="lib/@{zipname}.tar.gz"/> dest="lib/@{zipname}.tar.gz"/>
<gunzip src="lib/@{zipname}.tar.gz" dest="lib/@{zipname}.tar"/> <gunzip src="lib/@{zipname}.tar.gz" dest="lib/@{zipname}.tar"/>
<untar src="lib/@{zipname}.tar" dest="lib" overwrite="true"> <untar src="lib/@{zipname}.tar" dest="lib" overwrite="true">

View File

@@ -81,20 +81,22 @@
<pathelement path="lib/midpapi20.jar"/> <pathelement path="lib/midpapi20.jar"/>
<pathelement path="lib/mmapi.jar"/> <pathelement path="lib/mmapi.jar"/>
</path> </path>
<javac destdir="build/jme/classes" encoding="utf-8" source="1.3" target="1.2" bootclasspathref="wtk-libs" <javac includeantruntime="false" destdir="build/jme/classes" encoding="utf-8" source="1.8" target="1.8"
debug="on" debug="on"
srcdir="build/jme/src"/> srcdir="build/jme/src">
<javac destdir="build/jse/classes" encoding="utf-8" source="1.3" target="1.3" <classpath refid="wtk-libs"/>
</javac>
<javac includeantruntime="false" destdir="build/jse/classes" encoding="utf-8" source="1.8" target="1.8"
classpath="lib/bcel-5.2.jar" classpath="lib/bcel-5.2.jar"
debug="on" debug="on"
srcdir="build/jse/src" srcdir="build/jse/src"
excludes="**/script/*,**/Lua2Java*,**/server/*,lua*"/> excludes="**/script/*,**/Lua2Java*,**/server/*,lua*"/>
<javac destdir="build/jse/classes" encoding="utf-8" source="1.5" target="1.5" <javac includeantruntime="false" destdir="build/jse/classes" encoding="utf-8" source="1.8" target="1.8"
classpath="build/jse/classes" classpath="build/jse/classes"
debug="on" debug="on"
srcdir="build/jse/src" srcdir="build/jse/src"
includes="**/script/*,**/Lua2Java*,**/server/*"/> includes="**/script/*,**/Lua2Java*,**/server/*"/>
<javac destdir="build/jse/classes" encoding="utf-8" source="1.3" target="1.3" <javac includeantruntime="false" destdir="build/jse/classes" encoding="utf-8" source="1.8" target="1.8"
classpath="build/jse/classes" classpath="build/jse/classes"
debug="on" debug="on"
srcdir="build/jse/src" srcdir="build/jse/src"

View File

@@ -23,6 +23,10 @@ package org.luaj.vm2;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/** /**
* Subclass of {@link LuaValue} that implements * Subclass of {@link LuaValue} that implements
@@ -82,6 +86,19 @@ public class LuaThread extends LuaValue {
*/ */
public static long thread_orphan_check_interval = 5000; public static long thread_orphan_check_interval = 5000;
public static final String USE_PLATFORM_THREAD = "USE_PLATFORM_THREAD";
private static boolean SUPPORT_VIRTUAL_THREAD = false;
static {
try {
Thread.class.getMethod("ofVirtual");
SUPPORT_VIRTUAL_THREAD = true;
} catch (Exception e) {
//e.printStackTrace();
}
}
public static final int STATUS_INITIAL = 0; public static final int STATUS_INITIAL = 0;
public static final int STATUS_SUSPENDED = 1; public static final int STATUS_SUSPENDED = 1;
public static final int STATUS_RUNNING = 2; public static final int STATUS_RUNNING = 2;
@@ -184,6 +201,8 @@ public class LuaThread extends LuaValue {
public int bytecodes; public int bytecodes;
public int status = LuaThread.STATUS_INITIAL; public int status = LuaThread.STATUS_INITIAL;
private Lock locker = new ReentrantLock();
private Condition cond = locker.newCondition();
State(Globals globals, LuaThread lua_thread, LuaValue function) { State(Globals globals, LuaThread lua_thread, LuaValue function) {
this.globals = globals; this.globals = globals;
@@ -191,7 +210,9 @@ public class LuaThread extends LuaValue {
this.function = function; this.function = function;
} }
public synchronized void run() { public void run() {
locker.lock();
try {
try { try {
Varargs a = this.args; Varargs a = this.args;
this.args = LuaValue.NONE; this.args = LuaValue.NONE;
@@ -200,25 +221,45 @@ public class LuaThread extends LuaValue {
this.error = t.getMessage(); this.error = t.getMessage();
} finally { } finally {
this.status = LuaThread.STATUS_DEAD; this.status = LuaThread.STATUS_DEAD;
this.notify(); cond.signal();
}
} finally {
locker.unlock();
} }
} }
public synchronized Varargs lua_resume(LuaThread new_thread, Varargs args) { public Varargs lua_resume(LuaThread new_thread, Varargs args) {
locker.lock();
try {
LuaThread previous_thread = globals.running; LuaThread previous_thread = globals.running;
try { try {
globals.running = new_thread; globals.running = new_thread;
this.args = args; this.args = args;
if (this.status == STATUS_INITIAL) { if (this.status == STATUS_INITIAL) {
this.status = STATUS_RUNNING; this.status = STATUS_RUNNING;
new Thread(this, "Coroutine-"+(++coroutine_count)).start(); Thread t = null;
if(SUPPORT_VIRTUAL_THREAD) {
LuaValue setting = globals.get(USE_PLATFORM_THREAD);
if(setting.isnil()) {//default
if(Thread.currentThread().isVirtual()) {
t = Thread.ofVirtual().name("Coroutine-"+(++coroutine_count)).start(this);
}
} else { } else {
this.notify(); if(!setting.toboolean()) {
t = Thread.ofVirtual().name("Coroutine-"+(++coroutine_count)).start(this);
}
}
}
if (t == null){
new Thread(this, "Coroutine-"+(++coroutine_count)).start();
}
} else {
cond.signal();
} }
if (previous_thread != null) if (previous_thread != null)
previous_thread.state.status = STATUS_NORMAL; previous_thread.state.status = STATUS_NORMAL;
this.status = STATUS_RUNNING; this.status = STATUS_RUNNING;
this.wait(); cond.await();
return (this.error != null? return (this.error != null?
LuaValue.varargsOf(LuaValue.FALSE, LuaValue.valueOf(this.error)): LuaValue.varargsOf(LuaValue.FALSE, LuaValue.valueOf(this.error)):
LuaValue.varargsOf(LuaValue.TRUE, this.result)); LuaValue.varargsOf(LuaValue.TRUE, this.result));
@@ -232,15 +273,20 @@ public class LuaThread extends LuaValue {
if (previous_thread != null) if (previous_thread != null)
globals.running.state.status =STATUS_RUNNING; globals.running.state.status =STATUS_RUNNING;
} }
} finally {
locker.unlock();
}
} }
public synchronized Varargs lua_yield(Varargs args) { public Varargs lua_yield(Varargs args) {
locker.lock();
try {
try { try {
this.result = args; this.result = args;
this.status = STATUS_SUSPENDED; this.status = STATUS_SUSPENDED;
this.notify(); cond.signal();
do { do {
this.wait(thread_orphan_check_interval); cond.await(thread_orphan_check_interval,TimeUnit.MILLISECONDS);
if (this.lua_thread.get() == null) { if (this.lua_thread.get() == null) {
this.status = STATUS_DEAD; this.status = STATUS_DEAD;
throw new OrphanedThread(); throw new OrphanedThread();
@@ -254,6 +300,9 @@ public class LuaThread extends LuaValue {
this.args = LuaValue.NONE; this.args = LuaValue.NONE;
this.result = LuaValue.NONE; this.result = LuaValue.NONE;
} }
} finally {
locker.unlock();
}
} }
} }

View File

@@ -479,7 +479,7 @@ public class FuncState extends Constants {
return ((Integer) h.get(v)).intValue(); return ((Integer) h.get(v)).intValue();
} }
final int idx = this.nk; final int idx = this.nk;
this.h.put(v, new Integer(idx)); this.h.put(v, idx);
final Prototype f = this.f; final Prototype f = this.f;
if (f.k == null || nk + 1 >= f.k.length) if (f.k == null || nk + 1 >= f.k.length)
f.k = realloc( f.k, nk*2 + 1 ); f.k = realloc( f.k, nk*2 + 1 );

View File

@@ -170,7 +170,7 @@ public class LexState extends Constants {
static { static {
for ( int i=0; i<NUM_RESERVED; i++ ) { for ( int i=0; i<NUM_RESERVED; i++ ) {
LuaString ts = (LuaString) LuaValue.valueOf( luaX_tokens[i] ); LuaString ts = (LuaString) LuaValue.valueOf( luaX_tokens[i] );
RESERVED.put(ts, new Integer(FIRST_RESERVED+i)); RESERVED.put(ts, FIRST_RESERVED+i);
} }
} }

View File

@@ -79,7 +79,7 @@ public class CoroutineLib extends TwoArgFunction {
coroutine.set("resume", new resume()); coroutine.set("resume", new resume());
coroutine.set("running", new running()); coroutine.set("running", new running());
coroutine.set("status", new status()); coroutine.set("status", new status());
coroutine.set("yield", new yield()); coroutine.set("yield", new Yield());
coroutine.set("wrap", new wrap()); coroutine.set("wrap", new wrap());
env.set("coroutine", coroutine); env.set("coroutine", coroutine);
if (!env.get("package").isnil()) env.get("package").get("loaded").set("coroutine", coroutine); if (!env.get("package").isnil()) env.get("package").get("loaded").set("coroutine", coroutine);
@@ -113,7 +113,7 @@ public class CoroutineLib extends TwoArgFunction {
} }
} }
final class yield extends VarArgFunction { private final class Yield extends VarArgFunction {
public Varargs invoke(Varargs args) { public Varargs invoke(Varargs args) {
return globals.yield( args ); return globals.yield( args );
} }

View File

@@ -21,6 +21,9 @@
******************************************************************************/ ******************************************************************************/
package org.luaj.vm2.lib; package org.luaj.vm2.lib;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.luaj.vm2.Globals; import org.luaj.vm2.Globals;
import org.luaj.vm2.Lua; import org.luaj.vm2.Lua;
import org.luaj.vm2.LuaBoolean; import org.luaj.vm2.LuaBoolean;
@@ -507,14 +510,22 @@ public class DebugLib extends TwoArgFunction {
final static CallFrame[] EMPTY = {}; final static CallFrame[] EMPTY = {};
CallFrame[] frame = EMPTY; CallFrame[] frame = EMPTY;
int calls = 0; int calls = 0;
Lock lock = new ReentrantLock();
CallStack() {} CallStack() {}
synchronized int currentline() { int currentline() {
lock.lock();
try {
return calls > 0? frame[calls-1].currentline(): -1; return calls > 0? frame[calls-1].currentline(): -1;
} finally {
lock.unlock();
}
} }
private synchronized CallFrame pushcall() { private CallFrame pushcall() {
lock.lock();
try {
if (calls >= frame.length) { if (calls >= frame.length) {
int n = Math.max(4, frame.length * 3 / 2); int n = Math.max(4, frame.length * 3 / 2);
CallFrame[] f = new CallFrame[n]; CallFrame[] f = new CallFrame[n];
@@ -526,24 +537,48 @@ public class DebugLib extends TwoArgFunction {
f[i].previous = f[i-1]; f[i].previous = f[i-1];
} }
return frame[calls++]; return frame[calls++];
} finally {
lock.unlock();
}
} }
final synchronized void onCall(LuaFunction function) { final void onCall(LuaFunction function) {
lock.lock();
try {
pushcall().set(function); pushcall().set(function);
} finally {
lock.unlock();
}
} }
final synchronized void onCall(LuaClosure function, Varargs varargs, LuaValue[] stack) { final void onCall(LuaClosure function, Varargs varargs, LuaValue[] stack) {
lock.lock();
try {
pushcall().set(function, varargs, stack); pushcall().set(function, varargs, stack);
} finally {
lock.unlock();
} }
final synchronized void onReturn() { }
final void onReturn() {
lock.lock();
try {
if (calls > 0) if (calls > 0)
frame[--calls].reset(); frame[--calls].reset();
} finally {
lock.unlock();
}
} }
final synchronized void onInstruction(int pc, Varargs v, int top) { final void onInstruction(int pc, Varargs v, int top) {
lock.lock();
try {
if (calls > 0) if (calls > 0)
frame[calls-1].instr(pc, v, top); frame[calls-1].instr(pc, v, top);
} finally {
lock.unlock();
}
} }
/** /**
@@ -551,7 +586,9 @@ public class DebugLib extends TwoArgFunction {
* @param level * @param level
* @return String containing the traceback. * @return String containing the traceback.
*/ */
synchronized String traceback(int level) { String traceback(int level) {
lock.lock();
try {
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
sb.append( "stack traceback:" ); sb.append( "stack traceback:" );
for (DebugLib.CallFrame c; (c = getCallFrame(level++)) != null; ) { for (DebugLib.CallFrame c; (c = getCallFrame(level++)) != null; ) {
@@ -578,23 +615,39 @@ public class DebugLib extends TwoArgFunction {
} }
sb.append("\n\t[Java]: in ?"); sb.append("\n\t[Java]: in ?");
return sb.toString(); return sb.toString();
} finally {
lock.unlock();
} }
synchronized DebugLib.CallFrame getCallFrame(int level) { }
DebugLib.CallFrame getCallFrame(int level) {
lock.lock();
try {
if (level < 1 || level > calls) if (level < 1 || level > calls)
return null; return null;
return frame[calls-level]; return frame[calls-level];
} finally {
lock.unlock();
}
} }
synchronized DebugLib.CallFrame findCallFrame(LuaValue func) { DebugLib.CallFrame findCallFrame(LuaValue func) {
lock.lock();
try {
for (int i = 1; i <= calls; ++i) for (int i = 1; i <= calls; ++i)
if (frame[calls-i].f == func) if (frame[calls-i].f == func)
return frame[i]; return frame[i];
return null; return null;
} finally {
lock.unlock();
}
} }
synchronized DebugInfo auxgetinfo(String what, LuaFunction f, CallFrame ci) { DebugInfo auxgetinfo(String what, LuaFunction f, CallFrame ci) {
lock.lock();
try {
DebugInfo ar = new DebugInfo(); DebugInfo ar = new DebugInfo();
for (int i = 0, n = what.length(); i < n; ++i) { for (int i = 0, n = what.length(); i < n; ++i) {
switch (what.charAt(i)) { switch (what.charAt(i)) {
@@ -645,8 +698,10 @@ public class DebugLib extends TwoArgFunction {
} }
} }
return ar; return ar;
} finally {
lock.unlock();
}
} }
} }
public static class CallFrame { public static class CallFrame {

View File

@@ -119,12 +119,16 @@ public class IoLib extends TwoArgFunction {
return "file: " + Integer.toHexString(hashCode()); return "file: " + Integer.toHexString(hashCode());
} }
public void finalize() { public void finalize() throws Throwable {
try {
if (!isclosed()) { if (!isclosed()) {
try { try {
close(); close();
} catch (IOException ignore) {} } catch (IOException ignore) {}
} }
} finally {
super.finalize();
}
} }
} }

View File

@@ -174,13 +174,13 @@ public class CoerceLuaToJava {
public Object coerce(LuaValue value) { public Object coerce(LuaValue value) {
switch ( targetType ) { switch ( targetType ) {
case TARGET_TYPE_BYTE: return new Byte( (byte) value.toint() ); case TARGET_TYPE_BYTE: return (byte) value.toint() ;
case TARGET_TYPE_CHAR: return new Character( (char) value.toint() ); case TARGET_TYPE_CHAR: return (char) value.toint() ;
case TARGET_TYPE_SHORT: return new Short( (short) value.toint() ); case TARGET_TYPE_SHORT: return (short) value.toint();
case TARGET_TYPE_INT: return new Integer( (int) value.toint() ); case TARGET_TYPE_INT: return value.toint();
case TARGET_TYPE_LONG: return new Long( (long) value.todouble() ); case TARGET_TYPE_LONG: return (long) value.todouble();
case TARGET_TYPE_FLOAT: return new Float( (float) value.todouble() ); case TARGET_TYPE_FLOAT: return (float) value.todouble();
case TARGET_TYPE_DOUBLE: return new Double( (double) value.todouble() ); case TARGET_TYPE_DOUBLE: return (double) value.todouble();
default: return null; default: return null;
} }
} }
@@ -308,7 +308,7 @@ public class CoerceLuaToJava {
public Object coerce(LuaValue value) { public Object coerce(LuaValue value) {
switch ( value.type() ) { switch ( value.type() ) {
case LuaValue.TNUMBER: case LuaValue.TNUMBER:
return value.isint()? (Object)new Integer(value.toint()): (Object)new Double(value.todouble()); return value.isint()? value.toint() : value.todouble();
case LuaValue.TBOOLEAN: case LuaValue.TBOOLEAN:
return value.toboolean()? Boolean.TRUE: Boolean.FALSE; return value.toboolean()? Boolean.TRUE: Boolean.FALSE;
case LuaValue.TSTRING: case LuaValue.TSTRING:

View File

@@ -244,8 +244,8 @@ public class LuaScriptEngine extends AbstractScriptEngine implements ScriptEngin
case LuaValue.TSTRING: return luajValue.tojstring(); case LuaValue.TSTRING: return luajValue.tojstring();
case LuaValue.TUSERDATA: return luajValue.checkuserdata(Object.class); case LuaValue.TUSERDATA: return luajValue.checkuserdata(Object.class);
case LuaValue.TNUMBER: return luajValue.isinttype()? case LuaValue.TNUMBER: return luajValue.isinttype()?
(Object) new Integer(luajValue.toint()): luajValue.toint():
(Object) new Double(luajValue.todouble()); luajValue.todouble();
default: return luajValue; default: return luajValue;
} }
} }

View File

@@ -1 +1 @@
version: 3.0.2 version: 3.1.0