private void genMethodReadJSONBObject()

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