Skip to content

Commit 6094295

Browse files
committed
broad base refactoring to create a different object handler that does code generation
1 parent 7624278 commit 6094295

21 files changed

Lines changed: 369 additions & 163 deletions

compiler/src/main/java/com/github/mustachejava/asm/CodeCompiler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public class CodeCompiler {
2323
public static CompiledCodes compile(Code[] codes, Code[] newcodes) {
2424
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
2525
int classId = id.incrementAndGet();
26-
String className = "com.github.mustachejava.codes.RunCodes" + classId;
26+
String className = "com.github.mustachejava.asm.RunCodes" + classId;
2727
String internalClassName = className.replace(".", "/");
2828
cw.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, internalClassName, null, "java/lang/Object", new String[]{CompiledCodes.class.getName().replace(".", "/")});
2929
cw.visitSource("runCodes", null);

compiler/src/main/java/com/github/mustachejava/asm/CompilableGuard.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,12 @@ public interface CompilableGuard extends Guard, Opcodes {
2525
Type OH_TYPE = Type.getType(ObjectHandler.class);
2626
Type WRAPPERS_TYPE = Type.getType(Wrapper[].class);
2727
Type ROH_TYPE = Type.getType(ReflectionObjectHandler.class);
28+
Type GUARD_TYPE = Type.getType(Guard.class);
2829
Method CLASS_FORNAME = Method.getMethod("Class forName(String)");
2930
Method OBJECT_GETCLASS = Method.getMethod("Class getClass()");
3031
Method ROH_UNWRAP = Method.getMethod("Object unwrap(com.github.mustachejava.ObjectHandler, int, com.github.mustachejava.util.Wrapper[], Object[])");
3132
Method MAP_CONTAINSKEY = Method.getMethod("boolean containsKey(Object)");
33+
Method GUARD_APPLY = Method.getMethod("boolean apply(Object[])");
3234

3335
public abstract void addGuard(Label returnFalse,
3436
GeneratorAdapter gm,

compiler/src/main/java/com/github/mustachejava/asm/GuardCompiler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public static Guard[] compile(Guard[] guards) {
4343
public static Guard compile(String source, Iterable<CompilableGuard> guards) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
4444
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
4545
int classId = id.incrementAndGet();
46-
String className = "com.github.mustachejava.reflect.CompiledGuards" + classId;
46+
String className = "com.github.mustachejava.asm.CompiledGuards" + classId;
4747
String internalClassName = className.replace(".", "/");
4848
cw.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, internalClassName, null, "java/lang/Object", new String[]{Guard.class.getName().replace(".", "/")});
4949
cw.visitSource(source, null);

compiler/src/main/java/com/github/mustachejava/reflect/ClassGuard.java renamed to compiler/src/main/java/com/github/mustachejava/asm/guards/CompilableClassGuard.java

Lines changed: 7 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
package com.github.mustachejava.reflect;
1+
package com.github.mustachejava.asm.guards;
22

33
import com.github.mustachejava.asm.CompilableGuard;
4+
import com.github.mustachejava.reflect.guards.ClassGuard;
45
import org.objectweb.asm.ClassWriter;
56
import org.objectweb.asm.Label;
67
import org.objectweb.asm.Type;
@@ -13,39 +14,12 @@
1314
import static org.objectweb.asm.commons.GeneratorAdapter.NE;
1415

1516
/**
16-
* Ensure that the class of the current scope is that same as when this wrapper was generated.
17-
* User: spullara
18-
* Date: 4/13/12
19-
* Time: 9:23 AM
20-
* To change this template use File | Settings | File Templates.
17+
* Compiled form of the class guard.
2118
*/
22-
public class ClassGuard implements CompilableGuard {
23-
private final Class classGuard;
24-
private final int scopeIndex;
19+
public class CompilableClassGuard extends ClassGuard implements CompilableGuard {
2520

26-
public ClassGuard(int scopeIndex, Object scope) {
27-
this.scopeIndex = scopeIndex;
28-
this.classGuard = scope == null ? null : scope.getClass();
29-
}
30-
31-
@Override
32-
public int hashCode() {
33-
return classGuard == null ? 0 : classGuard.hashCode();
34-
}
35-
36-
@Override
37-
public boolean equals(Object o) {
38-
ClassGuard other = (ClassGuard) o;
39-
return o instanceof ClassGuard && (classGuard == null ? classGuard == other.classGuard : classGuard.equals(other.classGuard));
40-
}
41-
42-
@Override
43-
public boolean apply(Object[] scopes) {
44-
if (scopes == null || scopes.length <= scopeIndex) return false;
45-
Object scope = scopes[scopeIndex];
46-
if (scope != null && classGuard != scope.getClass()) return false;
47-
if (scope == null && classGuard != null) return false;
48-
return true;
21+
public CompilableClassGuard(int scopeIndex, Object scope) {
22+
super(scopeIndex, scope);
4923
}
5024

5125
@Override
@@ -105,4 +79,5 @@ public void addGuard(Label returnFalse, GeneratorAdapter gm, GeneratorAdapter cm
10579
}
10680

10781

82+
10883
}

compiler/src/main/java/com/github/mustachejava/reflect/DepthGuard.java renamed to compiler/src/main/java/com/github/mustachejava/asm/guards/CompilableDepthGuard.java

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,22 @@
1-
package com.github.mustachejava.reflect;
1+
package com.github.mustachejava.asm.guards;
22

33
import com.github.mustachejava.asm.CompilableGuard;
4+
import com.github.mustachejava.reflect.guards.DepthGuard;
45
import org.objectweb.asm.ClassWriter;
56
import org.objectweb.asm.Label;
67
import org.objectweb.asm.Type;
78
import org.objectweb.asm.commons.GeneratorAdapter;
89

9-
import javax.annotation.Nullable;
1010
import java.util.List;
1111
import java.util.concurrent.atomic.AtomicInteger;
1212

1313
/**
14-
* Check that there are the same number of scope levels.
14+
* Compiled version of the depth guard.
1515
*/
16-
public class DepthGuard implements CompilableGuard {
17-
private final int length;
16+
public class CompilableDepthGuard extends DepthGuard implements CompilableGuard {
1817

19-
public DepthGuard(int length) {
20-
this.length = length;
21-
}
22-
23-
@Override
24-
public int hashCode() {
25-
return length;
26-
}
27-
28-
@Override
29-
public boolean equals(Object o) {
30-
if (o instanceof DepthGuard) {
31-
DepthGuard depthGuard = (DepthGuard) o;
32-
return length == depthGuard.length;
33-
}
34-
return false;
35-
}
36-
37-
@Override
38-
public boolean apply(@Nullable Object[] objects) {
39-
return objects != null && length == objects.length;
18+
public CompilableDepthGuard(int length) {
19+
super(length);
4020
}
4121

4222
@Override
@@ -51,4 +31,5 @@ public void addGuard(Label returnFalse, GeneratorAdapter gm, GeneratorAdapter cm
5131
gm.push(length);
5232
gm.ifICmp(GeneratorAdapter.NE, returnFalse);
5333
}
34+
5435
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.github.mustachejava.asm.guards;
2+
3+
import com.github.mustachejava.asm.CompilableGuard;
4+
import com.github.mustachejava.reflect.guards.DotGuard;
5+
import org.objectweb.asm.ClassWriter;
6+
import org.objectweb.asm.Label;
7+
import org.objectweb.asm.Type;
8+
import org.objectweb.asm.commons.GeneratorAdapter;
9+
10+
import java.util.List;
11+
import java.util.concurrent.atomic.AtomicInteger;
12+
13+
/**
14+
* Compiled dot guard.
15+
*/
16+
public class CompilableDotGuard extends DotGuard implements CompilableGuard {
17+
18+
public CompilableDotGuard(String lookup, int scopeIndex, Object classGuard) {
19+
super(lookup, scopeIndex, classGuard);
20+
}
21+
22+
@Override
23+
public void addGuard(Label returnFalse, GeneratorAdapter gm, GeneratorAdapter cm, GeneratorAdapter sm, ClassWriter cw, AtomicInteger atomicId, List<Object> cargs, Type thisType) {
24+
// do nothing and it is assumed true
25+
}
26+
}

compiler/src/main/java/com/github/mustachejava/reflect/MapGuard.java renamed to compiler/src/main/java/com/github/mustachejava/asm/guards/CompilableMapGuard.java

Lines changed: 12 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,27 @@
1-
package com.github.mustachejava.reflect;
1+
package com.github.mustachejava.asm.guards;
22

33
import com.github.mustachejava.ObjectHandler;
44
import com.github.mustachejava.asm.CompilableGuard;
5+
import com.github.mustachejava.reflect.guards.MapGuard;
56
import com.github.mustachejava.util.Wrapper;
67
import org.objectweb.asm.ClassWriter;
78
import org.objectweb.asm.Label;
89
import org.objectweb.asm.Type;
910
import org.objectweb.asm.commons.GeneratorAdapter;
1011

1112
import java.util.List;
12-
import java.util.Map;
1313
import java.util.concurrent.atomic.AtomicInteger;
1414

15-
import static com.github.mustachejava.reflect.ReflectionObjectHandler.unwrap;
15+
import static org.objectweb.asm.commons.GeneratorAdapter.EQ;
16+
import static org.objectweb.asm.commons.GeneratorAdapter.NE;
1617

1718
/**
18-
* Guards whether or not a name was present in the map.
19+
* Compiled version of map guard.
1920
*/
20-
public class MapGuard implements CompilableGuard {
21-
private final ObjectHandler oh;
22-
private final int scopeIndex;
23-
private final String name;
24-
private final boolean contains;
25-
private final Wrapper[] wrappers;
21+
public class CompilableMapGuard extends MapGuard implements CompilableGuard {
2622

27-
public MapGuard(ObjectHandler oh, int scopeIndex, String name, boolean contains, Wrapper[] wrappers) {
28-
this.oh = oh;
29-
this.scopeIndex = scopeIndex;
30-
this.name = name;
31-
this.contains = contains;
32-
this.wrappers = wrappers;
33-
}
34-
35-
@Override
36-
public boolean apply(Object[] objects) {
37-
Object scope = unwrap(oh, scopeIndex, wrappers, objects);
38-
if (scope instanceof Map) {
39-
Map map = (Map) scope;
40-
if (contains) {
41-
return map.containsKey(name);
42-
} else {
43-
return !map.containsKey(name);
44-
}
45-
}
46-
return false;
23+
public CompilableMapGuard(ObjectHandler oh, int scopeIndex, String name, boolean contains, Wrapper[] wrappers) {
24+
super(oh, scopeIndex, name, contains, wrappers);
4725
}
4826

4927
@Override
@@ -91,18 +69,14 @@ public void addGuard(Label returnFalse, GeneratorAdapter gm, GeneratorAdapter cm
9169
// Check to see if it is a map
9270
gm.loadLocal(scopeLocal);
9371
gm.instanceOf(MAP_TYPE);
94-
gm.ifZCmp(GeneratorAdapter.EQ, returnFalse);
72+
gm.ifZCmp(EQ, returnFalse);
9573

9674
// It is a map
9775
gm.loadLocal(scopeLocal);
9876
gm.checkCast(MAP_TYPE);
9977
gm.push(name);
100-
if (contains) {
101-
gm.invokeInterface(MAP_TYPE, MAP_CONTAINSKEY);
102-
gm.ifZCmp(GeneratorAdapter.EQ, returnFalse);
103-
} else {
104-
gm.invokeInterface(MAP_TYPE, MAP_CONTAINSKEY);
105-
gm.ifZCmp(GeneratorAdapter.NE, returnFalse);
106-
}
78+
gm.invokeInterface(MAP_TYPE, MAP_CONTAINSKEY);
79+
gm.ifZCmp(contains ? EQ : NE, returnFalse);
10780
}
81+
10882
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.github.mustachejava.asm.guards;
2+
3+
import com.github.mustachejava.asm.CompilableGuard;
4+
import com.github.mustachejava.reflect.guards.NullGuard;
5+
import org.objectweb.asm.ClassWriter;
6+
import org.objectweb.asm.Label;
7+
import org.objectweb.asm.Type;
8+
import org.objectweb.asm.commons.GeneratorAdapter;
9+
10+
import java.util.List;
11+
import java.util.concurrent.atomic.AtomicInteger;
12+
13+
/**
14+
* Compiled null guard.
15+
*/
16+
public class CompilableNullGuard extends NullGuard implements CompilableGuard {
17+
18+
@Override
19+
public void addGuard(Label returnFalse, GeneratorAdapter gm, GeneratorAdapter cm, GeneratorAdapter sm, ClassWriter cw, AtomicInteger atomicId, List<Object> cargs, Type thisType) {
20+
gm.loadArg(0);
21+
gm.push(0);
22+
gm.arrayLoad(OBJECT_TYPE);
23+
gm.ifNonNull(returnFalse);
24+
}
25+
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package com.github.mustachejava.asm.guards;
2+
3+
import com.github.mustachejava.MustacheException;
4+
import com.github.mustachejava.ObjectHandler;
5+
import com.github.mustachejava.asm.CompilableGuard;
6+
import com.github.mustachejava.asm.GuardCompiler;
7+
import com.github.mustachejava.reflect.Guard;
8+
import com.github.mustachejava.reflect.guards.WrappedGuard;
9+
import com.github.mustachejava.util.Wrapper;
10+
import org.objectweb.asm.ClassWriter;
11+
import org.objectweb.asm.Label;
12+
import org.objectweb.asm.Type;
13+
import org.objectweb.asm.commons.GeneratorAdapter;
14+
15+
import java.util.List;
16+
import java.util.concurrent.atomic.AtomicInteger;
17+
18+
import static org.objectweb.asm.commons.GeneratorAdapter.EQ;
19+
20+
/**
21+
* Compiled wrapper guard.
22+
*/
23+
public class CompilableWrappedGuard extends WrappedGuard implements CompilableGuard {
24+
private Guard guard;
25+
26+
@SuppressWarnings("unchecked")
27+
public CompilableWrappedGuard(ObjectHandler oh, int index, List<Wrapper> wrappers, List<Guard> wrapperGuard) {
28+
super(oh, index, wrappers, wrapperGuard);
29+
Guard[] guards = GuardCompiler.compile(wrapperGuard.toArray(new Guard[wrapperGuard.size()]));
30+
if (guards.length != 1) {
31+
throw new MustacheException("Invalid guard in wrappers: " + wrapperGuard);
32+
} else {
33+
guard = guards[0];
34+
}
35+
}
36+
37+
@Override
38+
public void addGuard(Label returnFalse, GeneratorAdapter gm, GeneratorAdapter cm, GeneratorAdapter sm, ClassWriter cw, AtomicInteger atomicId, List<Object> cargs, Type thisType) {
39+
int id = atomicId.incrementAndGet();
40+
41+
String wrappersFieldName = "wrappers" + id;
42+
String ohFieldName = "oh" + id;
43+
String guardFieldName = "guard" + id;
44+
45+
// Add the two fields we need
46+
cw.visitField(ACC_PRIVATE, ohFieldName, "Lcom/github/mustachejava/ObjectHandler;", null, null);
47+
cw.visitField(ACC_PRIVATE, wrappersFieldName, "[Lcom/github/mustachejava/util/Wrapper;", null, null);
48+
cw.visitField(ACC_PRIVATE, guardFieldName, "[Lcom/github/mustachejava/reflect/Guard;", null, null);
49+
50+
// Initialize them in the constructor
51+
int ohArg = cargs.size();
52+
cargs.add(oh);
53+
cm.loadThis();
54+
cm.loadArg(0);
55+
cm.push(ohArg);
56+
cm.arrayLoad(OBJECT_TYPE);
57+
cm.checkCast(OH_TYPE);
58+
cm.putField(thisType, ohFieldName, OH_TYPE);
59+
60+
int wrappersArg = cargs.size();
61+
cargs.add(wrappers);
62+
cm.loadThis();
63+
cm.loadArg(0);
64+
cm.push(wrappersArg);
65+
cm.arrayLoad(OBJECT_TYPE);
66+
cm.checkCast(WRAPPERS_TYPE);
67+
cm.putField(thisType, wrappersFieldName, WRAPPERS_TYPE);
68+
69+
int guardArg = cargs.size();
70+
cargs.add(guard);
71+
cm.loadThis();
72+
cm.loadArg(0);
73+
cm.push(guardArg);
74+
cm.arrayLoad(OBJECT_TYPE);
75+
cm.checkCast(GUARD_TYPE);
76+
cm.putField(thisType, guardFieldName, GUARD_TYPE);
77+
78+
// Unwrap the scope
79+
gm.loadThis();
80+
gm.getField(thisType, ohFieldName, OH_TYPE);
81+
gm.push(index);
82+
gm.loadThis();
83+
gm.getField(thisType, wrappersFieldName, WRAPPERS_TYPE);
84+
gm.loadArg(0);
85+
gm.invokeStatic(ROH_TYPE, ROH_UNWRAP);
86+
int scopeLocal = gm.newLocal(OBJECT_TYPE);
87+
gm.storeLocal(scopeLocal);
88+
89+
// Put the guard on the stack
90+
gm.loadLocal(guardArg);
91+
92+
// Create the object array
93+
gm.push(1);
94+
gm.newArray(OBJECT_TYPE);
95+
int arrayLocal = gm.newLocal(Type.getType(Object[].class));
96+
gm.storeLocal(arrayLocal);
97+
98+
// Put the scope in the array
99+
gm.push(0);
100+
gm.loadLocal(scopeLocal);
101+
gm.loadLocal(arrayLocal);
102+
gm.arrayStore(OBJECT_TYPE);
103+
104+
// Call the apply method on the guard
105+
gm.invokeInterface(GUARD_TYPE, GUARD_APPLY);
106+
107+
// If this is false, return false
108+
gm.ifZCmp(EQ, returnFalse);
109+
}
110+
}

0 commit comments

Comments
 (0)