From 7a9bc0ba0fd215bd5b9a2e370937d81870aadba5 Mon Sep 17 00:00:00 2001 From: brian Date: Sat, 5 Jun 2004 02:02:20 -0700 Subject: [PATCH] cleanup, more efficient exec, better win32 support darcs-hash:20040605090220-24bed-4e05a02c751d826b58cb3fdd1c5ad90ee5d71e84.gz --- Makefile | 9 +- src/org/ibex/nestedvm/ClassFileCompiler.java | 22 ++++- src/org/ibex/nestedvm/Runtime.java | 86 +++++++++++++------ src/org/ibex/nestedvm/RuntimeCompiler.java | 2 +- src/org/ibex/nestedvm/UnixRuntime.java | 115 ++++++++++++++++---------- upstream/Makefile | 2 +- 6 files changed, 158 insertions(+), 78 deletions(-) diff --git a/Makefile b/Makefile index bac1e26..57074b0 100644 --- a/Makefile +++ b/Makefile @@ -218,6 +218,7 @@ runtime.jar: $(runtime_classes:%=build/org/ibex/nestedvm/%.class) nestedvm.jar: $(java_classes) .manifest cd build && jar cfm ../$@ ../.manifest $(java_classes:build/%.class=%*.class) + cd $(CLASSGEN_PATH) && jar uf $(mips2java_root)/$@ . compact_runtime_compiler.jar: $(java_classes) .manifest $(tasks)/build_darcs_gcclass mkdir -p tmp/pruned @@ -471,11 +472,13 @@ doc/charts/%.pdf: doc/charts/%.dat doc/charts/%.gnuplot doc/ivme04.pdf: doc/ivme04.tex doc/acmconf.cls $(charts:%.dat=%.pdf) build/tests/TeX.class cp upstream/build/tex/tex.pool upstream/build/tex/texinputs/tex.pool - cd upstream/build/tex/texinputs && echo '\latex.ltx' | java -cp $(build) tests.TeX + cd upstream/build/tex/texinputs && echo '\latex.ltx' | java -cp $(mips2java_root)/build:$(mips2java_root)/$(CLASSGEN_PATH) tests.TeX cd upstream/build/tex/texinputs && ln -fs ../../../../doc/* .; rm -f ivme04.aux; touch ivme04.aux; touch ivme04.bbl - cd upstream/build/tex/texinputs && echo '\&latex \input ivme04.tex' | java -cp $(build) tests.TeX + cd upstream/build/tex/texinputs && echo '\&latex \input ivme04.tex' | java -cp $(mips2java_root)/build:$(mips2java_root)/$(CLASSGEN_PATH) tests.TeX + cd upstream/build/tex/texinputs && bibtex ivme04 + cd upstream/build/tex/texinputs && echo '\&latex \input ivme04.tex' | java -cp $(mips2java_root)/build:$(mips2java_root)/$(CLASSGEN_PATH) tests.TeX cd upstream/build/tex/texinputs && dvipdf ivme04.dvi - cp upstream/build/tex/texinputs/ivme04.pdf $@ + #cp upstream/build/tex/texinputs/ivme04.pdf $@ pdf: doc/ivme04.pdf open doc/ivme04.pdf diff --git a/src/org/ibex/nestedvm/ClassFileCompiler.java b/src/org/ibex/nestedvm/ClassFileCompiler.java index ccf7657..20652b6 100644 --- a/src/org/ibex/nestedvm/ClassFileCompiler.java +++ b/src/org/ibex/nestedvm/ClassFileCompiler.java @@ -99,11 +99,31 @@ public class ClassFileCompiler extends Compiler implements CGConst { init.add(INVOKESPECIAL,new MethodRef(me,"",Type.VOID,new Type[]{Type.INT,Type.INT})); init.add(RETURN); + // (Z) + init = cg.addMethod("",Type.VOID,new Type[]{Type.BOOLEAN},ACC_PUBLIC); + init.add(ALOAD_0); + init.add(LDC,pageSize); + init.add(LDC,totalPages); + init.add(ILOAD_1); + init.add(INVOKESPECIAL,new MethodRef(me,"",Type.VOID,new Type[]{Type.INT,Type.INT,Type.BOOLEAN})); + init.add(RETURN); + + // (II) init = cg.addMethod("",Type.VOID,new Type[]{Type.INT,Type.INT},ACC_PUBLIC); init.add(ALOAD_0); init.add(ILOAD_1); init.add(ILOAD_2); - init.add(INVOKESPECIAL,new MethodRef(superClass,"",Type.VOID,new Type[]{Type.INT,Type.INT})); + init.add(ICONST_0); + init.add(INVOKESPECIAL,new MethodRef(me,"",Type.VOID,new Type[]{Type.INT,Type.INT,Type.BOOLEAN})); + init.add(RETURN); + + // (IIZ) + init = cg.addMethod("",Type.VOID,new Type[]{Type.INT,Type.INT,Type.BOOLEAN},ACC_PUBLIC); + init.add(ALOAD_0); + init.add(ILOAD_1); + init.add(ILOAD_2); + init.add(ILOAD_3); + init.add(INVOKESPECIAL,new MethodRef(superClass,"",Type.VOID,new Type[]{Type.INT,Type.INT,Type.BOOLEAN})); if(onePage) { cg.addField("page",Type.arrayType(Type.INT),ACC_PRIVATE|ACC_FINAL); diff --git a/src/org/ibex/nestedvm/Runtime.java b/src/org/ibex/nestedvm/Runtime.java index a54fbc2..0c40bc9 100644 --- a/src/org/ibex/nestedvm/Runtime.java +++ b/src/org/ibex/nestedvm/Runtime.java @@ -70,8 +70,8 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { public ExecutionException exitException; /** Table containing all open file descriptors. (Entries are null if the fd is not in use */ - FD[] fds = new FD[OPEN_MAX]; // package-private for UnixRuntime - boolean closeOnExec[] = new boolean[OPEN_MAX]; + FD[] fds; // package-private for UnixRuntime + boolean closeOnExec[]; /** Pointer to a SecurityManager for this process */ SecurityManager sm; @@ -102,6 +102,16 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { /** Subclasses should set the CPUState to the state held in state */ protected abstract void setCPUState(CPUState state); + /** True to enabled a few hacks to better support the win32 console */ + final static boolean win32Hacks; + + static { + String os = Platform.getProperty("os.name"); + String prop = Platform.getProperty("nestedvm.win32hacks"); + if(prop != null) { win32Hacks = Boolean.valueOf(prop).booleanValue(); } + else { win32Hacks = os != null && os.toLowerCase().indexOf("windows") != -1; } + } + protected Object clone() throws CloneNotSupportedException { Runtime r = (Runtime) super.clone(); r._byteBuf = null; @@ -119,7 +129,8 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { return r; } - protected Runtime(int pageSize, int totalPages) { + protected Runtime(int pageSize, int totalPages) { this(pageSize, totalPages,false); } + protected Runtime(int pageSize, int totalPages, boolean exec) { if(pageSize <= 0) throw new IllegalArgumentException("pageSize <= 0"); if(totalPages <= 0) throw new IllegalArgumentException("totalPages <= 0"); if((pageSize&(pageSize-1)) != 0) throw new IllegalArgumentException("pageSize not a power of two"); @@ -157,11 +168,16 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { readPages[i] = writePages[i] = new int[pageSize>>2]; } } - - InputStream stdin = Boolean.valueOf(Platform.getProperty("nestedvm.textstdin")).booleanValue() ? new TextInputStream(System.in) : System.in; - addFD(new TerminalFD(stdin)); - addFD(new TerminalFD(System.out)); - addFD(new TerminalFD(System.err)); + + if(!exec) { + fds = new FD[OPEN_MAX]; + closeOnExec = new boolean[OPEN_MAX]; + + InputStream stdin = win32Hacks ? new Win32ConsoleIS(System.in) : System.in; + addFD(new TerminalFD(stdin)); + addFD(new TerminalFD(System.out)); + addFD(new TerminalFD(System.err)); + } } /** Copy everything from src to addr initializing uninitialized pages if required. @@ -481,17 +497,16 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { } /** Calls _execute() (subclass's execute()) and catches exceptions */ - // FEATURE: Have these call kill() so we get a pretty message to stdout private void __execute() { try { _execute(); } catch(FaultException e) { if(STDERR_DIAG) e.printStackTrace(); - sys_exit(128+11); // SIGSEGV + exit(128+11,true); // SIGSEGV exitException = e; } catch(ExecutionException e) { if(STDERR_DIAG) e.printStackTrace(); - sys_exit(128+4); // SIGILL + exit(128+4,true); // SIGILL exitException = e; } } @@ -960,11 +975,21 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { /** Hook for subclasses to do something when the process exits */ void _exited() { } - private int sys_exit(int status) { + void exit(int status, boolean fromSignal) { + if(fromSignal && fds[2] != null) { + try { + byte[] msg = getBytes("Process exited on signal " + (status - 128)); + fds[2].write(msg,0,msg.length); + } catch(ErrnoException e) { } + } exitStatus = status; for(int i=0;i=0;i--) cwd += (String) vec.elementAt(i) + (i==0?"":"/"); + } + } + } } private static String posixTZ() { @@ -73,7 +95,7 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { if(!envHas("HOME",extra) && Platform.getProperty("user.home") != null) defaults[n++] = "HOME=" + Platform.getProperty("user.home"); if(!envHas("SHELL",extra)) defaults[n++] = "SHELL=/bin/sh"; - if(!envHas("TERM",extra)) defaults[n++] = "TERM=vt100"; + if(!envHas("TERM",extra) && !win32Hacks) defaults[n++] = "TERM=vt100"; if(!envHas("TZ",extra)) defaults[n++] = "TZ=" + posixTZ(); if(!envHas("PATH",extra)) defaults[n++] = "PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin"; String[] env = new String[extra.length+n]; @@ -149,6 +171,10 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { return parent == null ? 1 : parent.pid; } + // FEATURE: Signal handling + // check flag only on backwards jumps to basic blocks without compulsatory checks + // (see A Portable Research Framework for the Execution of Java Bytecode - Etienne Gagnon, Chapter 2) + /** The kill syscall. SIGSTOP, SIGTSTO, SIGTTIN, and SIGTTOUT pause the process. SIGCONT, SIGCHLD, SIGIO, and SIGWINCH are ignored. @@ -164,16 +190,13 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { case 18: // SIGTSTP case 21: // SIGTTIN case 22: // SIGTTOU - state = PAUSED; - break; case 19: // SIGCONT case 20: // SIGCHLD case 23: // SIGIO case 28: // SIGWINCH break; default: - // FEATURE: This is ugly, make a clean interface to sys_exit - return syscall(SYS_exit,128+signal,0,0,0,0,0); + exit(128+signal, true); } return 0; } @@ -350,7 +373,8 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { if(o instanceof Class) { Class c = (Class) o; try { - return exec((UnixRuntime) c.newInstance(),argv,envp); + UnixRuntime r = (UnixRuntime) c.getDeclaredConstructor(new Class[]{Boolean.TYPE}).newInstance(new Object[]{Boolean.TRUE}); + return exec(r,argv,envp); } catch(Exception e) { e.printStackTrace(); return -ENOEXEC; @@ -391,10 +415,7 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { return 0; } - // FEATURE: Make sure fstat info is correct - // FEATURE: This could be faster if we did direct copies from each process' memory - // FEATURE: Check this logic one more time - public static class Pipe { + static class Pipe { private final byte[] pipebuf = new byte[PIPE_BUF*4]; private int readPos; private int writePos; @@ -403,7 +424,7 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { public final FD writer = new Writer(); public class Reader extends FD { - protected FStat _fstat() { return new FStat(); } + protected FStat _fstat() { return new SocketFStat(); } public int read(byte[] buf, int off, int len) throws ErrnoException { if(len == 0) return 0; synchronized(Pipe.this) { @@ -418,11 +439,12 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { return len; } } + public int flags() { return O_RDONLY; } public void _close() { synchronized(Pipe.this) { readPos = -1; Pipe.this.notify(); } } } public class Writer extends FD { - protected FStat _fstat() { return new FStat(); } + protected FStat _fstat() { return new SocketFStat(); } public int write(byte[] buf, int off, int len) throws ErrnoException { if(len == 0) return 0; synchronized(Pipe.this) { @@ -442,6 +464,7 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { return len; } } + public int flags() { return O_WRONLY; } public void _close() { synchronized(Pipe.this) { writePos = -1; Pipe.this.notify(); } } } } @@ -626,16 +649,8 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { } } - // FEATURE: Check that these are correct - public int flags() { - if(is != null && os != null) return O_RDWR; - if(is != null) return O_RDONLY; - if(os != null) return O_WRONLY; - return 0; - } - - // FEATURE: Populate this properly - public FStat _fstat() { return new FStat(); } + public int flags() { return O_RDWR; } + public FStat _fstat() { return new SocketFStat(); } } private int sys_socket(int domain, int type, int proto) { @@ -1049,8 +1064,8 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { public synchronized Object exec(UnixRuntime r, String path) throws ErrnoException { // HACK: Hideous hack to make a standalone busybox possible - if(path.equals("bin/busybox") && Boolean.valueOf(Platform.getProperty("nestedvm.busyboxhack")).booleanValue()) - return r.getClass(); + if(path.equals("bin/busybox") && r.getClass().getName().endsWith("BusyBox")) return r.getClass(); + FStat fstat = stat(r,path); if(fstat == null) return null; long mtime = fstat.mtime(); @@ -1155,10 +1170,11 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { public abstract void unlink(UnixRuntime r, String path) throws ErrnoException; } - // FEATURE: chroot support in here + // chroot support should go in here if it is ever implemented chroot support in here private String normalizePath(String path) { boolean absolute = path.startsWith("/"); int cwdl = cwd.length(); + // NOTE: This isn't just a fast path, it handles cases the code below doesn't if(!path.startsWith(".") && path.indexOf("./") == -1 && path.indexOf("//") == -1 && !path.endsWith(".")) return absolute ? path.substring(1) : cwdl == 0 ? path : path.length() == 0 ? cwd : cwd + "/" + path; @@ -1173,23 +1189,29 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { cwd.getChars(0,cwdl,out,0); outp = cwdl; } - + path.getChars(0,path.length(),in,0); while(in[inp] != 0) { - if(inp != 0 || cwdl==0) { - if(in[inp] != '/') { out[outp++] = in[inp++]; continue; } + if(inp != 0) { + while(in[inp] != 0 && in[inp] != '/') { out[outp++] = in[inp++]; } + if(in[inp] == '\0') break; while(in[inp] == '/') inp++; } - if(in[inp] == '\0') continue; + + // Just read a / + if(in[inp] == '\0') break; if(in[inp] != '.') { out[outp++] = '/'; out[outp++] = in[inp++]; continue; } + // Just read a /. if(in[inp+1] == '\0' || in[inp+1] == '/') { inp++; continue; } if(in[inp+1] == '.' && (in[inp+2] == '\0' || in[inp+2] == '/')) { // .. + // Just read a /..{$,/} inp += 2; if(outp > 0) outp--; while(outp > 0 && out[outp] != '/') outp--; //System.err.println("After ..: " + new String(out,0,outp)); continue; } + // Just read a /.[^.] or /..[^/$] inp++; out[outp++] = '/'; out[outp++] = '.'; @@ -1228,7 +1250,7 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { protected File root; public File getRoot() { return root; } - private static File hostRootDir() { + static File hostRootDir() { if(Platform.getProperty("nestedvm.root") != null) { File f = new File(Platform.getProperty("nestedvm.root")); if(f.isDirectory()) return f; @@ -1332,9 +1354,10 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { protected abstract String name(int n); protected abstract int inode(int n); protected abstract int myDev(); - protected int parentInode() { return -1; } - protected int myInode() { return -1; } - + protected abstract int parentInode(); + protected abstract int myInode(); + public int flags() { return O_RDONLY; } + public int getdents(byte[] buf, int off, int len) { int ooff = off; int ino; @@ -1385,11 +1408,12 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { private static final int FD_INODE = 4; private static final int FD_INODES = 32; - private class DevFStat extends FStat { + private abstract class DevFStat extends FStat { public int dev() { return devno; } public int mode() { return 0666; } public int type() { return S_IFCHR; } public int nlink() { return 1; } + public abstract int inode(); } private abstract class DevDirFD extends DirFD { @@ -1405,12 +1429,14 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { public int write(byte[] a, int off, int length) { return length; } public int seek(int n, int whence) { return 0; } public FStat _fstat() { return new DevFStat(){ public int inode() { return ZERO_INODE; } }; } + public int flags() { return O_RDWR; } }; private FD devNullFD = new FD() { public int read(byte[] a, int off, int length) { return 0; } public int write(byte[] a, int off, int length) { return length; } public int seek(int n, int whence) { return 0; } public FStat _fstat() { return new DevFStat(){ public int inode() { return NULL_INODE; } }; } + public int flags() { return O_RDWR; } }; public FD open(UnixRuntime r, String path, int mode, int flags) throws ErrnoException { @@ -1483,9 +1509,8 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { if(r.fds[n] == null) return null; return r.fds[n].fstat(); } - // FEATURE: inode stuff - if(path.equals("fd")) return new FStat() { public int type() { return S_IFDIR; } public int mode() { return 0444; }}; - if(path.equals("")) return new FStat() { public int type() { return S_IFDIR; } public int mode() { return 0444; }}; + if(path.equals("fd")) return new FStat() { public int inode() { return FD_INODE; } public int dev() { return devno; } public int type() { return S_IFDIR; } public int mode() { return 0444; }}; + if(path.equals("")) return new FStat() { public int inode() { return ROOT_INODE; } public int dev() { return devno; } public int type() { return S_IFDIR; } public int mode() { return 0444; }}; return null; } diff --git a/upstream/Makefile b/upstream/Makefile index 7a25bee..2ee56f0 100644 --- a/upstream/Makefile +++ b/upstream/Makefile @@ -335,7 +335,7 @@ tasks/build_tex: tasks/build_tex_tangle tasks/build_gpc tasks/download_texinputs cp misc/tex.ch build/tex/tex.ch cd build/tex && \ $(TAR) xfz ../../download/texinputs-$(version_texinputs).tgz && \ - java -cp $(root)/build tests.Tangle \ + java -cp $(root)/build:$(upstream)/build/classgen/build tests.Tangle \ --gpc-rts=-nPascalfile:tex.p \ --gpc-rts=-npool:tex.pool \ --gpc-rts=-nwebfile:tex.web \ -- 1.7.10.4