Commit e5f5f4fc authored by Stephanie Gawroriski's avatar Stephanie Gawroriski
Browse files

Cleanup the Java SE system call handling code accordingly.

parent 1943f06e
...@@ -31,9 +31,13 @@ import java.util.Map; ...@@ -31,9 +31,13 @@ import java.util.Map;
*/ */
public final class Assembly public final class Assembly
{ {
/** Errors used in system calls. */ /** Extra call stack depth. */
private static final int[] _ERRORS = private static final int _EXTRA_STACK_DEPTH =
new int[SystemCallIndex.NUM_SYSCALLS]; 3;
/** Local thread data. */
private static final ThreadLocal<ThreadData> _THREAD_DATA =
new ThreadLocal<>();
/** Unique string map. */ /** Unique string map. */
private static final Map<String, Integer> _STRINGS = private static final Map<String, Integer> _STRINGS =
...@@ -1735,71 +1739,108 @@ public final class Assembly ...@@ -1735,71 +1739,108 @@ public final class Assembly
// Make at least 8! // Make at least 8!
if (__args == null) if (__args == null)
__args = new int[8]; __args = new int[8];
if (__args.length < 8) else if (__args.length < 8)
__args = Arrays.copyOf(__args, 8); __args = Arrays.copyOf(__args, 8);
// Get thread data
ThreadData data = _THREAD_DATA.get();
if (data == null)
_THREAD_DATA.set((data = new ThreadData()));
// The error ID
int eid = ((__si < 0 || __si >= SystemCallIndex.NUM_SYSCALLS) ?
SystemCallIndex.QUERY_INDEX : __si);
// Error state for the last call of this type // Error state for the last call of this type
int[] errors = _ERRORS; int[] errors = data.errors;
// Return value with error value, to set if any // Try executing it
long rv; try
int err; {
// Execute call
long rv = Assembly.__sysCallInternal(data, __si, __args);
// No error
errors[eid] = 0;
// Return the result
return rv;
}
// Exception was caught
catch (RuntimeException e)
{
// Use thrown error code?
if (e instanceof SystemCallException)
errors[eid] = ((SystemCallException)e).code;
// Otherwise set as unknown
else
errors[eid] = SystemCallError.UNKNOWN;
// Fail
return 0;
}
}
/**
* Internal system call handling.
*
* @param __data The thread data.
* @param __si System call index.
* @param __args Arguments.
* @return The result.
* @throws NullPointerException On null arguments.
* @since 2019/12/29
*/
private static final long __sysCallInternal(ThreadData __data,
short __si, int... __args)
throws NullPointerException
{
// Depends on the system call type // Depends on the system call type
switch (__si) switch (__si)
{ {
// Check if system call is supported // Check if system call is supported
case SystemCallIndex.QUERY_INDEX: case SystemCallIndex.QUERY_INDEX:
switch (__args[0])
{ {
err = 0; case SystemCallIndex.API_LEVEL:
switch (__args[0]) case SystemCallIndex.CALL_STACK_HEIGHT:
{ case SystemCallIndex.CALL_STACK_ITEM:
case SystemCallIndex.API_LEVEL: case SystemCallIndex.ERROR_GET:
case SystemCallIndex.CALL_STACK_HEIGHT: case SystemCallIndex.ERROR_SET:
case SystemCallIndex.CALL_STACK_ITEM: case SystemCallIndex.EXCEPTION_LOAD:
case SystemCallIndex.ERROR_GET: case SystemCallIndex.EXCEPTION_STORE:
case SystemCallIndex.ERROR_SET: case SystemCallIndex.EXIT:
case SystemCallIndex.EXIT: case SystemCallIndex.FRAMEBUFFER:
case SystemCallIndex.FRAMEBUFFER: case SystemCallIndex.IPC_CALL:
case SystemCallIndex.IPC_CALL: case SystemCallIndex.GARBAGE_COLLECT:
case SystemCallIndex.GARBAGE_COLLECT: case SystemCallIndex.LOAD_STRING:
case SystemCallIndex.LOAD_STRING: case SystemCallIndex.PD_OF_STDERR:
case SystemCallIndex.PD_OF_STDERR: case SystemCallIndex.PD_OF_STDIN:
case SystemCallIndex.PD_OF_STDIN: case SystemCallIndex.PD_OF_STDOUT:
case SystemCallIndex.PD_OF_STDOUT: case SystemCallIndex.PD_WRITE_BYTE:
case SystemCallIndex.PD_WRITE_BYTE: case SystemCallIndex.SLEEP:
case SystemCallIndex.SLEEP: case SystemCallIndex.TIME_MILLI_WALL:
case SystemCallIndex.TIME_MILLI_WALL: case SystemCallIndex.TIME_NANO_MONO:
case SystemCallIndex.TIME_NANO_MONO: case SystemCallIndex.VMI_MEM_FREE:
case SystemCallIndex.VMI_MEM_FREE: case SystemCallIndex.VMI_MEM_MAX:
case SystemCallIndex.VMI_MEM_MAX: case SystemCallIndex.VMI_MEM_USED:
case SystemCallIndex.VMI_MEM_USED: return 1;
rv = 1;
break; default:
return 0;
default:
rv = 0;
break;
}
} }
break;
// API level // API level
case SystemCallIndex.API_LEVEL: case SystemCallIndex.API_LEVEL:
{ return ApiLevel.LEVEL_SQUIRRELJME_0_3_0_DEV;
rv = ApiLevel.LEVEL_SQUIRRELJME_0_3_0_DEV;
err = 0;
}
break;
// Call trace height // Call trace height
case SystemCallIndex.CALL_STACK_HEIGHT: case SystemCallIndex.CALL_STACK_HEIGHT:
{ // Remove traces for sysCall() and this method
// Remove traces for sysCall() and this method return new Throwable().getStackTrace().length -
rv = new Throwable().getStackTrace().length - 2; _EXTRA_STACK_DEPTH;
err = 0;
}
break;
// Call trace item // Call trace item
case SystemCallIndex.CALL_STACK_ITEM: case SystemCallIndex.CALL_STACK_ITEM:
...@@ -1809,16 +1850,14 @@ public final class Assembly ...@@ -1809,16 +1850,14 @@ public final class Assembly
// Get element trace here // Get element trace here
// Remove traces for sysCall() and this method // Remove traces for sysCall() and this method
int depth = 2 + __args[0]; int depth = _EXTRA_STACK_DEPTH + __args[0];
StackTraceElement ele = (depth < 0 || depth >= stk.length ? StackTraceElement ele = (depth < 0 || depth >= stk.length ?
null : stk[depth]); null : stk[depth]);
// Fail? // Fail?
if (ele == null) if (ele == null)
{ throw new SystemCallException(
rv = 0; SystemCallError.VALUE_OUT_OF_RANGE);
err = SystemCallError.VALUE_OUT_OF_RANGE;
}
// Handle normally // Handle normally
else else
...@@ -1828,39 +1867,29 @@ public final class Assembly ...@@ -1828,39 +1867,29 @@ public final class Assembly
{ {
// Class name // Class name
case CallStackItem.CLASS_NAME: case CallStackItem.CLASS_NAME:
rv = Assembly.__uniqueStringId( return Assembly.__uniqueStringId(
ele.getClassName().replace('.', '/')); ele.getClassName().replace('.', '/'));
err = 0;
break;
// The method name. // The method name.
case CallStackItem.METHOD_NAME: case CallStackItem.METHOD_NAME:
rv = Assembly.__uniqueStringId( return Assembly.__uniqueStringId(
ele.getMethodName()); ele.getMethodName());
err = 0;
break;
// The current file. // The current file.
case CallStackItem.SOURCE_FILE: case CallStackItem.SOURCE_FILE:
rv = Assembly.__uniqueStringId( return Assembly.__uniqueStringId(
ele.getFileName()); ele.getFileName());
err = 0;
break;
// Source line. // Source line.
case CallStackItem.SOURCE_LINE: case CallStackItem.SOURCE_LINE:
rv = ele.getLineNumber(); return ele.getLineNumber();
err = 0;
break;
default: default:
rv = 0; throw new SystemCallException(
err = SystemCallError.VALUE_OUT_OF_RANGE; SystemCallError.VALUE_OUT_OF_RANGE);
break;
} }
} }
} }
break;
// Get error // Get error
case SystemCallIndex.ERROR_GET: case SystemCallIndex.ERROR_GET:
...@@ -1871,15 +1900,8 @@ public final class Assembly ...@@ -1871,15 +1900,8 @@ public final class Assembly
dx = SystemCallIndex.QUERY_INDEX; dx = SystemCallIndex.QUERY_INDEX;
// Return the stored error code // Return the stored error code
synchronized (errors) return __data.errors[dx];
{
rv = errors[dx];
}
// Always succeeds
err = 0;
} }
break;
// Set error // Set error
case SystemCallIndex.ERROR_SET: case SystemCallIndex.ERROR_SET:
...@@ -1890,34 +1912,34 @@ public final class Assembly ...@@ -1890,34 +1912,34 @@ public final class Assembly
dx = SystemCallIndex.QUERY_INDEX; dx = SystemCallIndex.QUERY_INDEX;
// Return last error code, and set new one // Return last error code, and set new one
synchronized (errors) long rv = __data.errors[dx];
{ __data.errors[dx] = __args[0];
rv = errors[dx]; return rv;
errors[dx] = __args[0];
}
// Always succeeds
err = 0;
} }
break;
// Exit the VM // Load IPC Exception
case SystemCallIndex.EXIT: case SystemCallIndex.EXCEPTION_LOAD:
return __data.exception;
// Store IPC Exception
case SystemCallIndex.EXCEPTION_STORE:
{ {
System.exit(__args[0]); long rv = __data.exception;
__data.exception = __args[0];
rv = 0; return rv;
err = 0;
} }
break;
// Exit the VM
case SystemCallIndex.EXIT:
System.exit(__args[0]);
return 0;
// Property of the framebuffer // Property of the framebuffer
case SystemCallIndex.FRAMEBUFFER: case SystemCallIndex.FRAMEBUFFER:
try try
{ {
rv = SwingFramebuffer.instance().vfb.framebufferProperty( return SwingFramebuffer.instance().vfb.
__args); framebufferProperty(__args);
err = 0;
} }
catch (Throwable t) catch (Throwable t)
{ {
...@@ -1925,20 +1947,14 @@ public final class Assembly ...@@ -1925,20 +1947,14 @@ public final class Assembly
t.printStackTrace(); t.printStackTrace();
// Drop // Drop
rv = 0; throw new SystemCallException(
err = SystemCallError.NO_FRAMEBUFFER; SystemCallError.NO_FRAMEBUFFER);
} }
break;
// Invoke the garbage collector // Invoke the garbage collector
case SystemCallIndex.GARBAGE_COLLECT: case SystemCallIndex.GARBAGE_COLLECT:
{ Runtime.getRuntime().gc();
Runtime.getRuntime().gc(); return 0;
rv = 0;
err = 0;
}
break;
// IPC Call // IPC Call
case SystemCallIndex.IPC_CALL: case SystemCallIndex.IPC_CALL:
...@@ -1946,36 +1962,20 @@ public final class Assembly ...@@ -1946,36 +1962,20 @@ public final class Assembly
// Loads a string // Loads a string
case SystemCallIndex.LOAD_STRING: case SystemCallIndex.LOAD_STRING:
{ return Assembly.__uniqueObjectId(
rv = Assembly.__uniqueObjectId( Assembly.__uniqueString(__args[0]));
Assembly.__uniqueString(__args[0]));
err = 0;
}
break;
// Pipe descriptor of standard input // Pipe descriptor of standard input
case SystemCallIndex.PD_OF_STDIN: case SystemCallIndex.PD_OF_STDIN:
{ return 0;
rv = 0;
err = 0;
}
break;
// Pipe descriptor of standard output // Pipe descriptor of standard output
case SystemCallIndex.PD_OF_STDOUT: case SystemCallIndex.PD_OF_STDOUT:
{ return 1;
rv = 1;
err = 0;
}
break;
// Pipe descriptor of standard error // Pipe descriptor of standard error
case SystemCallIndex.PD_OF_STDERR: case SystemCallIndex.PD_OF_STDERR:
{ return 2;
rv = 1;
err = 0;
}
break;
// Write single byte to PD // Write single byte to PD
case SystemCallIndex.PD_WRITE_BYTE: case SystemCallIndex.PD_WRITE_BYTE:
...@@ -1993,105 +1993,64 @@ public final class Assembly ...@@ -1993,105 +1993,64 @@ public final class Assembly
os.write(__args[1]); os.write(__args[1]);
// Okay // Okay
rv = 1; return 1;
err = 0;
} }
// Failed // Failed
catch (IOException e) catch (IOException e)
{ {
rv = -1; throw new SystemCallException(
err = SystemCallError.PIPE_DESCRIPTOR_BAD_WRITE; SystemCallError.PIPE_DESCRIPTOR_BAD_WRITE);
} }
} }
// Failed // Failed
else else
{ {
rv = -1; throw new SystemCallException(
err = SystemCallError.PIPE_DESCRIPTOR_INVALID; SystemCallError.PIPE_DESCRIPTOR_INVALID);
} }
} }
break;
// Sleep // Sleep
case SystemCallIndex.SLEEP: case SystemCallIndex.SLEEP:
try try
{ {
Thread.sleep(__args[0], __args[1]); Thread.sleep(__args[0], __args[1]);
return 0;
rv = 0;
err = SystemCallError.NO_ERROR;
} }
catch (InterruptedException e) catch (InterruptedException e)
{ {
rv = 1; throw new SystemCallException(SystemCallError.INTERRUPTED);
err = SystemCallError.INTERRUPTED;
} }
break;
// Current wall clock milliseconds // Current wall clock milliseconds
case SystemCallIndex.TIME_MILLI_WALL: case SystemCallIndex.TIME_MILLI_WALL:
{ return System.currentTimeMillis();
rv = System.currentTimeMillis();
err = 0;
}
break;
// Current monotonic clock nanoseconds // Current monotonic clock nanoseconds
case SystemCallIndex.TIME_NANO_MONO: case SystemCallIndex.TIME_NANO_MONO:
{ return System.nanoTime();
rv = System.nanoTime();
err = 0;
}
break;
// VM information: Memory free bytes // VM information: Memory free bytes
case SystemCallIndex.VMI_MEM_FREE: case SystemCallIndex.VMI_MEM_FREE:
{ return (int)Math.min(Integer.MAX_VALUE,
rv = (int)Math.min(Integer.MAX_VALUE, Runtime.getRuntime().freeMemory());
Runtime.getRuntime().freeMemory());
err = 0;
}
break;
// VM information: Memory used bytes // VM information: Memory used bytes
case SystemCallIndex.VMI_MEM_USED: case SystemCallIndex.VMI_MEM_USED:
{ return (int)Math.min(Integer.MAX_VALUE,
rv = (int)Math.min(Integer.MAX_VALUE, Runtime.getRuntime().totalMemory());
Runtime.getRuntime().totalMemory());
err = 0;
}
break;
// VM information: Memory max bytes // VM information: Memory max bytes
case SystemCallIndex.VMI_MEM_MAX: case SystemCallIndex.VMI_MEM_MAX:
{ return (int)Math.min(Integer.MAX_VALUE,
rv = (int)Math.min(Integer.MAX_VALUE, Runtime.getRuntime().maxMemory());
Runtime.getRuntime().maxMemory());
err = 0;
}
break;
default: default:
// Returns no value but sets an error throw new SystemCallException(
rv = -1; SystemCallError.UNSUPPORTED_SYSTEM_CALL);
err = SystemCallError.UNSUPPORTED_SYSTEM_CALL;
// If the ID is valid then a bad array access will be used
if (__si < 0 || __si >= SystemCallIndex.NUM_SYSCALLS)
__si = SystemCallIndex.QUERY_INDEX;
break;
} }
// Set error state as needed
synchronized (errors)
{