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 057627a5b..b2b4d7677 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 @@ -597,11 +597,12 @@ public class PCEnhancer { if (_meta != null) { enhanceClass(pc); addFields(pc); - //X TODO finish addStaticInitializer(classNodeTracker); - AsmHelper.readIntoBCClass(pc, _pc); - addStaticInitializer(); - pc = AsmHelper.toClassNode(_pc); + //X For now we cannot take the new version as it uses LDC for classes which Serp doesn't understand. + //X So we can only enable it in a later step + //X addStaticInitializer(pc); + addStaticInitializer(); // removeme + addPCMethods(pc); addAccessors(); @@ -857,7 +858,7 @@ public class PCEnhancer { LabelNode caseLabel = new LabelNode(); switchNd.labels.add(caseLabel); instructions.add(caseLabel); - instructions.add(new LdcInsnNode(_attrsToFields.get(fmd.getName()))); + instructions.add(AsmHelper.getLoadConstantInsn(_attrsToFields.get(fmd.getName()))); instructions.add(new InsnNode(Opcodes.ARETURN)); } @@ -876,7 +877,7 @@ public class PCEnhancer { instructions.add(caseLabel); switchNd.labels.add(caseLabel); switchNd.keys.add(propFmds.get(i)); - instructions.add(new LdcInsnNode(_attrsToFields.get(fmds[i].getName()))); + instructions.add(AsmHelper.getLoadConstantInsn(_attrsToFields.get(fmds[i].getName()))); instructions.add(new InsnNode(Opcodes.ARETURN)); } } @@ -1219,7 +1220,7 @@ public class PCEnhancer { InsnList insns = new InsnList(); insns.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this - insns.add(new LdcInsnNode(fmd.getIndex())); + insns.add(AsmHelper.getLoadConstantInsn(fmd.getIndex())); insns.add(new MethodInsnNode(Opcodes.INVOKESTATIC, Type.getInternalName(RedefinitionHelper.class), "accessingField", @@ -1253,7 +1254,7 @@ public class PCEnhancer { InsnList insns = new InsnList(); insns.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this - insns.add(new LdcInsnNode(fmd.getIndex())); + insns.add(AsmHelper.getLoadConstantInsn(fmd.getIndex())); Class type = fmd.getDeclaredType(); // we only have special signatures for primitives and Strings @@ -1547,7 +1548,7 @@ public class PCEnhancer { // pcInheritedFieldCount field isn't initialized! so instead, // return + .pcGetManagedFieldCount () final InsnList instructions = getFieldCountMeth.instructions; - instructions.add(new LdcInsnNode(_meta.getDeclaredFields().length)); + instructions.add(AsmHelper.getLoadConstantInsn(_meta.getDeclaredFields().length)); if (_meta.getPCSuperclass() != null) { Class superClass = getType(_meta.getPCSuperclassMetaData()); String superName = getCreateSubclass() ? @@ -3284,6 +3285,7 @@ public class PCEnhancer { @Deprecated private void addStaticInitializer() { + AsmHelper.readIntoBCClass(pc, _pc); Code code = getOrCreateClassInitCode(true); if (_meta.getPCSuperclass() != null) { if (getCreateSubclass()) { @@ -3368,6 +3370,7 @@ public class PCEnhancer { code.vreturn(); code.calculateMaxStack(); + pc = AsmHelper.toClassNode(_pc); } /** @@ -3380,91 +3383,97 @@ public class PCEnhancer { InsnList instructions = new InsnList(); if (_meta.getPCSuperclass() != null) { if (getCreateSubclass()) { - instructions.add(new LdcInsnNode(0)); - instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, classNode.name, INHERIT, Type.INT_TYPE.getDescriptor())); + instructions.add(AsmHelper.getLoadConstantInsn(0)); + instructions.add(new FieldInsnNode(Opcodes.PUTSTATIC, classNode.name, INHERIT, Type.INT_TYPE.getDescriptor())); } else { // pcInheritedFieldCount = .pcGetManagedFieldCount() instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC, classNode.superName, PRE + "GetManagedFieldCount", Type.getMethodDescriptor(Type.INT_TYPE))); - instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, classNode.name, INHERIT, Type.INT_TYPE.getDescriptor())); + instructions.add(new FieldInsnNode(Opcodes.PUTSTATIC, classNode.name, INHERIT, Type.INT_TYPE.getDescriptor())); } // pcPCSuperclass = ; // this intentionally calls getDescribedType() directly // instead of PCEnhancer.getType() - instructions.add(new LdcInsnNode(Type.getType(_meta.getPCSuperclassMetaData().getDescribedType()))); + instructions.add(AsmHelper.getLoadConstantInsn(_meta.getPCSuperclassMetaData().getDescribedType())); instructions.add(new FieldInsnNode(Opcodes.PUTSTATIC, classNode.name, SUPER, Type.getDescriptor(Class.class))); } - // pcFieldNames = new String[] { "", "", ... }; FieldMetaData[] fmds = _meta.getDeclaredFields(); -/* - // pcFieldNames = new String[] { "", "", ... }; - FieldMetaData[] fmds = _meta.getDeclaredFields(); - code.constant().setValue(fmds.length); - code.anewarray().setType(String.class); + instructions.add(AsmHelper.getLoadConstantInsn(fmds.length)); + instructions.add(new TypeInsnNode(Opcodes.ANEWARRAY, Type.getInternalName(String.class))); for (int i = 0; i < fmds.length; i++) { - code.dup(); - code.constant().setValue(i); - code.constant().setValue(fmds[i].getName()); - code.aastore(); + instructions.add(new InsnNode(Opcodes.DUP)); + instructions.add(AsmHelper.getLoadConstantInsn(i)); + instructions.add(AsmHelper.getLoadConstantInsn(fmds[i].getName())); + instructions.add(new InsnNode(Opcodes.AASTORE)); } - code.putstatic().setField(PRE + "FieldNames", String[].class); + instructions.add(new FieldInsnNode(Opcodes.PUTSTATIC, classNode.name, PRE + "FieldNames", Type.getDescriptor(String[].class))); // pcFieldTypes = new Class[] { .class, .class, ... }; - code.constant().setValue(fmds.length); - code.anewarray().setType(Class.class); + instructions.add(AsmHelper.getLoadConstantInsn(fmds.length)); + instructions.add(new TypeInsnNode(Opcodes.ANEWARRAY, Type.getInternalName(Class.class))); for (int i = 0; i < fmds.length; i++) { - code.dup(); - code.constant().setValue(i); - code.classconstant().setClass(fmds[i].getDeclaredType()); - code.aastore(); + instructions.add(new InsnNode(Opcodes.DUP)); + instructions.add(AsmHelper.getLoadConstantInsn(i)); + instructions.add(AsmHelper.getLoadConstantInsn(fmds[i].getDeclaredType())); + instructions.add(new InsnNode(Opcodes.AASTORE)); } - code.putstatic().setField(PRE + "FieldTypes", Class[].class); + instructions.add(new FieldInsnNode(Opcodes.PUTSTATIC, classNode.name, PRE + "FieldTypes", Type.getDescriptor(Class[].class))); // pcFieldFlags = new byte[] { , , ... }; - code.constant().setValue(fmds.length); - code.newarray().setType(byte.class); + instructions.add(AsmHelper.getLoadConstantInsn(fmds.length)); + instructions.add(new IntInsnNode(Opcodes.NEWARRAY, Opcodes.T_BYTE)); for (int i = 0; i < fmds.length; i++) { - code.dup(); - code.constant().setValue(i); - code.constant().setValue(getFieldFlag(fmds[i])); - code.bastore(); + instructions.add(new InsnNode(Opcodes.DUP)); + instructions.add(AsmHelper.getLoadConstantInsn(i)); + instructions.add(AsmHelper.getLoadConstantInsn(getFieldFlag(fmds[i]))); + instructions.add(new InsnNode(Opcodes.BASTORE)); } - code.putstatic().setField(PRE + "FieldFlags", byte[].class); + instructions.add(new FieldInsnNode(Opcodes.PUTSTATIC, classNode.name, PRE + "FieldFlags", Type.getDescriptor(byte[].class))); +/* // PCRegistry.register (cls, // pcFieldNames, pcFieldTypes, pcFieldFlags, // pcPCSuperclass, alias, new XXX ()); - code.classconstant().setClass(_meta.getDescribedType()); - code.getstatic().setField(PRE + "FieldNames", String[].class); - code.getstatic().setField(PRE + "FieldTypes", Class[].class); - code.getstatic().setField(PRE + "FieldFlags", byte[].class); - code.getstatic().setField(SUPER, Class.class); + instructions.add(AsmHelper.getLoadConstantInsn(_meta.getDescribedType())); + instructions.add(new FieldInsnNode(Opcodes.GETSTATIC, classNode.name, PRE + "FieldNames", Type.getDescriptor(String[].class))); + instructions.add(new FieldInsnNode(Opcodes.GETSTATIC, classNode.name, PRE + "FieldTypes", Type.getDescriptor(Class[].class))); + instructions.add(new FieldInsnNode(Opcodes.GETSTATIC, classNode.name, PRE + "FieldFlags", Type.getDescriptor(byte[].class))); + instructions.add(new FieldInsnNode(Opcodes.GETSTATIC, classNode.name, SUPER, Type.getDescriptor(Class.class))); - if (_meta.isMapped() || _meta.isAbstract()) - code.constant().setValue(_meta.getTypeAlias()); - else - code.constant().setNull(); - - if (_pc.isAbstract()) - code.constant().setNull(); + if (_meta.isMapped() || _meta.isAbstract()) { + instructions.add(AsmHelper.getLoadConstantInsn(_meta.getTypeAlias())); + } else { - code.anew().setType(_pc); - code.dup(); - code.invokespecial().setMethod("", void.class, null); + instructions.add(new InsnNode(Opcodes.ACONST_NULL)); } - code.invokestatic().setMethod(HELPERTYPE, "register", void.class, - new Class[]{ Class.class, String[].class, Class[].class, - byte[].class, Class.class, String.class, PCTYPE }); + if (_pc.isAbstract()) { + instructions.add(new InsnNode(Opcodes.ACONST_NULL)); + } + else { + instructions.add(new TypeInsnNode(Opcodes.NEW, classNode.name)); + instructions.add(new InsnNode(Opcodes.DUP)); + instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, + classNode.name, + "", + Type.getMethodDescriptor(Type.VOID_TYPE))); + } + + instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC, + Type.getInternalName(HELPERTYPE), + "register", + Type.getMethodDescriptor(Type.VOID_TYPE, + Type.getType(Class.class), Type.getType(String[].class), + Type.getType(Class[].class), Type.getType(byte[].class), + Type.getType(Class.class), Type.getType(String.class), + Type.getType(PersistenceCapable.class)))); - code.vreturn(); - code.calculateMaxStack(); */ // now add those instructions to the method @@ -3991,9 +4000,9 @@ public class PCEnhancer { } else { // add static initializer method if non exists - MethodNode clinit = new MethodNode(Opcodes.ACC_STATIC | Opcodes.ACC_FINAL, + MethodNode clinit = new MethodNode(Opcodes.ACC_STATIC, "", - Type.getMethodDescriptor(Type.VOID_TYPE), + "()V", null, null); clinit.instructions.add(new InsnNode(Opcodes.RETURN)); classNode.methods.add(clinit); @@ -4483,8 +4492,8 @@ public class PCEnhancer { // Reflection.getXXX(this, Reflection.findField(...)); // Reflection.findField(declarer, fieldName, true); - instructions.add(new LdcInsnNode(Type.getType(declarer))); - instructions.add(new LdcInsnNode(fieldName)); + instructions.add(AsmHelper.getLoadConstantInsn(declarer)); + instructions.add(AsmHelper.getLoadConstantInsn(fieldName)); instructions.add(new InsnNode(Opcodes.ICONST_1)); // true instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC, Type.getInternalName(Reflection.class), @@ -4615,8 +4624,8 @@ public class PCEnhancer { if (getRedefine() || getCreateSubclass()) { // Reflection.set(this, Reflection.findField(...), value); // Reflection.findField(declarer, fieldName, true); - instructions.add(new LdcInsnNode(Type.getType(declarer))); - instructions.add(new LdcInsnNode(fieldName)); + instructions.add(AsmHelper.getLoadConstantInsn(declarer)); + instructions.add(AsmHelper.getLoadConstantInsn(fieldName)); instructions.add(new InsnNode(Opcodes.ICONST_1)); // true instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC, Type.getInternalName(Reflection.class), @@ -5214,7 +5223,7 @@ public class PCEnhancer { instructions.add(new InsnNode(Opcodes.ACONST_NULL)); } else { - instructions.add(new LdcInsnNode(value)); + instructions.add(AsmHelper.getLoadConstantInsn(value)); } // if redefining, then we must always reflect (or access the field @@ -5428,7 +5437,7 @@ public class PCEnhancer { PRE + "GetEnhancementContractVersion", Type.getMethodDescriptor(Type.INT_TYPE), null, null); - methodNode.instructions.add(new LdcInsnNode(ENHANCER_VERSION)); + methodNode.instructions.add(AsmHelper.getLoadConstantInsn(ENHANCER_VERSION)); methodNode.instructions.add(new InsnNode(Opcodes.IRETURN)); cnt.getClassNode().methods.add(methodNode); } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/AsmHelper.java b/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/AsmHelper.java index 2a23a01c0..b3783c818 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/AsmHelper.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/AsmHelper.java @@ -30,6 +30,9 @@ import org.apache.xbean.asm9.Type; import org.apache.xbean.asm9.tree.AbstractInsnNode; import org.apache.xbean.asm9.tree.ClassNode; import org.apache.xbean.asm9.tree.FieldInsnNode; +import org.apache.xbean.asm9.tree.InsnNode; +import org.apache.xbean.asm9.tree.IntInsnNode; +import org.apache.xbean.asm9.tree.LdcInsnNode; import org.apache.xbean.asm9.tree.VarInsnNode; import serp.bytecode.BCClass; @@ -180,6 +183,77 @@ public final class AsmHelper { return Opcodes.ARETURN; } + public static AbstractInsnNode getLoadConstantInsn(Object val) { + if (val == null) { + return new InsnNode(Opcodes.ACONST_NULL); + } + if (val instanceof Integer) { + final int iVal = ((Integer) val).intValue(); + switch (iVal) { + case 0: + return new InsnNode(Opcodes.ICONST_0); + case 1: + return new InsnNode(Opcodes.ICONST_1); + case 2: + return new InsnNode(Opcodes.ICONST_2); + case 3: + return new InsnNode(Opcodes.ICONST_3); + case 4: + return new InsnNode(Opcodes.ICONST_4); + case 5: + return new InsnNode(Opcodes.ICONST_5); + default: + break; + } + if (iVal < 0 && iVal >= -128 || iVal >= 6 && iVal < 128) { + // use bipush for small numbers + return new IntInsnNode(Opcodes.BIPUSH, iVal); + } + else if (iVal < -128 && iVal >= -32768 || iVal >= 128 && iVal < 32768) { + // use sipush for a bit bigger numbers + return new IntInsnNode(Opcodes.SIPUSH, iVal); + } + } + + if (val instanceof Class) { + if (boolean.class.equals(val)) { + return new FieldInsnNode(Opcodes.GETSTATIC, Type.getInternalName(Boolean.class), "TYPE", + Type.getDescriptor(Class.class)); + } + if (char.class.equals(val)) { + return new FieldInsnNode(Opcodes.GETSTATIC, Type.getInternalName(Character.class), "TYPE", + Type.getDescriptor(Class.class)); + } + if (int.class.equals(val)) { + return new FieldInsnNode(Opcodes.GETSTATIC, Type.getInternalName(Integer.class), "TYPE", + Type.getDescriptor(Class.class)); + } + if (long.class.equals(val)) { + return new FieldInsnNode(Opcodes.GETSTATIC, Type.getInternalName(Long.class), "TYPE", + Type.getDescriptor(Class.class)); + } + if (byte.class.equals(val)) { + return new FieldInsnNode(Opcodes.GETSTATIC, Type.getInternalName(Byte.class), "TYPE", + Type.getDescriptor(Class.class)); + } + if (short.class.equals(val)) { + return new FieldInsnNode(Opcodes.GETSTATIC, Type.getInternalName(Short.class), "TYPE", + Type.getDescriptor(Class.class)); + } + if (float.class.equals(val)) { + return new FieldInsnNode(Opcodes.GETSTATIC, Type.getInternalName(Float.class), "TYPE", + Type.getDescriptor(Class.class)); + } + if (double.class.equals(val)) { + return new FieldInsnNode(Opcodes.GETSTATIC, Type.getInternalName(Double.class), "TYPE", + Type.getDescriptor(Class.class)); + } + return new LdcInsnNode(Type.getType((Class) val)); + } + + return new LdcInsnNode(val); + } + /** * Calclates the proper STORE instruction opcode for the given type * diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/SimpleEntity.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/SimpleEntity.java index ff5423d56..87f28c265 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/SimpleEntity.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/SimpleEntity.java @@ -69,6 +69,20 @@ public class SimpleEntity implements Serializable { public static final String NAMED_QUERY_WITH_POSITIONAL_PARAMS = "SelectWithPositionalParameter"; public static final String NAMED_QUERY_WITH_NAMED_PARAMS = "SelectWithNamedParameter"; + public static Integer dummy; + + static { + dummy = -32766; + dummy = -32767; + dummy = -32768; + dummy = -32769; + + dummy = 32765; + dummy = 32766; + dummy = 32767; + dummy = 32768; + } + @Id @GeneratedValue @Column(name = "ID")