changeset 1400:221eedb0f54e

fix inner class gc bug
author Franklin Schmidt <fschmidt@gmail.com>
date Fri, 13 Sep 2019 05:05:51 -0600
parents 38a1c1b4279a
children ef1620aa99cb
files src/luan/LuanClosure.java src/luan/LuanException.java src/luan/host/WebHandler.java src/luan/impl/LuanParser.java src/luan/lib/webserver/handlers/DomainHandler.java src/luan/modules/http/LuanDomainHandler.java src/luan/modules/http/LuanHandler.java
diffstat 7 files changed, 160 insertions(+), 99 deletions(-) [+]
line wrap: on
line diff
--- a/src/luan/LuanClosure.java	Wed Sep 11 16:28:38 2019 -0600
+++ b/src/luan/LuanClosure.java	Fri Sep 13 05:05:51 2019 -0600
@@ -8,9 +8,9 @@
 	public boolean javaOk;
 	public final String sourceName;
 
-	public LuanClosure(Luan luan,int nUpValues,boolean javaOk,String sourceName) throws LuanException {
+	public LuanClosure(Luan luan,Pointer[] upValues,boolean javaOk,String sourceName) throws LuanException {
 		super(luan);
-		this.upValues = new Pointer[nUpValues];
+		this.upValues = upValues;
 		this.javaOk = javaOk;
 		this.sourceName = sourceName;
 	}
@@ -21,7 +21,7 @@
 		super.completeClone(dc,cloner);
 	}
 
-	@Override public final Object call(Object[] args) throws LuanException {
+	@Override public final Object call(Object... args) throws LuanException {
 		Luan luan = luan();
 		luan.push(this);
 		try {
--- a/src/luan/LuanException.java	Wed Sep 11 16:28:38 2019 -0600
+++ b/src/luan/LuanException.java	Fri Sep 13 05:05:51 2019 -0600
@@ -86,11 +86,23 @@
 		return list;
 	}
 
-	public static String toString(StackTraceElement ste) {
+	public static String toLuanString(StackTraceElement ste) {
+		int line = ste.getLineNumber();
+		String method = ste.getMethodName();
+		boolean hasMethod = !method.equals("doCall");
+		if( hasMethod ) {
+			int i = method.indexOf('$');
+			if( i != -1 ) {
+				int n = Integer.parseInt(method.substring(i+1));
+				line -= n;
+				method = method.substring(0,i);
+				if( method.equals("_") )
+					hasMethod = false;
+			}
+		}
 		StringBuilder sb = new StringBuilder();
-		sb.append( ste.getFileName() ).append( " line " ).append( ste.getLineNumber() );
-		String method = ste.getMethodName();
-		if( !method.equals("doCall") )
+		sb.append( ste.getFileName() ).append( " line " ).append( line );
+		if( hasMethod )
 			sb.append( " in function '" ).append( method.substring(1) ).append( "'" );
 		return sb.toString();
 	}
@@ -99,7 +111,7 @@
 		StringBuilder sb = new StringBuilder();
 		sb.append( getMessage() );
 		for( StackTraceElement ste : justLuan(getStackTrace()) ) {
-			sb.append( "\n\t" ).append( toString(ste) );
+			sb.append( "\n\t" ).append( toLuanString(ste) );
 		}
 		return sb;
 	}
@@ -111,13 +123,7 @@
 			sb.append( "\nCaused by: " ).append( getJavaStackTraceString(cause) );
 		return sb.toString();
 	}
-/*
-	public static String currentSource() {
-		LuanException ex = new LuanException("currentSource");
-		List<StackTraceElement> st = ex.justLuan(ex.getStackTrace());
-		return st.isEmpty() ? null : st.get(0).getFileName();
-	}
-*/
+
 	@Override public void printStackTrace(PrintStream s) {
 		s.print("Luan: ");
 		s.println(luanStackTrace());
--- a/src/luan/host/WebHandler.java	Wed Sep 11 16:28:38 2019 -0600
+++ b/src/luan/host/WebHandler.java	Fri Sep 13 05:05:51 2019 -0600
@@ -24,7 +24,7 @@
 	private static final DomainHandler.Factory factory = new DomainHandler.Factory() {
 		public Handler newHandler(String domain) {
 			File dir = new File(sitesDir,domain);
-			if( !dir.exists() /* && !recover(dir) */ )
+			if( !dir.exists() )
 				return null;
 			String dirStr = dir.toString();
 
@@ -34,7 +34,7 @@
 			Luan luan = new Luan();
 			Log4j.newLoggerRepository(luan);
 			initLuan(luan,dirStr,domain);
-			return new LuanHandler(luan);
+			return new LuanHandler(luan,domain);
 		}
 	};
 
@@ -59,26 +59,6 @@
 		return luanHandler.call_rpc(fnName,args);
 	}
 
-/*
-	private static boolean recover(File dir) {
-		File backups = new File(dir.getParentFile().getParentFile(),"backups");
-		if( !backups.exists() )
-			return false;
-		String name = dir.getName();
-		File from = null;
-		for( File backup : backups.listFiles() ) {
-			File d = new File(backup,"current/"+name);
-			if( d.exists() && (from==null || from.lastModified() < d.lastModified()) )
-				from = d;
-		}
-		if( from == null )
-			return false;
-		if( !from.renameTo(dir) )
-			throw new RuntimeException("couldn't rename "+from+" to "+dir);
-		logger.info("recovered "+name+" from "+from);
-		return true;
-	}
-*/
 	private static void initLuan(Luan luan,String dir,String domain) {
 		security(luan,dir);
 		try {
--- a/src/luan/impl/LuanParser.java	Wed Sep 11 16:28:38 2019 -0600
+++ b/src/luan/impl/LuanParser.java	Fri Sep 13 05:05:51 2019 -0600
@@ -89,11 +89,11 @@
 			this.i = i;
 			this.value = value;
 		}
-
+/*
 		String init() {
 			return "upValues[" + i + "] = " + value + ";  ";
 		}
-
+*/
 		@Override public Expr exp() {
 			Expr exp = new Expr(Val.SINGLE,false);
 			exp.add( new Object() {
@@ -168,6 +168,10 @@
 
 	}
 
+	private static AtomicInteger classCounter = new AtomicInteger();
+	private int innerCounter = 0;
+	private final List<Inner> inners = new ArrayList<Inner>();
+
 	private Frame frame;
 	private final Parser parser;
 	private final Stmts top;
@@ -225,36 +229,29 @@
 		return t;
 	}
 
-	private Class newFnClass(Stmts stmt) {
-		return toFnClass( stmt, frame.upValueSymbols );
+	private Expr newFnExp(Stmts stmt,String name) {
+		String className = "INNER" + ++innerCounter;
+		Inner inner = new Inner( stmt, name, className );
+		inners.add(inner);
+		return inner.toInnerFnExp( frame.upValueSymbols );
+//		return toFnExp( stmt, frame.upValueSymbols, name );
 	}
 
-	private Expr newFnExp(Stmts stmt,String name) {
-		return toFnExp( stmt, frame.upValueSymbols, name );
-	}
-/*
-	Class Expression() throws ParseException {
-		Spaces();
-		parser.begin();
-		Expr expr = ExprZ();
-		if( expr != null && parser.endOfInput() ) {
-			top.add( "return " );
-			top.addAll( expr );
-			top.add( ";  " );
-			top.hasReturn = true;
-			return parser.success(newFnClass(top));
-		}
-		return parser.failure(null);
-	}
-*/
 	Class RequiredModule() throws ParseException {
 		GetRequiredModule();
-		return newFnClass(top);
+		String className = "EXP" + classCounter.incrementAndGet();
+		String classCode = toFnString( top, frame.upValueSymbols, className, inners );
+		try {
+			return LuanJavaCompiler.compile("luan.impl."+className,parser.sourceName,classCode);
+		} catch(ClassNotFoundException e) {
+			throw new RuntimeException(e);
+		}
 	}
 
 	String RequiredModuleSource() throws ParseException {
 		GetRequiredModule();
-		return toFnString( top, frame.upValueSymbols );
+		String className = "EXP" + classCounter.incrementAndGet();
+		return toFnString( top, frame.upValueSymbols, className, inners );
 	}
 
 	void GetRequiredModule() throws ParseException {
@@ -729,7 +726,7 @@
 
 	private Stmts ExpressionsStmt() throws ParseException {
 		parser.begin();
-		Expr exp = ExprZ();
+		Expr exp = Expression();
 		if( exp != null && exp.isStmt ) {
 			Stmts stmt = new Stmts();
 			if( exp.valType==Val.SINGLE ) {
@@ -755,10 +752,10 @@
 
 	private Expr RequiredExpr() throws ParseException {
 		parser.begin();
-		return parser.success(required(ExprZ(),"Bad expression"));
+		return parser.success(required(Expression(),"Bad expression"));
 	}
 
-	private Expr ExprZ() throws ParseException {
+	private Expr Expression() throws ParseException {
 		return OrExpr();
 	}
 
@@ -1175,7 +1172,7 @@
 			return parser.success(newExp);
 		}
 		parser.rollback();
-		Expr exprs = ExprZ();
+		Expr exprs = Expression();
 		if( exprs != null ) {
 			return parser.success(exprs);
 		}
@@ -1381,7 +1378,7 @@
 
 	private boolean ExpList(List<Expr> builder) throws ParseException {
 		parser.begin();
-		Expr exp = ExprZ();
+		Expr exp = Expression();
 		if( exp==null )
 			return parser.failure();
 		exp.addNewLines();
@@ -1872,8 +1869,6 @@
 	}
 
 
-	private static AtomicInteger classCounter = new AtomicInteger();
-
 	private enum Val { SINGLE, ARRAY }
 
 	private class Expr extends ParseList {
@@ -1956,27 +1951,11 @@
 		boolean hasReturn = false;
 	}
 
-	private Class toFnClass(Stmts stmts,List<UpSym> upValueSymbols) {
-		String className = "EXP" + classCounter.incrementAndGet();
-		String classCode = toFnString(stmts,upValueSymbols,className);
-		try {
-//System.out.println(parser.sourceName);
-//System.out.println(classCode);
-			return LuanJavaCompiler.compile("luan.impl."+className,parser.sourceName,classCode);
-		} catch(ClassNotFoundException e) {
-			throw new RuntimeException(e);
-		}
-	}
-
-	private String toFnString(Stmts stmts,List<UpSym> upValueSymbols) {
-		String className = "EXP" + classCounter.incrementAndGet();
-		return toFnString(stmts,upValueSymbols,className);
-	}
-
-	private String toFnString(Stmts stmts,List<UpSym> upValueSymbols,String className) {
+	private static String toFnString(Stmts stmts,List<UpSym> upValueSymbols,String className,List<Inner> inners) {
 		if( !stmts.hasReturn )
 			stmts.add( "\nreturn LuanFunction.NOTHING;" );
-		return ""
+		StringBuilder sb = new StringBuilder();
+		sb.append( ""
 			+"package luan.impl;  "
 			+"import luan.LuanClosure;  "
 			+"import luan.Luan;  "
@@ -1986,8 +1965,7 @@
 
 			+"public class " + className +" extends LuanClosure {  "
 				+"public "+className+"(Luan luan,boolean javaOk,String sourceName) throws LuanException {  "
-					+"super(luan,"+upValueSymbols.size()+",javaOk,sourceName);  "
-					+ init(upValueSymbols)
+					+"super(luan,"+toUpValues(upValueSymbols)+",javaOk,sourceName);  "
 				+"}  "
 
 				+"@Override public Object doCall(Luan luan,Object[] args) throws LuanException {  "
@@ -1995,11 +1973,87 @@
 					+"Object t;  "
 					+"Object[] a;  "
 					+ stmts
-				+"\n}  "
+				+"\n}\n"
+		);
+		for( Inner inner : inners ) {
+			sb.append( '\n' );
+			sb.append( inner.toInnerFnString(lines(sb.toString())) + '\n' );
+		}
+		sb.append( ""
 			+"}\n"
-		;
+		);
+		return sb.toString();
 	}
 
+	private class Inner {
+		private final Stmts stmts;
+		private final String name;
+		private final String className;
+		private final int lines;
+		private final int endLine;
+
+		Inner(Stmts stmts,String name,String className) {
+			this.stmts = stmts;
+			this.name = name;
+			this.className = className;
+
+			stmts.addNewLines();
+			if( !stmts.hasReturn )
+				stmts.add( "return LuanFunction.NOTHING;  " );
+			this.lines = lines( stmts.toString() );
+			this.endLine = lines( parser.textFrom(0) );
+		}
+
+		Expr toInnerFnExp(List<UpSym> upValueSymbols) {
+			StringBuilder sb = new StringBuilder();
+			sb.append(
+				"new "+className+"(luan(),"+toUpValues(upValueSymbols)+",javaOk,sourceName)"
+			);
+			for( int i=0; i<lines; i++ ) {
+				sb.append('\n');
+			}
+
+			Expr exp = new Expr(Val.SINGLE,false);
+			exp.add( sb.toString() );
+			return exp;
+		}
+
+		String toInnerFnString(int line) {
+			int diff = line + lines - endLine;
+			String name = this.name!=null ? this.name : "";
+			name += "$" + diff;
+			//name += "_" + lines + "_" + endLine + "_" + line;
+			StringBuilder sb = new StringBuilder();
+			sb.append( ""
+				+"private static class " + className +" extends LuanClosure {  "
+					+className+"(Luan luan,Pointer[] upValues,boolean javaOk,String sourceName) throws LuanException {  "
+						+"super(luan,upValues,javaOk,sourceName);  "
+					+"}  "
+					+"@Override public Object doCall(Luan luan,Object[] args) throws LuanException {  "
+						+"return _" + name + "(luan,args);  "
+					+"}  "
+					+"private Object _" + name + "(Luan luan,Object[] args) throws LuanException {  "
+						+"final Pointer[] parentUpValues = upValues;  "
+						+"Object t;  "
+						+"Object[] a;  "
+						+ stmts
+					+"}  "
+				+"}  "
+			);
+			return sb.toString();
+		}
+	}
+
+	private static int lines(String s) {
+		int lines = 0;
+		final int n = s.length();
+		for( int i=0; i<n; i++ ) {
+			if( s.charAt(i) == '\n' )
+				lines++;
+		}
+		return lines;
+	}
+/*
 	private Expr toFnExp(Stmts stmt,List<UpSym> upValueSymbols,String name) {
 		stmt.addNewLines();
 		if( !stmt.hasReturn )
@@ -2039,5 +2093,15 @@
 		}
 		return sb.toString();
 	}
+*/
+	private static String toUpValues(List<UpSym> upValueSymbols) {
+		StringBuilder sb = new StringBuilder();
+		sb.append( "new Pointer[]{ " );
+		for( UpSym upSym : upValueSymbols ) {
+			sb.append( upSym.value + ", " );
+		}
+		sb.append( "}" );
+		return sb.toString();
+	}
 
 }
--- a/src/luan/lib/webserver/handlers/DomainHandler.java	Wed Sep 11 16:28:38 2019 -0600
+++ b/src/luan/lib/webserver/handlers/DomainHandler.java	Fri Sep 13 05:05:51 2019 -0600
@@ -3,6 +3,7 @@
 import java.io.Closeable;
 import java.io.IOException;
 import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
 import java.lang.ref.SoftReference;
 import java.lang.ref.ReferenceQueue;
 import java.util.Map;
@@ -31,7 +32,7 @@
 
 	private final ReferenceQueue<Ref> queue = new ReferenceQueue<Ref>();
 
-	private class MyReference extends SoftReference<Ref> {
+	private class MyReference extends WeakReference<Ref> {
 		private Handler handler;
 
 		private MyReference(Ref r) {
--- a/src/luan/modules/http/LuanDomainHandler.java	Wed Sep 11 16:28:38 2019 -0600
+++ b/src/luan/modules/http/LuanDomainHandler.java	Fri Sep 13 05:05:51 2019 -0600
@@ -24,7 +24,7 @@
 
 	@Override public Handler newHandler(String domain) {
 		Luan luan = newLuan(domain);
-		return new LuanHandler(luan);
+		return new LuanHandler(luan,domain);
 	}
 
 	protected void newLoggerRepository(Luan luan) {
--- a/src/luan/modules/http/LuanHandler.java	Wed Sep 11 16:28:38 2019 -0600
+++ b/src/luan/modules/http/LuanHandler.java	Fri Sep 13 05:05:51 2019 -0600
@@ -13,6 +13,7 @@
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 import luan.lib.logging.Logger;
+import luan.lib.logging.LoggerFactory;
 import luan.lib.webserver.Request;
 import luan.lib.webserver.Response;
 import luan.lib.webserver.Status;
@@ -31,8 +32,11 @@
 
 
 public final class LuanHandler implements Handler, Luan.OnClose {
+	private static final Logger sysLogger = LoggerFactory.getLogger(LuanHandler.class);
+
 	private final Luan luanInit;
-	private final Logger logger;
+	private final String domain;
+	private final Logger luanLogger;
 	private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
 	private final List<Reference<Closeable>> onClose = new ArrayList<Reference<Closeable>>();
 	private volatile Luan currentLuan;
@@ -51,9 +55,10 @@
 		}
 	}
 
-	public LuanHandler(Luan luanInit) {
+	public LuanHandler(Luan luanInit,String domain) {
 		this.luanInit = luanInit;
-		this.logger = LuanLogger.getLogger(luanInit,LuanHandler.class.getName());
+		this.domain = domain;
+		this.luanLogger = luanInit.getLogger(LuanHandler.class);
 		try {
 			LuanTable Http = (LuanTable)luanInit.require("luan:http/Http.luan");
 			if( Http.get("reset_luan") == null )
@@ -64,6 +69,11 @@
 			throw new RuntimeException(e);
 		}
 		currentLuan = newLuan();
+		sysLogger.info("new "+domain);
+	}
+
+	protected void finalize() throws Throwable {
+		sysLogger.info("gc  "+domain);
 	}
 
 	private Luan newLuan() {
@@ -78,7 +88,7 @@
 		} catch(LuanException e) {
 			//e.printStackTrace();
 			String err = e.getLuanStackTraceString();
-			logger.error(err);
+			luanLogger.error(err);
 		}
 		return luan;
 	}
@@ -107,7 +117,7 @@
 			return service(request,notFound);
 		} catch(LuanException e) {
 			String err = e.getLuanStackTraceString();
-			logger.error(err+"\n"+request.rawHead.trim()+"\n");
+			luanLogger.error(err+"\n"+request.rawHead.trim()+"\n");
 			String msg = "Internel Server Error\n\n" + err;
 			return Response.errorResponse( Status.INTERNAL_SERVER_ERROR, msg );
 		} finally {
@@ -130,7 +140,7 @@
 					try {
 						c.close();
 					} catch(IOException e) {
-						logger.error(c.toString(),e);
+						luanLogger.error(c.toString(),e);
 					}
 				}
 			}