ObjectReaderCreatorASM.java
package com.alibaba.fastjson2.reader;
import com.alibaba.fastjson2.*;
import com.alibaba.fastjson2.codec.BeanInfo;
import com.alibaba.fastjson2.codec.FieldInfo;
import com.alibaba.fastjson2.function.*;
import com.alibaba.fastjson2.internal.asm.*;
import com.alibaba.fastjson2.schema.JSONSchema;
import com.alibaba.fastjson2.util.*;
import com.alibaba.fastjson2.writer.ObjectWriterProvider;
import java.io.Serializable;
import java.lang.reflect.*;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.*;
import static com.alibaba.fastjson2.internal.CodeGenUtils.fieldReader;
import static com.alibaba.fastjson2.internal.asm.ASMUtils.*;
import static com.alibaba.fastjson2.reader.ObjectReader.HASH_TYPE;
import static com.alibaba.fastjson2.reader.ObjectReaderCreatorASM.MethodWriterContext.*;
import static com.alibaba.fastjson2.util.JDKUtils.*;
public class ObjectReaderCreatorASM
extends ObjectReaderCreator {
// GraalVM not support
// Android not support
public static final ObjectReaderCreatorASM INSTANCE = new ObjectReaderCreatorASM(DynamicClassLoader.getInstance());
protected static final AtomicLong seed = new AtomicLong();
protected final DynamicClassLoader classLoader;
static final String METHOD_DESC_GET_ITEM_OBJECT_READER = "(" + DESC_JSON_READER + ")" + DESC_OBJECT_READER;
static final String METHOD_DESC_GET_OBJECT_READER_1 = "(" + DESC_JSON_READER + ")" + DESC_OBJECT_READER;
static final String METHOD_DESC_INIT = "(Ljava/lang/Class;" + DESC_SUPPLIER + DESC_FIELD_READER_ARRAY + ")V";
static final String METHOD_DESC_ADAPTER_INIT = "(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;J" + DESC_JSONSCHEMA + DESC_SUPPLIER + "Ljava/util/function/Function;" + DESC_FIELD_READER_ARRAY + ")V";
static final String METHOD_DESC_READ_OBJECT = "(" + DESC_JSON_READER + "Ljava/lang/reflect/Type;Ljava/lang/Object;J)Ljava/lang/Object;";
static final String METHOD_DESC_GET_FIELD_READER = "(J)" + DESC_FIELD_READER;
static final String METHOD_DESC_READ_FIELD_VALUE = "(" + DESC_JSON_READER + "Ljava/lang/Object;)V";
static final String READ_FIELD_READER_UL = "(J" + DESC_JSON_READER + "JLjava/lang/Object;)V";
static final String METHOD_DESC_ADD_RESOLVE_TASK = "(" + DESC_JSON_READER + "Ljava/lang/Object;Ljava/lang/String;)V";
static final String METHOD_DESC_CHECK_ARRAY_AUTO_TYPE = "(" + DESC_JSON_READER + ")" + DESC_OBJECT_READER;
static final String METHOD_DESC_PROCESS_EXTRA = "(" + DESC_JSON_READER + "Ljava/lang/Object;J)V";
static final String METHOD_DESC_JSON_READER_CHECK_ARRAY_AUTO_TYPE = "(" + DESC_JSON_READER + "J)" + DESC_OBJECT_READER;
static final String METHOD_DESC_READ_ARRAY_MAPPING_JSONB_OBJECT0 = "(" + DESC_JSON_READER + "Ljava/lang/Object;I)V";
static final int THIS = 0;
static final String packageName;
static final Map<Class, FieldReaderInfo> infos = new HashMap<>();
static {
Package pkg = ObjectReaderCreatorASM.class.getPackage();
packageName = pkg != null ? pkg.getName() : "";
infos.put(boolean.class, new FieldReaderInfo(ASMUtils.type(ObjBoolConsumer.class), "(Ljava/lang/Object;Z)V", "(Z)V", Opcodes.ILOAD, "readFieldBoolValue", "()Z", Opcodes.ISTORE));
infos.put(char.class, new FieldReaderInfo(ASMUtils.type(ObjCharConsumer.class), "(Ljava/lang/Object;C)V", "(C)V", Opcodes.ILOAD, "readInt32Value", "()C", Opcodes.ISTORE));
infos.put(byte.class, new FieldReaderInfo(ASMUtils.type(ObjByteConsumer.class), "(Ljava/lang/Object;B)V", "(B)V", Opcodes.ILOAD, "readInt32Value", "()B", Opcodes.ISTORE));
infos.put(short.class, new FieldReaderInfo(ASMUtils.type(ObjShortConsumer.class), "(Ljava/lang/Object;S)V", "(S)V", Opcodes.ILOAD, "readInt32Value", "()S", Opcodes.ISTORE));
infos.put(int.class, new FieldReaderInfo(ASMUtils.type(ObjIntConsumer.class), "(Ljava/lang/Object;I)V", "(I)V", Opcodes.ILOAD, "readInt32Value", "()I", Opcodes.ISTORE));
infos.put(long.class, new FieldReaderInfo(ASMUtils.type(ObjLongConsumer.class), "(Ljava/lang/Object;J)V", "(J)V", Opcodes.LLOAD, "readInt64Value", "()V", Opcodes.LSTORE));
infos.put(float.class, new FieldReaderInfo(ASMUtils.type(ObjFloatConsumer.class), "(Ljava/lang/Object;F)V", "(F)V", Opcodes.FLOAD, "readFieldFloatValue", "()F", Opcodes.FSTORE));
infos.put(double.class, new FieldReaderInfo(ASMUtils.type(ObjDoubleConsumer.class), "(Ljava/lang/Object;D)V", "(D)V", Opcodes.DLOAD, "readFloatDoubleValue", "()D", Opcodes.DSTORE));
infos.put(String.class, new FieldReaderInfo(ASMUtils.type(BiConsumer.class), "(Ljava/lang/Object;Ljava/lang/Object;)V", "(Ljava/lang/String;)V", Opcodes.ALOAD, "readString", "()Ljava/lang/String;", Opcodes.ASTORE));
infos.put(Integer.class, new FieldReaderInfo(ASMUtils.type(BiConsumer.class), "(Ljava/lang/Object;Ljava/lang/Integer;)V", "(Ljava/lang/Integer;)V", Opcodes.ALOAD, "readInt32", "()Ljava/lang/Integer;", Opcodes.ASTORE));
}
static final String[] fieldItemObjectReader = new String[1024];
static String fieldObjectReader(int i) {
switch (i) {
case 0:
return "objectReader0";
case 1:
return "objectReader1";
case 2:
return "objectReader2";
case 3:
return "objectReader3";
case 4:
return "objectReader4";
case 5:
return "objectReader5";
case 6:
return "objectReader6";
case 7:
return "objectReader7";
case 8:
return "objectReader8";
case 9:
return "objectReader9";
case 10:
return "objectReader10";
case 11:
return "objectReader11";
case 12:
return "objectReader12";
case 13:
return "objectReader13";
case 14:
return "objectReader14";
case 15:
return "objectReader15";
default:
String base = "objectReader";
int size = IOUtils.stringSize(i);
char[] chars = new char[base.length() + size];
base.getChars(0, base.length(), chars, 0);
IOUtils.getChars(i, chars.length, chars);
return new String(chars);
}
}
static String fieldItemObjectReader(int i) {
String fieldName = fieldItemObjectReader[i];
if (fieldName != null) {
return fieldName;
}
String base = "itemReader";
int size = IOUtils.stringSize(i);
char[] chars = new char[base.length() + size];
base.getChars(0, base.length(), chars, 0);
IOUtils.getChars(i, chars.length, chars);
fieldItemObjectReader[i] = fieldName = new String(chars);
return fieldName;
}
private static class FieldReaderInfo {
final String interfaceDesc;
final String acceptDesc;
final String setterDesc;
final int loadCode;
final String readMethodName;
final String readMethodDesc;
final int storeCode;
FieldReaderInfo(
String interfaceDesc,
String acceptDesc,
String setterDesc,
int loadCode,
String readMethodName,
String readMethodDesc,
int storeCode) {
this.interfaceDesc = interfaceDesc;
this.acceptDesc = acceptDesc;
this.setterDesc = setterDesc;
this.loadCode = loadCode;
this.readMethodName = readMethodName;
this.readMethodDesc = readMethodDesc;
this.storeCode = storeCode;
}
}
public ObjectReaderCreatorASM(ClassLoader classLoader) {
this.classLoader = classLoader instanceof DynamicClassLoader
? (DynamicClassLoader) classLoader
: new DynamicClassLoader(classLoader);
}
@Override
public <T> ObjectReader<T> createObjectReader(
Class<T> objectClass,
Type objectType,
boolean fieldBased,
ObjectReaderProvider provider
) {
boolean externalClass = objectClass != null && classLoader.isExternalClass(objectClass);
int objectClassModifiers = objectClass.getModifiers();
if (Modifier.isAbstract(objectClassModifiers) || Modifier.isInterface(objectClassModifiers)) {
return super.createObjectReader(objectClass, objectType, fieldBased, provider);
}
BeanInfo beanInfo = new BeanInfo(provider);
provider.getBeanInfo(beanInfo, objectClass);
if (externalClass || !Modifier.isPublic(objectClassModifiers)) {
beanInfo.readerFeatures |= FieldInfo.JIT;
}
if (beanInfo.deserializer != null && ObjectReader.class.isAssignableFrom(beanInfo.deserializer)) {
try {
Constructor constructor = beanInfo.deserializer.getDeclaredConstructor();
constructor.setAccessible(true);
return (ObjectReader<T>) constructor.newInstance();
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException |
InvocationTargetException e) {
throw new JSONException("create deserializer error", e);
}
}
if (fieldBased && (objectClass.isInterface() || BeanUtils.isRecord(objectClass))) {
fieldBased = false;
}
if (Enum.class.isAssignableFrom(objectClass) && (beanInfo.createMethod == null || beanInfo.createMethod.getParameterCount() == 1)) {
return createEnumReader(objectClass, beanInfo.createMethod, provider);
}
if (beanInfo.creatorConstructor != null || beanInfo.createMethod != null) {
return createObjectReaderWithCreator(objectClass, objectType, provider, beanInfo);
}
if (beanInfo.builder != null) {
return createObjectReaderWithBuilder(objectClass, objectType, provider, beanInfo);
}
if (Throwable.class.isAssignableFrom(objectClass) || BeanUtils.isExtendedMap(objectClass)) {
return super.createObjectReader(objectClass, objectType, fieldBased, provider);
}
if (objectClass == Class.class) {
return ObjectReaderImplClass.INSTANCE;
}
FieldReader[] fieldReaderArray = createFieldReaders(objectClass, objectType, beanInfo, fieldBased, provider);
boolean match = fieldReaderArray.length <= 96;
if (!fieldBased) {
if (JVM_VERSION >= 9 && objectClass == StackTraceElement.class) {
try {
Constructor<StackTraceElement> constructor = StackTraceElement.class.getConstructor(String.class, String.class, String.class, String.class, String.class, String.class, int.class);
return createObjectReaderNoneDefaultConstructor(constructor, "", "classLoaderName", "moduleName", "moduleVersion", "declaringClass", "methodName", "fileName", "lineNumber");
} catch (NoSuchMethodException | SecurityException ignored) {
}
}
for (FieldReader fieldReader : fieldReaderArray) {
if (fieldReader.isReadOnly()
|| fieldReader.isUnwrapped()
) {
match = false;
break;
}
if ((fieldReader.features & FieldInfo.READ_USING_MASK) != 0) {
match = false;
break;
}
}
}
if (beanInfo.autoTypeBeforeHandler != null) {
match = false;
}
if (match) {
for (FieldReader fieldReader : fieldReaderArray) {
if (fieldReader.defaultValue != null || fieldReader.schema != null) {
match = false;
break;
}
Class fieldClass = fieldReader.fieldClass;
if (fieldClass != null && !Modifier.isPublic(fieldClass.getModifiers())) {
match = false;
break;
}
if (fieldReader instanceof FieldReaderMapField
&& ((FieldReaderMapField<?>) fieldReader).arrayToMapKey != null) {
match = false;
break;
}
if (fieldReader instanceof FieldReaderMapMethod
&& ((FieldReaderMapMethod<?>) fieldReader).arrayToMapKey != null) {
match = false;
break;
}
}
}
if (match
&& (beanInfo.rootName != null
|| (beanInfo.schema != null && !beanInfo.schema.isEmpty()))) {
match = false;
}
if (!match) {
return super.createObjectReader(objectClass, objectType, fieldBased, provider);
}
Constructor defaultConstructor = null;
if (!Modifier.isInterface(objectClassModifiers) && !Modifier.isAbstract(objectClassModifiers)) {
Constructor constructor = BeanUtils.getDefaultConstructor(objectClass, true);
if (constructor != null) {
defaultConstructor = constructor;
try {
constructor.setAccessible(true);
} catch (SecurityException ignored) {
// ignored
}
}
}
if (beanInfo.seeAlso != null && beanInfo.seeAlso.length != 0) {
return createObjectReaderSeeAlso(
objectClass,
beanInfo.typeKey,
beanInfo.seeAlso,
beanInfo.seeAlsoNames,
beanInfo.seeAlsoDefault,
fieldReaderArray
);
}
if (!fieldBased) {
if (defaultConstructor == null) {
return super.createObjectReader(objectClass, objectType, false, provider);
}
}
return jitObjectReader(
objectClass,
objectType,
fieldBased,
externalClass,
objectClassModifiers,
beanInfo,
null,
fieldReaderArray,
defaultConstructor
);
}
@Override
protected <T> ObjectReaderNoneDefaultConstructor createNoneDefaultConstructorObjectReader(
Class objectClass,
BeanInfo beanInfo,
Function<Map<Long, Object>, T> constructorFunction,
List<Constructor> alternateConstructors,
String[] parameterNames,
FieldReader[] paramFieldReaders,
FieldReader[] fieldReaderArray
) {
ObjectReaderNoneDefaultConstructor objectReaderAdapter = new ObjectReaderNoneDefaultConstructor(
objectClass,
beanInfo.typeKey,
beanInfo.typeName,
beanInfo.readerFeatures,
constructorFunction,
alternateConstructors,
parameterNames,
paramFieldReaders,
fieldReaderArray,
beanInfo.seeAlso,
beanInfo.seeAlsoNames
);
boolean match = true;
if (beanInfo.autoTypeBeforeHandler != null
|| fieldReaderArray.length != 0
|| (!(constructorFunction instanceof ConstructorFunction) && (!(constructorFunction instanceof FactoryFunction)))
|| (alternateConstructors != null && !alternateConstructors.isEmpty())
|| classLoader.isExternalClass(objectClass)
|| (beanInfo.readerFeatures & JSONReader.Feature.SupportAutoType.mask) != 0
|| (objectReaderAdapter.noneDefaultConstructor != null && objectReaderAdapter.noneDefaultConstructor.getParameterCount() != paramFieldReaders.length)
|| (constructorFunction instanceof FactoryFunction && ((FactoryFunction<T>) constructorFunction).paramNames.length != paramFieldReaders.length)
|| paramFieldReaders.length > 64
) {
match = false;
}
if (match) {
for (FieldReader fieldReader : paramFieldReaders) {
if (fieldReader.getInitReader() != null) {
match = false;
break;
}
if (fieldReader.defaultValue != null || fieldReader.schema != null) {
match = false;
break;
}
Class fieldClass = fieldReader.fieldClass;
if (fieldClass != null && (!Modifier.isPublic(fieldClass.getModifiers()) || classLoader.isExternalClass(fieldClass))) {
match = false;
break;
}
if (fieldReader instanceof FieldReaderMapField
&& ((FieldReaderMapField<?>) fieldReader).arrayToMapKey != null) {
match = false;
break;
}
if (fieldReader instanceof FieldReaderMapMethod
&& ((FieldReaderMapMethod<?>) fieldReader).arrayToMapKey != null) {
match = false;
break;
}
}
}
if (!match) {
return objectReaderAdapter;
}
boolean externalClass = objectClass != null && classLoader.isExternalClass(objectClass);
ClassWriter cw = new ClassWriter(
(e) -> objectClass.getName().equals(e) ? objectClass : null
);
beanInfo.readerFeatures |= FieldInfo.DISABLE_REFERENCE_DETECT;
ObjectReadContext context = new ObjectReadContext(beanInfo, objectClass, cw, externalClass, paramFieldReaders, null);
context.objectReaderAdapter = objectReaderAdapter;
genFields(paramFieldReaders, cw, TYPE_OBJECT_READER_NONE_DEFAULT_CONSTRUCTOR);
cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_SUPER, context.classNameType, TYPE_OBJECT_READER_NONE_DEFAULT_CONSTRUCTOR, new String[]{});
{
String MD_INIT = "(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;JLjava/util/function/Function;Ljava/util/List;[Ljava/lang/String;[Lcom/alibaba/fastjson2/reader/FieldReader;[Lcom/alibaba/fastjson2/reader/FieldReader;[Ljava/lang/Class;[Ljava/lang/String;)V";
MethodWriter mw = cw.visitMethod(
Opcodes.ACC_PUBLIC,
"<init>",
MD_INIT,
fieldReaderArray.length <= 12 ? 32 : 128);
mw.aload(THIS);
mw.aload(1); // CLASS
mw.aload(2); // TYPE_KEY
mw.aload(3); // TYPE_NAME
mw.lload(4); // FEATURES
mw.aload(6); // CREATOR
mw.aload(7); // alternateConstructors
mw.aload(8); // paramNames
mw.aload(9); // paramFieldReaders
mw.aload(10); // setterFieldReaders
mw.aload(11); // seeAlso
mw.aload(12); // seeAlsoNames
mw.invokespecial(TYPE_OBJECT_READER_NONE_DEFAULT_CONSTRUCTOR, "<init>", MD_INIT);
int FIELD_READER_ARRAY = 9;
genInitFields(paramFieldReaders, context.classNameType, true, FIELD_READER_ARRAY, mw, TYPE_OBJECT_READER_NONE_DEFAULT_CONSTRUCTOR);
mw.return_();
mw.visitMaxs(3, 3);
}
genMethodReadObject(context, beanInfo.readerFeatures);
if (!context.disableJSONB()) {
genMethodReadJSONBObject(context, beanInfo.readerFeatures);
}
byte[] code = cw.toByteArray();
try {
Class<?> readerClass = classLoader.defineClassPublic(context.classNameFull, code, 0, code.length);
Constructor<?> constructor = readerClass.getConstructors()[0];
return (ObjectReaderNoneDefaultConstructor) constructor
.newInstance(
objectClass,
beanInfo.typeKey,
beanInfo.typeName,
beanInfo.readerFeatures,
constructorFunction,
alternateConstructors,
parameterNames,
paramFieldReaders,
fieldReaderArray,
null,
null
);
} catch (Throwable e) {
throw new JSONException(
"create objectReader error"
+ (objectClass == null ? "" : ", objectType " + objectClass.getTypeName()), e);
}
}
@Override
public <T> ObjectReader<T> createObjectReader(
Class<T> objectClass,
String typeKey,
String rootName,
long features,
JSONSchema schema,
Supplier<T> defaultCreator,
Function buildFunction,
FieldReader... fieldReaders
) {
if (objectClass == null && defaultCreator != null && buildFunction == null) {
boolean allFunction = true;
for (int i = 0; i < fieldReaders.length; i++) {
FieldReader fieldReader = fieldReaders[i];
if (fieldReader.getFunction() == null) {
allFunction = false;
break;
}
}
if (allFunction) {
BeanInfo beanInfo = new BeanInfo(JSONFactory.getDefaultObjectReaderProvider());
return jitObjectReader(
objectClass,
objectClass,
false,
false,
0,
beanInfo,
defaultCreator,
fieldReaders,
null
);
}
}
return super.createObjectReader(
objectClass,
typeKey,
rootName,
features,
schema,
defaultCreator,
buildFunction,
fieldReaders
);
}
private <T> ObjectReaderBean jitObjectReader(
Class<T> objectClass,
Type objectType,
boolean fieldBased,
boolean externalClass,
int objectClassModifiers,
BeanInfo beanInfo,
Supplier<T> defaultCreator,
FieldReader[] fieldReaderArray,
Constructor defaultConstructor
) {
ClassWriter cw = new ClassWriter(
(e) -> objectClass.getName().equals(e) ? objectClass : null
);
ObjectReadContext context = new ObjectReadContext(beanInfo, objectClass, cw, externalClass, fieldReaderArray, defaultConstructor);
final boolean generatedFields = fieldReaderArray.length <= 96;
String objectReaderSuper;
switch (fieldReaderArray.length) {
case 1:
objectReaderSuper = TYPE_OBJECT_READER_1;
break;
case 2:
objectReaderSuper = TYPE_OBJECT_READER_2;
break;
case 3:
objectReaderSuper = TYPE_OBJECT_READER_3;
break;
case 4:
objectReaderSuper = TYPE_OBJECT_READER_4;
break;
case 5:
objectReaderSuper = TYPE_OBJECT_READER_5;
break;
case 6:
objectReaderSuper = TYPE_OBJECT_READER_6;
break;
case 7:
objectReaderSuper = TYPE_OBJECT_READER_7;
break;
case 8:
objectReaderSuper = TYPE_OBJECT_READER_8;
break;
case 9:
objectReaderSuper = TYPE_OBJECT_READER_9;
break;
case 10:
objectReaderSuper = TYPE_OBJECT_READER_10;
break;
case 11:
objectReaderSuper = TYPE_OBJECT_READER_11;
break;
case 12:
objectReaderSuper = TYPE_OBJECT_READER_12;
break;
default:
objectReaderSuper = TYPE_OBJECT_READER_ADAPTER;
break;
}
if (generatedFields) {
genFields(fieldReaderArray, cw, objectReaderSuper);
}
cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_SUPER, context.classNameType, objectReaderSuper, new String[]{});
{
final int CLASS = 1, SUPPLIER = 2, FIELD_READER_ARRAY = 3;
MethodWriter mw = cw.visitMethod(
Opcodes.ACC_PUBLIC,
"<init>",
METHOD_DESC_INIT,
fieldReaderArray.length <= 12 ? 32 : 128);
mw.aload(THIS);
mw.aload(CLASS);
if (beanInfo.typeKey != null) {
mw.visitLdcInsn(beanInfo.typeKey);
} else {
mw.aconst_null();
}
mw.aconst_null();
mw.visitLdcInsn(beanInfo.readerFeatures);
mw.aconst_null();
mw.aload(SUPPLIER);
mw.aconst_null();
mw.aload(FIELD_READER_ARRAY);
mw.invokespecial(objectReaderSuper, "<init>", METHOD_DESC_ADAPTER_INIT);
genInitFields(fieldReaderArray, context.classNameType, generatedFields, FIELD_READER_ARRAY, mw, objectReaderSuper);
mw.return_();
mw.visitMaxs(3, 3);
}
{
String methodName = fieldBased && defaultConstructor == null ? "createInstance0" : "createInstance";
if ((externalClass && defaultConstructor != null)
|| fieldBased && (defaultConstructor == null || !Modifier.isPublic(defaultConstructor.getModifiers()) || !Modifier.isPublic(objectClass.getModifiers()))) {
MethodWriter mw = cw.visitMethod(
Opcodes.ACC_PUBLIC,
methodName,
"(J)Ljava/lang/Object;",
32
);
mw.getstatic(TYPE_UNSAFE_UTILS, "UNSAFE", "Lsun/misc/Unsafe;");
mw.aload(0);
mw.getfield(TYPE_OBJECT_READER_ADAPTER, "objectClass", "Ljava/lang/Class;");
mw.invokevirtual("sun/misc/Unsafe", "allocateInstance", "(Ljava/lang/Class;)Ljava/lang/Object;");
mw.areturn();
mw.visitMaxs(3, 3);
} else if (defaultConstructor != null && Modifier.isPublic(defaultConstructor.getModifiers()) && Modifier.isPublic(objectClass.getModifiers())) {
MethodWriter mw = cw.visitMethod(
Opcodes.ACC_PUBLIC,
methodName,
"(J)Ljava/lang/Object;",
32
);
newObject(mw, context.objectType, defaultConstructor);
mw.areturn();
mw.visitMaxs(3, 3);
}
}
Supplier<T> supplier;
if (defaultConstructor != null) {
boolean publicObject = Modifier.isPublic(objectClassModifiers) && !classLoader.isExternalClass(objectClass);
boolean jit = !publicObject || !Modifier.isPublic(defaultConstructor.getModifiers());
supplier = createSupplier(defaultConstructor, jit);
} else {
supplier = defaultCreator;
}
if (generatedFields) {
long readerFeatures = beanInfo.readerFeatures;
if (fieldBased) {
readerFeatures |= JSONReader.Feature.FieldBased.mask;
}
boolean disableArrayMapping = context.disableSupportArrayMapping();
boolean disableJSONB = context.disableJSONB();
context.objectReaderAdapter = new ObjectReaderAdapter(objectClass, beanInfo.typeKey, beanInfo.typeName, readerFeatures, null, supplier, null, fieldReaderArray);
if (!disableJSONB) {
genMethodReadJSONBObject(context, readerFeatures);
if (!disableArrayMapping) {
genMethodReadJSONBObjectArrayMapping(context, readerFeatures);
}
}
genMethodReadObject(context, readerFeatures);
if (objectReaderSuper == TYPE_OBJECT_READER_ADAPTER
|| objectReaderSuper == TYPE_OBJECT_READER_1
|| objectReaderSuper == TYPE_OBJECT_READER_2
|| objectReaderSuper == TYPE_OBJECT_READER_3
|| objectReaderSuper == TYPE_OBJECT_READER_4
|| objectReaderSuper == TYPE_OBJECT_READER_5
|| objectReaderSuper == TYPE_OBJECT_READER_6
|| objectReaderSuper == TYPE_OBJECT_READER_7
|| objectReaderSuper == TYPE_OBJECT_READER_8
|| objectReaderSuper == TYPE_OBJECT_READER_9
|| objectReaderSuper == TYPE_OBJECT_READER_10
|| objectReaderSuper == TYPE_OBJECT_READER_11
|| objectReaderSuper == TYPE_OBJECT_READER_12
) {
genMethodGetFieldReader(context);
genMethodGetFieldReaderLCase(context);
}
}
byte[] code = cw.toByteArray();
try {
Class<?> readerClass = classLoader.defineClassPublic(context.classNameFull, code, 0, code.length);
Constructor<?> constructor = readerClass.getConstructors()[0];
return (ObjectReaderBean) constructor
.newInstance(objectClass, supplier, fieldReaderArray);
} catch (Throwable e) {
throw new JSONException(
"create objectReader error"
+ (objectType == null ? "" : ", objectType " + objectType.getTypeName()),
e
);
}
}
private static void newObject(MethodWriter mw, String TYPE_OBJECT, Constructor defaultConstructor) {
mw.new_(TYPE_OBJECT);
mw.dup();
if (defaultConstructor.getParameterCount() == 0) {
mw.invokespecial(TYPE_OBJECT, "<init>", "()V");
} else {
Class paramType = defaultConstructor.getParameterTypes()[0];
mw.aconst_null();
mw.invokespecial(TYPE_OBJECT, "<init>", "(" + ASMUtils.desc(paramType) + ")V");
}
}
private void genMethodGetFieldReader(ObjectReadContext context) {
ObjectReaderAdapter objectReaderAdapter = context.objectReaderAdapter;
FieldReader[] fieldReaderArray = context.fieldReaders;
MethodWriter mw = context.cw.visitMethod(
Opcodes.ACC_PUBLIC,
"getFieldReader",
"(J)" + DESC_FIELD_READER,
512
);
final int HASH_CODE_64 = 1;
final int HASH_CODE_32 = 3;
Label rtnlt = new Label();
if (fieldReaderArray.length > 6) {
Map<Integer, List<Long>> map = new TreeMap();
for (int i = 0; i < objectReaderAdapter.hashCodes.length; i++) {
long hashCode64 = objectReaderAdapter.hashCodes[i];
int hashCode32 = (int) (hashCode64 ^ (hashCode64 >>> 32));
List<Long> hashCode64List = map.computeIfAbsent(hashCode32, k -> new ArrayList<>());
hashCode64List.add(hashCode64);
}
int[] hashCode32Keys = new int[map.size()];
{
int off = 0;
for (Integer key : map.keySet()) {
hashCode32Keys[off++] = key;
}
}
Arrays.sort(hashCode32Keys);
// // int hashCode32 = (int)(hashCode64 ^ (hashCode64 >>> 32));
mw.lload(HASH_CODE_64);
mw.lload(HASH_CODE_64);
mw.bipush(32);
mw.lushr();
mw.lxor();
mw.l2i();
mw.istore(HASH_CODE_32);
Label dflt = new Label();
Label[] labels = new Label[hashCode32Keys.length];
for (int i = 0; i < labels.length; i++) {
labels[i] = new Label();
}
mw.iload(HASH_CODE_32);
mw.visitLookupSwitchInsn(dflt, hashCode32Keys, labels);
for (int i = 0; i < labels.length; i++) {
mw.visitLabel(labels[i]);
int hashCode32 = hashCode32Keys[i];
List<Long> hashCode64Array = map.get(hashCode32);
for (int j = 0, size = hashCode64Array.size(); j < size; j++) {
long hashCode64 = hashCode64Array.get(j);
Label next = size > 1 ? new Label() : dflt;
mw.lload(HASH_CODE_64);
mw.visitLdcInsn(hashCode64);
mw.lcmp();
mw.ifne(next);
int m = Arrays.binarySearch(objectReaderAdapter.hashCodes, hashCode64);
int index = objectReaderAdapter.mapping[m];
mw.aload(THIS);
mw.getfield(context.classNameType, fieldReader(index), DESC_FIELD_READER);
mw.goto_(rtnlt);
if (next != dflt) {
mw.visitLabel(next);
}
}
mw.goto_(dflt);
}
mw.visitLabel(dflt);
} else {
for (int i = 0; i < fieldReaderArray.length; ++i) {
Label next_ = new Label(), get_ = new Label();
String fieldName = fieldReaderArray[i].fieldName;
long hashCode64 = fieldReaderArray[i].fieldNameHash;
mw.lload(HASH_CODE_64);
mw.visitLdcInsn(hashCode64);
mw.lcmp();
mw.ifne(next_);
mw.visitLabel(get_);
mw.aload(THIS);
mw.getfield(context.classNameType, fieldReader(i), DESC_FIELD_READER);
mw.goto_(rtnlt);
mw.visitLabel(next_);
}
}
mw.aconst_null();
mw.areturn();
mw.visitLabel(rtnlt);
mw.areturn();
mw.visitMaxs(5, 5);
}
private void genMethodGetFieldReaderLCase(ObjectReadContext context) {
ObjectReaderAdapter objectReaderAdapter = context.objectReaderAdapter;
FieldReader[] fieldReaderArray = context.fieldReaders;
MethodWriter mw = context.cw.visitMethod(
Opcodes.ACC_PUBLIC,
"getFieldReaderLCase",
"(J)" + DESC_FIELD_READER,
512
);
final int HASH_CODE_64 = 1;
final int HASH_CODE_32 = 3;
Label rtnlt = new Label();
if (fieldReaderArray.length > 6) {
Map<Integer, List<Long>> map = new TreeMap();
for (int i = 0; i < objectReaderAdapter.hashCodesLCase.length; i++) {
long hashCode64 = objectReaderAdapter.hashCodesLCase[i];
int hashCode32 = (int) (hashCode64 ^ (hashCode64 >>> 32));
List<Long> hashCode64List = map.computeIfAbsent(hashCode32, k -> new ArrayList<>());
hashCode64List.add(hashCode64);
}
int[] hashCode32Keys = new int[map.size()];
{
int off = 0;
for (Integer key : map.keySet()) {
hashCode32Keys[off++] = key;
}
}
Arrays.sort(hashCode32Keys);
// // int hashCode32 = (int)(hashCode64 ^ (hashCode64 >>> 32));
mw.lload(HASH_CODE_64);
mw.lload(HASH_CODE_64);
mw.bipush(32);
mw.lushr();
mw.lxor();
mw.l2i();
mw.istore(HASH_CODE_32);
Label dflt = new Label();
Label[] labels = new Label[hashCode32Keys.length];
for (int i = 0; i < labels.length; i++) {
labels[i] = new Label();
}
mw.iload(HASH_CODE_32);
mw.visitLookupSwitchInsn(dflt, hashCode32Keys, labels);
for (int i = 0; i < labels.length; i++) {
mw.visitLabel(labels[i]);
int hashCode32 = hashCode32Keys[i];
List<Long> hashCode64Array = map.get(hashCode32);
for (long hashCode64 : hashCode64Array) {
mw.lload(HASH_CODE_64);
mw.visitLdcInsn(hashCode64);
mw.lcmp();
mw.ifne(dflt);
int m = Arrays.binarySearch(objectReaderAdapter.hashCodesLCase, hashCode64);
int index = objectReaderAdapter.mappingLCase[m];
mw.aload(THIS);
mw.getfield(context.classNameType, fieldReader(index), DESC_FIELD_READER);
mw.goto_(rtnlt);
}
mw.goto_(dflt);
}
mw.visitLabel(dflt);
} else {
for (int i = 0; i < fieldReaderArray.length; ++i) {
Label next_ = new Label(), get_ = new Label();
String fieldName = fieldReaderArray[i].fieldName;
long hashCode64 = fieldReaderArray[i].fieldNameHashLCase;
mw.lload(HASH_CODE_64);
mw.visitLdcInsn(hashCode64);
mw.lcmp();
mw.ifne(next_);
mw.visitLabel(get_);
mw.aload(THIS);
mw.getfield(context.classNameType, fieldReader(i), DESC_FIELD_READER);
mw.goto_(rtnlt);
mw.visitLabel(next_);
}
}
mw.aconst_null();
mw.areturn();
mw.visitLabel(rtnlt);
mw.areturn();
mw.visitMaxs(5, 5);
}
private void genInitFields(
FieldReader[] fieldReaderArray,
String classNameType,
boolean generatedFields,
int FIELD_READER_ARRAY,
MethodWriter mw,
String objectReaderSuper
) {
if ((objectReaderSuper != TYPE_OBJECT_READER_ADAPTER && objectReaderSuper != TYPE_OBJECT_READER_NONE_DEFAULT_CONSTRUCTOR) || !generatedFields) {
return;
}
for (int i = 0; i < fieldReaderArray.length; i++) {
mw.aload(THIS);
mw.aload(FIELD_READER_ARRAY);
mw.iconst_n(i);
mw.aaload();
mw.putfield(classNameType, fieldReader(i), DESC_FIELD_READER);
}
}
private void genFields(FieldReader[] fieldReaderArray, ClassWriter cw, String objectReaderSuper) {
if (objectReaderSuper == TYPE_OBJECT_READER_ADAPTER || objectReaderSuper == TYPE_OBJECT_READER_NONE_DEFAULT_CONSTRUCTOR) {
for (int i = 0; i < fieldReaderArray.length; i++) {
FieldWriter fv = cw.visitField(Opcodes.ACC_PUBLIC, fieldReader(i), DESC_FIELD_READER);
}
for (int i = 0; i < fieldReaderArray.length; i++) {
FieldWriter fv = cw.visitField(Opcodes.ACC_PUBLIC, fieldObjectReader(i), DESC_OBJECT_READER);
}
}
for (int i = 0; i < fieldReaderArray.length; i++) {
Class fieldClass = fieldReaderArray[i].fieldClass;
if (List.class.isAssignableFrom(fieldClass)) {
cw.visitField(Opcodes.ACC_PUBLIC, fieldItemObjectReader(i), DESC_OBJECT_READER);
}
}
}
/**
* <blockquote><pre>
* class Bean {
* private String field1;
* private int field2;
* }
*
* public void readJSONBObject(JSONReader jsonReader, Type fieldType, Object fieldName, long features) {
* features = jsonReader.features(features);
* if (nextIfNull()) {
* return null;
* }
*
* jsonReader.errorOnNoneSerializable(this.objectClass);
*
* if (jsonReader.isArray() && jsonReader.isSupportBeanArray()) {
* return readArrayMappingObject(jsonReader, fieldType, fieldName, features);
* }
*
* Bean object = new Bean();
*
* jsonReader.nextIfObjectStart();
*
* for (;;) {
* if (jsonReader.nextIfObjectEnd()) {
* break;
* }
* switch(jsonReader.getRawInt()) {
* case field1NameHash32:
* if(jsonReader.nextIfName4Match2()) {
* object.field1 = jsonReader.readString();
* break;
* }
* goto hashCode64Start;
* case field2NameHash32:
* if(jsonReader.nextIfName4Match2()) {
* object.field2 = jsonReader.readInt();
* break;
* }
* goto hashCode64Start;
* default:
* goto hashCode64Start;
* }
*
* hashCode64Start:
* long hashCode64 = readFieldNameHashCode();
*
* if (this.typeKeyHashCode == hashCode64) {
* object = this.autoType(jsonReader);
* }
*
* switch(jsonReader.getFieldOrdinal(hashCode64)) {
* case 0:
* object.field1 = jsonReader.readString();
* }
* }
*
*
* }
* </pre></blockquote>
*/
private <T> void genMethodReadJSONBObject(ObjectReadContext context, long readerFeatures) {
String classNameType = context.classNameType;
FieldReader[] fieldReaderArray = context.fieldReaders;
Class objectClass = context.objectClass;
boolean fieldBased = (readerFeatures & JSONReader.Feature.FieldBased.mask) != 0;
ObjectReaderAdapter objectReaderAdapter = context.objectReaderAdapter;
MethodWriter mw = context.cw.visitMethod(Opcodes.ACC_PUBLIC,
"readJSONBObject",
METHOD_DESC_READ_OBJECT,
2048
);
boolean disableArrayMapping = context.disableSupportArrayMapping();
boolean disableAutoType = context.disableAutoType();
MethodWriterContext mwc = new MethodWriterContext(mw, 6, true);
mw.aload(JSON_READER);
mw.lload(FEATURES);
mw.invokevirtual(TYPE_JSON_READER, "features", "(J)J");
mw.lstore(FEATURES);
final int OBJECT = mwc.var("object");
final int I = mwc.var("I");
final int HASH_CODE64 = mwc.var2("hashCode64");
final int HASH_CODE_32 = mwc.var("hashCode32");
final int FIELD_READER = mwc.var("fieldReader");
if (!disableAutoType) {
genCheckAutoType(classNameType, mwc);
}
{
/*
* if (jsonReader.nextIfNull()) {
* return null;
* }
*/
Label notNull_ = new Label();
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "nextIfNull", "()Z");
mw.ifeq(notNull_);
mw.aconst_null();
mw.areturn();
mw.visitLabel(notNull_);
}
if (objectClass != null && !Serializable.class.isAssignableFrom(objectClass)) {
mw.aload(JSON_READER);
mw.aload(THIS);
mw.getfield(classNameType, "objectClass", "Ljava/lang/Class;");
mw.invokevirtual(TYPE_JSON_READER, "errorOnNoneSerializable", "(Ljava/lang/Class;)V");
}
if (!disableArrayMapping) {
Label L0 = new Label();
// if (jsonReader.isArray() && jsonReader.isSupportBeanArray()) {
{
Label startArray_ = new Label(), endArray_ = new Label();
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "isArray", "()Z");
mw.ifeq(L0);
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "isSupportBeanArray", "()Z");
mw.ifeq(endArray_);
mw.aload(THIS);
mw.aload(JSON_READER);
mw.aload(FIELD_TYPE);
mw.aload(FIELD_NAME);
mw.lload(FEATURES);
mw.invokevirtual(classNameType, "readArrayMappingObject", METHOD_DESC_READ_OBJECT);
mw.areturn();
mw.visitLabel(endArray_);
}
mw.visitLabel(L0);
}
if (context.objectReaderAdapter instanceof ObjectReaderNoneDefaultConstructor) {
{
/*
* if (jsonReader.hasAutoTypeBeforeHandler()
* || (features & (JSONReader.Feature.SupportSmartMatch.mask | JSONReader.Feature.SupportAutoType.mask)) != 0
* ) {
* return super.readObject(jsonReader, fieldType, fieldName, features);
* }
*/
Label L3 = new Label(), L4 = new Label();
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "hasAutoTypeBeforeHandler", "()Z");
mw.ifne(L3);
mw.lload(FEATURES);
mw.visitLdcInsn(JSONReader.Feature.SupportSmartMatch.mask | JSONReader.Feature.SupportAutoType.mask);
mw.land();
mw.lconst_0();
mw.lcmp();
mw.ifeq(L4);
mw.visitLabel(L3);
mw.aload(THIS);
mw.aload(JSON_READER);
mw.aload(FIELD_TYPE);
mw.aload(FIELD_NAME);
mw.lload(FEATURES);
mw.invokespecial(TYPE_OBJECT_READER_NONE_DEFAULT_CONSTRUCTOR, "readJSONBObject", METHOD_DESC_READ_OBJECT);
mw.areturn();
mw.visitLabel(L4);
}
genInitForNonDefaultConstructor(fieldReaderArray, mwc);
} else {
genCreateObject(mw, context, classNameType);
mw.astore(OBJECT);
}
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "nextIfObjectStart", "()Z");
mw.pop();
// for (int i = 0; i < entry_cnt; ++i) {
Label L_FOR_START = new Label(), L_FOR_END = new Label(), L_FOR_INC = new Label();
if (!disableAutoType) {
mw.iconst_0();
mw.istore(I);
}
mw.visitLabel(L_FOR_START);
Label hashCode64Start = new Label();
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "nextIfObjectEnd", "()Z");
mw.ifne(L_FOR_END);
boolean switchGen = false;
if (context.fieldNameLengthMin >= 2 && context.fieldNameLengthMax <= 43) {
genRead243(
context,
fieldBased,
mwc,
OBJECT,
L_FOR_INC,
hashCode64Start
);
switchGen = true;
}
mw.visitLabel(hashCode64Start);
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readFieldNameHashCode", "()J");
mw.dup2();
mw.lstore(HASH_CODE64);
mw.lconst_0();
mw.lcmp();
mw.ifeq(L_FOR_INC);
if (!disableAutoType && !(context.objectReaderAdapter instanceof ObjectReaderNoneDefaultConstructor)) {
/*
* if (hashCode64 == this.typeKeyHashCode() && hashCode64 != 0) {
* object = this.autoType(jsonReader);
* }
*/
Label endAutoType_ = new Label();
mw.lload(HASH_CODE64);
mw.aload(THIS);
mw.getfield(classNameType, "typeKeyHashCode", "J");
mw.lcmp();
mw.ifne(endAutoType_);
mw.lload(HASH_CODE64);
mw.lconst_0();
mw.lcmp();
mw.ifeq(endAutoType_);
// protected T autoType(JSONReader jsonReader, int entryCnt) {
mw.aload(THIS);
mw.aload(JSON_READER);
mw.invokevirtual(classNameType, "autoType", "(" + DESC_JSON_READER + ")Ljava/lang/Object;");
mw.astore(OBJECT);
mw.goto_(L_FOR_END);
mw.visitLabel(endAutoType_);
}
if (switchGen) {
if (context.objectReaderAdapter instanceof ObjectReaderNoneDefaultConstructor) {
genReadHashCode64ValueForNonDefaultConstructor(context, mwc, HASH_CODE64, fieldBased, OBJECT, L_FOR_INC);
} else {
/*
* this.readFieldValue(hashCode64, jsonReader, features, object);
*/
mw.aload(THIS);
mw.lload(HASH_CODE64);
mw.aload(JSON_READER);
mw.lload(FEATURES);
mw.aload(OBJECT);
mw.invokevirtual(TYPE_OBJECT_READER_ADAPTER, "readFieldValue", READ_FIELD_READER_UL);
}
mw.goto_(L_FOR_INC); // continue
// continue
} else if (fieldReaderArray.length > 6) {
// use switch
Map<Integer, List<Long>> map = new TreeMap();
for (int i = 0; i < objectReaderAdapter.hashCodes.length; i++) {
long hashCode64 = objectReaderAdapter.hashCodes[i];
int hashCode32 = (int) (hashCode64 ^ (hashCode64 >>> 32));
List<Long> hashCode64List = map.computeIfAbsent(hashCode32, k -> new ArrayList<>());
hashCode64List.add(hashCode64);
}
int[] hashCode32Keys = new int[map.size()];
{
int off = 0;
for (Integer key : map.keySet()) {
hashCode32Keys[off++] = key;
}
}
Arrays.sort(hashCode32Keys);
// int hashCode32 = (int)(hashCode64 ^ (hashCode64 >>> 32));
mw.lload(HASH_CODE64);
mw.lload(HASH_CODE64);
mw.bipush(32);
mw.lushr();
mw.lxor();
mw.l2i();
mw.istore(HASH_CODE_32);
Label dflt = new Label();
Label[] labels = new Label[hashCode32Keys.length];
for (int i = 0; i < labels.length; i++) {
labels[i] = new Label();
}
mw.iload(HASH_CODE_32);
mw.visitLookupSwitchInsn(dflt, hashCode32Keys, labels);
for (int i = 0; i < labels.length; i++) {
mw.visitLabel(labels[i]);
int hashCode32 = hashCode32Keys[i];
List<Long> hashCode64Array = map.get(hashCode32);
for (int j = 0, size = hashCode64Array.size(); j < size; j++) {
long hashCode64 = hashCode64Array.get(j);
Label next = size > 1 ? new Label() : dflt;
mw.lload(HASH_CODE64);
mw.visitLdcInsn(hashCode64);
mw.lcmp();
mw.ifne(next);
int m = Arrays.binarySearch(objectReaderAdapter.hashCodes, hashCode64);
int index = objectReaderAdapter.mapping[m];
FieldReader fieldReader = fieldReaderArray[index];
genReadFieldValue(
context,
fieldReader,
fieldBased,
mwc,
OBJECT,
index,
true // JSONB
);
mw.goto_(L_FOR_INC);
if (next != dflt) {
mw.visitLabel(next);
}
}
mw.goto_(L_FOR_INC);
}
// switch_default
mw.visitLabel(dflt);
boolean disableSmartMatch = context.disableSmartMatch();
if (!disableSmartMatch && !(context.objectReaderAdapter instanceof ObjectReaderNoneDefaultConstructor)) {
Label fieldReaderNull_ = new Label();
if ((readerFeatures & JSONReader.Feature.SupportSmartMatch.mask) == 0) {
mw.aload(JSON_READER);
mw.lload(FEATURES);
mw.invokevirtual(TYPE_JSON_READER, "isSupportSmartMatch", "(J)Z");
mw.ifeq(fieldReaderNull_);
}
mw.aload(THIS);
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "getNameHashCodeLCase", "()J");
mw.invokeinterface(TYPE_OBJECT_READER, "getFieldReaderLCase", METHOD_DESC_GET_FIELD_READER);
mw.dup();
mw.astore(FIELD_READER);
mw.ifnull(fieldReaderNull_);
mw.aload(FIELD_READER);
mw.aload(JSON_READER);
mw.aload(OBJECT);
mw.invokevirtual(TYPE_FIELD_READE, "readFieldValueJSONB", METHOD_DESC_READ_FIELD_VALUE);
mw.goto_(L_FOR_INC); // continue
mw.visitLabel(fieldReaderNull_);
}
} else {
for (int i = 0; i < fieldReaderArray.length; ++i) {
Label next_ = new Label();
// if (hashCode64 == <nameHashCode>) {
FieldReader fieldReader = fieldReaderArray[i];
long hashCode64 = Fnv.hashCode64(fieldReader.fieldName);
mw.lload(HASH_CODE64);
mw.visitLdcInsn(hashCode64);
mw.lcmp();
mw.ifne(next_);
genReadFieldValue(
context,
fieldReader,
fieldBased,
mwc,
OBJECT,
i,
false // arrayMapping
);
mw.goto_(L_FOR_INC); // continue
mw.visitLabel(next_);
}
Label processExtra_ = new Label();
if ((readerFeatures & JSONReader.Feature.SupportSmartMatch.mask) == 0) {
mw.aload(JSON_READER);
mw.lload(FEATURES);
mw.invokevirtual(TYPE_JSON_READER, "isSupportSmartMatch", "(J)Z");
mw.ifeq(processExtra_);
}
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "getNameHashCodeLCase", "()J");
mw.lstore(HASH_CODE64);
for (int i = 0; i < fieldReaderArray.length; ++i) {
Label next_ = new Label();
// if (hashCode64 == <nameHashCode>) {
FieldReader fieldReader = fieldReaderArray[i];
long hashCode64 = Fnv.hashCode64(fieldReader.fieldName);
mw.lload(HASH_CODE64);
mw.visitLdcInsn(hashCode64);
mw.lcmp();
mw.ifne(next_);
genReadFieldValue(
context,
fieldReader,
fieldBased,
mwc,
OBJECT,
i,
false // arrayMapping
);
mw.goto_(L_FOR_INC); // continue
mw.visitLabel(next_);
}
mw.visitLabel(processExtra_);
}
if (context.objectReaderAdapter instanceof ObjectReaderNoneDefaultConstructor) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "skipValue", "()V");
} else {
mw.aload(THIS);
mw.aload(JSON_READER);
mw.aload(OBJECT);
mw.lload(FEATURES);
mw.invokevirtual(TYPE_OBJECT_READER_ADAPTER, "processExtra", METHOD_DESC_PROCESS_EXTRA);
}
mw.goto_(L_FOR_INC); // continue
mw.visitLabel(L_FOR_INC);
if (!disableAutoType) {
mw.visitIincInsn(I, 1);
}
mw.goto_(L_FOR_START);
mw.visitLabel(L_FOR_END);
if (context.objectReaderAdapter instanceof ObjectReaderNoneDefaultConstructor) {
createObjectForNonConstructor(context, mwc);
} else {
mw.aload(OBJECT);
}
mw.areturn();
mw.visitMaxs(5, 10);
}
private void genReadHashCode64ValueForNonDefaultConstructor(
ObjectReadContext context,
MethodWriterContext mwc,
int HASH_CODE64,
boolean fieldBased,
int OBJECT,
Label L_FOR_INC
) {
/*
* swith(this.getFieldOrdinal(hashCode64)) {
* case 0:
* fieldValue0 = ...;
* break;
* case 1:
* fieldValue0 = ...;
* break;
* default:
* skipValue();
* break;
* }
* goto
*/
FieldReader[] fieldReaderArray = context.fieldReaders;
MethodWriter mw = mwc.mw;
mw.aload(THIS);
mw.lload(HASH_CODE64);
mw.invokevirtual(TYPE_OBJECT_READER_ADAPTER, "getFieldOrdinal", "(J)I");
Label dflt = new Label();
Label[] labels = new Label[fieldReaderArray.length];
int[] switchKeys = new int[fieldReaderArray.length];
for (int i = 0; i < fieldReaderArray.length; i++) {
labels[i] = new Label();
switchKeys[i] = i;
}
mw.visitLookupSwitchInsn(dflt, switchKeys, labels);
for (int i = 0; i < fieldReaderArray.length; i++) {
mw.visitLabel(labels[i]);
FieldReader fieldReader = fieldReaderArray[i];
genReadFieldValue(
context,
fieldReader,
fieldBased,
mwc,
OBJECT,
i,
false
);
mw.goto_(L_FOR_INC);
}
// jsonReader.skipValue();
mw.visitLabel(dflt);
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "skipValue", "()V");
}
private <T> void genMethodReadJSONBObjectArrayMapping(ObjectReadContext context, long readerFeatures) {
FieldReader[] fieldReaderArray = context.fieldReaders;
String classNameType = context.classNameType;
boolean fieldBased = (readerFeatures & JSONReader.Feature.FieldBased.mask) != 0;
MethodWriter mw = context.cw.visitMethod(Opcodes.ACC_PUBLIC,
"readArrayMappingJSONBObject",
METHOD_DESC_READ_OBJECT,
512
);
MethodWriterContext mwc = new MethodWriterContext(mw, 6, true);
mw.aload(JSON_READER);
mw.lload(FEATURES);
mw.invokevirtual(TYPE_JSON_READER, "features", "(J)J");
mw.lstore(FEATURES);
final int OBJECT = mwc.var("object");
final int ENTRY_CNT = mwc.var("entryCnt");
if (!context.disableAutoType()) {
genCheckAutoType(classNameType, mwc);
}
{
Label notNull_ = new Label();
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "nextIfNull", "()Z");
mw.ifeq(notNull_);
mw.aconst_null();
mw.areturn();
mw.visitLabel(notNull_);
}
genCreateObject(mw, context, classNameType);
mw.astore(OBJECT);
Label fieldEnd_ = new Label(), entryCountMatch_ = new Label();
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "startArray", "()I");
mw.dup();
mw.istore(ENTRY_CNT);
mw.visitLdcInsn(fieldReaderArray.length);
mw.if_icmpne(entryCountMatch_);
for (int i = 0; i < fieldReaderArray.length; ++i) {
FieldReader fieldReader = fieldReaderArray[i];
genReadFieldValue(
context,
fieldReader,
fieldBased,
mwc,
OBJECT,
i,
true // arrayMapping
);
}
mw.goto_(fieldEnd_);
mw.visitLabel(entryCountMatch_);
mw.aload(THIS);
mw.aload(JSON_READER);
mw.aload(OBJECT);
mw.iload(ENTRY_CNT);
mw.invokevirtual(TYPE_OBJECT_READER_ADAPTER, "readArrayMappingJSONBObject0", METHOD_DESC_READ_ARRAY_MAPPING_JSONB_OBJECT0);
mw.visitLabel(fieldEnd_);
mw.aload(OBJECT);
mw.areturn();
mw.visitMaxs(5, 10);
}
private void genCheckAutoType(String classNameType, MethodWriterContext mwc) {
MethodWriter mw = mwc.mw;
int AUTO_TYPE_OBJECT_READER = mwc.var("autoTypeObjectReader");
Label checkArrayAutoTypeNull_ = new Label();
mw.aload(THIS);
mw.aload(JSON_READER);
mw.lload(FEATURES);
mw.invokevirtual(classNameType, "checkAutoType", METHOD_DESC_JSON_READER_CHECK_ARRAY_AUTO_TYPE);
mw.dup();
mw.astore(AUTO_TYPE_OBJECT_READER);
mw.ifnull(checkArrayAutoTypeNull_);
mw.aload(AUTO_TYPE_OBJECT_READER);
mw.aload(JSON_READER);
mw.aload(FIELD_TYPE);
mw.aload(FIELD_NAME);
mw.lload(FEATURES);
mw.invokeinterface(TYPE_OBJECT_READER, "readJSONBObject", METHOD_DESC_READ_OBJECT);
mw.areturn();
mw.visitLabel(checkArrayAutoTypeNull_);
}
private <T> void genMethodReadObject(ObjectReadContext context, long readerFeatures) {
FieldReader[] fieldReaderArray = context.fieldReaders;
String classNameType = context.classNameType;
boolean fieldBased = (readerFeatures & JSONReader.Feature.FieldBased.mask) != 0;
MethodWriter mw = context.cw.visitMethod(
Opcodes.ACC_PUBLIC,
"readObject",
METHOD_DESC_READ_OBJECT,
2048
);
MethodWriterContext mwc = new MethodWriterContext(mw, 6, false);
final int OBJECT = mwc.var("object");
final int I = mwc.var("I");
final int HASH_CODE64 = mwc.var2("hashCode64");
final int HASH_CODE_32 = mwc.var("hashCode32");
final int FIELD_READER = mwc.var("fieldReader");
boolean disableArrayMapping = context.disableSupportArrayMapping();
boolean disableAutoType = context.disableAutoType();
boolean disableJSONB = context.disableJSONB();
boolean disableSmartMatch = context.disableSmartMatch();
if (!disableJSONB) {
/*
* if (jsonReader.json) {
* return readJSONBObject(jsonReader, fieldType, fieldName, features);
* }
*/
Label L0 = new Label();
mw.aload(JSON_READER);
mw.getfield(TYPE_JSON_READER, "jsonb", "Z");
mw.ifeq(L0);
mw.aload(THIS);
mw.aload(JSON_READER);
mw.aload(FIELD_TYPE);
mw.aload(FIELD_NAME);
mw.lload(FEATURES);
mw.invokevirtual(classNameType, "readJSONBObject", METHOD_DESC_READ_OBJECT);
mw.areturn();
mw.visitLabel(L0);
}
/*
* long features = jsonReader.features(features);
*/
mw.aload(JSON_READER);
mw.lload(FEATURES);
mw.invokevirtual(TYPE_JSON_READER, "features", "(J)J");
mw.lstore(FEATURES);
if (!disableSmartMatch || !disableArrayMapping) {
/*
* if (jsonReader.isArray()) {
* if ((features & JSONReader.Feature.SupportArrayToBean.mask) != 0) {
* return readArrayMappingObject(jsonReader, fieldType, fieldName, features);
* }
* return processObjectInputSingleItemArray(jsonReader, fieldType, fieldName, features);
* }
*/
Label L1 = new Label();
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "isArray", "()Z");
mw.ifeq(L1);
if (!disableArrayMapping) {
Label singleItemArray_ = new Label();
if ((readerFeatures & JSONReader.Feature.SupportArrayToBean.mask) == 0) {
mw.aload(JSON_READER);
mw.lload(FEATURES);
mw.invokevirtual(TYPE_JSON_READER, "isSupportBeanArray", "(J)Z");
mw.ifeq(singleItemArray_);
}
mw.aload(THIS);
mw.aload(JSON_READER);
mw.aload(FIELD_TYPE);
mw.aload(FIELD_NAME);
mw.lload(FEATURES);
mw.invokevirtual(classNameType, "readArrayMappingObject", METHOD_DESC_READ_OBJECT);
mw.areturn();
mw.visitLabel(singleItemArray_);
}
mw.aload(THIS);
mw.aload(JSON_READER);
mw.aload(FIELD_TYPE);
mw.aload(FIELD_NAME);
mw.lload(FEATURES);
mw.invokevirtual(classNameType, "processObjectInputSingleItemArray", METHOD_DESC_READ_OBJECT);
mw.areturn();
mw.visitLabel(L1);
}
Label end_ = new Label();
{
/*
* if (jsonReader.nextIfObjectStart()) {
* if (jsonReader.nextIfNull()) {
* return null;
* }
* }
*/
Label L2 = new Label();
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "nextIfObjectStart", "()Z");
mw.ifne(L2);
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "nextIfNullOrEmptyString", "()Z");
mw.ifeq(L2);
mw.aconst_null();
mw.areturn();
mw.visitLabel(L2);
}
if (context.objectReaderAdapter instanceof ObjectReaderNoneDefaultConstructor) {
{
/*
* if (jsonReader.hasAutoTypeBeforeHandler()
* || (features & (JSONReader.Feature.SupportSmartMatch.mask | JSONReader.Feature.SupportAutoType.mask)) != 0
* ) {
* return super.readObject(jsonReader, fieldType, fieldName, features);
* }
*/
Label L3 = new Label(), L4 = new Label();
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "hasAutoTypeBeforeHandler", "()Z");
mw.ifne(L3);
mw.lload(FEATURES);
mw.visitLdcInsn(JSONReader.Feature.SupportSmartMatch.mask | JSONReader.Feature.SupportAutoType.mask);
mw.land();
mw.lconst_0();
mw.lcmp();
mw.ifeq(L4);
mw.visitLabel(L3);
mw.aload(THIS);
mw.aload(JSON_READER);
mw.aload(FIELD_TYPE);
mw.aload(FIELD_NAME);
mw.lload(FEATURES);
mw.invokespecial(TYPE_OBJECT_READER_NONE_DEFAULT_CONSTRUCTOR, "readObject", METHOD_DESC_READ_OBJECT);
mw.areturn();
mw.visitLabel(L4);
}
genInitForNonDefaultConstructor(fieldReaderArray, mwc);
} else {
genCreateObject(mw, context, classNameType);
mw.astore(OBJECT);
}
/*
* for (int i = 0; i < entry_cnt; ++i) {
* long hashCode64 = jsonReader.readFieldNameHashCode();
* }
*/
Label L_FOR_START = new Label(), L_FOR_END = new Label(), L_FOR_INC = new Label();
if (!disableAutoType) {
mw.iconst_0();
mw.istore(I);
}
mw.visitLabel(L_FOR_START);
Label hashCode64Start = new Label();
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "nextIfObjectEnd", "()Z");
mw.ifne(L_FOR_END);
boolean switchGen = false;
if (context.fieldNameLengthMin >= 5 && context.fieldNameLengthMax <= 7) {
genRead57(
context,
fieldBased,
mwc,
OBJECT,
L_FOR_INC,
hashCode64Start
);
switchGen = true;
} else if (context.fieldNameLengthMin >= 2 && context.fieldNameLengthMax <= 43) {
genRead243(
context,
fieldBased,
mwc,
OBJECT,
L_FOR_INC,
hashCode64Start
);
switchGen = true;
}
mw.visitLabel(hashCode64Start);
{
/*
* long hashCode64 = jsonReader.readFieldNameHashCode();
* if (hashCode64 == -1) {
* break;
* }
*/
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readFieldNameHashCode", "()J");
mw.dup2();
mw.lstore(HASH_CODE64);
mw.visitLdcInsn(-1L);
mw.lcmp();
mw.ifeq(L_FOR_END);
}
if (!disableAutoType && !(context.objectReaderAdapter instanceof ObjectReaderNoneDefaultConstructor)) {
Label noneAutoType_ = new Label();
// if (i != 0 && hash == HASH_TYPE && jsonReader.isSupportAutoType())
mw.iload(I);
mw.ifne(noneAutoType_);
mw.lload(HASH_CODE64);
mw.visitLdcInsn(HASH_TYPE);
mw.lcmp();
mw.ifne(noneAutoType_);
if ((readerFeatures & JSONReader.Feature.SupportAutoType.mask) == 0) {
mw.aload(JSON_READER);
mw.lload(FEATURES);
mw.invokevirtual(TYPE_JSON_READER, "isSupportAutoTypeOrHandler", "(J)Z");
mw.ifeq(noneAutoType_);
}
mw.aload(THIS);
mw.aload(JSON_READER);
mw.aload(THIS);
mw.getfield(classNameType, "objectClass", "Ljava/lang/Class;");
mw.lload(FEATURES);
mw.invokevirtual(TYPE_OBJECT_READER_ADAPTER, "autoType", "(" + ASMUtils.desc(JSONReader.class) + "Ljava/lang/Class;J)Ljava/lang/Object;");
mw.areturn();
mw.visitLabel(noneAutoType_);
}
// continue
if (switchGen) {
if (context.objectReaderAdapter instanceof ObjectReaderNoneDefaultConstructor) {
genReadHashCode64ValueForNonDefaultConstructor(context, mwc, HASH_CODE64, fieldBased, OBJECT, L_FOR_INC);
} else {
/*
* this.readFieldValue(hashCode64, jsonReader, features, object);
*/
mw.aload(THIS);
mw.lload(HASH_CODE64);
mw.aload(JSON_READER);
mw.lload(FEATURES);
mw.aload(OBJECT);
mw.invokevirtual(TYPE_OBJECT_READER_ADAPTER, "readFieldValue", READ_FIELD_READER_UL);
}
mw.goto_(L_FOR_INC); // continue
} else if (fieldReaderArray.length > 6) {
// use switch
Map<Integer, List<Long>> map = new TreeMap();
for (int i = 0; i < context.objectReaderAdapter.hashCodes.length; i++) {
long hashCode64 = context.objectReaderAdapter.hashCodes[i];
int hashCode32 = (int) (hashCode64 ^ (hashCode64 >>> 32));
List<Long> hashCode64List = map.computeIfAbsent(hashCode32, k -> new ArrayList<>());
hashCode64List.add(hashCode64);
}
int[] hashCode32Keys = new int[map.size()];
{
int off = 0;
for (Integer key : map.keySet()) {
hashCode32Keys[off++] = key;
}
}
Arrays.sort(hashCode32Keys);
// int hashCode32 = (int)(hashCode64 ^ (hashCode64 >>> 32));
mw.lload(HASH_CODE64);
mw.lload(HASH_CODE64);
mw.bipush(32);
mw.lushr();
mw.lxor();
mw.l2i();
mw.istore(HASH_CODE_32);
Label dflt = new Label();
Label[] labels = new Label[hashCode32Keys.length];
for (int i = 0; i < labels.length; i++) {
labels[i] = new Label();
}
mw.iload(HASH_CODE_32);
mw.visitLookupSwitchInsn(dflt, hashCode32Keys, labels);
for (int i = 0; i < labels.length; i++) {
mw.visitLabel(labels[i]);
int hashCode32 = hashCode32Keys[i];
List<Long> hashCode64Array = map.get(hashCode32);
for (int j = 0, size = hashCode64Array.size(); j < size; j++) {
long hashCode64 = hashCode64Array.get(j);
Label next = size > 1 ? new Label() : dflt;
mw.lload(HASH_CODE64);
mw.visitLdcInsn(hashCode64);
mw.lcmp();
mw.ifne(next);
int m = Arrays.binarySearch(context.objectReaderAdapter.hashCodes, hashCode64);
int index = context.objectReaderAdapter.mapping[m];
FieldReader fieldReader = fieldReaderArray[index];
genReadFieldValue(
context,
fieldReader,
fieldBased,
mwc,
OBJECT,
index,
false // arrayMapping
);
mw.goto_(L_FOR_INC);
if (next != dflt) {
mw.visitLabel(next);
}
}
mw.goto_(L_FOR_INC);
}
mw.visitLabel(dflt);
if (!disableSmartMatch && !(context.objectReaderAdapter instanceof ObjectReaderNoneDefaultConstructor)) {
Label fieldReaderNull_ = new Label();
if ((readerFeatures & JSONReader.Feature.SupportSmartMatch.mask) == 0) {
mw.lload(FEATURES);
mw.visitLdcInsn(JSONReader.Feature.SupportSmartMatch.mask);
mw.land();
mw.lconst_0();
mw.lcmp();
mw.ifeq(fieldReaderNull_);
}
mw.aload(THIS);
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "getNameHashCodeLCase", "()J");
mw.invokeinterface(TYPE_OBJECT_READER, "getFieldReaderLCase", METHOD_DESC_GET_FIELD_READER);
mw.dup();
mw.astore(FIELD_READER);
mw.ifnull(fieldReaderNull_);
mw.aload(FIELD_READER);
mw.aload(JSON_READER);
mw.aload(OBJECT);
mw.invokevirtual(TYPE_FIELD_READE, "readFieldValue", METHOD_DESC_READ_FIELD_VALUE);
mw.goto_(L_FOR_INC); // continue
mw.visitLabel(fieldReaderNull_);
}
} else {
for (int i = 0; i < fieldReaderArray.length; ++i) {
Label next_ = new Label(), get_ = new Label();
// if (hashCode64 == <nameHashCode>) {
FieldReader fieldReader = fieldReaderArray[i];
String fieldName = fieldReader.fieldName;
long hashCode64 = fieldReader.fieldNameHash;
mw.lload(HASH_CODE64);
mw.visitLdcInsn(hashCode64);
mw.lcmp();
mw.ifne(next_);
mw.visitLabel(get_);
genReadFieldValue(
context,
fieldReader,
fieldBased,
mwc,
OBJECT,
i,
false // arrayMapping
);
mw.goto_(L_FOR_INC); // continue
mw.visitLabel(next_);
}
Label processExtra_ = new Label();
if (!disableSmartMatch) {
if ((readerFeatures & JSONReader.Feature.SupportSmartMatch.mask) == 0) {
mw.lload(FEATURES);
mw.visitLdcInsn(JSONReader.Feature.SupportSmartMatch.mask);
mw.land();
mw.lconst_0();
mw.lcmp();
mw.ifeq(processExtra_);
}
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "getNameHashCodeLCase", "()J");
mw.lstore(HASH_CODE64);
for (int i = 0; i < fieldReaderArray.length; ++i) {
Label next_ = new Label(), get_ = new Label();
// if (hashCode64 == <nameHashCode>) {
FieldReader fieldReader = fieldReaderArray[i];
String fieldName = fieldReader.fieldName;
long hashCode64 = fieldReader.fieldNameHash;
long hashCode64LCase = fieldReader.fieldNameHashLCase;
mw.lload(HASH_CODE64);
mw.visitLdcInsn(hashCode64);
mw.lcmp();
mw.ifeq(get_);
if (hashCode64LCase != hashCode64) {
mw.lload(HASH_CODE64);
mw.visitLdcInsn(hashCode64LCase);
mw.lcmp();
mw.ifne(next_);
} else {
mw.goto_(next_);
}
mw.visitLabel(get_);
genReadFieldValue(
context,
fieldReader,
fieldBased,
mwc,
OBJECT,
i,
false // arrayMapping
);
mw.goto_(L_FOR_INC); // continue
mw.visitLabel(next_);
}
}
mw.visitLabel(processExtra_);
}
if (!switchGen) {
if (context.objectReaderAdapter instanceof ObjectReaderNoneDefaultConstructor) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "skipValue", "()V");
} else {
mw.aload(THIS);
mw.aload(JSON_READER);
mw.aload(OBJECT);
mw.lload(FEATURES);
mw.invokevirtual(TYPE_OBJECT_READER_ADAPTER, "processExtra", METHOD_DESC_PROCESS_EXTRA);
}
mw.goto_(L_FOR_INC); // continue
}
mw.visitLabel(L_FOR_INC);
if (!disableAutoType) {
mw.visitIincInsn(I, 1);
}
mw.goto_(L_FOR_START);
mw.visitLabel(L_FOR_END);
mw.visitLabel(end_);
if (context.objectReaderAdapter instanceof ObjectReaderNoneDefaultConstructor) {
createObjectForNonConstructor(context, mwc);
} else {
mw.aload(OBJECT);
}
mw.areturn();
mw.visitMaxs(5, 10);
}
private void createObjectForNonConstructor(ObjectReadContext context, MethodWriterContext mwc) {
FieldReader[] fieldReaderArray = context.fieldReaders;
MethodWriter mw = mwc.mw;
ObjectReaderNoneDefaultConstructor objectReaderNoneDefaultConstructor = (ObjectReaderNoneDefaultConstructor) context.objectReaderAdapter;
boolean constructDirect = true;
if (classLoader.isExternalClass(context.objectClass)
|| context.objectClass.getTypeParameters().length != 0
|| (objectReaderNoneDefaultConstructor.constructor != null && !Modifier.isPublic(objectReaderNoneDefaultConstructor.constructor.getModifiers()))
|| (context.objectClass != null && !Modifier.isPublic(context.objectClass.getModifiers()))
|| objectReaderNoneDefaultConstructor.factoryFunction != null
|| objectReaderNoneDefaultConstructor.noneDefaultConstructor != null && !Modifier.isPublic(objectReaderNoneDefaultConstructor.noneDefaultConstructor.getModifiers())
) {
constructDirect = false;
}
if (constructDirect) {
mw.new_(context.objectType);
mw.dup();
StringBuilder buf = new StringBuilder().append("(");
for (FieldReader fieldReader : fieldReaderArray) {
mw.loadLocal(fieldReader.fieldClass, mwc.var(fieldReader));
buf.append(ASMUtils.desc(fieldReader.fieldClass));
}
buf.append(")V");
mw.invokespecial(context.objectType, "<init>", buf.toString());
} else {
mw.aload(THIS);
mw.iconst_n(fieldReaderArray.length);
mw.anewArray("java/lang/Object");
for (int i = 0; i < fieldReaderArray.length; i++) {
FieldReader fieldReader = fieldReaderArray[i];
mw.dup();
mw.iconst_n(i);
mw.loadLocal(fieldReader.fieldClass, mwc.var(fieldReader));
if (fieldReader.fieldClass == int.class) {
mw.invokestatic("java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
} else if (fieldReader.fieldClass == long.class) {
mw.invokestatic("java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");
} else if (fieldReader.fieldClass == float.class) {
mw.invokestatic("java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");
} else if (fieldReader.fieldClass == double.class) {
mw.invokestatic("java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");
} else if (fieldReader.fieldClass == boolean.class) {
mw.invokestatic("java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;");
} else if (fieldReader.fieldClass == short.class) {
mw.invokestatic("java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");
} else if (fieldReader.fieldClass == byte.class) {
mw.invokestatic("java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");
} else if (fieldReader.fieldClass == char.class) {
mw.invokestatic("java/lang/Character", "valueOf", "(C)Ljava/lang/Character;");
}
mw.aastore();
}
mw.invokevirtual(TYPE_OBJECT_READER_NONE_DEFAULT_CONSTRUCTOR, "createInstance", "([Ljava/lang/Object;)Ljava/lang/Object;");
}
}
private static void genInitForNonDefaultConstructor(FieldReader[] fieldReaderArray, MethodWriterContext mwc) {
MethodWriter mw = mwc.mw;
for (FieldReader fieldReader : fieldReaderArray) {
Class fieldClass = fieldReader.fieldClass;
int var = mwc.var(fieldReader);
if (fieldClass == byte.class || fieldClass == short.class || fieldClass == int.class || fieldClass == boolean.class || fieldClass == char.class) {
mw.iconst_0();
mw.istore(var);
} else if (fieldClass == long.class) {
mw.lconst_0();
mw.lstore(var);
} else if (fieldClass == float.class) {
mw.iconst_0();
mw.i2f();
mw.fstore(var);
} else if (fieldClass == double.class) {
mw.iconst_0();
mw.i2d();
mw.dstore(var);
} else {
mw.aconst_null();
mw.astore(var);
}
}
}
private void genRead243(
ObjectReadContext context,
boolean fieldBased,
MethodWriterContext mwc,
int OBJECT,
Label L_FOR_INC,
Label hashCode64Start
) {
String classNameType = context.classNameType;
FieldReader[] fieldReaderArray = context.fieldReaders;
boolean jsonb = mwc.jsonb;
MethodWriter mw = mwc.mw;
IdentityHashMap<FieldReader, Integer> readerIndexMap = new IdentityHashMap<>();
Map<Integer, List<FieldReader>> name0Map = new TreeMap<>();
for (int i = 0; i < fieldReaderArray.length; ++i) {
FieldReader fieldReader = fieldReaderArray[i];
readerIndexMap.put(fieldReader, i);
byte[] name0Bytes = new byte[4];
if (jsonb) {
byte[] fieldNameJSONB = JSONB.toBytes(fieldReader.fieldName);
System.arraycopy(fieldNameJSONB, 0, name0Bytes, 0, Math.min(4, fieldNameJSONB.length));
} else {
byte[] fieldName = fieldReader.fieldName.getBytes(StandardCharsets.UTF_8);
name0Bytes[0] = '"';
if (fieldName.length == 2) {
System.arraycopy(fieldName, 0, name0Bytes, 1, 2);
name0Bytes[3] = '"';
} else {
System.arraycopy(fieldName, 0, name0Bytes, 1, 3);
}
}
int name0 = UNSAFE.getInt(name0Bytes, ARRAY_BYTE_BASE_OFFSET);
List<FieldReader> fieldReaders = name0Map.get(name0);
if (fieldReaders == null) {
fieldReaders = new ArrayList<>();
name0Map.put(name0, fieldReaders);
}
fieldReaders.add(fieldReader);
}
Label dflt = new Label();
int[] switchKeys = new int[name0Map.size()];
Label[] labels = new Label[name0Map.size()];
{
Iterator it = name0Map.keySet().iterator();
for (int i = 0; i < labels.length; i++) {
labels[i] = new Label();
switchKeys[i] = (Integer) it.next();
}
}
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "getRawInt", "()I");
mw.visitLookupSwitchInsn(dflt, switchKeys, labels);
for (int i = 0; i < labels.length; i++) {
mw.visitLabel(labels[i]);
int name0 = switchKeys[i];
List<FieldReader> fieldReaders = name0Map.get(name0);
for (int j = 0; j < fieldReaders.size(); j++) {
Label nextJ = null;
if (j + 1 != fieldReaders.size()) {
nextJ = new Label();
}
FieldReader fieldReader = fieldReaders.get(j);
int fieldReaderIndex = readerIndexMap.get(fieldReader);
byte[] fieldName = fieldReader.fieldName.getBytes(StandardCharsets.UTF_8);
int fieldNameLength = fieldName.length;
switch (fieldNameLength) {
case 2:
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match2", "()Z");
break;
case 3:
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match3", "()Z");
break;
case 4: {
mw.aload(JSON_READER);
mw.iconst_n(fieldName[3]);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match4", "(B)Z");
break;
}
case 5: {
byte[] bytes4 = new byte[4];
bytes4[0] = fieldName[3];
bytes4[1] = fieldName[4];
bytes4[2] = '"';
bytes4[3] = ':';
int name1 = UNSAFE.getInt(bytes4, ARRAY_BYTE_BASE_OFFSET);
if (jsonb) {
name1 &= 0xFFFF;
}
mw.aload(JSON_READER);
mw.iconst_n(name1);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match5", "(I)Z");
break;
}
case 6: {
byte[] bytes4 = new byte[4];
bytes4[0] = fieldName[3];
bytes4[1] = fieldName[4];
bytes4[2] = fieldName[5];
bytes4[3] = '"';
int name1 = UNSAFE.getInt(bytes4, ARRAY_BYTE_BASE_OFFSET);
if (jsonb) {
name1 &= 0xFFFFFF;
}
mw.aload(JSON_READER);
mw.iconst_n(name1);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match6", "(I)Z");
break;
}
case 7: {
int name1 = UNSAFE.getInt(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
mw.aload(JSON_READER);
mw.iconst_n(name1);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match7", "(I)Z");
break;
}
case 8: {
int name1 = UNSAFE.getInt(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
mw.aload(JSON_READER);
mw.iconst_n(name1);
mw.iconst_n(fieldName[7]);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match8", "(IB)Z");
break;
}
case 9: {
byte[] bytes8 = new byte[8];
System.arraycopy(fieldName, 3, bytes8, 0, 6);
bytes8[6] = '"';
bytes8[7] = ':';
long name1 = UNSAFE.getLong(bytes8, ARRAY_BYTE_BASE_OFFSET);
if (jsonb) {
name1 &= 0xFFFFFFFFFFFFL;
}
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match9", "(J)Z");
break;
}
case 10: {
byte[] bytes8 = new byte[8];
System.arraycopy(fieldName, 3, bytes8, 0, 7);
bytes8[7] = '"';
long name1 = UNSAFE.getLong(bytes8, ARRAY_BYTE_BASE_OFFSET);
if (jsonb) {
name1 &= 0xFFFFFFFFFFFFFFL;
}
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match10", "(J)Z");
break;
}
case 11: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match11", "(J)Z");
break;
}
case 12: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.iconst_n(fieldName[11]);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match12", "(JB)Z");
break;
}
case 13: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
byte[] bytes4 = new byte[4];
bytes4[0] = fieldName[11];
bytes4[1] = fieldName[12];
bytes4[2] = '"';
bytes4[3] = ':';
int name2 = UNSAFE.getInt(bytes4, ARRAY_BYTE_BASE_OFFSET);
if (jsonb) {
name2 &= 0xFFFF;
}
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.iconst_n(name2);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match13", "(JI)Z");
break;
}
case 14: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
byte[] bytes4 = new byte[4];
bytes4[0] = fieldName[11];
bytes4[1] = fieldName[12];
bytes4[2] = fieldName[13];
bytes4[3] = '"';
int name2 = UNSAFE.getInt(bytes4, ARRAY_BYTE_BASE_OFFSET);
if (jsonb) {
name2 &= 0xFFFFFF;
}
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.iconst_n(name2);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match14", "(JI)Z");
break;
}
case 15: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
int name2 = UNSAFE.getInt(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.iconst_n(name2);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match15", "(JI)Z");
break;
}
case 16: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
int name2 = UNSAFE.getInt(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.iconst_n(name2);
mw.visitLdcInsn(fieldName[15]);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match16", "(JIB)Z");
break;
}
case 17: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
byte[] bytes8 = new byte[8];
System.arraycopy(fieldName, 11, bytes8, 0, 6);
bytes8[6] = '"';
bytes8[7] = ':';
long name2 = UNSAFE.getLong(bytes8, ARRAY_BYTE_BASE_OFFSET);
if (jsonb) {
name2 &= 0xFFFFFFFFFFFFL;
}
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.visitLdcInsn(name2);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match17", "(JJ)Z");
break;
}
case 18: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
byte[] bytes8 = new byte[8];
System.arraycopy(fieldName, 11, bytes8, 0, 7);
bytes8[7] = '"';
long name2 = UNSAFE.getLong(bytes8, ARRAY_BYTE_BASE_OFFSET);
if (jsonb) {
name2 &= 0xFFFFFFFFFFFFFFL;
}
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.visitLdcInsn(name2);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match18", "(JJ)Z");
break;
}
case 19: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.visitLdcInsn(name2);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match19", "(JJ)Z");
break;
}
case 20: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.visitLdcInsn(name2);
mw.iconst_n(fieldName[19]);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match20", "(JJB)Z");
break;
}
case 21: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
byte[] bytes4 = new byte[4];
bytes4[0] = fieldName[19];
bytes4[1] = fieldName[20];
bytes4[2] = '"';
bytes4[3] = ':';
int name3 = UNSAFE.getInt(bytes4, ARRAY_BYTE_BASE_OFFSET);
if (jsonb) {
name3 &= 0xFFFF;
}
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.visitLdcInsn(name2);
mw.iconst_n(name3);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match21", "(JJI)Z");
break;
}
case 22: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
byte[] bytes4 = new byte[4];
bytes4[0] = fieldName[19];
bytes4[1] = fieldName[20];
bytes4[2] = fieldName[21];
bytes4[3] = '"';
int name3 = UNSAFE.getInt(bytes4, ARRAY_BYTE_BASE_OFFSET);
if (jsonb) {
name3 &= 0xFFFFFF;
}
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.visitLdcInsn(name2);
mw.iconst_n(name3);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match22", "(JJI)Z");
break;
}
case 23: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
int name3 = UNSAFE.getInt(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.visitLdcInsn(name2);
mw.iconst_n(name3);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match23", "(JJI)Z");
break;
}
case 24: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
int name3 = UNSAFE.getInt(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.visitLdcInsn(name2);
mw.iconst_n(name3);
mw.visitLdcInsn(fieldName[23]);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match24", "(JJIB)Z");
break;
}
case 25: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
byte[] bytes8 = new byte[8];
System.arraycopy(fieldName, 19, bytes8, 0, 6);
bytes8[6] = '"';
bytes8[7] = ':';
long name3 = UNSAFE.getLong(bytes8, ARRAY_BYTE_BASE_OFFSET);
if (jsonb) {
name3 &= 0xFFFFFFFFFFFFL;
}
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.visitLdcInsn(name2);
mw.visitLdcInsn(name3);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match25", "(JJJ)Z");
break;
}
case 26: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
byte[] bytes8 = new byte[8];
System.arraycopy(fieldName, 19, bytes8, 0, 7);
bytes8[7] = '"';
long name3 = UNSAFE.getLong(bytes8, ARRAY_BYTE_BASE_OFFSET);
if (jsonb) {
name3 &= 0xFFFFFFFFFFFFFFL;
}
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.visitLdcInsn(name2);
mw.visitLdcInsn(name3);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match26", "(JJJ)Z");
break;
}
case 27: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.visitLdcInsn(name2);
mw.visitLdcInsn(name3);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match27", "(JJJ)Z");
break;
}
case 28: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.visitLdcInsn(name2);
mw.visitLdcInsn(name3);
mw.visitLdcInsn(fieldName[27]);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match28", "(JJJB)Z");
break;
}
case 29: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
byte[] bytes4 = new byte[4];
bytes4[0] = fieldName[27];
bytes4[1] = fieldName[28];
bytes4[2] = '"';
bytes4[3] = ':';
int name4 = UNSAFE.getInt(bytes4, ARRAY_BYTE_BASE_OFFSET);
if (jsonb) {
name4 &= 0xFFFF;
}
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.visitLdcInsn(name2);
mw.visitLdcInsn(name3);
mw.iconst_n(name4);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match29", "(JJJI)Z");
break;
}
case 30: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
byte[] bytes4 = new byte[4];
bytes4[0] = fieldName[27];
bytes4[1] = fieldName[28];
bytes4[2] = fieldName[29];
bytes4[3] = '"';
int name4 = UNSAFE.getInt(bytes4, ARRAY_BYTE_BASE_OFFSET);
if (jsonb) {
name4 &= 0xFFFFFF;
}
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.visitLdcInsn(name2);
mw.visitLdcInsn(name3);
mw.iconst_n(name4);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match30", "(JJJI)Z");
break;
}
case 31: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
int name4 = UNSAFE.getInt(fieldName, ARRAY_BYTE_BASE_OFFSET + 27);
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.visitLdcInsn(name2);
mw.visitLdcInsn(name3);
mw.iconst_n(name4);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match31", "(JJJI)Z");
break;
}
case 32: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
int name4 = UNSAFE.getInt(fieldName, ARRAY_BYTE_BASE_OFFSET + 27);
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.visitLdcInsn(name2);
mw.visitLdcInsn(name3);
mw.visitLdcInsn(name4);
mw.iconst_n(fieldName[31]);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match32", "(JJJIB)Z");
break;
}
case 33: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
byte[] bytes8 = new byte[8];
System.arraycopy(fieldName, 27, bytes8, 0, 6);
bytes8[6] = '"';
bytes8[7] = ':';
long name4 = UNSAFE.getLong(bytes8, ARRAY_BYTE_BASE_OFFSET);
if (jsonb) {
name4 &= 0xFFFFFFFFFFFFL;
}
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.visitLdcInsn(name2);
mw.visitLdcInsn(name3);
mw.visitLdcInsn(name4);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match33", "(JJJJ)Z");
break;
}
case 34: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
byte[] bytes8 = new byte[8];
System.arraycopy(fieldName, 27, bytes8, 0, 7);
bytes8[7] = '"';
long name4 = UNSAFE.getLong(bytes8, ARRAY_BYTE_BASE_OFFSET);
if (jsonb) {
name4 &= 0xFFFFFFFFFFFFFFL;
}
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.visitLdcInsn(name2);
mw.visitLdcInsn(name3);
mw.visitLdcInsn(name4);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match34", "(JJJJ)Z");
break;
}
case 35: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
long name4 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 27);
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.visitLdcInsn(name2);
mw.visitLdcInsn(name3);
mw.visitLdcInsn(name4);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match35", "(JJJJ)Z");
break;
}
case 36: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
long name4 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 27);
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.visitLdcInsn(name2);
mw.visitLdcInsn(name3);
mw.visitLdcInsn(name4);
mw.iconst_n(fieldName[35]);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match36", "(JJJJB)Z");
break;
}
case 37: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
long name4 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 27);
byte[] bytes4 = new byte[4];
bytes4[0] = fieldName[35];
bytes4[1] = fieldName[36];
bytes4[2] = '"';
bytes4[3] = ':';
int name5 = UNSAFE.getInt(bytes4, ARRAY_BYTE_BASE_OFFSET);
if (jsonb) {
name5 &= 0xFFFF;
}
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.visitLdcInsn(name2);
mw.visitLdcInsn(name3);
mw.visitLdcInsn(name4);
mw.iconst_n(name5);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match37", "(JJJJI)Z");
break;
}
case 38: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
long name4 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 27);
byte[] bytes4 = new byte[4];
bytes4[0] = fieldName[35];
bytes4[1] = fieldName[36];
bytes4[2] = fieldName[37];
bytes4[3] = '"';
int name5 = UNSAFE.getInt(bytes4, ARRAY_BYTE_BASE_OFFSET);
if (jsonb) {
name5 &= 0xFFFFFF;
}
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.visitLdcInsn(name2);
mw.visitLdcInsn(name3);
mw.visitLdcInsn(name4);
mw.iconst_n(name5);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match38", "(JJJJI)Z");
break;
}
case 39: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
long name4 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 27);
int name5 = UNSAFE.getInt(fieldName, ARRAY_BYTE_BASE_OFFSET + 35);
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.visitLdcInsn(name2);
mw.visitLdcInsn(name3);
mw.visitLdcInsn(name4);
mw.iconst_n(name5);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match39", "(JJJJI)Z");
break;
}
case 40: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
long name4 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 27);
int name5 = UNSAFE.getInt(fieldName, ARRAY_BYTE_BASE_OFFSET + 35);
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.visitLdcInsn(name2);
mw.visitLdcInsn(name3);
mw.visitLdcInsn(name4);
mw.iconst_n(name5);
mw.iconst_n(fieldName[39]);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match40", "(JJJJIB)Z");
break;
}
case 41: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
long name4 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 27);
byte[] bytes8 = new byte[8];
System.arraycopy(fieldName, 35, bytes8, 0, 6);
bytes8[6] = '"';
bytes8[7] = ':';
long name5 = UNSAFE.getLong(bytes8, ARRAY_BYTE_BASE_OFFSET);
if (jsonb) {
name5 &= 0xFFFFFFFFFFFFL;
}
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.visitLdcInsn(name2);
mw.visitLdcInsn(name3);
mw.visitLdcInsn(name4);
mw.visitLdcInsn(name5);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match41", "(JJJJJ)Z");
break;
}
case 42: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
long name4 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 27);
byte[] bytes8 = new byte[8];
System.arraycopy(fieldName, 35, bytes8, 0, 7);
bytes8[7] = '"';
long name5 = UNSAFE.getLong(bytes8, ARRAY_BYTE_BASE_OFFSET);
if (jsonb) {
name5 &= 0xFFFFFFFFFFFFFFL;
}
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.visitLdcInsn(name2);
mw.visitLdcInsn(name3);
mw.visitLdcInsn(name4);
mw.visitLdcInsn(name5);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match42", "(JJJJJ)Z");
break;
}
case 43: {
long name1 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 3);
long name2 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 11);
long name3 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 19);
long name4 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 27);
long name5 = UNSAFE.getLong(fieldName, ARRAY_BYTE_BASE_OFFSET + 35);
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.visitLdcInsn(name2);
mw.visitLdcInsn(name3);
mw.visitLdcInsn(name4);
mw.visitLdcInsn(name5);
mw.invokevirtual(TYPE_JSON_READER, "nextIfName4Match43", "(JJJJJ)Z");
break;
}
default:
throw new IllegalStateException("fieldNameLength " + fieldNameLength);
}
mw.ifeq(nextJ != null ? nextJ : hashCode64Start);
genReadFieldValue(
context,
fieldReader,
fieldBased,
mwc,
OBJECT,
fieldReaderIndex,
false // arrayMapping
);
mw.goto_(L_FOR_INC);
if (nextJ != null) {
mw.visitLabel(nextJ);
}
}
mw.goto_(dflt);
}
mw.visitLabel(dflt);
}
private void genRead57(
ObjectReadContext context,
boolean fieldBased,
MethodWriterContext mwc,
int OBJECT,
Label L_FOR_INC,
Label hashCode64Start
) {
FieldReader[] fieldReaderArray = context.fieldReaders;
/*
* long rawLong = jsonReader.getRawLong();
* if (rawLong == 0) {
* goto hashCode64Start;
* }
*/
int RAW_LONG = mwc.var2("RAW_LONG");
MethodWriter mw = mwc.mw;
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "getRawLong", "()J");
mw.dup2();
mw.lstore(RAW_LONG);
mw.lconst_0();
mw.lcmp();
mw.ifeq(hashCode64Start);
for (int i = 0; i < fieldReaderArray.length; ++i) {
Label next_ = new Label();
FieldReader fieldReader = fieldReaderArray[i];
byte[] fieldName = fieldReader.fieldName.getBytes(StandardCharsets.UTF_8);
int fieldNameLength = fieldName.length;
byte[] bytes8 = new byte[8];
String nextMethodName;
switch (fieldNameLength) {
case 5:
bytes8[0] = '"';
System.arraycopy(fieldName, 0, bytes8, 1, 5);
bytes8[6] = '"';
bytes8[7] = ':';
nextMethodName = "nextIfName8Match0";
break;
case 6:
bytes8[0] = '"';
System.arraycopy(fieldName, 0, bytes8, 1, 6);
bytes8[7] = '"';
nextMethodName = "nextIfName8Match1";
break;
case 7:
bytes8[0] = '"';
System.arraycopy(fieldName, 0, bytes8, 1, 7);
nextMethodName = "nextIfName8Match2";
break;
default:
throw new IllegalStateException("length " + fieldNameLength);
}
long rawLong = UNSAFE.getLong(bytes8, ARRAY_BYTE_BASE_OFFSET);
mw.lload(RAW_LONG);
mw.visitLdcInsn(rawLong);
mw.lcmp();
mw.ifne(next_);
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, nextMethodName, "()Z");
mw.ifeq(hashCode64Start);
genReadFieldValue(
context,
fieldReader,
fieldBased,
mwc,
OBJECT,
i,
false // arrayMapping
);
mw.goto_(L_FOR_INC); // continue
mw.visitLabel(next_);
}
}
private <T> void genCreateObject(
MethodWriter mw,
ObjectReadContext context,
String classNameType
) {
Constructor defaultConstructor = context.defaultConstructor;
Supplier creator = context.objectReaderAdapter.creator;
Class objectClass = context.objectClass;
int objectModifiers = objectClass == null ? Modifier.PUBLIC : objectClass.getModifiers();
boolean publicObject = Modifier.isPublic(objectModifiers) && (objectClass == null || !classLoader.isExternalClass(objectClass));
if (defaultConstructor == null || !publicObject || !Modifier.isPublic(defaultConstructor.getModifiers())) {
if (creator != null) {
mw.aload(THIS);
mw.getfield(classNameType, "creator", "Ljava/util/function/Supplier;");
mw.invokeinterface("java/util/function/Supplier", "get", "()Ljava/lang/Object;");
} else {
mw.aload(THIS);
mw.aload(JSON_READER);
mw.lload(FEATURES);
mw.invokevirtual(TYPE_JSON_READER, "features", "(J)J");
mw.invokevirtual(classNameType, "createInstance", "(J)Ljava/lang/Object;");
}
if (publicObject) {
mw.checkcast(context.objectType);
}
} else {
newObject(mw, context.objectType, context.defaultConstructor);
}
if (context.hasStringField) {
/*
* if ((features & JSONReader.Feature.InitStringFieldAsEmpty.mask) != 0) {
* this.initStringFieldAsEmpty(object);
* }
*/
Label L0 = new Label();
mw.lload(FEATURES);
mw.visitLdcInsn(JSONReader.Feature.InitStringFieldAsEmpty.mask);
mw.land();
mw.lconst_0();
mw.lcmp();
mw.ifeq(L0);
mw.dup();
mw.aload(THIS);
mw.swap();
mw.invokevirtual(classNameType, "initStringFieldAsEmpty", "(Ljava/lang/Object;)V");
mw.visitLabel(L0);
}
}
private <T> void genReadFieldValue(
ObjectReadContext context,
FieldReader fieldReader,
boolean fieldBased,
MethodWriterContext mwc,
int OBJECT,
int fieldReaderIndex,
boolean arrayMapping
) {
String classNameType = context.classNameType;
boolean jsonb = mwc.jsonb;
Class objectClass = context.objectClass;
Class fieldClass = fieldReader.fieldClass;
Type fieldType = fieldReader.fieldType;
long fieldFeatures = fieldReader.features;
String format = fieldReader.format;
Type itemType = fieldReader.itemType;
MethodWriter mw = mwc.mw;
if ((fieldFeatures & JSONReader.Feature.NullOnError.mask) != 0) {
mw.aload(THIS);
mw.getfield(classNameType, fieldReader(fieldReaderIndex), DESC_FIELD_READER);
mw.aload(JSON_READER);
mw.aload(OBJECT);
mw.invokevirtual(TYPE_FIELD_READE, "readFieldValue", METHOD_DESC_READ_FIELD_VALUE);
return;
}
Field field = fieldReader.field;
Method method = fieldReader.method;
Label endSet_ = new Label();
String TYPE_FIELD_CLASS = ASMUtils.type(fieldClass);
String DESC_FIELD_CLASS = ASMUtils.desc(fieldClass);
if (!(context.objectReaderAdapter instanceof ObjectReaderNoneDefaultConstructor)) {
mw.aload(OBJECT);
}
int fieldModifier = 0;
if ((fieldBased || method == null) && field != null) {
fieldModifier = field.getModifiers();
}
if (fieldBased
&& Modifier.isPublic(objectClass.getModifiers())
&& Modifier.isPublic(fieldModifier)
&& !Modifier.isFinal(fieldModifier)
&& !classLoader.isExternalClass(objectClass)
) {
mw.checkcast(context.objectType);
}
if (fieldClass == boolean.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readBoolValue", "()Z");
} else if (fieldClass == byte.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readInt32Value", "()I");
} else if (fieldClass == short.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readInt32Value", "()I");
} else if (fieldClass == int.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readInt32Value", "()I");
} else if (fieldClass == long.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readInt64Value", "()J");
} else if (fieldClass == float.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readFloatValue", "()F");
} else if (fieldClass == double.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readDoubleValue", "()D");
} else if (fieldClass == char.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readCharValue", "()C");
} else if (fieldClass == String.class) {
mw.aload(JSON_READER);
Label null_ = new Label();
mw.invokevirtual(TYPE_JSON_READER, "readString", "()Ljava/lang/String;");
mw.dup();
mw.ifnull(null_);
if ("trim".equals(format)) {
mw.invokevirtual("java/lang/String", "trim", "()Ljava/lang/String;");
} else if ("upper".equals(format)) {
mw.invokevirtual("java/lang/String", "toUpperCase", "()Ljava/lang/String;");
}
mw.visitLabel(null_);
} else if (fieldClass == Boolean.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readBool", "()Ljava/lang/Boolean;");
} else if (fieldClass == Byte.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readInt8", "()Ljava/lang/Byte;");
} else if (fieldClass == Short.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readInt16", "()Ljava/lang/Short;");
} else if (fieldClass == Integer.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readInt32", "()Ljava/lang/Integer;");
} else if (fieldClass == Long.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readInt64", "()Ljava/lang/Long;");
} else if (fieldClass == Float.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readFloat", "()Ljava/lang/Float;");
} else if (fieldClass == Double.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readDouble", "()Ljava/lang/Double;");
} else if (fieldClass == BigDecimal.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readBigDecimal", "()Ljava/math/BigDecimal;");
} else if (fieldClass == BigInteger.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readBigInteger", "()Ljava/math/BigInteger;");
} else if (fieldClass == Number.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readNumber", "()Ljava/lang/Number;");
} else if (fieldClass == UUID.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readUUID", "()Ljava/util/UUID;");
} else if (fieldClass == LocalDate.class && fieldReader.format == null) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readLocalDate", "()Ljava/time/LocalDate;");
} else if (fieldClass == OffsetDateTime.class && fieldReader.format == null) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readOffsetDateTime", "()Ljava/time/OffsetDateTime;");
} else if (fieldClass == Date.class && fieldReader.format == null) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readDate", "()Ljava/util/Date;");
} else if (fieldClass == Calendar.class && fieldReader.format == null) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readCalendar", "()Ljava/util/Calendar;");
} else {
Label endObject_ = new Label();
boolean disableReferenceDetect = context.disableReferenceDetect();
Integer REFERENCE = null;
if (!disableReferenceDetect) {
REFERENCE = mwc.var("REFERENCE");
}
if ((!disableReferenceDetect) && (!ObjectWriterProvider.isPrimitiveOrEnum(fieldClass))) {
Label endReference_ = new Label(), addResolveTask_ = new Label();
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "isReference", "()Z");
mw.ifeq(endReference_);
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readReference", "()Ljava/lang/String;");
if (context.objectClass == null || fieldClass.isAssignableFrom(context.objectClass)) {
mw.dup();
mw.astore(REFERENCE);
mw.visitLdcInsn("..");
mw.invokevirtual("java/lang/String", "equals", "(Ljava/lang/Object;)Z");
mw.ifeq(addResolveTask_);
if (objectClass != null && fieldClass.isAssignableFrom(objectClass)) {
mw.aload(OBJECT);
// mw.visitTypeInsn(CHECKCAST, TYPE_FIELD_CLASS); // cast
mw.goto_(endObject_);
}
mw.visitLabel(addResolveTask_);
} else {
mw.astore(REFERENCE);
}
mw.aload(THIS);
mw.getfield(classNameType, fieldReader(fieldReaderIndex), DESC_FIELD_READER);
mw.aload(JSON_READER);
mw.aload(OBJECT);
mw.aload(REFERENCE);
mw.invokevirtual(TYPE_FIELD_READE, "addResolveTask", METHOD_DESC_ADD_RESOLVE_TASK);
mw.pop();
mw.goto_(endSet_);
mw.visitLabel(endReference_);
}
if (!fieldReader.fieldClassSerializable) {
Label endIgnoreCheck_ = new Label();
/*
* if ((features & Feature.IgnoreNoneSerializable.mask) != 0) {
* jsonReader.skipValue();
* goto endSet_;
* }
*/
mw.lload(FEATURES);
mw.visitLdcInsn(JSONReader.Feature.IgnoreNoneSerializable.mask);
mw.land();
mw.lconst_0();
mw.lcmp();
mw.ifeq(endIgnoreCheck_);
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "skipValue", "()V");
if (!(context.objectReaderAdapter instanceof ObjectReaderNoneDefaultConstructor)) {
mw.pop();
}
mw.goto_(endSet_);
mw.visitLabel(endIgnoreCheck_);
}
boolean list = List.class.isAssignableFrom(fieldClass)
&& fieldReader.getInitReader() == null
&& !fieldClass.getName().startsWith("com.google.common.collect.Immutable");
if (list) {
Class itemClass = TypeUtils.getMapping(itemType);
if (itemClass != null
&& (Collection.class.isAssignableFrom(itemClass) || !Modifier.isPublic(itemClass.getModifiers()))
) {
list = false;
}
}
if (list && !fieldClass.isInterface() && !BeanUtils.hasPublicDefaultConstructor(fieldClass)) {
list = false;
}
if (list) {
genReadFieldValueList(
fieldReader,
classNameType,
mwc,
OBJECT,
fieldReaderIndex,
arrayMapping,
objectClass,
fieldClass,
fieldType,
fieldFeatures,
itemType,
TYPE_FIELD_CLASS,
context,
fieldBased
);
} else {
final String FIELD_OBJECT_READER = fieldObjectReader(fieldReaderIndex);
Label valueNotNull_ = new Label();
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "nextIfNull", "()Z");
mw.ifeq(valueNotNull_);
if (fieldClass == Optional.class) {
mw.invokestatic("java/util/Optional", "empty", "()Ljava/util/Optional;");
} else if (fieldClass == OptionalInt.class) {
mw.invokestatic("java/util/OptionalInt", "empty", "()Ljava/util/OptionalInt;");
} else if (fieldClass == OptionalLong.class) {
mw.invokestatic("java/util/OptionalLong", "empty", "()Ljava/util/OptionalLong;");
} else if (fieldClass == OptionalDouble.class) {
mw.invokestatic("java/util/OptionalDouble", "empty", "()Ljava/util/OptionalDouble;");
} else {
mw.aconst_null();
}
mw.goto_(endObject_);
mw.visitLabel(valueNotNull_);
if (fieldClass == String[].class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readStringArray", "()[Ljava/lang/String;");
} else if (fieldClass == int[].class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readInt32ValueArray", "()[I");
} else if (fieldClass == long[].class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readInt64ValueArray", "()[J");
} else {
if (Enum.class.isAssignableFrom(fieldClass) & !jsonb) {
genReadEnumValueRaw(
fieldReader,
classNameType,
mwc,
fieldReaderIndex,
fieldType,
fieldClass,
fieldFeatures,
FIELD_OBJECT_READER
);
} else {
genReadObject(
fieldReader,
classNameType,
mwc,
fieldReaderIndex,
fieldType,
fieldFeatures,
FIELD_OBJECT_READER
);
}
if (method != null
|| ((objectClass == null || Modifier.isPublic(objectClass.getModifiers()))
&& Modifier.isPublic(fieldModifier)
&& !Modifier.isFinal(fieldModifier)
&& !classLoader.isExternalClass(objectClass))
) {
mw.checkcast(TYPE_FIELD_CLASS); // cast
}
if (fieldReader.noneStaticMemberClass) {
try {
Field this0 = fieldClass.getDeclaredField("this$0");
long fieldOffset = UNSAFE.objectFieldOffset(this0);
Label notNull_ = new Label();
mw.dup();
mw.ifnull(notNull_);
mw.dup();
mw.getstatic(TYPE_UNSAFE_UTILS, "UNSAFE", "Lsun/misc/Unsafe;");
mw.swap();
mw.visitLdcInsn(fieldOffset);
mw.aload(OBJECT);
mw.invokevirtual("sun/misc/Unsafe", "putObject", "(Ljava/lang/Object;JLjava/lang/Object;)V");
mw.visitLabel(notNull_);
} catch (NoSuchFieldException e) {
// ignored
}
}
}
}
mw.visitLabel(endObject_);
}
if (field != null) {
String fieldClassName = fieldClass.getName();
boolean setDirect = (objectClass.getModifiers() & Modifier.PUBLIC) != 0
&& (fieldModifier & Modifier.PUBLIC) != 0
&& (fieldModifier & Modifier.FINAL) == 0
&& (ObjectWriterProvider.isPrimitiveOrEnum(fieldClass) || fieldClassName.startsWith("java.") || fieldClass.getClassLoader() == ObjectReaderProvider.FASTJSON2_CLASS_LOADER)
&& !classLoader.isExternalClass(objectClass)
&& field.getDeclaringClass() == objectClass;
if (setDirect) {
mw.putfield(context.objectType, field.getName(), DESC_FIELD_CLASS);
} else {
int FIELD_VALUE = mwc.var(fieldClass);
String methodName, methodDes;
int LOAD;
if (fieldClass == int.class) {
methodName = "putInt";
methodDes = "(Ljava/lang/Object;JI)V";
mw.istore(FIELD_VALUE);
LOAD = Opcodes.ILOAD;
} else if (fieldClass == long.class) {
methodName = "putLong";
methodDes = "(Ljava/lang/Object;JJ)V";
mw.lstore(FIELD_VALUE);
LOAD = Opcodes.LLOAD;
} else if (fieldClass == float.class) {
methodName = "putFloat";
methodDes = "(Ljava/lang/Object;JF)V";
mw.fstore(FIELD_VALUE);
LOAD = Opcodes.FLOAD;
} else if (fieldClass == double.class) {
methodName = "putDouble";
methodDes = "(Ljava/lang/Object;JD)V";
mw.dstore(FIELD_VALUE);
LOAD = Opcodes.DLOAD;
} else if (fieldClass == char.class) {
methodName = "putChar";
methodDes = "(Ljava/lang/Object;JC)V";
mw.istore(FIELD_VALUE);
LOAD = Opcodes.ILOAD;
} else if (fieldClass == byte.class) {
methodName = "putByte";
methodDes = "(Ljava/lang/Object;JB)V";
mw.istore(FIELD_VALUE);
LOAD = Opcodes.ILOAD;
} else if (fieldClass == short.class) {
methodName = "putShort";
methodDes = "(Ljava/lang/Object;JS)V";
mw.istore(FIELD_VALUE);
LOAD = Opcodes.ILOAD;
} else if (fieldClass == boolean.class) {
methodName = "putBoolean";
methodDes = "(Ljava/lang/Object;JZ)V";
mw.istore(FIELD_VALUE);
LOAD = Opcodes.ILOAD;
} else {
methodName = "putObject";
methodDes = "(Ljava/lang/Object;JLjava/lang/Object;)V";
mw.astore(FIELD_VALUE);
LOAD = Opcodes.ALOAD;
}
mw.getstatic(TYPE_UNSAFE_UTILS, "UNSAFE", "Lsun/misc/Unsafe;");
mw.swap();
mw.visitLdcInsn(
UNSAFE.objectFieldOffset(field));
mw.visitVarInsn(LOAD, FIELD_VALUE);
mw.invokevirtual("sun/misc/Unsafe", methodName, methodDes);
}
} else if (context.objectReaderAdapter instanceof ObjectReaderNoneDefaultConstructor) {
if (!fieldClass.isPrimitive()) {
mw.checkcast(ASMUtils.type(fieldClass));
}
mw.storeLocal(fieldClass, mwc.var(fieldReader));
} else {
boolean invokeFieldReaderAccept = context.externalClass || method == null || !context.publicClass;
if (invokeFieldReaderAccept) {
int FIELD_VALUE = mwc.var(fieldClass);
String acceptMethodDesc;
int LOAD;
if (fieldClass == boolean.class) {
acceptMethodDesc = "(Ljava/lang/Object;Z)V";
mw.istore(FIELD_VALUE);
LOAD = Opcodes.ILOAD;
} else if (fieldClass == byte.class) {
acceptMethodDesc = "(Ljava/lang/Object;B)V";
mw.istore(FIELD_VALUE);
LOAD = Opcodes.ILOAD;
} else if (fieldClass == short.class) {
acceptMethodDesc = "(Ljava/lang/Object;S)V";
mw.istore(FIELD_VALUE);
LOAD = Opcodes.ILOAD;
} else if (fieldClass == int.class) {
acceptMethodDesc = "(Ljava/lang/Object;I)V";
mw.istore(FIELD_VALUE);
LOAD = Opcodes.ILOAD;
} else if (fieldClass == long.class) {
acceptMethodDesc = "(Ljava/lang/Object;J)V";
mw.lstore(FIELD_VALUE);
LOAD = Opcodes.LLOAD;
} else if (fieldClass == char.class) {
acceptMethodDesc = "(Ljava/lang/Object;C)V";
mw.istore(FIELD_VALUE);
LOAD = Opcodes.ILOAD;
} else if (fieldClass == float.class) {
acceptMethodDesc = "(Ljava/lang/Object;F)V";
mw.fstore(FIELD_VALUE);
LOAD = Opcodes.FLOAD;
} else if (fieldClass == double.class) {
acceptMethodDesc = "(Ljava/lang/Object;D)V";
mw.dstore(FIELD_VALUE);
LOAD = Opcodes.DLOAD;
} else {
acceptMethodDesc = "(Ljava/lang/Object;Ljava/lang/Object;)V";
mw.astore(FIELD_VALUE);
LOAD = Opcodes.ALOAD;
}
mw.aload(THIS);
mw.getfield(classNameType, fieldReader(fieldReaderIndex), DESC_FIELD_READER);
BiConsumer function = fieldReader.getFunction();
if (function instanceof FieldBiConsumer) {
FieldBiConsumer fieldBiConsumer = (FieldBiConsumer) function;
mw.invokevirtual(TYPE_FIELD_READE, "getFunction", "()Ljava/util/function/BiConsumer;");
mw.checkcast(type(FieldBiConsumer.class));
mw.getfield(type(FieldBiConsumer.class), "consumer", desc(FieldConsumer.class));
mw.swap();
mw.visitLdcInsn(fieldBiConsumer.fieldIndex);
mw.visitVarInsn(LOAD, FIELD_VALUE);
mw.invokeinterface(type(FieldConsumer.class), "accept", "(Ljava/lang/Object;ILjava/lang/Object;)V");
} else {
mw.swap();
mw.visitVarInsn(LOAD, FIELD_VALUE);
mw.invokevirtual(TYPE_FIELD_READE, "accept", acceptMethodDesc);
}
} else {
Class<?> returnType = method.getReturnType();
String methodName = method.getName();
String methodDesc = null;
if (returnType == Void.TYPE) {
if (fieldClass == boolean.class) {
methodDesc = "(Z)V";
} else if (fieldClass == byte.class) {
methodDesc = "(B)V";
} else if (fieldClass == short.class) {
methodDesc = "(S)V";
} else if (fieldClass == int.class) {
methodDesc = "(I)V";
} else if (fieldClass == long.class) {
methodDesc = "(J)V";
} else if (fieldClass == char.class) {
methodDesc = "(C)V";
} else if (fieldClass == float.class) {
methodDesc = "(F)V";
} else if (fieldClass == double.class) {
methodDesc = "(D)V";
} else if (fieldClass == Boolean.class) {
methodDesc = "(Ljava/lang/Boolean;)V";
} else if (fieldClass == Integer.class) {
methodDesc = "(Ljava/lang/Integer;)V";
} else if (fieldClass == Long.class) {
methodDesc = "(Ljava/lang/Long;)V";
} else if (fieldClass == Float.class) {
methodDesc = "(Ljava/lang/Float;)V";
} else if (fieldClass == Double.class) {
methodDesc = "(Ljava/lang/Double;)V";
} else if (fieldClass == BigDecimal.class) {
methodDesc = "(Ljava/math/BigDecimal;)V";
} else if (fieldClass == String.class) {
methodDesc = "(Ljava/lang/String;)V";
} else if (fieldClass == UUID.class) {
methodDesc = "(Ljava/util/UUID;)V";
} else if (fieldClass == List.class) {
methodDesc = "(Ljava/util/List;)V";
} else if (fieldClass == Map.class) {
methodDesc = "(Ljava/util/Map;)V";
}
}
if (methodDesc == null) {
methodDesc = "(" + DESC_FIELD_CLASS + ")" + ASMUtils.desc(returnType);
}
mw.invokevirtual(context.objectType, methodName, methodDesc);
if (returnType != void.class) {
mw.pop();
}
}
// TODO BUILD METHOD
}
mw.visitLabel(endSet_);
}
private void genReadObject(
FieldReader fieldReader,
String classNameType,
MethodWriterContext mwc,
int i,
Type fieldType,
long fieldFeatures,
String FIELD_OBJECT_READER
) {
// object.<setMethod>(this.objectReader_<i>.readObject(jsonReader))
Label notNull_ = new Label();
MethodWriter mw = mwc.mw;
boolean jsonb = mwc.jsonb;
mw.aload(THIS);
mw.getfield(classNameType, FIELD_OBJECT_READER, DESC_OBJECT_READER);
mw.ifnonnull(notNull_);
mw.aload(THIS);
mw.aload(THIS);
mw.getfield(classNameType, fieldReader(i), DESC_FIELD_READER);
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_FIELD_READE, "getObjectReader", METHOD_DESC_GET_OBJECT_READER_1);
mw.putfield(classNameType, FIELD_OBJECT_READER, DESC_OBJECT_READER);
mw.visitLabel(notNull_);
mw.aload(THIS);
mw.getfield(classNameType, FIELD_OBJECT_READER, DESC_OBJECT_READER);
mw.aload(JSON_READER);
gwGetFieldType(classNameType, mw, i, fieldType);
mw.visitLdcInsn(fieldReader.fieldName);
mw.visitLdcInsn(fieldFeatures);
mw.invokeinterface(
TYPE_OBJECT_READER,
jsonb ? "readJSONBObject" : "readObject",
METHOD_DESC_READ_OBJECT);
}
private void genReadEnumValueRaw(
FieldReader fieldReader,
String classNameType,
MethodWriterContext mwc,
int fieldIndex,
Type fieldType,
Class fieldClass,
long fieldFeatures,
String FIELD_OBJECT_READER
) {
MethodWriter mw = mwc.mw;
boolean jsonb = mwc.jsonb;
Object[] enums = fieldClass.getEnumConstants();
Map<Integer, List<Enum>> name0Map = new TreeMap<>();
int nameLengthMin = 0, nameLengthMax = 0;
if (enums != null) {
for (int i = 0; i < enums.length; i++) {
Enum e = (Enum) enums[i];
byte[] enumName = e.name().getBytes(StandardCharsets.UTF_8);
int nameLength = enumName.length;
if (i == 0) {
nameLengthMin = nameLength;
nameLengthMax = nameLength;
} else {
nameLengthMin = Math.min(nameLength, nameLengthMin);
nameLengthMax = Math.max(nameLength, nameLengthMax);
}
byte[] name0Bytes = new byte[4];
name0Bytes[0] = '"';
if (enumName.length == 2) {
System.arraycopy(enumName, 0, name0Bytes, 1, 2);
name0Bytes[3] = '"';
} else if (enumName.length >= 3) {
System.arraycopy(enumName, 0, name0Bytes, 1, 3);
}
int name0 = UNSAFE.getInt(name0Bytes, ARRAY_BYTE_BASE_OFFSET);
List<Enum> enumList = name0Map.get(name0);
if (enumList == null) {
enumList = new ArrayList<>();
name0Map.put(name0, enumList);
}
enumList.add(e);
}
}
Label dflt = new Label(), enumEnd = new Label();
Label notNull_ = new Label();
mw.aload(THIS);
mw.getfield(classNameType, FIELD_OBJECT_READER, DESC_OBJECT_READER);
mw.ifnonnull(notNull_);
mw.aload(THIS);
mw.aload(THIS);
mw.getfield(classNameType, fieldReader(fieldIndex), DESC_FIELD_READER);
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_FIELD_READE, "getObjectReader", METHOD_DESC_GET_OBJECT_READER_1);
mw.putfield(classNameType, FIELD_OBJECT_READER, DESC_OBJECT_READER);
mw.visitLabel(notNull_);
mw.aload(THIS);
mw.getfield(classNameType, FIELD_OBJECT_READER, DESC_OBJECT_READER);
mw.instanceOf(type(ObjectReaderImplEnum.class));
mw.ifeq(dflt);
if (nameLengthMin >= 2 && nameLengthMax <= 11) {
int[] switchKeys = new int[name0Map.size()];
Label[] labels = new Label[name0Map.size()];
{
Iterator it = name0Map.keySet().iterator();
for (int j = 0; j < labels.length; j++) {
labels[j] = new Label();
switchKeys[j] = (Integer) it.next();
}
}
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "getRawInt", "()I");
mw.visitLookupSwitchInsn(dflt, switchKeys, labels);
for (int i = 0; i < labels.length; i++) {
mw.visitLabel(labels[i]);
int name0 = switchKeys[i];
List<Enum> enumList = name0Map.get(name0);
for (int j = 0; j < enumList.size(); j++) {
Label nextJ = null;
if (j > 0) {
nextJ = new Label();
}
Enum e = enumList.get(j);
byte[] enumName = e.name().getBytes(StandardCharsets.UTF_8);
int fieldNameLength = enumName.length;
switch (fieldNameLength) {
case 2:
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "nextIfValue4Match2", "()Z");
break;
case 3:
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "nextIfValue4Match3", "()Z");
break;
case 4: {
mw.aload(JSON_READER);
mw.visitLdcInsn(enumName[3]);
mw.invokevirtual(TYPE_JSON_READER, "nextIfValue4Match4", "(B)Z");
break;
}
case 5: {
mw.aload(JSON_READER);
mw.visitLdcInsn(enumName[3]);
mw.visitLdcInsn(enumName[4]);
mw.invokevirtual(TYPE_JSON_READER, "nextIfValue4Match5", "(BB)Z");
break;
}
case 6: {
byte[] bytes4 = new byte[4];
bytes4[0] = enumName[3];
bytes4[1] = enumName[4];
bytes4[2] = enumName[5];
bytes4[3] = '"';
int name1 = UNSAFE.getInt(bytes4, ARRAY_BYTE_BASE_OFFSET);
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.invokevirtual(TYPE_JSON_READER, "nextIfValue4Match6", "(I)Z");
break;
}
case 7: {
int name1 = UNSAFE.getInt(enumName, ARRAY_BYTE_BASE_OFFSET + 3);
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.invokevirtual(TYPE_JSON_READER, "nextIfValue4Match7", "(I)Z");
break;
}
case 8: {
int name1 = UNSAFE.getInt(enumName, ARRAY_BYTE_BASE_OFFSET + 3);
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.visitLdcInsn(enumName[7]);
mw.invokevirtual(TYPE_JSON_READER, "nextIfValue4Match8", "(IB)Z");
break;
}
case 9: {
int name1 = UNSAFE.getInt(enumName, ARRAY_BYTE_BASE_OFFSET + 3);
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.visitLdcInsn(enumName[7]);
mw.visitLdcInsn(enumName[8]);
mw.invokevirtual(TYPE_JSON_READER, "nextIfValue4Match9", "(IBB)Z");
break;
}
case 10: {
byte[] bytes8 = new byte[8];
System.arraycopy(enumName, 3, bytes8, 0, 7);
bytes8[7] = '"';
long name1 = UNSAFE.getLong(bytes8, ARRAY_BYTE_BASE_OFFSET);
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.invokevirtual(TYPE_JSON_READER, "nextIfValue4Match10", "(J)Z");
break;
}
case 11: {
byte[] bytes8 = new byte[8];
System.arraycopy(enumName, 3, bytes8, 0, 8);
long name1 = UNSAFE.getLong(bytes8, ARRAY_BYTE_BASE_OFFSET);
mw.aload(JSON_READER);
mw.visitLdcInsn(name1);
mw.invokevirtual(TYPE_JSON_READER, "nextIfValue4Match11", "(J)Z");
break;
}
default:
throw new IllegalStateException("fieldNameLength " + fieldNameLength);
}
mw.ifeq(nextJ != null ? nextJ : dflt);
mw.aload(THIS);
mw.getfield(classNameType, FIELD_OBJECT_READER, DESC_OBJECT_READER);
mw.checkcast(type(ObjectReaderImplEnum.class));
mw.visitLdcInsn(e.ordinal());
mw.invokevirtual(type(ObjectReaderImplEnum.class), "getEnumByOrdinal", "(I)Ljava/lang/Enum;");
mw.goto_(enumEnd);
if (nextJ != null) {
mw.visitLabel(nextJ);
}
}
mw.goto_(dflt);
}
}
mw.visitLabel(dflt);
mw.aload(THIS);
mw.getfield(classNameType, FIELD_OBJECT_READER, DESC_OBJECT_READER);
mw.aload(JSON_READER);
gwGetFieldType(classNameType, mw, fieldIndex, fieldType);
mw.visitLdcInsn(fieldReader.fieldName);
mw.visitLdcInsn(fieldFeatures);
mw.invokeinterface(
TYPE_OBJECT_READER,
jsonb ? "readJSONBObject" : "readObject",
METHOD_DESC_READ_OBJECT);
mw.visitLabel(enumEnd);
}
private void genReadFieldValueList(
FieldReader fieldReader,
String classNameType,
MethodWriterContext mwc,
int OBJECT,
int i,
boolean arrayMapping,
Class objectClass,
Class fieldClass,
Type fieldType,
long fieldFeatures,
Type itemType,
String TYPE_FIELD_CLASS,
ObjectReadContext context,
boolean fieldBased
) {
boolean jsonb = mwc.jsonb;
if (itemType == null) {
itemType = Object.class;
}
Class itemClass = TypeUtils.getMapping(itemType);
String ITEM_OBJECT_READER = fieldItemObjectReader(i);
MethodWriter mw = mwc.mw;
int LIST;
if (context.objectReaderAdapter instanceof ObjectReaderNoneDefaultConstructor) {
LIST = mwc.var(fieldReader);
} else {
LIST = mwc.var(fieldClass);
}
Integer AUTO_TYPE_OBJECT_READER = mwc.var(ObjectReader.class);
String LIST_TYPE = fieldClass.isInterface() ? "java/util/ArrayList" : TYPE_FIELD_CLASS;
Label loadList_ = new Label(), listNotNull_ = new Label(), listInitEnd_ = new Label();
boolean initCapacity = JVM_VERSION == 8 && "java/util/ArrayList".equals(LIST_TYPE);
int ITEM_CNT = mwc.var("ITEM_CNT");
if (jsonb) {
if (!context.disableAutoType()) {
Label checkAutoTypeNull_ = new Label();
mw.aload(THIS);
mw.getfield(classNameType, fieldReader(i), DESC_FIELD_READER);
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_FIELD_READE, "checkObjectAutoType", METHOD_DESC_CHECK_ARRAY_AUTO_TYPE);
mw.dup();
mw.astore(AUTO_TYPE_OBJECT_READER);
mw.ifnull(checkAutoTypeNull_);
mw.aload(AUTO_TYPE_OBJECT_READER);
mw.aload(JSON_READER);
gwGetFieldType(classNameType, mw, i, fieldType);
mw.visitLdcInsn(fieldReader.fieldName);
mw.visitLdcInsn(fieldFeatures);
mw.invokeinterface(TYPE_OBJECT_READER, "readJSONBObject", METHOD_DESC_READ_OBJECT);
mw.checkcast(TYPE_FIELD_CLASS);
mw.astore(LIST);
mw.goto_(loadList_);
mw.visitLabel(checkAutoTypeNull_);
}
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "startArray", "()I");
mw.dup();
mw.istore(ITEM_CNT);
mw.visitLdcInsn(-1);
mw.if_icmpne(listNotNull_);
mw.aconst_null();
mw.astore(LIST);
mw.goto_(loadList_);
mw.visitLabel(listNotNull_);
if (fieldReader.method == null && fieldReader.field != null) {
long fieldOffset = UNSAFE.objectFieldOffset(fieldReader.field);
mw.getstatic(TYPE_UNSAFE_UTILS, "UNSAFE", "Lsun/misc/Unsafe;");
mw.aload(OBJECT);
mw.visitLdcInsn(fieldOffset);
mw.invokevirtual("sun/misc/Unsafe", "getObject", "(Ljava/lang/Object;J)Ljava/lang/Object;");
mw.dup();
mw.checkcast(TYPE_FIELD_CLASS);
mw.astore(LIST);
Label listNull_ = new Label();
mw.ifnull(listNull_);
mw.aload(LIST);
mw.invokevirtual("java/lang/Object", "getClass", "()Ljava/lang/Class;");
mw.getstatic("java/util/Collections", "EMPTY_LIST", "Ljava/util/List;");
mw.invokevirtual("java/lang/Object", "getClass", "()Ljava/lang/Class;");
mw.if_acmpne(listInitEnd_);
mw.visitLabel(listNull_);
}
mw.new_(LIST_TYPE);
mw.dup();
if (initCapacity) {
mw.iload(ITEM_CNT);
mw.invokespecial(LIST_TYPE, "<init>", "(I)V");
} else {
mw.invokespecial(LIST_TYPE, "<init>", "()V");
}
mw.astore(LIST);
mw.visitLabel(listInitEnd_);
} else {
Label match_ = new Label(), skipValue_ = new Label(), loadNull_ = new Label();
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "nextIfNull", "()Z");
mw.ifne(loadNull_);
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "nextIfArrayStart", "()Z");
mw.ifne(match_);
if (itemClass == String.class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "isString", "()Z");
mw.ifeq(skipValue_);
mw.new_(LIST_TYPE);
mw.dup();
if (initCapacity) {
mw.visitLdcInsn(10);
mw.invokespecial(LIST_TYPE, "<init>", "(I)V");
} else {
mw.invokespecial(LIST_TYPE, "<init>", "()V");
}
mw.astore(LIST);
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "nextIfNullOrEmptyString", "()Z");
mw.ifne(loadList_);
mw.aload(LIST);
mw.aload(JSON_READER);
if (itemClass == String.class) {
mw.invokevirtual(TYPE_JSON_READER, "readString", "()Ljava/lang/String;");
}
mw.invokeinterface("java/util/List", "add", "(Ljava/lang/Object;)Z");
mw.pop();
mw.goto_(loadList_);
} else if (itemType instanceof Class) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "nextIfNullOrEmptyString", "()Z");
mw.ifne(loadNull_);
// nextIfNullOrEmptyString
mw.new_(LIST_TYPE);
mw.dup();
if (initCapacity) {
mw.visitLdcInsn(10);
mw.invokespecial(LIST_TYPE, "<init>", "(I)V");
} else {
mw.invokespecial(LIST_TYPE, "<init>", "()V");
}
mw.astore(LIST);
mw.aload(JSON_READER);
mw.aload(LIST);
mw.visitLdcInsn((Class) itemType);
mw.invokevirtual(TYPE_JSON_READER, "readArray", "(Ljava/util/List;Ljava/lang/reflect/Type;)V");
mw.goto_(loadList_);
}
mw.visitLabel(skipValue_);
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "skipValue", "()V");
mw.visitLabel(loadNull_);
mw.aconst_null();
mw.astore(LIST);
mw.goto_(loadList_);
mw.visitLabel(match_);
mw.new_(LIST_TYPE);
mw.dup();
if (initCapacity) {
mw.visitLdcInsn(10);
mw.invokespecial(LIST_TYPE, "<init>", "(I)V");
} else {
mw.invokespecial(LIST_TYPE, "<init>", "()V");
}
mw.astore(LIST);
}
int J = mwc.var("J");
Label for_start_j_ = new Label(), for_end_j_ = new Label(), for_inc_j_ = new Label();
mw.iconst_0();
mw.istore(J);
mw.visitLabel(for_start_j_);
if (jsonb) {
// j < item_cnt
mw.iload(J);
mw.iload(ITEM_CNT);
mw.if_icmpge(for_end_j_);
} else {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "nextIfArrayEnd", "()Z");
mw.ifne(for_end_j_);
}
if (itemType == String.class) {
mw.aload(LIST);
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readString", "()Ljava/lang/String;");
} else if (itemType == Integer.class) {
mw.aload(LIST);
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readInt32", "()Ljava/lang/Integer;");
} else if (itemType == Long.class) {
mw.aload(LIST);
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "readInt64", "()Ljava/lang/Long;");
} else {
Label notNull_ = new Label();
mw.aload(THIS);
mw.getfield(classNameType, ITEM_OBJECT_READER, DESC_OBJECT_READER);
mw.ifnonnull(notNull_);
mw.aload(THIS);
mw.aload(THIS);
mw.getfield(classNameType, fieldReader(i), DESC_FIELD_READER);
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_FIELD_READE, "getItemObjectReader", METHOD_DESC_GET_ITEM_OBJECT_READER);
mw.putfield(classNameType, ITEM_OBJECT_READER, DESC_OBJECT_READER);
mw.visitLabel(notNull_);
if (!context.disableReferenceDetect()) {
mw.aload(JSON_READER);
mw.aload(LIST);
mw.iload(J);
mw.invokevirtual(TYPE_JSON_READER, "readReference", "(Ljava/util/List;I)Z");
mw.ifne(for_inc_j_);
}
mw.aload(LIST);
Label readObject_ = new Label(), readObjectEnd_ = new Label();
if (arrayMapping) {
mw.aload(JSON_READER);
mw.invokevirtual(TYPE_JSON_READER, "isArray", "()Z");
mw.ifeq(readObject_);
mw.aload(THIS);
mw.getfield(classNameType, ITEM_OBJECT_READER, DESC_OBJECT_READER);
mw.aload(JSON_READER);
gwGetFieldType(classNameType, mw, i, fieldType);
mw.visitLdcInsn(fieldReader.fieldName);
mw.lload(FEATURES);
mw.invokeinterface(
TYPE_OBJECT_READER,
jsonb ? "readArrayMappingJSONBObject" : "readArrayMappingObject",
METHOD_DESC_READ_OBJECT);
mw.goto_(readObjectEnd_);
mw.visitLabel(readObject_);
}
mw.aload(THIS);
mw.getfield(classNameType, ITEM_OBJECT_READER, DESC_OBJECT_READER);
mw.aload(JSON_READER);
gwGetFieldType(classNameType, mw, i, fieldType);
mw.visitLdcInsn(fieldReader.fieldName);
mw.lload(FEATURES);
mw.invokeinterface(
TYPE_OBJECT_READER,
jsonb ? "readJSONBObject" : "readObject",
METHOD_DESC_READ_OBJECT);
if (arrayMapping) {
mw.visitLabel(readObjectEnd_);
}
}
mw.invokeinterface("java/util/List", "add", "(Ljava/lang/Object;)Z");
mw.pop();
mw.visitLabel(for_inc_j_);
mw.visitIincInsn(J, 1);
mw.goto_(for_start_j_);
mw.visitLabel(for_end_j_);
mw.visitLabel(loadList_);
mw.aload(LIST);
}
private void gwGetFieldType(String classNameType, MethodWriter mw, int i, Type fieldType) {
if (fieldType instanceof Class) {
Class fieldClass = (Class) fieldType;
String fieldClassName = fieldClass.getName();
boolean publicClass = Modifier.isPublic(fieldClass.getModifiers());
boolean internalClass = fieldClassName.startsWith("java.")
|| fieldClass == JSONArray.class
|| fieldClass == JSONObject.class;
if (publicClass && internalClass) {
mw.visitLdcInsn((Class) fieldType);
return;
}
}
mw.aload(THIS);
mw.getfield(classNameType, fieldReader(i), DESC_FIELD_READER);
mw.getfield(TYPE_FIELD_READE, "fieldType", "Ljava/lang/reflect/Type;");
}
static class ObjectReadContext {
final BeanInfo beanInfo;
final Class objectClass;
final ClassWriter cw;
final boolean publicClass;
final boolean externalClass;
final FieldReader[] fieldReaders;
final boolean hasStringField;
final int fieldNameLengthMin;
final int fieldNameLengthMax;
final String classNameType;
final String classNameFull;
final Constructor defaultConstructor;
ObjectReaderAdapter objectReaderAdapter;
final String objectType;
public ObjectReadContext(
BeanInfo beanInfo,
Class objectClass,
ClassWriter cw,
boolean externalClass,
FieldReader[] fieldReaders,
Constructor defaultConstructor
) {
this.beanInfo = beanInfo;
this.objectClass = objectClass;
this.cw = cw;
this.publicClass = objectClass == null || Modifier.isPublic(objectClass.getModifiers());
this.externalClass = externalClass;
this.fieldReaders = fieldReaders;
this.defaultConstructor = defaultConstructor;
this.objectType = objectClass == null ? ASMUtils.TYPE_OBJECT : ASMUtils.type(objectClass);
int fieldNameLengthMin = 0, fieldNameLengthMax = 0;
boolean hasStringField = false;
for (int i = 0; i < fieldReaders.length; i++) {
FieldReader fieldReader = fieldReaders[i];
if (fieldReader.fieldClass == String.class) {
hasStringField = true;
}
byte[] nameUTF8 = fieldReader.fieldName.getBytes(StandardCharsets.UTF_8);
int fieldNameLength = nameUTF8.length;
for (byte ch : nameUTF8) {
if (ch <= 0) {
fieldNameLength = -1;
break;
}
}
if (i == 0) {
fieldNameLengthMin = fieldNameLength;
fieldNameLengthMax = fieldNameLength;
} else {
fieldNameLengthMin = Math.min(fieldNameLength, fieldNameLengthMin);
fieldNameLengthMax = Math.max(fieldNameLength, fieldNameLengthMax);
}
}
this.hasStringField = hasStringField;
this.fieldNameLengthMin = fieldNameLengthMin;
this.fieldNameLengthMax = fieldNameLengthMax;
String className = "ORG_" + seed.incrementAndGet() + "_" + fieldReaders.length + (objectClass == null ? "" : "_" + objectClass.getSimpleName());
Package pkg = ObjectReaderCreatorASM.class.getPackage();
if (pkg != null) {
classNameFull = packageName + '.' + className;
classNameType = classNameFull.replace('.', '/');
} else {
classNameType = className;
classNameFull = className;
}
}
public boolean disableSupportArrayMapping() {
return (beanInfo.readerFeatures & FieldInfo.DISABLE_ARRAY_MAPPING) != 0;
}
public boolean disableReferenceDetect() {
return (beanInfo.readerFeatures & FieldInfo.DISABLE_REFERENCE_DETECT) != 0;
}
public boolean disableAutoType() {
return (beanInfo.readerFeatures & FieldInfo.DISABLE_AUTO_TYPE) != 0;
}
public boolean disableJSONB() {
return (beanInfo.readerFeatures & FieldInfo.DISABLE_JSONB) != 0;
}
public boolean disableSmartMatch() {
return (beanInfo.readerFeatures & FieldInfo.DISABLE_SMART_MATCH) != 0;
}
}
public Function<Consumer, ByteArrayValueConsumer> createByteArrayValueConsumerCreator(
Class objectClass,
FieldReader[] fieldReaderArray
) {
return createValueConsumer0(objectClass, fieldReaderArray, true);
}
public Function<Consumer, CharArrayValueConsumer> createCharArrayValueConsumerCreator(
Class objectClass,
FieldReader[] fieldReaderArray
) {
return createValueConsumer0(objectClass, fieldReaderArray, false);
}
private Function createValueConsumer0(
Class objectClass,
FieldReader[] fieldReaderArray,
boolean bytes
) {
Constructor defaultConstructor = BeanUtils.getDefaultConstructor(objectClass, false);
if (defaultConstructor == null || !Modifier.isPublic(objectClass.getModifiers())) {
return null;
}
ClassWriter cw = new ClassWriter(
(e) -> objectClass.getName().equals(e) ? objectClass : null
);
String className = (bytes ? "VBACG_" : "VCACG_")
+ seed.incrementAndGet()
+ "_" + fieldReaderArray.length
+ "_" + objectClass.getSimpleName();
String classNameType;
String classNameFull;
Package pkg = ObjectReaderCreatorASM.class.getPackage();
if (pkg != null) {
classNameFull = packageName + '.' + className;
classNameType = classNameFull.replace('.', '/');
} else {
classNameType = className;
classNameFull = className;
}
String TYPE_OBJECT = ASMUtils.type(objectClass);
String DESC_OBJECT = ASMUtils.desc(objectClass);
cw.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, "consumer", "Ljava/util/function/Consumer;");
cw.visitField(Opcodes.ACC_PUBLIC, "object", DESC_OBJECT);
cw.visit(
Opcodes.V1_8,
Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_SUPER,
classNameType,
"java/lang/Object",
new String[]{
bytes ? TYPE_BYTE_ARRAY_VALUE_CONSUMER : TYPE_CHAR_ARRAY_VALUE_CONSUMER
}
);
{
final int CONSUMER = 1;
MethodWriter mw = cw.visitMethod(
Opcodes.ACC_PUBLIC,
"<init>",
"(Ljava/util/function/Consumer;)V",
32
);
mw.aload(THIS);
mw.invokespecial("java/lang/Object", "<init>", "()V");
mw.aload(THIS);
mw.aload(CONSUMER);
mw.putfield(classNameType, "consumer", "Ljava/util/function/Consumer;");
mw.return_();
mw.visitMaxs(3, 3);
}
{
MethodWriter mw = cw.visitMethod(
Opcodes.ACC_PUBLIC,
"beforeRow",
"(I)V",
32
);
mw.aload(THIS);
newObject(mw, TYPE_OBJECT, defaultConstructor);
mw.putfield(classNameType, "object", DESC_OBJECT);
mw.return_();
mw.visitMaxs(3, 3);
}
{
MethodWriter mw = cw.visitMethod(
Opcodes.ACC_PUBLIC,
"afterRow",
"(I)V",
32
);
mw.aload(THIS);
mw.getfield(classNameType, "consumer", "Ljava/util/function/Consumer;");
mw.aload(THIS);
mw.getfield(classNameType, "object", DESC_OBJECT);
mw.invokeinterface("java/util/function/Consumer", "accept", "(Ljava/lang/Object;)V");
mw.aload(THIS);
mw.aconst_null();
mw.putfield(classNameType, "object", DESC_OBJECT);
mw.return_();
mw.visitMaxs(3, 3);
}
{
final int ROW = 1, COLUMN = 2, BYTES = 3, OFF = 4, LEN = 5, CHARSET = 6;
String methodDesc;
if (bytes) {
methodDesc = "(II[BIILjava/nio/charset/Charset;)V";
} else {
methodDesc = "(II[CII)V";
}
MethodWriter mw = cw.visitMethod(
Opcodes.ACC_PUBLIC,
"accept",
methodDesc,
32
);
Label switch_ = new Label(), L0_ = new Label(), L1_ = new Label();
mw.iload(LEN);
mw.ifne(L0_);
mw.return_();
mw.visitLabel(L0_);
mw.iload(COLUMN);
mw.ifge(L1_);
mw.return_();
mw.visitLabel(L1_);
mw.iload(COLUMN);
mw.visitLdcInsn(fieldReaderArray.length);
mw.if_icmple(switch_);
mw.return_();
mw.visitLabel(switch_);
Label dflt = new Label();
Label[] labels = new Label[fieldReaderArray.length];
int[] columns = new int[fieldReaderArray.length];
for (int i = 0; i < columns.length; i++) {
columns[i] = i;
labels[i] = new Label();
}
mw.iload(COLUMN);
mw.visitLookupSwitchInsn(dflt, columns, labels);
for (int i = 0; i < labels.length; i++) {
mw.visitLabel(labels[i]);
FieldReader fieldReader = fieldReaderArray[i];
Field field = fieldReader.field;
Class fieldClass = fieldReader.fieldClass;
Type fieldType = fieldReader.fieldType;
mw.aload(THIS);
mw.getfield(classNameType, "object", DESC_OBJECT);
String DESC_FIELD_CLASS, DESC_METHOD;
if (fieldType == Integer.class
|| fieldType == int.class
|| fieldType == Short.class
|| fieldType == short.class
|| fieldType == Byte.class
|| fieldType == byte.class
) {
mw.aload(BYTES);
mw.iload(OFF);
mw.iload(LEN);
mw.invokestatic(TYPE_TYPE_UTILS, "parseInt", bytes ? "([BII)I" : "([CII)I");
if (fieldType == short.class) {
DESC_FIELD_CLASS = "S";
DESC_METHOD = "(S)V";
} else if (fieldType == Short.class) {
mw.invokestatic("java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");
DESC_FIELD_CLASS = "Ljava/lang/Short;";
DESC_METHOD = "(Ljava/lang/Short;)V";
} else if (fieldType == byte.class) {
DESC_FIELD_CLASS = "B";
DESC_METHOD = "(B)V";
} else if (fieldType == Byte.class) {
mw.invokestatic("java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");
DESC_FIELD_CLASS = "Ljava/lang/Byte;";
DESC_METHOD = "(Ljava/lang/Byte;)V";
} else if (fieldType == int.class) {
DESC_FIELD_CLASS = "I";
DESC_METHOD = "(I)V";
} else {
mw.invokestatic("java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
DESC_FIELD_CLASS = "Ljava/lang/Integer;";
DESC_METHOD = "(Ljava/lang/Integer;)V";
}
} else if (fieldType == Long.class || fieldType == long.class) {
mw.aload(BYTES);
mw.iload(OFF);
mw.iload(LEN);
mw.invokestatic(TYPE_TYPE_UTILS, "parseLong", bytes ? "([BII)J" : "([CII)J");
if (fieldType == long.class) {
DESC_FIELD_CLASS = "J";
DESC_METHOD = "(J)V";
} else {
mw.invokestatic("java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");
DESC_FIELD_CLASS = "Ljava/lang/Long;";
DESC_METHOD = "(Ljava/lang/Long;)V";
}
} else if (fieldType == Float.class || fieldType == float.class) {
mw.aload(BYTES);
mw.iload(OFF);
mw.iload(LEN);
mw.invokestatic(TYPE_TYPE_UTILS, "parseFloat", bytes ? "([BII)F" : "([CII)F");
if (fieldType == float.class) {
DESC_FIELD_CLASS = "F";
DESC_METHOD = "(F)V";
} else {
mw.invokestatic("java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");
DESC_FIELD_CLASS = "Ljava/lang/Float;";
DESC_METHOD = "(Ljava/lang/Float;)V";
}
} else if (fieldType == Double.class || fieldType == double.class) {
mw.aload(BYTES);
mw.iload(OFF);
mw.iload(LEN);
mw.invokestatic(TYPE_TYPE_UTILS, "parseDouble", bytes ? "([BII)D" : "([CII)D");
if (fieldType == double.class) {
DESC_FIELD_CLASS = "D";
DESC_METHOD = "(D)V";
} else {
mw.invokestatic("java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");
DESC_FIELD_CLASS = "Ljava/lang/Double;";
DESC_METHOD = "(Ljava/lang/Double;)V";
}
} else if (fieldType == Boolean.class || fieldType == boolean.class) {
mw.aload(BYTES);
mw.iload(OFF);
mw.iload(LEN);
mw.invokestatic(TYPE_TYPE_UTILS, "parseBoolean", bytes ? "([BII)Ljava/lang/Boolean;" : "([CII)Ljava/lang/Boolean;");
if (fieldType == boolean.class) {
mw.invokevirtual("java/lang/Boolean", "booleanValue", "()Z");
DESC_FIELD_CLASS = "Z";
DESC_METHOD = "(Z)V";
} else {
DESC_FIELD_CLASS = "Ljava/lang/Boolean;";
DESC_METHOD = "(Ljava/lang/Boolean;)V";
}
} else if (fieldType == Date.class) {
mw.new_("java/util/Date");
// long millis = DateUtils.parseMillis(bytes, off, len, charset);
mw.dup();
mw.aload(BYTES);
mw.iload(OFF);
mw.iload(LEN);
if (bytes) {
mw.aload(CHARSET);
mw.invokestatic(TYPE_DATE_UTILS, "parseMillis", "([BIILjava/nio/charset/Charset;)J");
} else {
mw.invokestatic(TYPE_DATE_UTILS, "parseMillis", "([CII)J");
}
mw.invokespecial("java/util/Date", "<init>", "(J)V");
DESC_FIELD_CLASS = "Ljava/util/Date;";
DESC_METHOD = "(Ljava/util/Date;)V";
} else if (fieldType == BigDecimal.class) {
mw.aload(BYTES);
mw.iload(OFF);
mw.iload(LEN);
mw.invokestatic(TYPE_TYPE_UTILS, "parseBigDecimal", bytes ? "([BII)Ljava/math/BigDecimal;" : "([CII)Ljava/math/BigDecimal;");
DESC_FIELD_CLASS = "Ljava/math/BigDecimal;";
DESC_METHOD = "(Ljava/math/BigDecimal;)V";
} else {
mw.new_("java/lang/String");
mw.dup();
mw.aload(BYTES);
mw.iload(OFF);
mw.iload(LEN);
if (bytes) {
mw.aload(CHARSET);
mw.invokespecial("java/lang/String", "<init>", "([BIILjava/nio/charset/Charset;)V");
} else {
mw.invokespecial("java/lang/String", "<init>", "([CII)V");
}
if (fieldType == String.class) {
DESC_FIELD_CLASS = "Ljava/lang/String;";
DESC_METHOD = "(Ljava/lang/String;)V";
} else {
DESC_FIELD_CLASS = ASMUtils.desc(fieldClass);
if (fieldClass == char.class) {
DESC_METHOD = "(C)V";
} else {
DESC_METHOD = "(" + DESC_FIELD_CLASS + ")V";
}
mw.visitLdcInsn(fieldClass);
mw.invokestatic(TYPE_TYPE_UTILS, "cast", "(Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;");
mw.checkcast(ASMUtils.type(fieldClass));
}
}
if (fieldReader.method != null) {
if (fieldReader.method.getReturnType() != void.class) {
return null;
}
mw.invokevirtual(TYPE_OBJECT, fieldReader.method.getName(), DESC_METHOD);
} else if (field != null) {
mw.putfield(TYPE_OBJECT, field.getName(), DESC_FIELD_CLASS);
} else {
return null;
}
mw.goto_(dflt);
}
mw.visitLabel(dflt);
mw.return_();
mw.visitMaxs(3, 3);
}
byte[] code = cw.toByteArray();
try {
Class<?> consumerClass = classLoader.defineClassPublic(classNameFull, code, 0, code.length);
Constructor<?> constructor = consumerClass.getConstructor(Consumer.class);
return (c) -> {
try {
return constructor.newInstance(c);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
throw new JSONException("create ByteArrayValueConsumer error", e);
}
};
} catch (Throwable e) {
e.printStackTrace();
}
return null;
}
static class MethodWriterContext {
final MethodWriter mw;
final Map<Object, Integer> variants = new LinkedHashMap<>();
final boolean jsonb;
int maxVariant;
static final int JSON_READER = 1;
static final int FIELD_TYPE = 2;
static final int FIELD_NAME = 3;
static final int FEATURES = 4;
public MethodWriterContext(MethodWriter mw, int maxVariant, boolean jsonb) {
this.mw = mw;
this.maxVariant = maxVariant;
this.jsonb = jsonb;
}
int var(Object key) {
Integer var = variants.get(key);
if (var == null) {
var = maxVariant;
variants.put(key, var);
if (key == long.class || key == double.class) {
maxVariant += 2;
} else {
maxVariant += 1;
}
}
return var;
}
int var(FieldReader fieldReader) {
return var("_param_" + fieldReader.fieldName, fieldReader.fieldClass);
}
int var(String name, Class type) {
Integer var = variants.get(name);
if (var == null) {
var = maxVariant;
variants.put(name, var);
if (type == long.class || type == double.class) {
maxVariant += 2;
} else {
maxVariant += 1;
}
}
return var;
}
int var2(Object key) {
Integer var = variants.get(key);
if (var == null) {
var = maxVariant;
variants.put(key, var);
maxVariant += 2;
}
return var;
}
}
}