summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2008-01-28 20:22:41 +0000
committerRich Hickey <richhickey@gmail.com>2008-01-28 20:22:41 +0000
commit28b5f12e50f37f1e520512c96c7d18494e779eca (patch)
tree4473c5f9e997aa69c6facd409cfcdd8aa7a04200 /src
parente952d81f687abea07327724d15e60a1500080b67 (diff)
interim checkin, do not use
new constant handling
Diffstat (limited to 'src')
-rw-r--r--src/jvm/clojure/lang/Compiler.java219
-rw-r--r--src/jvm/clojure/lang/DynamicClassLoader.java10
2 files changed, 160 insertions, 69 deletions
diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java
index 0c24f319..cfd875fa 100644
--- a/src/jvm/clojure/lang/Compiler.java
+++ b/src/jvm/clojure/lang/Compiler.java
@@ -88,17 +88,17 @@ static IPersistentMap specials = RT.map(
DOT, new HostExpr.Parser(),
ASSIGN, new AssignExpr.Parser(),
// TRY_FINALLY, new TryFinallyExpr.Parser(),
- TRY, new TryExpr.Parser(),
- THROW, new ThrowExpr.Parser(),
- MONITOR_ENTER, new MonitorEnterExpr.Parser(),
- MONITOR_EXIT, new MonitorExitExpr.Parser(),
+TRY, new TryExpr.Parser(),
+THROW, new ThrowExpr.Parser(),
+MONITOR_ENTER, new MonitorEnterExpr.Parser(),
+MONITOR_EXIT, new MonitorExitExpr.Parser(),
// INSTANCE, new InstanceExpr.Parser(),
// IDENTICAL, new IdenticalExpr.Parser(),
- THISFN, null,
- CATCH, null,
- FINALLY, null,
+THISFN, null,
+CATCH, null,
+FINALLY, null,
// CLASS, new ClassExpr.Parser(),
- NEW, new NewExpr.Parser(),
+NEW, new NewExpr.Parser(),
// UNQUOTE, null,
// UNQUOTE_SPLICING, null,
// SYNTAX_QUOTE, null,
@@ -151,10 +151,13 @@ static public Var LOOP_LOCALS = Var.create();
//Label
static public Var LOOP_LABEL = Var.create();
-//keyword->keywordexpr
+//vector<object>
+static public Var CONSTANTS = Var.create();
+
+//keyword->constid
static public Var KEYWORDS = Var.create();
-//var->var
+//var->constid
static public Var VARS = Var.create();
//FnFrame
@@ -1098,16 +1101,13 @@ static class ConstantExpr extends LiteralExpr{
//this won't work for static compilation...
final Object v;
final int id;
- final static Type DYNAMIC_CLASSLOADER_TYPE = Type.getType(DynamicClassLoader.class);
- final static Method getClassMethod = Method.getMethod("Class getClass()");
- final static Method getClassLoaderMethod = Method.getMethod("ClassLoader getClassLoader()");
- final static Method getQuotedValMethod = Method.getMethod("Object getQuotedVal(int)");
public ConstantExpr(Object v){
this.v = v;
- this.id = RT.nextID();
- DynamicClassLoader loader = (DynamicClassLoader) LOADER.get();
- loader.registerQuotedVal(id, v);
+ this.id = registerConstant(v);
+// this.id = RT.nextID();
+// DynamicClassLoader loader = (DynamicClassLoader) LOADER.get();
+// loader.registerQuotedVal(id, v);
}
Object val(){
@@ -1117,21 +1117,24 @@ static class ConstantExpr extends LiteralExpr{
public void emit(C context, FnExpr fn, GeneratorAdapter gen){
if(context != C.STATEMENT)
{
- gen.loadThis();
- gen.invokeVirtual(OBJECT_TYPE, getClassMethod);
- gen.invokeVirtual(CLASS_TYPE, getClassLoaderMethod);
- gen.checkCast(DYNAMIC_CLASSLOADER_TYPE);
- gen.push(id);
- gen.invokeVirtual(DYNAMIC_CLASSLOADER_TYPE, getQuotedValMethod);
+ fn.emitConstant(gen, id);
+// gen.loadThis();
+// gen.invokeVirtual(OBJECT_TYPE, getClassMethod);
+// gen.invokeVirtual(CLASS_TYPE, getClassLoaderMethod);
+// gen.checkCast(DYNAMIC_CLASSLOADER_TYPE);
+// gen.push(id);
+// gen.invokeVirtual(DYNAMIC_CLASSLOADER_TYPE, getQuotedValMethod);
}
}
public boolean hasJavaClass(){
- return false;
+ return Modifier.isPublic(v.getClass().getModifiers());
+ //return false;
}
public Class getJavaClass() throws Exception{
- throw new IllegalArgumentException("Has no Java class");
+ return v.getClass();
+ //throw new IllegalArgumentException("Has no Java class");
}
static class Parser implements IParser{
@@ -1140,17 +1143,17 @@ static class ConstantExpr extends LiteralExpr{
if(v == null)
return NIL_EXPR;
- Class fclass = v.getClass();
- if(fclass == Keyword.class)
- return registerKeyword((Keyword) v);
- else if(v instanceof Num)
- return new NumExpr((Num) v);
- else if(fclass == String.class)
- return new StringExpr((String) v);
- else if(fclass == Character.class)
- return new CharExpr((Character) v);
- else if(v instanceof IPersistentCollection && ((IPersistentCollection) v).count() == 0)
- return new EmptyExpr(v);
+// Class fclass = v.getClass();
+// if(fclass == Keyword.class)
+// return registerKeyword((Keyword) v);
+// else if(v instanceof Num)
+// return new NumExpr((Num) v);
+// else if(fclass == String.class)
+// return new StringExpr((String) v);
+// else if(fclass == Character.class)
+// return new CharExpr((Character) v);
+// else if(v instanceof IPersistentCollection && ((IPersistentCollection) v).count() == 0)
+// return new EmptyExpr(v);
else
return new ConstantExpr(v);
}
@@ -2300,6 +2303,7 @@ static class SourceDebugExtensionAttribute extends Attribute{
}
static class FnExpr implements Expr{
+ static final String CONST_PREFIX = "const__";
IPersistentCollection methods;
//if there is a variadic overload (there can only be one) it is stored here
FnMethod variadicMethod = null;
@@ -2314,6 +2318,8 @@ static class FnExpr implements Expr{
IPersistentMap vars = PersistentHashMap.EMPTY;
Class compiledClass;
int line;
+ PersistentVector constants;
+ int constantsID;
final static Method kwintern = Method.getMethod("clojure.lang.Keyword intern(String, String)");
final static Method symcreate = Method.getMethod("clojure.lang.Symbol create(String)");
@@ -2324,6 +2330,11 @@ static class FnExpr implements Expr{
final static Type aFnType = Type.getType(AFn.class);
final static Type restFnType = Type.getType(RestFn.class);
+ final static Type DYNAMIC_CLASSLOADER_TYPE = Type.getType(DynamicClassLoader.class);
+ final static Method getClassMethod = Method.getMethod("Class getClass()");
+ final static Method getClassLoaderMethod = Method.getMethod("ClassLoader getClassLoader()");
+ final static Method getConstantsMethod = Method.getMethod("Object[] getConstants(int)");
+
static Expr parse(C context, ISeq form, String name) throws Exception{
FnExpr fn = new FnExpr();
FnMethod enclosingMethod = (FnMethod) METHOD.get();
@@ -2339,9 +2350,9 @@ static class FnExpr implements Expr{
try
{
Var.pushThreadBindings(
- RT.map(
- KEYWORDS, PersistentHashMap.EMPTY,
- VARS, PersistentHashMap.EMPTY));
+ RT.map(CONSTANTS, PersistentVector.EMPTY,
+ KEYWORDS, PersistentHashMap.EMPTY,
+ VARS, PersistentHashMap.EMPTY));
//(fn [args] body...) or (fn ([args] body...) ([args2] body2...) ...)
//turn former into latter
if(RT.second(form) instanceof IPersistentVector)
@@ -2383,6 +2394,10 @@ static class FnExpr implements Expr{
fn.variadicMethod = variadicMethod;
fn.keywords = (IPersistentMap) KEYWORDS.get();
fn.vars = (IPersistentMap) VARS.get();
+ fn.constants = (PersistentVector) CONSTANTS.get();
+ fn.constantsID = RT.nextID();
+ DynamicClassLoader loader = (DynamicClassLoader) LOADER.get();
+ loader.registerConstants(fn.constantsID, fn.constants.toArray());
}
finally
{
@@ -2421,6 +2436,15 @@ static class FnExpr implements Expr{
if(source != null && SOURCE_PATH.get() != null)
//cv.visitSource(source, null);
cv.visitSource(source, smap);
+
+ //static fields for constants
+ for(int i = 0; i < constants.count(); i++)
+ {
+ cv.visitField(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, constantName(i), constantType(i).getDescriptor(),
+ null, null);
+ }
+
+/*
//static fields for keywords
for(ISeq s = RT.keys(keywords); s != null; s = s.rest())
{
@@ -2435,7 +2459,8 @@ static class FnExpr implements Expr{
cv.visitField(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, munge(v.sym.toString()),
VAR_TYPE.getDescriptor(), null, null);
}
- //static init for keywords and vars
+ */
+ //static init for constants, keywords and vars
GeneratorAdapter clinitgen = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC,
Method.getMethod("void <clinit> ()"),
null,
@@ -2443,25 +2468,49 @@ static class FnExpr implements Expr{
cv);
clinitgen.visitCode();
clinitgen.visitLineNumber(line, clinitgen.mark());
- for(ISeq s = RT.keys(keywords); s != null; s = s.rest())
- {
- Keyword k = (Keyword) s.first();
- clinitgen.push(k.sym.ns);
- clinitgen.push(k.sym.name);
- clinitgen.invokeStatic(KEYWORD_TYPE, kwintern);
- clinitgen.putStatic(fntype, munge(k.sym.toString()), KEYWORD_TYPE);
- }
- for(ISeq s = RT.keys(vars); s != null; s = s.rest())
+// Label begin = clinitgen.newLabel();
+// Label end = clinitgen.newLabel();
+
+ if(constants.count() > 0)
{
- Var v = (Var) s.first();
- clinitgen.push(v.ns.name.name);
- clinitgen.invokeStatic(SYMBOL_TYPE, symcreate);
- clinitgen.push(v.sym.name);
- clinitgen.invokeStatic(SYMBOL_TYPE, symcreate);
- clinitgen.invokeStatic(VAR_TYPE, varintern);
- clinitgen.putStatic(fntype, munge(v.sym.toString()), VAR_TYPE);
+// clinitgen.mark(begin);
+ clinitgen.visitLdcInsn(fntype);
+ clinitgen.invokeVirtual(CLASS_TYPE, getClassLoaderMethod);
+ clinitgen.checkCast(DYNAMIC_CLASSLOADER_TYPE);
+ clinitgen.push(constantsID);
+ clinitgen.invokeVirtual(DYNAMIC_CLASSLOADER_TYPE, getConstantsMethod);
+
+ for(int i = 0; i < constants.count(); i++)
+ {
+ clinitgen.dup();
+ clinitgen.push(i);
+ clinitgen.arrayLoad(OBJECT_TYPE);
+ clinitgen.checkCast(constantType(i));
+ clinitgen.putStatic(fntype, constantName(i), constantType(i));
+ }
}
+// for(ISeq s = RT.keys(keywords); s != null; s = s.rest())
+// {
+// Keyword k = (Keyword) s.first();
+// clinitgen.push(k.sym.ns);
+// clinitgen.push(k.sym.name);
+// clinitgen.invokeStatic(KEYWORD_TYPE, kwintern);
+// clinitgen.putStatic(fntype, munge(k.sym.toString()), KEYWORD_TYPE);
+// }
+// for(ISeq s = RT.keys(vars); s != null; s = s.rest())
+// {
+// Var v = (Var) s.first();
+// clinitgen.push(v.ns.name.name);
+// clinitgen.invokeStatic(SYMBOL_TYPE, symcreate);
+// clinitgen.push(v.sym.name);
+// clinitgen.invokeStatic(SYMBOL_TYPE, symcreate);
+// clinitgen.invokeStatic(VAR_TYPE, varintern);
+// clinitgen.putStatic(fntype, munge(v.sym.toString()), VAR_TYPE);
+// }
+// clinitgen.mark(end);
+// clinitgen.visitLocalVariable("constants", "[Ljava/lang/Object;", null, begin, end, 0);
clinitgen.returnValue();
+
clinitgen.endMethod();
// clinitgen.visitMaxs(1, 1);
//instance fields for closed-overs
@@ -2552,11 +2601,34 @@ static class FnExpr implements Expr{
}
public void emitVar(GeneratorAdapter gen, Var var){
- gen.getStatic(fntype, munge(var.sym.toString()), VAR_TYPE);
+ Integer i = (Integer) vars.valAt(var);
+ emitConstant(gen, i);
+ //gen.getStatic(fntype, munge(var.sym.toString()), VAR_TYPE);
}
public void emitKeyword(GeneratorAdapter gen, Keyword k){
- gen.getStatic(fntype, munge(k.sym.toString()), KEYWORD_TYPE);
+ Integer i = (Integer) keywords.valAt(k);
+ emitConstant(gen, i);
+// gen.getStatic(fntype, munge(k.sym.toString()), KEYWORD_TYPE);
+ }
+
+ public void emitConstant(GeneratorAdapter gen, int id){
+ gen.getStatic(fntype, constantName(id), constantType(id));
+ }
+
+
+ String constantName(int id){
+ return CONST_PREFIX + id;
+ }
+
+ Type constantType(int id){
+ Object o = constants.nth(id);
+ Class c = o.getClass();
+ if(Modifier.isPublic(c.getModifiers()))
+ {
+ return Type.getType(c);
+ }
+ return OBJECT_TYPE;
}
}
@@ -3120,15 +3192,29 @@ public static Object eval(Object form) throws Exception{
}
}
+private static int registerConstant(Object o){
+ if(!CONSTANTS.isBound())
+ return -1;
+ IPersistentVector v = (IPersistentVector) CONSTANTS.get();
+ CONSTANTS.set(RT.conj(v, o));
+ return v.count();
+}
+
private static KeywordExpr registerKeyword(Keyword keyword){
if(!KEYWORDS.isBound())
return new KeywordExpr(keyword);
IPersistentMap keywordsMap = (IPersistentMap) KEYWORDS.get();
- KeywordExpr ke = (KeywordExpr) RT.get(keywordsMap, keyword);
- if(ke == null)
- KEYWORDS.set(RT.assoc(keywordsMap, keyword, ke = new KeywordExpr(keyword)));
- return ke;
+ Object id = RT.get(keywordsMap, keyword);
+ if(id == null)
+ {
+ KEYWORDS.set(RT.assoc(keywordsMap, keyword, registerConstant(keyword)));
+ }
+ return new KeywordExpr(keyword);
+// KeywordExpr ke = (KeywordExpr) RT.get(keywordsMap, keyword);
+// if(ke == null)
+// KEYWORDS.set(RT.assoc(keywordsMap, keyword, ke = new KeywordExpr(keyword)));
+// return ke;
}
private static Expr analyzeSymbol(Symbol sym) throws Exception{
@@ -3227,8 +3313,13 @@ private static void registerVar(Var var) throws Exception{
if(!VARS.isBound())
return;
IPersistentMap varsMap = (IPersistentMap) VARS.get();
- if(varsMap != null && RT.get(varsMap, var) == null)
- VARS.set(RT.assoc(varsMap, var, var));
+ Object id = RT.get(varsMap, var);
+ if(id == null)
+ {
+ VARS.set(RT.assoc(varsMap, var, registerConstant(var)));
+ }
+// if(varsMap != null && RT.get(varsMap, var) == null)
+// VARS.set(RT.assoc(varsMap, var, var));
}
static Namespace currentNS(){
diff --git a/src/jvm/clojure/lang/DynamicClassLoader.java b/src/jvm/clojure/lang/DynamicClassLoader.java
index ef3215c6..0a3395cc 100644
--- a/src/jvm/clojure/lang/DynamicClassLoader.java
+++ b/src/jvm/clojure/lang/DynamicClassLoader.java
@@ -17,7 +17,7 @@ import java.util.HashMap;
//todo: possibly extend URLClassLoader?
public class DynamicClassLoader extends ClassLoader{
-HashMap<Integer, Object> quotedVals = new HashMap<Integer, Object>();
+HashMap<Integer, Object[]> constantVals = new HashMap<Integer, Object[]>();
HashMap<String, byte[]> map = new HashMap<String, byte[]>();
public DynamicClassLoader(){
@@ -45,12 +45,12 @@ protected Class<?> findClass(String name) throws ClassNotFoundException{
throw new ClassNotFoundException(name);
}
-public void registerQuotedVal(int id, Object val){
- quotedVals.put(id, val);
+public void registerConstants(int id, Object[] val){
+ constantVals.put(id, val);
}
-public Object getQuotedVal(int id){
- return quotedVals.get(id);
+public Object[] getConstants(int id){
+ return constantVals.get(id);
}
}