private void genMethodReadObject()

in core/src/main/java/com/alibaba/fastjson2/reader/ObjectReaderCreatorASM.java [1618:2117]


    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);
    }