Skip to content

Commit ead22ec

Browse files
author
vsilaev
committed
Optimizing inheritance lookup in transformers (caching)
1 parent 84ea65a commit ead22ec

File tree

20 files changed

+462
-228
lines changed

20 files changed

+462
-228
lines changed

net.tascalate.javaflow.providers.asm3/src/main/java/org/apache/commons/javaflow/providers/asm3/Asm3ClassTransformer.java

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,22 +36,30 @@
3636
*/
3737
final class Asm3ClassTransformer implements ResourceTransformer {
3838

39-
final private ContinuableClassInfoResolver cciResolver;
39+
private final InheritanceLookup inheritanceLookup;
40+
private final ContinuableClassInfoResolver cciResolver;
4041

41-
Asm3ClassTransformer(final ContinuableClassInfoResolver cciResolver) {
42+
Asm3ClassTransformer(InheritanceLookup inheritanceLookup, ContinuableClassInfoResolver cciResolver) {
43+
this.inheritanceLookup = inheritanceLookup;
4244
this.cciResolver = cciResolver;
4345
}
4446

45-
public byte[] transform(final byte[] original) {
46-
final ComputeClassWriter cw = new ComputeClassWriter(ClassWriter.COMPUTE_FRAMES, cciResolver.resourceLoader());
47-
final ContinuableClassVisitor visitor = new ContinuableClassVisitor(
47+
public byte[] transform(byte[] original) {
48+
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES) {
49+
@Override
50+
protected String getCommonSuperClass(final String type1, final String type2) {
51+
return inheritanceLookup.getCommonSuperClass(type1, type2);
52+
}
53+
};
54+
ContinuableClassVisitor visitor = new ContinuableClassVisitor(
4855
cw /* BytecodeDebugUtils.decorateClassVisitor(cw, true, * System.err) -- DUMP*/,
56+
inheritanceLookup,
4957
cciResolver,
5058
original
5159
);
5260
try {
5361
new ClassReader(original).accept(visitor, ClassReader.SKIP_FRAMES);
54-
} catch (final StopException ex) {
62+
} catch (StopException ex) {
5563
// Preliminary stop visiting non-continuable class
5664
return null;
5765
}
@@ -60,7 +68,7 @@ public byte[] transform(final byte[] original) {
6068
return null;
6169
}
6270

63-
final byte[] bytecode = cw.toByteArray();
71+
byte[] bytecode = cw.toByteArray();
6472
// BytecodeDebugUtils.dumpClass(bytecode);
6573
return bytecode;
6674
}

net.tascalate.javaflow.providers.asm3/src/main/java/org/apache/commons/javaflow/providers/asm3/Asm3ResourceTransformationFactory.java

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,37 @@
1515
*/
1616
package org.apache.commons.javaflow.providers.asm3;
1717

18+
import java.util.Map;
19+
import java.util.WeakHashMap;
20+
1821
import org.apache.commons.javaflow.spi.ContinuableClassInfoResolver;
1922
import org.apache.commons.javaflow.spi.ResourceLoader;
2023
import org.apache.commons.javaflow.spi.ResourceTransformationFactory;
2124
import org.apache.commons.javaflow.spi.ResourceTransformer;
2225

2326
public class Asm3ResourceTransformationFactory implements ResourceTransformationFactory {
2427

25-
public ResourceTransformer createTransformer(final ContinuableClassInfoResolver cciResolver) {
26-
return new Asm3ClassTransformer(cciResolver);
28+
public ResourceTransformer createTransformer(ContinuableClassInfoResolver cciResolver) {
29+
return new Asm3ClassTransformer(getOrCreateInheritanceLookup(cciResolver), cciResolver);
2730
}
2831

29-
public ContinuableClassInfoResolver createResolver(final ResourceLoader resourceLoader) {
32+
public ContinuableClassInfoResolver createResolver(ResourceLoader resourceLoader) {
3033
return new Asm3ContinuableClassInfoResolver(resourceLoader);
3134
}
35+
36+
private static InheritanceLookup getOrCreateInheritanceLookup(ContinuableClassInfoResolver cciResolver) {
37+
InheritanceLookup result;
38+
synchronized (CACHED_INHERITANCE_LOOKUP) {
39+
result = CACHED_INHERITANCE_LOOKUP.get(cciResolver);
40+
if (null == result) {
41+
result = new InheritanceLookup(cciResolver.resourceLoader());
42+
CACHED_INHERITANCE_LOOKUP.put(cciResolver, result);
43+
}
44+
}
45+
return result;
46+
}
47+
48+
private static final Map<ContinuableClassInfoResolver, InheritanceLookup> CACHED_INHERITANCE_LOOKUP =
49+
new WeakHashMap<ContinuableClassInfoResolver, InheritanceLookup>();
3250

3351
}

net.tascalate.javaflow.providers.asm3/src/main/java/org/apache/commons/javaflow/providers/asm3/ContinuableClassVisitor.java

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.apache.commons.javaflow.spi.ContinuableClassInfoResolver;
2828
import org.apache.commons.javaflow.spi.StopException;
2929
import org.objectweb.asm.ClassAdapter;
30+
import org.objectweb.asm.ClassVisitor;
3031
import org.objectweb.asm.FieldVisitor;
3132
import org.objectweb.asm.MethodVisitor;
3233
import org.objectweb.asm.Opcodes;
@@ -38,16 +39,21 @@
3839
*/
3940
public class ContinuableClassVisitor extends ClassAdapter {
4041

41-
final private ContinuableClassInfoResolver cciResolver;
42-
final private byte[] originalBytes;
42+
private final InheritanceLookup inheritanceLookup;
43+
private final ContinuableClassInfoResolver cciResolver;
44+
private final byte[] originalBytes;
4345

4446
private String className;
4547
private ContinuableClassInfo classInfo;
4648
private boolean skipEnchancing = false;
4749
private boolean isInterface = false;
4850

49-
public ContinuableClassVisitor(ComputeClassWriter cv, ContinuableClassInfoResolver cciResolver, byte[] originalBytes) {
51+
public ContinuableClassVisitor(ClassVisitor cv,
52+
InheritanceLookup inheritanceLookup,
53+
ContinuableClassInfoResolver cciResolver,
54+
byte[] originalBytes) {
5055
super(cv);
56+
this.inheritanceLookup = inheritanceLookup;
5157
this.cciResolver = cciResolver;
5258
this.originalBytes = originalBytes;
5359
}
@@ -62,7 +68,9 @@ public void visit(int version, int access, String name, String signature, String
6268
className = name;
6369
classInfo = cciResolver.resolve(name, originalBytes);
6470

65-
if (null == classInfo || classInfo.isClassProcessed() || StopException.__dirtyCheckSkipContinuationsOnClass(version, access, name, signature, superName, interfaces)) {
71+
if (null == classInfo ||
72+
classInfo.isClassProcessed() ||
73+
StopException.__dirtyCheckSkipContinuationsOnClass(version, access, name, signature, superName, interfaces)) {
6674
skipEnchancing = true;
6775
// Must exit by throwing exception, otherwise NPE is possible in nested visitor
6876
throw StopException.INSTANCE;
@@ -95,14 +103,17 @@ public void visitEnd() {
95103
}
96104

97105
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
98-
final MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
99-
final boolean skip = skipEnchancing || null == classInfo || mv == null
106+
MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
107+
boolean skip = skipEnchancing || null == classInfo || mv == null
100108
|| (access & (Opcodes.ACC_ABSTRACT | Opcodes.ACC_NATIVE)) > 0 || "<init>".equals(name)
101109
|| !classInfo.isContinuableMethod(access, name, desc, signature);
102110
if (skip) {
103111
return mv;
104112
} else {
105-
return new ContinuableMethodNode(access, name, desc, signature, exceptions, className, (ComputeClassWriter)cv, cciResolver, mv);
113+
return new ContinuableMethodNode(
114+
access, name, desc, signature, exceptions,
115+
className, inheritanceLookup, cciResolver, mv
116+
);
106117
}
107118
}
108119
}

net.tascalate.javaflow.providers.asm3/src/main/java/org/apache/commons/javaflow/providers/asm3/ContinuableMethodNode.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
import org.objectweb.asm.tree.analysis.SourceValue;
5353

5454
public class ContinuableMethodNode extends MethodNode implements Opcodes {
55-
private final ComputeClassWriter verifierHelper;
55+
private final InheritanceLookup inheritanceLookup;
5656
private final ContinuableClassInfoResolver cciResolver;
5757
private final String className;
5858

@@ -67,12 +67,12 @@ public class ContinuableMethodNode extends MethodNode implements Opcodes {
6767

6868
public ContinuableMethodNode(int access, String name, String desc, String signature, String[] exceptions,
6969
String className,
70-
ComputeClassWriter verifierHelper,
70+
InheritanceLookup inheritanceLookup,
7171
ContinuableClassInfoResolver cciResolver,
7272
MethodVisitor mv) {
7373
super(access, name, desc, signature, exceptions);
7474
this.className = className;
75-
this.verifierHelper = verifierHelper;
75+
this.inheritanceLookup = inheritanceLookup;
7676
this.cciResolver = cciResolver;
7777
this.mv = mv;
7878
}
@@ -115,7 +115,7 @@ public void visitEnd() {
115115
try {
116116
moveNew();
117117

118-
analyzer = new Analyzer(new FastClassVerifier(verifierHelper)) {
118+
analyzer = new Analyzer(new FastClassVerifier(inheritanceLookup)) {
119119
@Override
120120
protected Frame newFrame(final int nLocals, final int nStack) {
121121
return new MonitoringFrame(nLocals, nStack);

net.tascalate.javaflow.providers.asm3/src/main/java/org/apache/commons/javaflow/providers/asm3/FastClassVerifier.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@
2929
import org.objectweb.asm.tree.analysis.Value;
3030

3131
public class FastClassVerifier extends SimpleVerifier {
32-
private ComputeClassWriter verifierHelper;
32+
private final InheritanceLookup inheritanceLookup;
3333

34-
public FastClassVerifier(ComputeClassWriter verifierHelper) {
35-
this.verifierHelper = verifierHelper;
34+
public FastClassVerifier(InheritanceLookup inheritanceLookup) {
35+
this.inheritanceLookup = inheritanceLookup;
3636
}
3737

3838
@Override
@@ -46,7 +46,6 @@ protected boolean isAssignableFrom(Type t, Type u) {
4646
}
4747
Type et, eu;
4848
if (t.getSort() == Type.ARRAY) {
49-
// u must be an array of bigger or equals dimension
5049
if (u.getSort() != Type.ARRAY ) {
5150
return false;
5251
}
@@ -55,6 +54,7 @@ protected boolean isAssignableFrom(Type t, Type u) {
5554
int dt = t.getDimensions();
5655
int du = u.getDimensions();
5756
boolean isObject = et.equals(((BasicValue)BasicValue.REFERENCE_VALUE).getType());
57+
// u must be an array of equals dimension or bigger dimension if t is Object
5858
if (dt == du || dt < du && isObject) {
5959
// Ok
6060
} else {
@@ -64,7 +64,7 @@ protected boolean isAssignableFrom(Type t, Type u) {
6464
et = t;
6565
eu = u;
6666
}
67-
Type commonType = verifierHelper.getCommonSuperType(et, eu);
67+
Type commonType = inheritanceLookup.getCommonSuperType(et, eu);
6868
return commonType.equals(et);
6969

7070
}
@@ -90,7 +90,7 @@ public Value merge(final Value v, final Value w) {
9090
if (isAssignableFrom(u, t)) {
9191
return w;
9292
}
93-
return new BasicValue(verifierHelper.getCommonSuperType(t, u));
93+
return new BasicValue(inheritanceLookup.getCommonSuperType(t, u));
9494
}
9595
}
9696
return BasicValue.UNINITIALIZED_VALUE;
@@ -99,17 +99,17 @@ public Value merge(final Value v, final Value w) {
9999
}
100100

101101
@Override
102-
protected Class<?> getClass(final Type t) {
102+
protected Class<?> getClass(Type t) {
103103
throw new UnsupportedOperationException();
104104
}
105105

106106
@Override
107-
protected boolean isInterface(final Type t) {
107+
protected boolean isInterface(Type t) {
108108
throw new UnsupportedOperationException();
109109
}
110110

111111
@Override
112-
protected Type getSuperClass(final Type t) {
112+
protected Type getSuperClass(Type t) {
113113
throw new UnsupportedOperationException();
114114
}
115115

0 commit comments

Comments
 (0)