Skip to content

Commit

Permalink
LDEV-5185 - add again caching for function members
Browse files Browse the repository at this point in the history
  • Loading branch information
michaeloffner committed Dec 9, 2024
1 parent 60b01ac commit c09b1d3
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 150 deletions.
35 changes: 23 additions & 12 deletions core/src/main/java/lucee/transformer/dynamic/DynamicInvoker.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
Expand All @@ -30,6 +31,7 @@
import org.objectweb.asm.Type;

import lucee.aprint;
import lucee.print;
import lucee.commons.digest.HashUtil;
import lucee.commons.io.SystemUtil;
import lucee.commons.io.log.Log;
Expand Down Expand Up @@ -253,6 +255,8 @@ public Pair<FunctionMember, Object> createInstance(Class<?> clazz, Key methodNam
mv.visitVarInsn(Opcodes.ALOAD, 1); // Load the first method argument (instance)
if (!fm.getDeclaringProviderClassWithSameAccess().equals(Object.class)) { // Only cast if clazz is not java.lang.Object
mv.visitTypeInsn(Opcodes.CHECKCAST, Type.getInternalName(fm.getDeclaringProviderClassWithSameAccess()));
print.e("-->" + fm.getDeclaringProviderClassNameWithSameAccess());
print.e("-->" + fm.getDeclaringProviderClassName());
}
}
}
Expand Down Expand Up @@ -285,6 +289,7 @@ public Pair<FunctionMember, Object> createInstance(Class<?> clazz, Key methodNam
if (argType.isPrimitive()) {
Type type = Type.getType(argType);
Class<?> wrapperType = Reflector.toReferenceClass(argType);

mv.visitTypeInsn(Opcodes.CHECKCAST, Type.getInternalName(wrapperType)); // Cast to wrapper type
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(wrapperType), ASMUtil.getClassName(type) + "Value", "()" + ASMUtil.getDescriptor(type),
false); // Unbox
Expand Down Expand Up @@ -431,6 +436,12 @@ public static void main(String[] args) throws Exception {
ResourceUtil.deleteContent(classes, null);
DynamicInvoker e = new DynamicInvoker(classes);

HashMap map = new HashMap<>();
map.put("aaa", "sss");
Iterator it = map.keySet().iterator();
// aprint.e(e.invokeInstanceMethod(it, "next", new Object[] {}, false));
aprint.e(e.invokeInstanceMethod(it, "hasNext", new Object[] {}, false));

if (false) {
FileInputStream fis = new java.io.FileInputStream("/Users/mic/Tmp3/test.prop");
InputStreamReader fir = new java.io.InputStreamReader(fis, "UTF-8");
Expand Down Expand Up @@ -466,7 +477,7 @@ public static void main(String[] args) throws Exception {

}

if (true) return;
// if (true) return;

StringBuilder sb = new StringBuilder("Susi");
Test t = new Test();
Expand Down Expand Up @@ -508,7 +519,7 @@ public static void main(String[] args) throws Exception {
// instance (double->int):String
{
Object reflection = t.test(134);
Object dynamic = e.invokeInstanceMethod(t, "test", new Object[] { 134D }, false);
Object dynamic = e.invokeInstanceMethod(t, "test", new Object[] { 134D }, true);
if (!reflection.equals(dynamic)) {
aprint.e("direct:");
aprint.e(reflection);
Expand All @@ -520,7 +531,7 @@ public static void main(String[] args) throws Exception {
// instance (double->int):String
{
Object reflection = t.test(134);
Object dynamic = e.invokeInstanceMethod(t, "test", new Object[] { 134D }, false);
Object dynamic = e.invokeInstanceMethod(t, "test", new Object[] { 134D }, true);
if (!reflection.equals(dynamic)) {
aprint.e("direct:");
aprint.e(reflection);
Expand All @@ -530,23 +541,23 @@ public static void main(String[] args) throws Exception {
}

aprint.e(t.complete("", 1, null));
aprint.e(e.invokeInstanceMethod(t, "complete", new Object[] { "", i, null }, false));
aprint.e(e.invokeInstanceMethod(t, "complete", new Object[] { "", bd, null }, false));
aprint.e(e.invokeInstanceMethod(t, "complete", new Object[] { "", i, null }, true));
aprint.e(e.invokeInstanceMethod(t, "complete", new Object[] { "", bd, null }, true));

aprint.e(t.testb(true, true));
aprint.e(e.invokeInstanceMethod(t, "testb", new Object[] { null, true }, false));
aprint.e(e.invokeInstanceMethod(t, "testb", new Object[] { null, true }, true));

aprint.e(t.testStr(1, "string", 1L));
aprint.e(e.invokeInstanceMethod(t, "testStr", new Object[] { "1", 1, Double.valueOf(1D) }, false));
aprint.e(e.invokeInstanceMethod(t, "testStr", new Object[] { "1", 1, Double.valueOf(1D) }, true));

aprint.e(e.invokeInstanceMethod(t, "test", new Object[] { "1" }, false));
aprint.e(e.invokeInstanceMethod(t, "test", new Object[] { 1D }, false));
aprint.e(e.invokeInstanceMethod(t, "test", new Object[] { "1" }, true));
aprint.e(e.invokeInstanceMethod(t, "test", new Object[] { 1D }, true));

aprint.e(e.invokeInstanceMethod(new SystemOut(), "setOut", new Object[] { null }, false));
aprint.e(e.invokeInstanceMethod(new SystemOut(), "setOut", new Object[] { null }, true));
System.setProperty("a.b.c", "- value -");
aprint.e(e.invokeInstanceMethod(sb, "toSTring", new Object[] {}, false));
aprint.e(e.invokeStaticMethod(SystemUtil.class, "getSystemPropOrEnvVar", new Object[] { "a.b.c", "default-value" }, false));
aprint.e(e.invokeStaticMethod(ListUtil.class, "arrayToList", new Object[] { new String[] { "a", "b" }, "," }, false));
aprint.e(e.invokeStaticMethod(SystemUtil.class, "getSystemPropOrEnvVar", new Object[] { "a.b.c", "default-value" }, true));
aprint.e(e.invokeStaticMethod(ListUtil.class, "arrayToList", new Object[] { new String[] { "a", "b" }, "," }, true));

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@

import lucee.commons.digest.HashUtil;
import lucee.commons.io.IOUtil;
import lucee.commons.io.SystemUtil;
import lucee.commons.io.log.Log;
import lucee.commons.io.res.Resource;
import lucee.commons.lang.ExceptionUtil;
Expand Down Expand Up @@ -187,10 +186,8 @@ public static String generateClassLoderId(Class<?> clazz) {
private ClazzDynamic(Class clazz, String clid, Log log) throws IOException {
this.clazz = clazz;
this.clid = clid;
LinkedHashMap<String, FunctionMember> members = new LinkedHashMap<>();
_getFunctionMembers(clazz, members, log);
// _getFunctionMembers(final Class clazz, Map<String, FunctionMember> members, Log log) throws
// IOException {
Map<String, FunctionMember> members = _getFunctionMembers(clazz, null, log);

LinkedList<FunctionMember> tmpMethods = new LinkedList<>();
LinkedList<FunctionMember> tmpDeclaredMethods = new LinkedList<>();
LinkedList<FunctionMember> tmpConstructors = new LinkedList<>();
Expand Down Expand Up @@ -366,7 +363,19 @@ public List<Constructor> getDeclaredConstructors(int argumentLength) throws IOEx
return list;
}

private static void _getFunctionMembers(final Class clazz, Map<String, FunctionMember> members, Log log) throws IOException {
private static Map<String, FunctionMember> _getFunctionMembers(final Class clazz, Map<String, FunctionMember> membersInput, Log log) throws IOException {

if (membersInput == null) membersInput = new LinkedHashMap<>();
final Map<String, FunctionMember> members = membersInput;

Map<String, FunctionMember> existing = membersCollection.get(clazz);
if (existing != null) {
for (Entry<String, FunctionMember> e: existing.entrySet()) {
members.put(e.getKey(), e.getValue());
}
return members;

}

final String classPath = clazz.getName().replace('.', '/') + ".class";
final ClassLoader cl = getClassLoader(clazz);
Expand Down Expand Up @@ -458,9 +467,8 @@ public MethodVisitor visitMethod(int access, String name, String descriptor, Str
Type tmpType = tmpClass != null ? Type.getType(tmpClass) : null;
Type rtnType = rtnClass != null ? Type.getType(rtnClass) : null;

if (Clazz.compareAccess(fmParent, fmCurrent) >= 0)
((FunctionMemberDynamic) fmCurrent).setDeclaringProviderClassWithSameAccess(tmpClass, tmpType, rtnClass, rtnType);
((FunctionMemberDynamic) fmCurrent).setDeclaringProviderClass(tmpClass, tmpType, rtnClass, rtnType);
if (Clazz.compareAccess(fmParent, fmCurrent) >= 0) fmCurrent.setDeclaringProviderClassWithSameAccess(tmpClass, tmpType, rtnClass, rtnType);
fmCurrent.setDeclaringProviderClass(tmpClass, tmpType, rtnClass, rtnType);

/*
* if (name.equals("nextElement")) { print.e(fm.getDeclaringProviderClassName());
Expand All @@ -475,139 +483,20 @@ public MethodVisitor visitMethod(int access, String name, String descriptor, Str
};
// Start visiting the class
classReader.accept(visitor, 0);
}

private static Map<Class, LinkedHashMap<String, FunctionMember>> membersCollection = new IdentityHashMap<>();

private static LinkedHashMap<String, FunctionMember> _getFunctionMembersOld(final Class clazz, Log log) throws IOException {

LinkedHashMap<String, FunctionMember> members = membersCollection.get(clazz);
if (members == null) {
synchronized (SystemUtil.createToken("ClazzDynamic", clazz.getName())) {
members = membersCollection.get(clazz);
if (members == null) {
LinkedHashMap<String, FunctionMember> tmpMembers = new LinkedHashMap<>();
// Map<String, FunctionMember> members,
final String classPath = clazz.getName().replace('.', '/') + ".class";
final ClassLoader cl = getClassLoader(clazz);
final RefInteger classAccess = new RefIntegerImpl();
ClassReader classReader;
try {
// print.e("new:" + clazz);
classReader = new ClassReader(cl.getResourceAsStream(classPath));
}
catch (IOException ioe) {
if ("Class not found".equals(ioe.getMessage())) {
IOException tmp = new IOException("unable to load class path [" + classPath + "]");
ExceptionUtil.initCauseEL(tmp, ioe);
ioe = tmp;
}
throw ioe;
}

// Create a ClassVisitor to visit the methods
ClassVisitor visitor = new ClassVisitor(Opcodes.ASM9) {

@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
classAccess.setValue(access);
if (interfaces != null && interfaces.length > 0) {
for (String interf: interfaces) {
try {
add(tmpMembers, _getFunctionMembersOld(cl.loadClass(ASMUtil.getClassName(Type.getObjectType(interf))), log));
}
catch (Exception e) {
if (log != null) log.error("dynamic", e);
}
}
}
if (superName != null) {
try {
add(tmpMembers, _getFunctionMembersOld(cl.loadClass(ASMUtil.getClassName(Type.getObjectType(superName))), log));
}
catch (IllegalArgumentException iae) {
String v = ASMUtil.getJavaVersionFromException(iae, null);
if (v != null) {
throw new RuntimeException("The class [" + superName + "] was compiled with Java version [" + v + "], "
+ "which is not supported by the current version of ASM. The highest supported version is ["
+ ASMUtil.toStringVersionFromBytceodeVersion(ASMUtil.getMaxVersion(), "unknown") + "]. ");

}
throw iae;
}
catch (RuntimeException re) {
throw re;
}
catch (Exception e) {
if (log != null) log.error("dynamic", e);
}
}

super.visit(version, access, name, signature, superName, interfaces);
}

@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
FunctionMember fmCurrent = FunctionMemberDynamic.createInstance(clazz, name, access, descriptor, exceptions, classAccess.toInt());
String id = Clazz.id(fmCurrent);
FunctionMember parent = tmpMembers.get(id);
if (parent instanceof FunctionMemberDynamic) {
FunctionMemberDynamic fmParent = (FunctionMemberDynamic) parent;
// java.lang.Appendable

Class tmpClass = fmParent.getDeclaringProviderClass(true);
if (tmpClass != null) {
Class rtnClass = null;
if (fmParent instanceof Method) {

Class tmpRtn = fmParent.getDeclaringProviderRtnClass(true);
rtnClass = tmpRtn;
}

/*
* if (name.equals("toLocalDateTime")) { print.e("xxxxxxxxxxxxxxx"); print.e(clazz + ":" + name +
* ":" + descriptor); // print.e(Clazz.getAccessModifier(fmCurrent)); //
* print.e(Clazz.getAccessModifier(fmParent)); print.e("curr: " +
* Clazz.getAccessModifierAsString(fmCurrent)); print.e("parr: " +
* Clazz.getAccessModifierAsString(fmParent)); print.e("DeclaringClassName: " +
* fmCurrent.getDeclaringClassName()); print.e("getDeclaringProviderClassName: " +
* fmCurrent.getDeclaringProviderClassNameWithSameAccess()); // print.e("-----------------" +
* Clazz.compareAccess(fmd, fm)); }
*/

Type tmpType = tmpClass != null ? Type.getType(tmpClass) : null;
Type rtnType = rtnClass != null ? Type.getType(rtnClass) : null;

if (Clazz.compareAccess(fmParent, fmCurrent) >= 0)
((FunctionMemberDynamic) fmCurrent).setDeclaringProviderClassWithSameAccess(tmpClass, tmpType, rtnClass, rtnType);
((FunctionMemberDynamic) fmCurrent).setDeclaringProviderClass(tmpClass, tmpType, rtnClass, rtnType);

/*
* if (name.equals("nextElement")) { print.e(fm.getDeclaringProviderClassName());
* print.e(fm.getDeclaringProviderClassNameWithSameAccess()); }
*/
}
}
tmpMembers.put(id, fmCurrent);

return super.visitMethod(access, name, descriptor, signature, exceptions);
}
};
// Start visiting the class
classReader.accept(visitor, 0);
membersCollection.put(clazz, members = tmpMembers);
}
}
}
membersCollection.put(clazz, cloneIt(members));
return members;
}

private static void add(LinkedHashMap<String, FunctionMember> members, LinkedHashMap<String, FunctionMember> rtn) {
for (Entry<String, FunctionMember> e: rtn.entrySet()) {
members.put(e.getKey(), e.getValue());
private static Map<String, FunctionMember> cloneIt(Map<String, FunctionMember> members) {
Map<String, FunctionMember> cloned = new LinkedHashMap<>();
for (Entry<String, FunctionMember> e: members.entrySet()) {
cloned.put(e.getKey(), e.getValue());
}
return cloned;
}

private static Map<Class, Map<String, FunctionMember>> membersCollection = new IdentityHashMap<>();

public static void serialize(Serializable o, OutputStream os) throws IOException {
ObjectOutputStream oos = null;
try {
Expand Down
2 changes: 1 addition & 1 deletion loader/build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<project default="core" basedir="." name="Lucee"
xmlns:resolver="antlib:org.apache.maven.resolver.ant">

<property name="version" value="6.2.0.190-SNAPSHOT"/>
<property name="version" value="6.2.0.191-SNAPSHOT"/>

<taskdef uri="antlib:org.apache.maven.resolver.ant" resource="org/apache/maven/resolver/ant/antlib.xml">
<classpath>
Expand Down
2 changes: 1 addition & 1 deletion loader/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

<groupId>org.lucee</groupId>
<artifactId>lucee</artifactId>
<version>6.2.0.190-SNAPSHOT</version>
<version>6.2.0.191-SNAPSHOT</version>
<packaging>jar</packaging>

<name>Lucee Loader Build</name>
Expand Down

0 comments on commit c09b1d3

Please sign in to comment.