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 972b5d0e62451b6b79ea82d4e7fd57c93f77835f
Author: Mark Struberg <strub...@apache.org>
AuthorDate: Tue Jun 6 17:34:28 2023 +0200

    OPENJPA-2911 migrate addNewInstance to ASM
---
 .../org/apache/openjpa/enhance/PCEnhancer.java     | 107 +++++++++++++--------
 1 file changed, 69 insertions(+), 38 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 bc46dea90..d8d94add8 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
@@ -107,9 +107,12 @@ import org.apache.xbean.asm9.tree.FieldInsnNode;
 import org.apache.xbean.asm9.tree.FieldNode;
 import org.apache.xbean.asm9.tree.InsnList;
 import org.apache.xbean.asm9.tree.InsnNode;
+import org.apache.xbean.asm9.tree.JumpInsnNode;
+import org.apache.xbean.asm9.tree.LabelNode;
 import org.apache.xbean.asm9.tree.LdcInsnNode;
 import org.apache.xbean.asm9.tree.MethodInsnNode;
 import org.apache.xbean.asm9.tree.MethodNode;
+import org.apache.xbean.asm9.tree.TypeInsnNode;
 import org.apache.xbean.asm9.tree.VarInsnNode;
 
 import serp.bytecode.BCClass;
@@ -1337,12 +1340,12 @@ public class PCEnhancer {
      * least-derived PersistenceCapable type.
      */
     private void addPCMethods(ClassNodeTracker classNodeTracker) throws 
NoSuchMethodException {
-        //X addClearFieldsMethod();
         addClearFieldsMethod(classNodeTracker.getClassNode());
+        addNewInstanceMethod(classNodeTracker.getClassNode(), true);
+        addNewInstanceMethod(classNodeTracker.getClassNode(), false);
+
         AsmHelper.readIntoBCClass(classNodeTracker, _pc);
 
-        addNewInstanceMethod(true);
-        addNewInstanceMethod(false);
         addManagedFieldCountMethod();
         addReplaceFieldsMethods();
         addProvideFieldsMethods();
@@ -1384,7 +1387,7 @@ public class PCEnhancer {
             addGetIDOwningClass();
         }
     }
-    
+
     /**
      * Add a method to clear all persistent fields; we'll call this from
      * the new instance method to ensure that unloaded fields have
@@ -1448,58 +1451,68 @@ public class PCEnhancer {
      * @param oid set to true to mimic the method version that takes
      * an oid value as well as a state manager
      */
-    private void addNewInstanceMethod(boolean oid) {
+    private void addNewInstanceMethod(ClassNode classNode, boolean oid) {
         // public PersistenceCapable pcNewInstance (...)
-        Class[] args =
-            (oid) ? new Class[]{ SMTYPE, Object.class, boolean.class }
-                : new Class[]{ SMTYPE, boolean.class };
-        BCMethod method = _pc.declareMethod(PRE + "NewInstance", PCTYPE, args);
-        Code code = method.getCode(true);
+        String desc = oid
+                ? Type.getMethodDescriptor(Type.getType(PCTYPE), 
Type.getType(SMTYPE), Type.getType(Object.class), Type.BOOLEAN_TYPE)
+                : Type.getMethodDescriptor(Type.getType(PCTYPE), 
Type.getType(SMTYPE), Type.BOOLEAN_TYPE);
+        MethodNode newInstance = new MethodNode(Opcodes.ACC_PUBLIC,
+                                                PRE + "NewInstance",
+                                                desc,
+                                                null, null);
+        classNode.methods.add(newInstance);
+        final InsnList instructions = newInstance.instructions;
 
-        // if the type is abstract, throw a UserException
         if (_pc.isAbstract()) {
-            throwException(code, USEREXCEP);
-
-            code.calculateMaxStack();
-            code.calculateMaxLocals();
+            instructions.add(throwException(USEREXCEP));
             return;
         }
 
         // XXX pc = new XXX ();
-        code.anew().setType(_pc);
-        code.dup();
-        code.invokespecial().setMethod("<init>", void.class, null);
-        int inst = code.getNextLocalsIndex();
-        code.astore().setLocal(inst);
+        instructions.add(new TypeInsnNode(Opcodes.NEW, classNode.name));
+        instructions.add(new InsnNode(Opcodes.DUP));
+        instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL,
+                                            classNode.name,
+                                            "<init>",
+                                            
Type.getMethodDescriptor(Type.VOID_TYPE)));
+
+        int newPcVarPos = (oid) ? 4 : 3; // number of params +1
+        instructions.add(new VarInsnNode(Opcodes.ASTORE, newPcVarPos));
 
         // if (clear)
         //   pc.pcClearFields ();
-        code.iload().setParam((oid) ? 2 : 1);
-        JumpInstruction noclear = code.ifeq();
-        code.aload().setLocal(inst);
-        code.invokevirtual().setMethod(PRE + "ClearFields", void.class, null);
+        instructions.add(new VarInsnNode(Opcodes.ILOAD, (oid) ? 3 : 2));
+        LabelNode labelAfterClearFields = new LabelNode();
+        instructions.add(new JumpInsnNode(Opcodes.IFEQ, 
labelAfterClearFields));
+
+        // inside the if
+        instructions.add(new VarInsnNode(Opcodes.ALOAD, newPcVarPos));
+        instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
+                                            classNode.name,
+                                            PRE + "ClearFields",
+                                            
Type.getMethodDescriptor(Type.VOID_TYPE)));
+
+        instructions.add(labelAfterClearFields);
 
         // pc.pcStateManager = sm;
-        noclear.setTarget(code.aload().setLocal(inst));
-        code.aload().setParam(0);
-        code.putfield().setField(SM, SMTYPE);
+        instructions.add(new VarInsnNode(Opcodes.ALOAD, newPcVarPos));
+        instructions.add(new VarInsnNode(Opcodes.ALOAD, 1)); // the 1st method 
param
+        instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, classNode.name, 
SM, Type.getDescriptor(SMTYPE)));
 
         // copy key fields from oid
         if (oid) {
-            code.aload().setLocal(inst);
-            code.aload().setParam(1);
-            code.invokevirtual().setMethod(PRE + "CopyKeyFieldsFromObjectId",
-                void.class, new Class[]{ Object.class });
+            instructions.add(new VarInsnNode(Opcodes.ALOAD, newPcVarPos));
+            instructions.add(new VarInsnNode(Opcodes.ALOAD, 2)); // the 2nd 
method param, Object
+            instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
+                                                classNode.name,
+                                                PRE + 
"CopyKeyFieldsFromObjectId",
+                                                
Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(Object.class))));
         }
 
-        // return pc;
-        code.aload().setLocal(inst);
-        code.areturn();
-
-        code.calculateMaxStack();
-        code.calculateMaxLocals();
+        instructions.add(new VarInsnNode(Opcodes.ALOAD, newPcVarPos));
+        instructions.add(new InsnNode(Opcodes.ARETURN));
     }
-
+    
     /**
      * Adds the <code>protected static int pcGetManagedFieldCount ()</code>
      * method to the bytecode, returning the inherited field count added
@@ -3061,6 +3074,24 @@ public class PCEnhancer {
         }
     }
 
+
+    /**
+     * Helper method to add the code necessary to throw the given
+     * exception type, sans message.
+     */
+    private InsnList throwException(Class type) {
+        InsnList instructions = new InsnList();
+        instructions.add(new TypeInsnNode(Opcodes.NEW, 
Type.getInternalName(type)));
+        instructions.add(new InsnNode(Opcodes.DUP));
+        instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL,
+                                            Type.getInternalName(type),
+                                            "<init>",
+                                            
Type.getMethodDescriptor(Type.VOID_TYPE)));
+        instructions.add(new InsnNode(Opcodes.ATHROW));
+
+        return instructions;
+    }
+
     /**
      * Helper method to add the code necessary to throw the given
      * exception type, sans message.

Reply via email to