summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/jvm/clojure/lang/Compiler.java52
1 files changed, 49 insertions, 3 deletions
diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java
index 6f1e88f4..c39026d9 100644
--- a/src/jvm/clojure/lang/Compiler.java
+++ b/src/jvm/clojure/lang/Compiler.java
@@ -73,6 +73,8 @@ static final Symbol ISEQ = Symbol.create("clojure.lang.ISeq");
static final Keyword inlineKey = Keyword.intern(null, "inline");
static final Keyword inlineAritiesKey = Keyword.intern(null, "inline-arities");
+static final Keyword volatileKey = Keyword.intern(null, "volatile");
+
static final Symbol NS = Symbol.create("ns");
static final Symbol IN_NS = Symbol.create("in-ns");
@@ -2707,6 +2709,10 @@ static public class ObjExpr implements Expr{
public final Object tag;
//localbinding->itself
IPersistentMap closes = PersistentHashMap.EMPTY;
+
+ //symbols
+ IPersistentSet volatiles = PersistentHashSet.EMPTY;
+
//Keyword->KeywordExpr
IPersistentMap keywords = PersistentHashMap.EMPTY;
IPersistentMap vars = PersistentHashMap.EMPTY;
@@ -2874,8 +2880,9 @@ static public class ObjExpr implements Expr{
for(ISeq s = RT.keys(closes); s != null; s = s.next())
{
LocalBinding lb = (LocalBinding) s.first();
+
if(lb.getPrimitiveType() != null)
- cv.visitField(ACC_PUBLIC + ACC_FINAL
+ cv.visitField(ACC_PUBLIC + (isVolatile(lb) ? ACC_VOLATILE : ACC_FINAL)
, lb.name, Type.getType(lb.getPrimitiveType()).getDescriptor(),
null, null);
else
@@ -3090,6 +3097,9 @@ static public class ObjExpr implements Expr{
}
}
+ boolean isVolatile(LocalBinding lb){
+ return closes.containsKey(lb) && volatiles.contains(lb.sym);
+ }
void emitClearCloses(GeneratorAdapter gen){
int a = 1;
@@ -3185,6 +3195,26 @@ static public class ObjExpr implements Expr{
return (tag != null) ? HostExpr.tagToClass(tag) : IFn.class;
}
+ public void emitAssignLocal(GeneratorAdapter gen, LocalBinding lb,Expr val){
+ if(!isVolatile(lb))
+ throw new IllegalArgumentException("Cannot assign to non-volatile: " + lb.name);
+ Class primc = lb.getPrimitiveType();
+ gen.loadThis();
+ if(primc != null)
+ {
+ MaybePrimitiveExpr me = (MaybePrimitiveExpr) val;
+ if(!me.canEmitPrimitive())
+ throw new IllegalArgumentException("Must assign primitive to primitive volatile: " + lb.name);
+ me.emitUnboxed(C.EXPRESSION, this, gen);
+ gen.putField(objtype, lb.name, Type.getType(primc));
+ }
+ else
+ {
+ val.emit(C.EXPRESSION, this, gen);
+ gen.putField(objtype, lb.name, OBJECT_TYPE);
+ }
+ }
+
private void emitLocal(GeneratorAdapter gen, LocalBinding lb){
if(closes.containsKey(lb))
{
@@ -3570,7 +3600,7 @@ public static class LocalBinding{
}
}
-public static class LocalBindingExpr implements Expr, MaybePrimitiveExpr{
+public static class LocalBindingExpr implements Expr, MaybePrimitiveExpr, AssignableExpr{
public final LocalBinding b;
public final Symbol tag;
@@ -3598,6 +3628,16 @@ public static class LocalBindingExpr implements Expr, MaybePrimitiveExpr{
objx.emitLocal(gen, b);
}
+ public Object evalAssign(Expr val) throws Exception{
+ throw new UnsupportedOperationException("Can't eval locals");
+ }
+
+ public void emitAssign(C context, ObjExpr objx, GeneratorAdapter gen, Expr val){
+ objx.emitAssignLocal(gen, b,val);
+ if(context != C.STATEMENT)
+ objx.emitLocal(gen, b);
+ }
+
public boolean hasJavaClass() throws Exception{
return tag != null || b.hasJavaClass();
}
@@ -4914,7 +4954,12 @@ static public class NewInstanceExpr extends ObjExpr{
ret.optionsMap = ((IPersistentMap) RT.first(rform));
rform = RT.next(rform);
}
-
+
+ if(RT.get(ret.optionsMap, volatileKey) != null)
+ {
+ ret.volatiles = PersistentHashSet.create(RT.seq(RT.get(ret.optionsMap, volatileKey)));
+ }
+
try
{
Var.pushThreadBindings(
@@ -4931,6 +4976,7 @@ static public class NewInstanceExpr extends ObjExpr{
methods = RT.conj(methods, m);
}
+
ret.methods = methods;
ret.keywords = (IPersistentMap) KEYWORDS.deref();
ret.vars = (IPersistentMap) VARS.deref();