On 28/04/2020 21:44, Maurizio Cimadamore wrote:
On 28/04/2020 19:09, Mandy Chung wrote:
On 4/28/20 12:58 AM, fo...@univ-mlv.fr wrote:
I don't think you need to store all the values into static
fields, you can directly do a ldc + aaload with the right index
right where you need it,
I think this is what you are thinking as reported in JDK-8243492:
http://cr.openjdk.java.net/~mchung/jdk15/webrevs/8239578/webrev.01-accessor/
if the accessors are declared ACC_STATIC, yes !
Thanks for catching this and this way will not be hit JDK-824349.
Here is the revised patch:
http://cr.openjdk.java.net/~mchung/jdk15/webrevs/8239578/webrev.02/
Maurizio - do you mind remerge MemoryAccessVarHandleGenerator.java
with webrev.02?
I'll take care of that
Not going down this road, sorry :-)
I've added the changes (see attached patch), and all benchmarks are
several order of magnitude slower. I think this is mostly caused by the
fact that the addOffset/multiplyOffset handle are no longer cached in
static constants.
While I understand that there might be better ways to generate the code,
I'd strongly prefer to leave the code as per last iteration. I can't
honestly see in which way having 3-4 static fields in a synthetic
VarHandle class is going to hurt (but I can see how much it hurts by not
having said fields).
Cheers
Maurizio
Maurizio
thanks
Mandy
diff -r 148c3b3445c6 src/java.base/share/classes/java/lang/invoke/MemoryAccessVarHandleGenerator.java
--- a/src/java.base/share/classes/java/lang/invoke/MemoryAccessVarHandleGenerator.java Mon Apr 27 13:01:54 2020 +0100
+++ b/src/java.base/share/classes/java/lang/invoke/MemoryAccessVarHandleGenerator.java Wed Apr 29 02:09:58 2020 +0100
@@ -54,11 +54,9 @@
import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SUPER;
import static jdk.internal.org.objectweb.asm.Opcodes.ALOAD;
import static jdk.internal.org.objectweb.asm.Opcodes.ARETURN;
-import static jdk.internal.org.objectweb.asm.Opcodes.ASTORE;
import static jdk.internal.org.objectweb.asm.Opcodes.BIPUSH;
import static jdk.internal.org.objectweb.asm.Opcodes.CHECKCAST;
import static jdk.internal.org.objectweb.asm.Opcodes.GETFIELD;
-import static jdk.internal.org.objectweb.asm.Opcodes.GETSTATIC;
import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKESTATIC;
import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_0;
import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_1;
@@ -73,7 +71,6 @@
import static jdk.internal.org.objectweb.asm.Opcodes.LLOAD;
import static jdk.internal.org.objectweb.asm.Opcodes.NEWARRAY;
import static jdk.internal.org.objectweb.asm.Opcodes.PUTFIELD;
-import static jdk.internal.org.objectweb.asm.Opcodes.PUTSTATIC;
import static jdk.internal.org.objectweb.asm.Opcodes.RETURN;
import static jdk.internal.org.objectweb.asm.Opcodes.DUP;
import static jdk.internal.org.objectweb.asm.Opcodes.SIPUSH;
@@ -192,7 +189,7 @@
cw.visitField(ACC_PRIVATE | ACC_FINAL, "dim" + i, "J", null, null);
}
- addStaticInitializer(cw);
+ addClassDataAccessors(cw);
addConstructor(cw);
@@ -210,44 +207,58 @@
return cw.toByteArray();
}
- void addStaticInitializer(ClassWriter cw) {
- // carrier and intermediate
- cw.visitField(ACC_PRIVATE | ACC_STATIC | ACC_FINAL, "carrier", Class.class.descriptorString(), null, null);
- cw.visitField(ACC_PRIVATE | ACC_STATIC | ACC_FINAL, "intermediate", Class[].class.descriptorString(), null, null);
- cw.visitField(ACC_PRIVATE | ACC_STATIC | ACC_FINAL, "addHandle", MethodHandle.class.descriptorString(), null, null);
- cw.visitField(ACC_PRIVATE | ACC_STATIC | ACC_FINAL, "mulHandle", MethodHandle.class.descriptorString(), null, null);
-
- MethodVisitor mv = cw.visitMethod(Opcodes.ACC_STATIC, "<clinit>", "()V", null, null);
- mv.visitCode();
- // extract class data in static final fields
+ void addClassDataAccessors(ClassWriter cw) {
+ // BSM to load class data
MethodType mtype = MethodType.methodType(Object.class, MethodHandles.Lookup.class, String.class, Class.class);
Handle bsm = new Handle(H_INVOKESTATIC, Type.getInternalName(MethodHandles.class), "classData",
- mtype.descriptorString(), false);
+ mtype.descriptorString(), false);
ConstantDynamic dynamic = new ConstantDynamic("classData", Object[].class.descriptorString(), bsm);
+
+ // static method to get carrierType
+ MethodVisitor mv = cw.visitMethod(ACC_FINAL | ACC_STATIC, "carrierType",
+ MethodType.methodType(Class.class).descriptorString(), null, null);
+ mv.visitCode();
mv.visitLdcInsn(dynamic);
- mv.visitTypeInsn(CHECKCAST, Type.getInternalName(Object[].class));
- mv.visitVarInsn(ASTORE, 0);
- mv.visitVarInsn(ALOAD, 0);
mv.visitInsn(ICONST_0);
mv.visitInsn(AALOAD);
mv.visitTypeInsn(CHECKCAST, Type.getInternalName(Class.class));
- mv.visitFieldInsn(PUTSTATIC, implClassName, "carrier", Class.class.descriptorString());
- mv.visitVarInsn(ALOAD, 0);
+ mv.visitInsn(ARETURN);
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+
+ // static method to get the types of "intermediate" parameter
+ mv = cw.visitMethod(ACC_FINAL | ACC_STATIC, "intermediateTypes",
+ MethodType.methodType(Class[].class).descriptorString(), null, null);
+ mv.visitCode();
+ mv.visitLdcInsn(dynamic);
mv.visitInsn(ICONST_1);
mv.visitInsn(AALOAD);
mv.visitTypeInsn(CHECKCAST, Type.getInternalName(Class[].class));
- mv.visitFieldInsn(PUTSTATIC, implClassName, "intermediate", Class[].class.descriptorString());
- mv.visitVarInsn(ALOAD, 0);
+ mv.visitInsn(ARETURN);
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+
+ // static method to get the MemoruAddressProxy::addOffsets handle
+ mv = cw.visitMethod(ACC_FINAL | ACC_STATIC, "addHandle",
+ MethodType.methodType(MethodHandle.class).descriptorString(), null, null);
+ mv.visitCode();
+ mv.visitLdcInsn(dynamic);
mv.visitInsn(ICONST_2);
mv.visitInsn(AALOAD);
mv.visitTypeInsn(CHECKCAST, Type.getInternalName(MethodHandle.class));
- mv.visitFieldInsn(PUTSTATIC, implClassName, "addHandle", MethodHandle.class.descriptorString());
- mv.visitVarInsn(ALOAD, 0);
+ mv.visitInsn(ARETURN);
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+
+ // static method to get the MemoruAddressProxy::multiplyOffsets handle
+ mv = cw.visitMethod(ACC_FINAL | ACC_STATIC, "mulHandle",
+ MethodType.methodType(MethodHandle.class).descriptorString(), null, null);
+ mv.visitCode();
+ mv.visitLdcInsn(dynamic);
mv.visitInsn(ICONST_3);
mv.visitInsn(AALOAD);
mv.visitTypeInsn(CHECKCAST, Type.getInternalName(MethodHandle.class));
- mv.visitFieldInsn(PUTSTATIC, implClassName, "mulHandle", MethodHandle.class.descriptorString());
- mv.visitInsn(Opcodes.RETURN);
+ mv.visitInsn(ARETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
@@ -287,8 +298,10 @@
mv.visitFieldInsn(GETFIELD, Type.getInternalName(VarHandle.AccessMode.class), "at", VarHandle.AccessType.class.descriptorString());
mv.visitLdcInsn(Type.getType(MemoryAddressProxy.class));
mv.visitTypeInsn(CHECKCAST, Type.getInternalName(Class.class));
- mv.visitFieldInsn(GETSTATIC, implClassName, "carrier", Class.class.descriptorString());
- mv.visitFieldInsn(GETSTATIC, implClassName, "intermediate", Class[].class.descriptorString());
+ mv.visitMethodInsn(INVOKESTATIC, implClassName, "carrierType",
+ MethodType.methodType(Class.class).descriptorString(), false);
+ mv.visitMethodInsn(INVOKESTATIC, implClassName, "intermediateTypes",
+ MethodType.methodType(Class[].class).descriptorString(), false);
mv.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(VarHandle.AccessType.class),
"accessModeType", MethodType.methodType(MethodType.class, Class.class, Class.class, Class[].class).toMethodDescriptorString(), false);
@@ -331,15 +344,16 @@
mv.visitFieldInsn(GETFIELD, Type.getInternalName(BASE_CLASS), "offset", "J");
for (int i = 0 ; i < dimensions ; i++) {
// load ADD MH
- mv.visitFieldInsn(GETSTATIC, implClassName, "addHandle", MethodHandle.class.descriptorString());
+ mv.visitMethodInsn(INVOKESTATIC, implClassName, "addHandle",
+ MethodType.methodType(MethodHandle.class).descriptorString(), false);
//fixup stack so that ADD MH ends up bottom
mv.visitInsn(Opcodes.DUP_X2);
mv.visitInsn(Opcodes.POP);
// load MUL MH
- mv.visitFieldInsn(GETSTATIC, implClassName, "mulHandle", MethodHandle.class.descriptorString());
- mv.visitTypeInsn(CHECKCAST, Type.getInternalName(MethodHandle.class));
+ mv.visitMethodInsn(INVOKESTATIC, implClassName, "mulHandle",
+ MethodType.methodType(MethodHandle.class).descriptorString(), false);
mv.visitVarInsn(ALOAD, 0); // load recv
mv.visitTypeInsn(CHECKCAST, implClassName);
@@ -403,7 +417,8 @@
void addCarrierAccessor(ClassWriter cw) {
MethodVisitor mv = cw.visitMethod(ACC_FINAL, "carrier", "()Ljava/lang/Class;", null, null);
mv.visitCode();
- mv.visitFieldInsn(GETSTATIC, implClassName, "carrier", Class.class.descriptorString());
+ mv.visitMethodInsn(INVOKESTATIC, implClassName, "carrierType",
+ MethodType.methodType(Class.class).descriptorString(), false);
mv.visitInsn(ARETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();