in core/src/main/java/com/alibaba/fastjson2/reader/ObjectReaderCreatorASM.java [1047:1458]
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);
}