This is an automated email from the ASF dual-hosted git repository.

struberg pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/openjpa.git

commit 5d63179b480a152b4e56d21c7f059b0c1727fa55
Author: Mark Struberg <strub...@apache.org>
AuthorDate: Sun Jun 25 22:17:34 2023 +0200

    OPENJPA-2911 addCopyKeyFieldsFromObjectIdMethod in ASM
---
 .../org/apache/openjpa/enhance/PCEnhancer.java     | 292 ++++++++++++---------
 1 file changed, 174 insertions(+), 118 deletions(-)

diff --git 
a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java 
b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java
index 7dafa3697..e660b6419 100644
--- a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java
+++ b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java
@@ -1386,21 +1386,20 @@ public class PCEnhancer {
 
             addCopyKeyFieldsToObjectIdMethod(true);
             addCopyKeyFieldsToObjectIdMethod(false);
-
-            AsmHelper.readIntoBCClass(pc, _pc);
-
             addCopyKeyFieldsFromObjectIdMethod(true);
             addCopyKeyFieldsFromObjectIdMethod(false);
+
+
             if (_meta.hasAbstractPKField()) {
-                pc = AsmHelper.toClassNode(_pc);
                 addGetIDOwningClass();
-                AsmHelper.readIntoBCClass(pc, _pc);
             }
 
             if (_meta.isEmbeddable() && _meta.getIdentityType() == 
ClassMetaData.ID_APPLICATION) {
                 _log.warn(_loc.get("ID-field-in-embeddable-unsupported", 
_meta.toString()));
             }
 
+            AsmHelper.readIntoBCClass(pc, _pc);
+
             addNewObjectIdInstanceMethod(true);
             addNewObjectIdInstanceMethod(false);
         }
@@ -2250,8 +2249,8 @@ public class PCEnhancer {
      * Adds the <code>pcCopyKeyFieldsToObjectId</code> methods
      * to classes using application identity.
      */
-    private void addCopyKeyFieldsToObjectIdMethod(boolean fieldManager)
-            throws NoSuchMethodException {
+    private void addCopyKeyFieldsToObjectIdMethod(boolean fieldManager) throws 
NoSuchMethodException {
+
         // public void pcCopyKeyFieldsToObjectId (ObjectIdFieldSupplier fs, 
Object oid)
         String mDesc = fieldManager
                 ? Type.getMethodDescriptor(Type.VOID_TYPE, 
Type.getType(OIDFSTYPE), TYPE_OBJECT)
@@ -2292,6 +2291,7 @@ public class PCEnhancer {
         }
 
         if (_meta.isObjectIdTypeShared()) {
+            // oid = ((ObjectId) id).getId ();
             instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, 
Type.getInternalName(ObjectId.class)));
             instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
                                                 
Type.getInternalName(ObjectId.class),
@@ -3087,177 +3087,233 @@ public class PCEnhancer {
      * Adds the <code>pcCopyKeyFieldsFromObjectId</code> methods
      * to classes using application identity.
      */
-    private void addCopyKeyFieldsFromObjectIdMethod(boolean fieldManager)
-            throws NoSuchMethodException {
-        // public void pcCopyKeyFieldsFromObjectId (ObjectIdFieldConsumer fc,
-        //    Object oid)
-        String[] args = (fieldManager)
-                ? new String[]{OIDFCTYPE.getName(), Object.class.getName()}
-                : new String[]{Object.class.getName()};
-        BCMethod method = _pc.declareMethod(PRE + "CopyKeyFieldsFromObjectId",
-                                            void.class.getName(), args);
-        Code code = method.getCode(true);
+    private void addCopyKeyFieldsFromObjectIdMethod(boolean fieldManager) 
throws NoSuchMethodException {
+        // public void pcCopyKeyFieldsFromObjectId (ObjectIdFieldConsumer fc, 
Object oid)
+        String mDesc = fieldManager
+                ? Type.getMethodDescriptor(Type.VOID_TYPE, 
Type.getType(OIDFCTYPE), TYPE_OBJECT)
+                : Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_OBJECT);
+        MethodNode copyKFMeth = new MethodNode(Opcodes.ACC_PUBLIC,
+                                               PRE + 
"CopyKeyFieldsFromObjectId",
+                                               mDesc,
+                                               null, null);
+        final ClassNode classNode = pc.getClassNode();
+        classNode.methods.add(copyKFMeth);
+        InsnList instructions = copyKFMeth.instructions;
+
 
         // call superclass method
         if (_meta.getPCSuperclass() != null && !getCreateSubclass()) {
-            loadManagedInstance(code, false);
-            for (int i = 0; i < args.length; i++)
-                code.aload().setParam(i);
-            code.invokespecial().setMethod(getType(_meta.
-                                                           
getPCSuperclassMetaData()).getName(),
-                                           PRE + "CopyKeyFieldsFromObjectId", 
void.class.getName(), args);
+            instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
+            instructions.add(new VarInsnNode(Opcodes.ALOAD, 1)); // 1st 
parameter object
+            if (fieldManager) {
+                instructions.add(new VarInsnNode(Opcodes.ALOAD, 2)); // 2nd 
parameter object
+            }
+            instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL,
+                                                
Type.getInternalName(getType(_meta.getPCSuperclassMetaData())),
+                                                PRE + 
"CopyKeyFieldsFromObjectId",
+                                                mDesc));
         }
 
-        if (fieldManager)
-            code.aload().setParam(1);
-        else
-            code.aload().setParam(0);
+        // Object id = oid;
+        if (fieldManager) {
+            instructions.add(new VarInsnNode(Opcodes.ALOAD, 2)); // 2nd 
parameter object
+        }
+        else {
+            instructions.add(new VarInsnNode(Opcodes.ALOAD, 1)); // 1st 
parameter object
+        }
 
         if (!_meta.isOpenJPAIdentity() && _meta.isObjectIdTypeShared()) {
             // oid = ((ObjectId) id).getId ();
-            code.checkcast().setType(ObjectId.class);
-            code.invokevirtual().setMethod(ObjectId.class, "getId",
-                                           Object.class, null);
+            instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, 
Type.getInternalName(ObjectId.class)));
+            instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
+                                                
Type.getInternalName(ObjectId.class),
+                                                "getId",
+                                                
Type.getMethodDescriptor(TYPE_OBJECT)));
         }
 
-        // <oid type> cast = (<oid type>) oid;
-        int id = code.getNextLocalsIndex();
+        // <oid type> id = (<oid type>) oid;
+        int nextFreeVarPos = (fieldManager) ? 3 : 2;
+        int idVarPos = nextFreeVarPos++;
+
         Class oidType = _meta.getObjectIdType();
-        code.checkcast().setType(oidType);
-        code.astore().setLocal(id);
+        instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, 
Type.getInternalName(oidType)));
+        instructions.add(new VarInsnNode(Opcodes.ASTORE, idVarPos));
 
         // fs.store<type>Field (<index>, id.<field>); or...
         // this.<field> = id.<field>
         // or for single field identity: id.getId ()
         FieldMetaData[] fmds = getCreateSubclass() ? _meta.getFields()
                 : _meta.getDeclaredFields();
-        String name;
-        Class type;
-        Class unwrapped;
-        Field field;
-        Method getter;
         for (int i = 0; i < fmds.length; i++) {
-            if (!fmds[i].isPrimaryKey())
+            if (!fmds[i].isPrimaryKey()) {
                 continue;
+            }
 
-            name = fmds[i].getName();
-            type = fmds[i].getObjectIdFieldType();
-            if (!fieldManager
-                    && fmds[i].getDeclaredTypeCode() == JavaTypes.PC) {
+            String name = fmds[i].getName();
+            Class<?> type = fmds[i].getObjectIdFieldType();
+
+            if (!fieldManager && fmds[i].getDeclaredTypeCode() == 
JavaTypes.PC) {
                 // if (sm == null) return;
-                loadManagedInstance(code, false);
-                code.getfield().setField(SM, SMTYPE);
-                JumpInstruction ifins = code.ifnonnull();
-                code.vreturn();
+                instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
+                instructions.add(new FieldInsnNode(Opcodes.GETFIELD, 
classNode.name, SM, Type.getDescriptor(SMTYPE)));
+
+                LabelNode lblEndIfNotNull = new LabelNode();
+                instructions.add(new JumpInsnNode(Opcodes.IFNONNULL, 
lblEndIfNotNull));
+                instructions.add(new InsnNode(Opcodes.RETURN));
+
+                instructions.add(lblEndIfNotNull);
+
                 // sm.getPCPrimaryKey(oid, i + pcInheritedFieldCount);
-                ifins.setTarget(loadManagedInstance(code, false));
-                code.dup(); // leave orig on stack to set value into
-                code.getfield().setField(SM, SMTYPE);
-                code.aload().setLocal(id);
-                code.constant().setValue(i);
-                code.getstatic().setField(INHERIT, int.class);
-                code.iadd();
-                code.invokeinterface().setMethod(StateManager.class,
-                                                 "getPCPrimaryKey", 
Object.class,
-                                                 new Class[]{Object.class, 
int.class});
-                code.checkcast().setType(fmds[i].getDeclaredType());
+                instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
+                instructions.add(new InsnNode(Opcodes.DUP)); // leave orig on 
stack to set value into
+                instructions.add(new FieldInsnNode(Opcodes.GETFIELD, 
classNode.name, SM, Type.getDescriptor(SMTYPE)));
+                instructions.add(new VarInsnNode(Opcodes.ALOAD, idVarPos));
+                instructions.add(AsmHelper.getLoadConstantInsn(i));
+                instructions.add(new FieldInsnNode(Opcodes.GETSTATIC, 
classNode.name, INHERIT, Type.INT_TYPE.getDescriptor()));
+                instructions.add(new InsnNode(Opcodes.IADD));
+                instructions.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE,
+                                                    
Type.getInternalName(SMTYPE),
+                                                    "getPCPrimaryKey",
+                                                    
Type.getMethodDescriptor(TYPE_OBJECT, TYPE_OBJECT, Type.INT_TYPE)));
+                instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, 
Type.getInternalName(fmds[i].getDeclaredType())));
             }
             else {
-                unwrapped = (fmds[i].getDeclaredTypeCode() == JavaTypes.PC)
-                        ? type : unwrapSingleFieldIdentity(fmds[i]);
+                Class<?> unwrapped = (fmds[i].getDeclaredTypeCode() == 
JavaTypes.PC) ? type : unwrapSingleFieldIdentity(fmds[i]);
                 if (fieldManager) {
-                    code.aload().setParam(0);
-                    code.constant().setValue(i);
-                    code.getstatic().setField(INHERIT, int.class);
-                    code.iadd();
+                    instructions.add(new VarInsnNode(Opcodes.ALOAD, 1)); // 
1st param
+                    instructions.add(AsmHelper.getLoadConstantInsn(i));
+                    instructions.add(new FieldInsnNode(Opcodes.GETSTATIC, 
classNode.name, INHERIT, Type.INT_TYPE.getDescriptor()));
+                    instructions.add(new InsnNode(Opcodes.IADD));
+                }
+                else {
+                    instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // 
this
                 }
-                else
-                    loadManagedInstance(code, false);
 
                 if (unwrapped != type) {
-                    code.anew().setType(type);
-                    code.dup();
+                    instructions.add(new TypeInsnNode(Opcodes.NEW, 
Type.getInternalName(type)));
+                    instructions.add(new InsnNode(Opcodes.DUP));
                 }
-                code.aload().setLocal(id);
+
+                instructions.add(new VarInsnNode(Opcodes.ALOAD, idVarPos));
                 if (_meta.isOpenJPAIdentity()) {
                     if (oidType == ObjectId.class) {
-                        code.invokevirtual().setMethod(oidType, "getId",
-                                                       Object.class, null);
-                        if (!fieldManager && type != Object.class)
-                            
code.checkcast().setType(fmds[i].getDeclaredType());
+                        instructions.add(new 
MethodInsnNode(Opcodes.INVOKEVIRTUAL,
+                                                            
Type.getInternalName(oidType),
+                                                            "getId",
+                                                            
Type.getMethodDescriptor(TYPE_OBJECT)));
+                        if (!fieldManager && type != Object.class) {
+                            instructions.add(new 
TypeInsnNode(Opcodes.CHECKCAST, 
Type.getInternalName(fmds[i].getDeclaredType())));
+                        }
                     }
                     else if (oidType == DateId.class) {
-                        code.invokevirtual().setMethod(oidType, "getId",
-                                                       Date.class, null);
-                        if (!fieldManager && type != Date.class)
-                            
code.checkcast().setType(fmds[i].getDeclaredType());
+                        instructions.add(new 
MethodInsnNode(Opcodes.INVOKEVIRTUAL,
+                                                            
Type.getInternalName(oidType),
+                                                            "getId",
+                                                            
Type.getMethodDescriptor(Type.getType(Date.class))));
+                        if (!fieldManager && type != Date.class) {
+                            instructions.add(new 
TypeInsnNode(Opcodes.CHECKCAST, 
Type.getInternalName(fmds[i].getDeclaredType())));
+                        }
                     }
                     else {
-                        code.invokevirtual().setMethod(oidType, "getId",
-                                                       unwrapped, null);
-                        if (unwrapped != type)
-                            code.invokespecial().setMethod(type, "<init>",
-                                                           void.class, new 
Class[]{unwrapped});
+                        instructions.add(new 
MethodInsnNode(Opcodes.INVOKEVIRTUAL,
+                                                            
Type.getInternalName(oidType),
+                                                            "getId",
+                                                            
Type.getMethodDescriptor(Type.getType(unwrapped))));
+                        if (unwrapped != type) {
+                            instructions.add(new 
MethodInsnNode(Opcodes.INVOKESPECIAL,
+                                                                
Type.getInternalName(type),
+                                                                "<init>",
+                                                                
Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(unwrapped))));
+                        }
                     }
                 }
                 else if (isFieldAccess(fmds[i])) {
-                    field = Reflection.findField(oidType, name, true);
-                    if (Modifier.isPublic(field.getModifiers()))
-                        code.getfield().setField(field);
+                    Field field = Reflection.findField(oidType, name, true);
+                    if (Modifier.isPublic(field.getModifiers())) {
+                        instructions.add(new FieldInsnNode(Opcodes.GETFIELD,
+                                                           
Type.getInternalName(field.getDeclaringClass()),
+                                                           field.getName(),
+                                                           
Type.getDescriptor(field.getType())));
+                    }
                     else {
                         boolean usedFastOid = false;
                         if (_optimizeIdCopy) {
                             // If fastOids, ignore access type and try to use 
a public getter
-                            getter = Reflection.findGetter(oidType, name, 
false);
+                            Method getter = Reflection.findGetter(oidType, 
name, false);
                             if (getter != null && 
Modifier.isPublic(getter.getModifiers())) {
                                 usedFastOid = true;
-                                code.invokevirtual().setMethod(getter);
+                                instructions.add(new 
MethodInsnNode(Opcodes.INVOKEVIRTUAL,
+                                                                    
Type.getInternalName(getter.getDeclaringClass()),
+                                                                    
getter.getName(),
+                                                                    
Type.getMethodDescriptor(getter)));
                             }
                         }
                         if (!usedFastOid) {
                             // Reflection.getXXX(oid, 
Reflection.findField(...));
-                            code.classconstant().setClass(oidType);
-                            code.constant().setValue(name);
-                            code.constant().setValue(true);
-                            code.invokestatic().setMethod(Reflection.class,
-                                                          "findField", 
Field.class, new Class[]{
-                                            Class.class, String.class, 
boolean.class});
-                            code.invokestatic().setMethod
-                                    (getReflectionGetterMethod(type, 
Field.class));
-                            if (!type.isPrimitive() && type != Object.class)
-                                code.checkcast().setType(type);
+                            
instructions.add(AsmHelper.getLoadConstantInsn(oidType));
+                            
instructions.add(AsmHelper.getLoadConstantInsn(name));
+                            
instructions.add(AsmHelper.getLoadConstantInsn(true));
+                            instructions.add(new 
MethodInsnNode(Opcodes.INVOKESTATIC,
+                                                                
Type.getInternalName(Reflection.class),
+                                                                "findField",
+                                                                
Type.getMethodDescriptor(Type.getType(Field.class), Type.getType(Class.class),
+                                                                               
          Type.getType(String.class), Type.BOOLEAN_TYPE)));
+
+                            final Method reflectionGetterMethod = 
getReflectionGetterMethod(type, Field.class);
+                            instructions.add(new 
MethodInsnNode(Opcodes.INVOKESTATIC,
+                                                                
Type.getInternalName(reflectionGetterMethod.getDeclaringClass()),
+                                                                
reflectionGetterMethod.getName(),
+                                                                
Type.getMethodDescriptor(reflectionGetterMethod)));
+                            if (!type.isPrimitive() && type != Object.class) {
+                                instructions.add(new 
TypeInsnNode(Opcodes.CHECKCAST, Type.getInternalName(type)));
+                            }
                         }
                     }
                 }
                 else {
-                    getter = Reflection.findGetter(oidType, name, true);
-                    if (Modifier.isPublic(getter.getModifiers()))
-                        code.invokevirtual().setMethod(getter);
+                    Method getter = Reflection.findGetter(oidType, name, true);
+                    if (Modifier.isPublic(getter.getModifiers())) {
+                        instructions.add(new 
MethodInsnNode(Opcodes.INVOKEVIRTUAL,
+                                                            
Type.getInternalName(getter.getDeclaringClass()),
+                                                            getter.getName(),
+                                                            
Type.getMethodDescriptor(getter)));
+                    }
                     else {
                         // Reflection.getXXX(oid, Reflection.findGetter(...));
-                        code.classconstant().setClass(oidType);
-                        code.constant().setValue(name);
-                        code.constant().setValue(true);
-                        code.invokestatic().setMethod(Reflection.class,
-                                                      "findGetter", 
Method.class, new Class[]{
-                                        Class.class, String.class, 
boolean.class});
-                        code.invokestatic().setMethod
-                                (getReflectionGetterMethod(type, 
Method.class));
-                        if (!type.isPrimitive() && type != Object.class)
-                            code.checkcast().setType(type);
+                        
instructions.add(AsmHelper.getLoadConstantInsn(oidType));
+                        instructions.add(AsmHelper.getLoadConstantInsn(name));
+                        instructions.add(AsmHelper.getLoadConstantInsn(true));
+                        instructions.add(new 
MethodInsnNode(Opcodes.INVOKESTATIC,
+                                                            
Type.getInternalName(Reflection.class),
+                                                            "findGetter",
+                                                            
Type.getMethodDescriptor(Type.getType(Method.class), Type.getType(Class.class),
+                                                                               
      Type.getType(String.class), Type.BOOLEAN_TYPE)));
+
+                        final Method reflectionGetterMethod = 
getReflectionGetterMethod(type, Method.class);
+                        instructions.add(new 
MethodInsnNode(Opcodes.INVOKESTATIC,
+                                                            
Type.getInternalName(reflectionGetterMethod.getDeclaringClass()),
+                                                            
reflectionGetterMethod.getName(),
+                                                            
Type.getMethodDescriptor(reflectionGetterMethod)));
+                        if (!type.isPrimitive() && type != Object.class) {
+                            instructions.add(new 
TypeInsnNode(Opcodes.CHECKCAST, Type.getInternalName(type)));
+                        }
                     }
                 }
             }
 
-            if (fieldManager)
-                code.invokeinterface().setMethod(getFieldConsumerMethod(type));
-            else
-                addSetManagedValueCode(code, fmds[i]);
+            if (fieldManager) {
+                final Method fieldConsumerMethod = 
getFieldConsumerMethod(type);
+                instructions.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE,
+                                                    
Type.getInternalName(fieldConsumerMethod.getDeclaringClass()),
+                                                    
fieldConsumerMethod.getName(),
+                                                    
Type.getMethodDescriptor(fieldConsumerMethod)));
+            }
+            else {
+                addSetManagedValueCode(classNode, instructions, fmds[i]);
+            }
         }
-        code.vreturn();
 
-        code.calculateMaxStack();
-        code.calculateMaxLocals();
+        instructions.add(new InsnNode(Opcodes.RETURN));
     }
 
     /**

Reply via email to