attempts at fixing multithread functionstack/garbage collector issues

This commit is contained in:
Daniella / Tove 2022-04-29 18:10:14 +02:00
parent 57ed698463
commit a161775ea6

View file

@ -3,6 +3,7 @@ import java.lang.reflect.*;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.file.Files;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
@ -35,7 +36,7 @@ public class ISBPL {
ArrayList<String> included = new ArrayList<>();
HashMap<String, ISBPLCallable> natives = new HashMap<>();
private Object syncMakeThread = new Object();
private final Object syncMakeThread = new Object();
private ISBPLKeyword getKeyword(String word) {
switch (word) {
case "native":
@ -51,7 +52,7 @@ public class ISBPL {
idx++;
Object var = new Object();
ISBPLCallable c;
vars.put(var, new ISBPLObject(getType("null"), 0));
vars.put(var, getNullObject());
addFunction(words[idx], c = ((stack1) -> stack1.push(vars.get(var))));
addFunction("=" + words[idx], (stack1) -> vars.put(var, stack1.pop()));
varLinks.put(c, var);
@ -165,20 +166,16 @@ public class ISBPL {
synchronized(syncMakeThread) {
idx++;
AtomicInteger i = new AtomicInteger(idx);
Stack<ISBPLObject> s = new Stack<>();
Stack<ISBPLObject> s = new ISBPLStack<>();
for(ISBPLObject obj : stack) {
s.push(obj);
}
ISBPLCallable block = readBlock(i, words, file, false);
// This cant be a non-function, unless we clone vars aswell to avoid garbage collecting them accidentally.
ISBPLCallable block = readBlock(i, words, file, true);
long tid = Thread.currentThread().getId();
Stack<HashMap<String, ISBPLCallable>> fs = new Stack<>();
for(HashMap<String, ISBPLCallable> map : functionStack.get()) {
fs.push(map);
}
new Thread(() -> {
debuggerIPC.run.put(Thread.currentThread().getId(), debuggerIPC.run.getOrDefault(tid, -1) == -1 ? -1 : 0);
debuggerIPC.stack.put(Thread.currentThread().getId(), s);
functionStack.set(fs);
try {
block.call(s);
} catch (ISBPLStop stop) {
@ -231,7 +228,7 @@ public class ISBPL {
i.checkType(getType("int"));
ISBPLObject[] arr = new ISBPLObject[((int) i.object)];
for (int j = 0 ; j < arr.length ; j++) {
arr[j] = new ISBPLObject(getType("null"), 0);
arr[j] = getNullObject();
}
stack.push(new ISBPLObject(getType("array"), arr));
};
@ -395,8 +392,7 @@ public class ISBPL {
end.checkType(getType("int"));
begin.checkType(getType("int"));
fileToRead.checkType(getType("file"));
try {
FileInputStream f = new FileInputStream((File) fileToRead.object);
try(FileInputStream f = new FileInputStream((File) fileToRead.object)) {
int b = ((int) begin.object);
int e = ((int) end.object);
byte[] bytes = new byte[e - b];
@ -972,7 +968,7 @@ public class ISBPL {
return nullObj;
}
private Object syncJIOClass = new Object();
private final Object syncJIOClass = new Object();
public ISBPLObject toISBPL(Class<?> clazz) {
synchronized(syncJIOClass) {
ISBPLType type = getType(clazz.getName());
@ -1123,27 +1119,6 @@ public class ISBPL {
return params[mid.get()];
}
private Object syncFromISBPL = new Object();
private Object fromISBPL(ISBPLObject o) {
synchronized(syncFromISBPL) {
ISBPLType type = o.type;
if (type.equals(getType("null"))) {
return null;
}
if (type.equals(getType("string")))
return toJavaString(o);
if (type.equals(getType("array"))) {
ISBPLObject[] isbplArray = ((ISBPLObject[]) o.object);
Object[] array = new Object[isbplArray.length];
for (int i = 0 ; i < array.length ; i++) {
array[i] = fromISBPL(isbplArray[i]);
}
return array;
}
return o.object;
}
}
public Object primitiveDefault(Class<?> expectedType) {
if(expectedType == long.class)
return 0L;
@ -1165,7 +1140,6 @@ public class ISBPL {
}
public Object fromISBPL(ISBPLObject o, Class<?> expectedType) {
synchronized(syncFromISBPL) {
ISBPLType type = o.type;
if (type.equals(getType("null"))) {
return null;
@ -1211,13 +1185,10 @@ public class ISBPL {
typeError(o.type.name, expectedType.getName());
return o.object;
}
}
private Object syncToISBPL = new Object();
public ISBPLObject toISBPL(Object object) {
synchronized (syncToISBPL) {
if(object == null) {
return new ISBPLObject(getType("null"), 0);
return getNullObject();
}
ISBPLObject o = toISBPL(object.getClass());
if (object instanceof String) {
@ -1246,7 +1217,6 @@ public class ISBPL {
o.object = object;
return o;
}
}
public void addFunction(ISBPLType type, String name, ISBPLCallable callable) {
type.methods.put(name, callable);
@ -1407,6 +1377,14 @@ public class ISBPL {
}
if(stack.size() > 0) {
// Doing this nonrecursively because it's much better despite the slight readability disadvantage.
if(stack.peek() == null) {
// We need to dump things immediately.
System.err.println("!!! ISBPL WORD PARSER ERROR !!!");
System.err.println("This is most likely due to a garbage collector malfunction.");
System.err.println("Stack: " + stack);
System.err.println("LastWords: " + lastWords);
System.err.println("FileStack: " + fileStack);
}
ISBPLType type = stack.peek().type;
Queue<ISBPLType> types = new LinkedList<>();
types.add(type);
@ -1462,9 +1440,12 @@ public class ISBPL {
finally {
if(isFunction) {
HashMap<String, ISBPLCallable> fstack = functionStack.get().pop();
for(ISBPLCallable c : fstack.values()) {
if(varLinks.containsKey(c)) {
vars.remove(varLinks.remove(c));
for(Map.Entry<String, ISBPLCallable> c : fstack.entrySet()) {
if(varLinks.containsKey(c.getValue())) {
vars.remove(varLinks.remove(c.getValue()));
if(printCalls) {
System.err.println("Garbage collector: removed " + c.getKey());
}
}
}
}
@ -1533,7 +1514,7 @@ public class ISBPL {
}
public static void main(String[] args) {
Stack<ISBPLObject> stack = new Stack<>();
Stack<ISBPLObject> stack = new ISBPLStack<>();
ISBPL isbpl = new ISBPL();
isbpl.debuggerIPC.stack.put(Thread.currentThread().getId(), stack);
debug = !System.getenv().getOrDefault("DEBUG", "").equals("");
@ -1566,6 +1547,7 @@ public class ISBPL {
}
private static String readFile(File f) throws IOException {
//noinspection resource
FileInputStream fis = new FileInputStream(f);
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
byte[] currentBytes = new byte[4096];
@ -1637,7 +1619,7 @@ class ISBPLObject {
}
public boolean isTruthy() {
return object != null && object != Integer.valueOf(0) && !object.equals(Boolean.valueOf(false));
return object != null && object != Integer.valueOf(0) && !object.equals(Boolean.FALSE);
}
// This has heavy optimizations, please do not change unless necessary
@ -1802,6 +1784,7 @@ class ISBPLDebugger extends Thread {
try {
ServerSocket socket = null;
try {
//noinspection resource
socket = new ServerSocket(Integer.parseInt(System.getenv().getOrDefault("DEBUG", "9736")));
port = socket.getLocalPort();
System.err.println("Debugger listening on :" + socket.getLocalPort());
@ -1809,6 +1792,7 @@ class ISBPLDebugger extends Thread {
catch (BindException e) {
while (socket == null) {
try {
//noinspection resource
socket = new ServerSocket((int) (Math.random() * 5000 + 5000));
port = socket.getLocalPort();
System.err.println("Debugger listening on :" + socket.getLocalPort());
@ -2033,7 +2017,7 @@ class ISBPLStreamer {
s = stack.pop();
s.checkType(isbpl.getType("string"));
f = new File(isbpl.toJavaString(s));
stream = new ISBPLStream(new FileInputStream(f), new OutputStream() {
stream = new ISBPLStream(Files.newInputStream(f.toPath()), new OutputStream() {
@Override
public void write(int b) {
throw new ISBPLError("IllegalArgument", "Can't write to a FILE_IN stream!");
@ -2051,7 +2035,7 @@ class ISBPLStreamer {
public int read() {
throw new ISBPLError("IllegalArgument", "Can't read a FILE_OUT stream!");
}
}, new FileOutputStream(f));
}, Files.newOutputStream(f.toPath()));
streams.add(stream);
stack.push(new ISBPLObject(isbpl.getType("int"), stream.id));
break;
@ -2143,4 +2127,19 @@ class ISBPLThreadLocal<T> {
public synchronized void set(T t) {
map.put(Thread.currentThread().getId(), t);
}
@Override
public String toString() {
return get().toString();
}
}
class ISBPLStack<T> extends Stack<T> {
@Override
public T push(T t) {
//if(t == null)
//throw new IllegalArgumentException("item is null");
return super.push(t);
}
}