mirror of
https://github.com/EsotericSoftware/reflectasm.git
synced 2025-01-21 09:10:24 +08:00
Fixed issue 9, hand calculated MAXS. Thanks serverperformance!
This commit is contained in:
parent
03e957db94
commit
14bbe83269
@ -104,7 +104,7 @@ public abstract class FieldAccess {
|
|||||||
String accessClassNameInternal = accessClassName.replace('.', '/');
|
String accessClassNameInternal = accessClassName.replace('.', '/');
|
||||||
String classNameInternal = className.replace('.', '/');
|
String classNameInternal = className.replace('.', '/');
|
||||||
|
|
||||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
|
ClassWriter cw = new ClassWriter(0);
|
||||||
cw.visit(V1_1, ACC_PUBLIC + ACC_SUPER, accessClassNameInternal, null, "com/esotericsoftware/reflectasm/FieldAccess",
|
cw.visit(V1_1, ACC_PUBLIC + ACC_SUPER, accessClassNameInternal, null, "com/esotericsoftware/reflectasm/FieldAccess",
|
||||||
null);
|
null);
|
||||||
|
|
||||||
@ -147,16 +147,18 @@ public abstract class FieldAccess {
|
|||||||
mv.visitVarInsn(ALOAD, 0);
|
mv.visitVarInsn(ALOAD, 0);
|
||||||
mv.visitMethodInsn(INVOKESPECIAL, "com/esotericsoftware/reflectasm/FieldAccess", "<init>", "()V");
|
mv.visitMethodInsn(INVOKESPECIAL, "com/esotericsoftware/reflectasm/FieldAccess", "<init>", "()V");
|
||||||
mv.visitInsn(RETURN);
|
mv.visitInsn(RETURN);
|
||||||
mv.visitMaxs(0, 0);
|
mv.visitMaxs(1, 1);
|
||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
static private void insertSetObject (ClassWriter cw, String classNameInternal, ArrayList<Field> fields) {
|
static private void insertSetObject (ClassWriter cw, String classNameInternal, ArrayList<Field> fields) {
|
||||||
|
int maxStack = 6;
|
||||||
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "set", "(Ljava/lang/Object;ILjava/lang/Object;)V", null, null);
|
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "set", "(Ljava/lang/Object;ILjava/lang/Object;)V", null, null);
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
mv.visitVarInsn(ILOAD, 2);
|
mv.visitVarInsn(ILOAD, 2);
|
||||||
|
|
||||||
if (!fields.isEmpty()) {
|
if (!fields.isEmpty()) {
|
||||||
|
maxStack--;
|
||||||
Label[] labels = new Label[fields.size()];
|
Label[] labels = new Label[fields.size()];
|
||||||
for (int i = 0, n = labels.length; i < n; i++)
|
for (int i = 0, n = labels.length; i < n; i++)
|
||||||
labels[i] = new Label();
|
labels[i] = new Label();
|
||||||
@ -222,16 +224,18 @@ public abstract class FieldAccess {
|
|||||||
mv.visitFrame(F_SAME, 0, null, 0, null);
|
mv.visitFrame(F_SAME, 0, null, 0, null);
|
||||||
}
|
}
|
||||||
mv = insertThrowExceptionForFieldNotFound(mv);
|
mv = insertThrowExceptionForFieldNotFound(mv);
|
||||||
mv.visitMaxs(0, 0);
|
mv.visitMaxs(maxStack, 4);
|
||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
static private void insertGetObject (ClassWriter cw, String classNameInternal, ArrayList<Field> fields) {
|
static private void insertGetObject (ClassWriter cw, String classNameInternal, ArrayList<Field> fields) {
|
||||||
|
int maxStack = 6;
|
||||||
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "get", "(Ljava/lang/Object;I)Ljava/lang/Object;", null, null);
|
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "get", "(Ljava/lang/Object;I)Ljava/lang/Object;", null, null);
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
mv.visitVarInsn(ILOAD, 2);
|
mv.visitVarInsn(ILOAD, 2);
|
||||||
|
|
||||||
if (!fields.isEmpty()) {
|
if (!fields.isEmpty()) {
|
||||||
|
maxStack--;
|
||||||
Label[] labels = new Label[fields.size()];
|
Label[] labels = new Label[fields.size()];
|
||||||
for (int i = 0, n = labels.length; i < n; i++)
|
for (int i = 0, n = labels.length; i < n; i++)
|
||||||
labels[i] = new Label();
|
labels[i] = new Label();
|
||||||
@ -282,49 +286,60 @@ public abstract class FieldAccess {
|
|||||||
mv.visitFrame(F_SAME, 0, null, 0, null);
|
mv.visitFrame(F_SAME, 0, null, 0, null);
|
||||||
}
|
}
|
||||||
insertThrowExceptionForFieldNotFound(mv);
|
insertThrowExceptionForFieldNotFound(mv);
|
||||||
mv.visitMaxs(0, 0);
|
mv.visitMaxs(maxStack, 3);
|
||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
static private void insertGetString (ClassWriter cw, String classNameInternal, ArrayList<Field> fields) {
|
static private void insertGetString (ClassWriter cw, String classNameInternal, ArrayList<Field> fields) {
|
||||||
|
int maxStack = 6;
|
||||||
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "getString", "(Ljava/lang/Object;I)Ljava/lang/String;", null, null);
|
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "getString", "(Ljava/lang/Object;I)Ljava/lang/String;", null, null);
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
mv.visitVarInsn(ILOAD, 2);
|
mv.visitVarInsn(ILOAD, 2);
|
||||||
|
|
||||||
if (!fields.isEmpty()) {
|
if (!fields.isEmpty()) {
|
||||||
|
maxStack--;
|
||||||
Label[] labels = new Label[fields.size()];
|
Label[] labels = new Label[fields.size()];
|
||||||
for (int i = 0, n = labels.length; i < n; i++)
|
Label labelForInvalidTypes = new Label();
|
||||||
labels[i] = new Label();
|
boolean hasAnyBadTypeLabel = false;
|
||||||
|
for (int i = 0, n = labels.length; i < n; i++) {
|
||||||
|
if (fields.get(i).getType().equals(String.class))
|
||||||
|
labels[i] = new Label();
|
||||||
|
else {
|
||||||
|
labels[i] = labelForInvalidTypes;
|
||||||
|
hasAnyBadTypeLabel = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
Label defaultLabel = new Label();
|
Label defaultLabel = new Label();
|
||||||
mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels);
|
mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels);
|
||||||
|
|
||||||
ArrayList<Label> labelsForOtherTypes = new ArrayList<Label>();
|
|
||||||
for (int i = 0, n = labels.length; i < n; i++) {
|
for (int i = 0, n = labels.length; i < n; i++) {
|
||||||
Field field = fields.get(i);
|
if (!labels[i].equals(labelForInvalidTypes)) {
|
||||||
if (field.getType().equals(String.class)) {
|
|
||||||
mv.visitLabel(labels[i]);
|
mv.visitLabel(labels[i]);
|
||||||
mv.visitFrame(F_SAME, 0, null, 0, null);
|
mv.visitFrame(F_SAME, 0, null, 0, null);
|
||||||
mv.visitVarInsn(ALOAD, 1);
|
mv.visitVarInsn(ALOAD, 1);
|
||||||
mv.visitTypeInsn(CHECKCAST, classNameInternal);
|
mv.visitTypeInsn(CHECKCAST, classNameInternal);
|
||||||
mv.visitFieldInsn(GETFIELD, classNameInternal, field.getName(), "Ljava/lang/String;");
|
mv.visitFieldInsn(GETFIELD, classNameInternal, fields.get(i).getName(), "Ljava/lang/String;");
|
||||||
mv.visitInsn(ARETURN);
|
mv.visitInsn(ARETURN);
|
||||||
} else
|
}
|
||||||
labelsForOtherTypes.add(labels[i]);
|
|
||||||
}
|
}
|
||||||
// Rest of fields: different type
|
// Rest of fields: different type
|
||||||
for (int i = 0, n = labelsForOtherTypes.size(); i < n; i++)
|
if (hasAnyBadTypeLabel) {
|
||||||
mv.visitLabel(labelsForOtherTypes.get(i));
|
mv.visitLabel(labelForInvalidTypes);
|
||||||
insertThrowExceptionForFieldType(mv, "String");
|
mv.visitFrame(F_SAME, 0, null, 0, null);
|
||||||
|
insertThrowExceptionForFieldType(mv, "String");
|
||||||
|
}
|
||||||
// Default: field not found
|
// Default: field not found
|
||||||
mv.visitLabel(defaultLabel);
|
mv.visitLabel(defaultLabel);
|
||||||
mv.visitFrame(F_SAME, 0, null, 0, null);
|
mv.visitFrame(F_SAME, 0, null, 0, null);
|
||||||
}
|
}
|
||||||
insertThrowExceptionForFieldNotFound(mv);
|
insertThrowExceptionForFieldNotFound(mv);
|
||||||
mv.visitMaxs(0, 0);
|
mv.visitMaxs(maxStack, 3);
|
||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
static private void insertSetPrimitive (ClassWriter cw, String classNameInternal, ArrayList<Field> fields, Type primitiveType) {
|
static private void insertSetPrimitive (ClassWriter cw, String classNameInternal, ArrayList<Field> fields, Type primitiveType) {
|
||||||
|
int maxStack = 6;
|
||||||
|
int maxLocals = 4; // See correction below for LLOAD and DLOAD
|
||||||
final String setterMethodName;
|
final String setterMethodName;
|
||||||
final String typeNameInternal = primitiveType.getDescriptor();
|
final String typeNameInternal = primitiveType.getDescriptor();
|
||||||
final int loadValueInstruction;
|
final int loadValueInstruction;
|
||||||
@ -356,10 +371,12 @@ public abstract class FieldAccess {
|
|||||||
case Type.LONG:
|
case Type.LONG:
|
||||||
setterMethodName = "setLong";
|
setterMethodName = "setLong";
|
||||||
loadValueInstruction = LLOAD;
|
loadValueInstruction = LLOAD;
|
||||||
|
maxLocals++; // (LLOAD and DLOAD actually load two slots)
|
||||||
break;
|
break;
|
||||||
case Type.DOUBLE:
|
case Type.DOUBLE:
|
||||||
setterMethodName = "setDouble";
|
setterMethodName = "setDouble";
|
||||||
loadValueInstruction = DLOAD;
|
loadValueInstruction = DLOAD; // (LLOAD and DLOAD actually load two slots)
|
||||||
|
maxLocals++;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
setterMethodName = "set";
|
setterMethodName = "set";
|
||||||
@ -372,41 +389,49 @@ public abstract class FieldAccess {
|
|||||||
mv.visitVarInsn(ILOAD, 2);
|
mv.visitVarInsn(ILOAD, 2);
|
||||||
|
|
||||||
if (!fields.isEmpty()) {
|
if (!fields.isEmpty()) {
|
||||||
|
maxStack--;
|
||||||
Label[] labels = new Label[fields.size()];
|
Label[] labels = new Label[fields.size()];
|
||||||
for (int i = 0, n = labels.length; i < n; i++)
|
Label labelForInvalidTypes = new Label();
|
||||||
labels[i] = new Label();
|
boolean hasAnyBadTypeLabel = false;
|
||||||
|
for (int i = 0, n = labels.length; i < n; i++) {
|
||||||
|
if (Type.getType(fields.get(i).getType()).equals(primitiveType))
|
||||||
|
labels[i] = new Label();
|
||||||
|
else {
|
||||||
|
labels[i] = labelForInvalidTypes;
|
||||||
|
hasAnyBadTypeLabel = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
Label defaultLabel = new Label();
|
Label defaultLabel = new Label();
|
||||||
|
|
||||||
mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels);
|
mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels);
|
||||||
|
|
||||||
ArrayList<Label> labelsForOtherTypes = new ArrayList<Label>();
|
|
||||||
for (int i = 0, n = labels.length; i < n; i++) {
|
for (int i = 0, n = labels.length; i < n; i++) {
|
||||||
Field field = fields.get(i);
|
if (!labels[i].equals(labelForInvalidTypes)) {
|
||||||
if (Type.getType(field.getType()).equals(primitiveType)) {
|
|
||||||
mv.visitLabel(labels[i]);
|
mv.visitLabel(labels[i]);
|
||||||
mv.visitFrame(F_SAME, 0, null, 0, null);
|
mv.visitFrame(F_SAME, 0, null, 0, null);
|
||||||
mv.visitVarInsn(ALOAD, 1);
|
mv.visitVarInsn(ALOAD, 1);
|
||||||
mv.visitTypeInsn(CHECKCAST, classNameInternal);
|
mv.visitTypeInsn(CHECKCAST, classNameInternal);
|
||||||
mv.visitVarInsn(loadValueInstruction, 3);
|
mv.visitVarInsn(loadValueInstruction, 3);
|
||||||
mv.visitFieldInsn(PUTFIELD, classNameInternal, field.getName(), typeNameInternal);
|
mv.visitFieldInsn(PUTFIELD, classNameInternal, fields.get(i).getName(), typeNameInternal);
|
||||||
mv.visitInsn(RETURN);
|
mv.visitInsn(RETURN);
|
||||||
} else
|
}
|
||||||
labelsForOtherTypes.add(labels[i]);
|
|
||||||
}
|
}
|
||||||
// Rest of fields: different type
|
// Rest of fields: different type
|
||||||
for (int i = 0, n = labelsForOtherTypes.size(); i < n; i++)
|
if (hasAnyBadTypeLabel) {
|
||||||
mv.visitLabel(labelsForOtherTypes.get(i));
|
mv.visitLabel(labelForInvalidTypes);
|
||||||
insertThrowExceptionForFieldType(mv, primitiveType.getClassName());
|
mv.visitFrame(F_SAME, 0, null, 0, null);
|
||||||
|
insertThrowExceptionForFieldType(mv, primitiveType.getClassName());
|
||||||
|
}
|
||||||
// Default: field not found
|
// Default: field not found
|
||||||
mv.visitLabel(defaultLabel);
|
mv.visitLabel(defaultLabel);
|
||||||
mv.visitFrame(F_SAME, 0, null, 0, null);
|
mv.visitFrame(F_SAME, 0, null, 0, null);
|
||||||
}
|
}
|
||||||
mv = insertThrowExceptionForFieldNotFound(mv);
|
mv = insertThrowExceptionForFieldNotFound(mv);
|
||||||
mv.visitMaxs(0, 0);
|
mv.visitMaxs(maxStack, maxLocals);
|
||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
static private void insertGetPrimitive (ClassWriter cw, String classNameInternal, ArrayList<Field> fields, Type primitiveType) {
|
static private void insertGetPrimitive (ClassWriter cw, String classNameInternal, ArrayList<Field> fields, Type primitiveType) {
|
||||||
|
int maxStack = 6;
|
||||||
final String getterMethodName;
|
final String getterMethodName;
|
||||||
final String typeNameInternal = primitiveType.getDescriptor();
|
final String typeNameInternal = primitiveType.getDescriptor();
|
||||||
final int returnValueInstruction;
|
final int returnValueInstruction;
|
||||||
@ -453,35 +478,44 @@ public abstract class FieldAccess {
|
|||||||
mv.visitVarInsn(ILOAD, 2);
|
mv.visitVarInsn(ILOAD, 2);
|
||||||
|
|
||||||
if (!fields.isEmpty()) {
|
if (!fields.isEmpty()) {
|
||||||
|
maxStack--;
|
||||||
Label[] labels = new Label[fields.size()];
|
Label[] labels = new Label[fields.size()];
|
||||||
for (int i = 0, n = labels.length; i < n; i++)
|
Label labelForInvalidTypes = new Label();
|
||||||
labels[i] = new Label();
|
boolean hasAnyBadTypeLabel = false;
|
||||||
|
for (int i = 0, n = labels.length; i < n; i++) {
|
||||||
|
if (Type.getType(fields.get(i).getType()).equals(primitiveType))
|
||||||
|
labels[i] = new Label();
|
||||||
|
else {
|
||||||
|
labels[i] = labelForInvalidTypes;
|
||||||
|
hasAnyBadTypeLabel = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
Label defaultLabel = new Label();
|
Label defaultLabel = new Label();
|
||||||
mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels);
|
mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels);
|
||||||
|
|
||||||
ArrayList<Label> labelsForOtherTypes = new ArrayList<Label>();
|
|
||||||
for (int i = 0, n = labels.length; i < n; i++) {
|
for (int i = 0, n = labels.length; i < n; i++) {
|
||||||
Field field = fields.get(i);
|
Field field = fields.get(i);
|
||||||
if (Type.getType(field.getType()).equals(primitiveType)) {
|
if (!labels[i].equals(labelForInvalidTypes)) {
|
||||||
mv.visitLabel(labels[i]);
|
mv.visitLabel(labels[i]);
|
||||||
mv.visitFrame(F_SAME, 0, null, 0, null);
|
mv.visitFrame(F_SAME, 0, null, 0, null);
|
||||||
mv.visitVarInsn(ALOAD, 1);
|
mv.visitVarInsn(ALOAD, 1);
|
||||||
mv.visitTypeInsn(CHECKCAST, classNameInternal);
|
mv.visitTypeInsn(CHECKCAST, classNameInternal);
|
||||||
mv.visitFieldInsn(GETFIELD, classNameInternal, field.getName(), typeNameInternal);
|
mv.visitFieldInsn(GETFIELD, classNameInternal, field.getName(), typeNameInternal);
|
||||||
mv.visitInsn(returnValueInstruction);
|
mv.visitInsn(returnValueInstruction);
|
||||||
} else
|
}
|
||||||
labelsForOtherTypes.add(labels[i]);
|
|
||||||
}
|
}
|
||||||
// Rest of fields: different type
|
// Rest of fields: different type
|
||||||
for (int i = 0, n = labelsForOtherTypes.size(); i < n; i++)
|
if (hasAnyBadTypeLabel) {
|
||||||
mv.visitLabel(labelsForOtherTypes.get(i));
|
mv.visitLabel(labelForInvalidTypes);
|
||||||
insertThrowExceptionForFieldType(mv, primitiveType.getClassName());
|
mv.visitFrame(F_SAME, 0, null, 0, null);
|
||||||
|
insertThrowExceptionForFieldType(mv, primitiveType.getClassName());
|
||||||
|
}
|
||||||
// Default: field not found
|
// Default: field not found
|
||||||
mv.visitLabel(defaultLabel);
|
mv.visitLabel(defaultLabel);
|
||||||
mv.visitFrame(F_SAME, 0, null, 0, null);
|
mv.visitFrame(F_SAME, 0, null, 0, null);
|
||||||
}
|
}
|
||||||
mv = insertThrowExceptionForFieldNotFound(mv);
|
mv = insertThrowExceptionForFieldNotFound(mv);
|
||||||
mv.visitMaxs(0, 0);
|
mv.visitMaxs(maxStack, 3);
|
||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -514,4 +548,5 @@ public abstract class FieldAccess {
|
|||||||
mv.visitInsn(ATHROW);
|
mv.visitInsn(ATHROW);
|
||||||
return mv;
|
return mv;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user