Example usage for org.objectweb.asm MethodVisitor visitLdcInsn

List of usage examples for org.objectweb.asm MethodVisitor visitLdcInsn

Introduction

In this page you can find the example usage for org.objectweb.asm MethodVisitor visitLdcInsn.

Prototype

public void visitLdcInsn(final Object value) 

Source Link

Document

Visits a LDC instruction.

Usage

From source file:com.cinnober.msgcodec.blink.BaseByteCodeGenerator.java

License:Open Source License

protected void generateConstructorAndFields(Schema schema, ClassVisitor cv, String genClassInternalName,
        boolean javaClassCodec) {
    MethodVisitor ctormv;
    ctormv = cv.visitMethod(ACC_PUBLIC, "<init>", "(L" + blinkCodecIName + ";Lcom/cinnober/msgcodec/Schema;)V",
            null, null);/*from w  w w.j  ava2  s  .c o  m*/
    int nextCtorVar = 3;
    ctormv.visitCode();
    ctormv.visitVarInsn(ALOAD, 0);
    ctormv.visitVarInsn(ALOAD, 1);
    ctormv.visitMethodInsn(INVOKESPECIAL, baseclassIName, "<init>", "(L" + blinkCodecIName + ";)V", false);

    // schema field
    FieldVisitor fv = cv.visitField(ACC_PRIVATE + ACC_FINAL, "schema", "Lcom/cinnober/msgcodec/Schema;", null,
            null);
    fv.visitEnd();
    ctormv.visitVarInsn(ALOAD, 0); // this
    ctormv.visitVarInsn(ALOAD, 2); // schema
    ctormv.visitFieldInsn(PUTFIELD, genClassInternalName, "schema", "Lcom/cinnober/msgcodec/Schema;");

    if (!javaClassCodec) {
        // store the group type accessor

        // field
        fv = cv.visitField(ACC_PRIVATE + ACC_FINAL, "groupTypeAccessor",
                "Lcom/cinnober/msgcodec/GroupTypeAccessor;", null, null);
        fv.visitEnd();

        // ctor, init field
        ctormv.visitVarInsn(ALOAD, 0); // this
        ctormv.visitVarInsn(ALOAD, 2); // schema
        ctormv.visitMethodInsn(INVOKEVIRTUAL, "com/cinnober/msgcodec/Schema", "getBinding",
                "()Lcom/cinnober/msgcodec/SchemaBinding;", false);
        ctormv.visitMethodInsn(INVOKEVIRTUAL, "com/cinnober/msgcodec/SchemaBinding", "getGroupTypeAccessor",
                "()Lcom/cinnober/msgcodec/GroupTypeAccessor;", false);
        ctormv.visitFieldInsn(PUTFIELD, genClassInternalName, "groupTypeAccessor",
                "Lcom/cinnober/msgcodec/GroupTypeAccessor;");
    }

    for (GroupDef group : schema.getGroups()) {
        if (!javaClassCodec) {
            // store the group type
            // field
            fv = cv.visitField(ACC_PRIVATE + ACC_FINAL, "groupType_" + group.getName(), "Ljava/lang/Object;",
                    null, null);
            fv.visitEnd();

            // ctor, init field
            ctormv.visitVarInsn(ALOAD, 0); // this
            ctormv.visitVarInsn(ALOAD, 2); // schema
            ctormv.visitLdcInsn(group.getName());
            ctormv.visitMethodInsn(INVOKEVIRTUAL, "com/cinnober/msgcodec/Schema", "getGroup",
                    "(Ljava/lang/String;)Lcom/cinnober/msgcodec/GroupDef;", false);
            ctormv.visitMethodInsn(INVOKEVIRTUAL, "com/cinnober/msgcodec/GroupDef", "getGroupType",
                    "()Ljava/lang/Object;", false);
            ctormv.visitFieldInsn(PUTFIELD, genClassInternalName, "groupType_" + group.getName(),
                    "Ljava/lang/Object;");
        }

        Factory<?> factory = group.getFactory();
        if (isPublicConstructorFactory(factory)) {
            // no factory is needed
        } else {
            // field
            fv = cv.visitField(ACC_PRIVATE + ACC_FINAL, "factory_" + group.getName(),
                    "Lcom/cinnober/msgcodec/Factory;", null, null);
            fv.visitEnd();

            // ctor, init field
            ctormv.visitVarInsn(ALOAD, 0); // this
            ctormv.visitVarInsn(ALOAD, 2); // schema
            ctormv.visitLdcInsn(group.getName());
            ctormv.visitMethodInsn(INVOKEVIRTUAL, "com/cinnober/msgcodec/Schema", "getGroup",
                    "(Ljava/lang/String;)Lcom/cinnober/msgcodec/GroupDef;", false);
            ctormv.visitMethodInsn(INVOKEVIRTUAL, "com/cinnober/msgcodec/GroupDef", "getFactory",
                    "()Lcom/cinnober/msgcodec/Factory;", false);
            ctormv.visitFieldInsn(PUTFIELD, genClassInternalName, "factory_" + group.getName(),
                    "Lcom/cinnober/msgcodec/Factory;");
        }

        for (FieldDef field : group.getFields()) {
            Accessor<?, ?> accessor = field.getAccessor();
            SymbolMapping<?> symbolMapping = field.getBinding().getSymbolMapping();
            TypeDef type = schema.resolveToType(field.getType(), true);
            TypeDef componentType = null;

            if (type.getType() == TypeDef.Type.SEQUENCE) {
                componentType = schema.resolveToType(((TypeDef.Sequence) type).getComponentType(), false);
            }

            if (isPublicFieldAccessor(accessor)) {
                // no accessor needed
            } else {
                // field
                fv = cv.visitField(ACC_PRIVATE + ACC_FINAL,
                        "accessor_" + group.getName() + "_" + field.getName(),
                        "Lcom/cinnober/msgcodec/Accessor;", null, null);
                fv.visitEnd();

                // ctor, init field
                ctormv.visitVarInsn(ALOAD, 0); // this
                ctormv.visitVarInsn(ALOAD, 2); // schema
                ctormv.visitLdcInsn(group.getName());
                ctormv.visitMethodInsn(INVOKEVIRTUAL, "com/cinnober/msgcodec/Schema", "getGroup",
                        "(Ljava/lang/String;)Lcom/cinnober/msgcodec/GroupDef;", false);
                ctormv.visitLdcInsn(field.getName());
                ctormv.visitMethodInsn(INVOKEVIRTUAL, "com/cinnober/msgcodec/GroupDef", "getField",
                        "(Ljava/lang/String;)Lcom/cinnober/msgcodec/FieldDef;", false);
                ctormv.visitMethodInsn(INVOKEVIRTUAL, "com/cinnober/msgcodec/FieldDef", "getAccessor",
                        "()Lcom/cinnober/msgcodec/Accessor;", false);
                ctormv.visitFieldInsn(PUTFIELD, genClassInternalName,
                        "accessor_" + group.getName() + "_" + field.getName(),
                        "Lcom/cinnober/msgcodec/Accessor;");
            }

            if (accessor.getClass() == CreateAccessor.class) {
                // No symbol map needed
            } else if ((type != null && type.getType() == TypeDef.Type.ENUM)
                    || (componentType != null && componentType.getType() == TypeDef.Type.ENUM)) {
                // If there is an enum and we need the symbol map
                Objects.requireNonNull(symbolMapping);

                // Create field
                String symbolMappingFieldName = "symbolMapping_" + group.getName() + "_" + field.getName();

                fv = cv.visitField(ACC_PRIVATE + ACC_FINAL, symbolMappingFieldName,
                        "Lcom/cinnober/msgcodec/SymbolMapping;", null, null);
                fv.visitEnd();

                // Init field in the constructor
                ctormv.visitVarInsn(ALOAD, 0); // this
                ctormv.visitVarInsn(ALOAD, 2); // schema
                ctormv.visitLdcInsn(group.getName());
                ctormv.visitMethodInsn(INVOKEVIRTUAL, "com/cinnober/msgcodec/Schema", "getGroup",
                        "(Ljava/lang/String;)Lcom/cinnober/msgcodec/GroupDef;", false);
                ctormv.visitLdcInsn(field.getName());
                ctormv.visitMethodInsn(INVOKEVIRTUAL, "com/cinnober/msgcodec/GroupDef", "getField",
                        "(Ljava/lang/String;)Lcom/cinnober/msgcodec/FieldDef;", false);
                ctormv.visitMethodInsn(INVOKEVIRTUAL, "com/cinnober/msgcodec/FieldDef", "getBinding",
                        "()Lcom/cinnober/msgcodec/FieldBinding;", false);
                ctormv.visitMethodInsn(INVOKEVIRTUAL, "com/cinnober/msgcodec/FieldBinding", "getSymbolMapping",
                        "()Lcom/cinnober/msgcodec/SymbolMapping;", false);

                ctormv.visitFieldInsn(PUTFIELD, genClassInternalName, symbolMappingFieldName,
                        "Lcom/cinnober/msgcodec/SymbolMapping;");
            }
        }
    }

    ctormv.visitInsn(RETURN);
    ctormv.visitMaxs(3, nextCtorVar);
    ctormv.visitEnd();
}

From source file:com.cinnober.msgcodec.blink.BaseByteCodeGenerator.java

License:Open Source License

protected void generateWriteStaticGroup(Schema schema, ClassVisitor cv, String genClassInternalName,
        boolean javaClassCodec) {
    // method writeStaticGroupWithId - switch
    MethodVisitor mv = cv.visitMethod(ACC_PROTECTED, "writeStaticGroupWithId",
            "(Lcom/cinnober/msgcodec/io/ByteSink;Ljava/lang/Object;)V", null,
            new String[] { "java/io/IOException" });
    int nextVar = 3;
    mv.visitCode();/*from  w w  w  . j  av  a  2  s  .c  o m*/

    mv.visitVarInsn(ALOAD, 2);
    if (javaClassCodec) {
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false);
    } else {
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, genClassInternalName, "groupTypeAccessor",
                "Lcom/cinnober/msgcodec/GroupTypeAccessor;");
        mv.visitVarInsn(ALOAD, 2);
        mv.visitMethodInsn(INVOKEINTERFACE, "com/cinnober/msgcodec/GroupTypeAccessor", "getGroupType",
                "(Ljava/lang/Object;)Ljava/lang/Object;", true);
    }
    int groupTypeVar = nextVar++;
    mv.visitInsn(DUP);
    mv.visitVarInsn(ASTORE, groupTypeVar);
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "hashCode", "()I", false);

    // switch on class.hashCode()
    Map<Integer, ObjectHashCodeSwitchCase<Object>> casesByHashCode = new TreeMap<>();
    Map<Integer, Label> labelsByGroupId = new TreeMap<>();
    for (GroupDef group : schema.getGroups()) {
        Object groupType = group.getGroupType();
        int groupHash = groupType.hashCode();
        ObjectHashCodeSwitchCase<Object> hashCase = casesByHashCode.get(groupHash);
        if (hashCase == null) {
            hashCase = new ObjectHashCodeSwitchCase<>(groupHash);
            casesByHashCode.put(hashCase.hashCode, hashCase);
        }
        hashCase.add(groupType);
    }

    Label unknownHashLabel = new Label();
    {
        int[] caseValues = new int[casesByHashCode.size()];
        int i = 0;
        for (int hashCode : casesByHashCode.keySet()) {
            caseValues[i++] = hashCode;
        }
        Label[] caseLabels = new Label[casesByHashCode.size()];
        i = 0;
        for (ObjectHashCodeSwitchCase<Object> hashCase : casesByHashCode.values()) {
            caseLabels[i++] = hashCase.label;
        }
        mv.visitLookupSwitchInsn(unknownHashLabel, caseValues, caseLabels);
    }
    for (ObjectHashCodeSwitchCase<Object> hashCase : casesByHashCode.values()) {
        mv.visitLabel(hashCase.label);
        mv.visitFrame(F_SAME, 0, null, 0, null);
        for (ObjectSwitchCase<Object> classCase : hashCase.cases) {
            GroupDef group = schema.getGroup(classCase.object);
            int groupId = schema.getGroup(classCase.object).getId();
            if (groupId != -1) {
                labelsByGroupId.put(groupId, classCase.label);
            }

            mv.visitVarInsn(ALOAD, groupTypeVar);
            if (javaClassCodec) {
                mv.visitLdcInsn(getJavaType(classCase.object));
                mv.visitJumpInsn(IF_ACMPEQ, classCase.label);
            } else {
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, genClassInternalName, "groupType_" + group.getName(),
                        "Ljava/lang/Object;");
                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "equals", "(Ljava/lang/Object;)Z", false);
                mv.visitJumpInsn(IFNE, classCase.label); // IFNE = if not false
            }
        }
    }
    // Default case for class hashcode switch, do lookup using schema.getGroup(Object)
    {
        Label unknownGroupIdLabel = new Label();
        mv.visitLabel(unknownHashLabel);
        mv.visitFrame(F_SAME, 0, null, 0, null);
        Label[] groupIdLabels = new Label[labelsByGroupId.size()];
        int[] groupIds = new int[groupIdLabels.length];

        {
            int i = 0;
            for (Entry<Integer, Label> entry : labelsByGroupId.entrySet()) {
                groupIds[i] = entry.getKey();
                groupIdLabels[i] = new Label();
                i++;
            }
        }

        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, genClassInternalName, "schema", "Lcom/cinnober/msgcodec/Schema;");

        mv.visitVarInsn(ALOAD, groupTypeVar);
        mv.visitMethodInsn(INVOKEVIRTUAL, SCHEMA_INAME, "getGroup",
                "(Ljava/lang/Object;)Lcom/cinnober/msgcodec/GroupDef;", false);

        // check for null result from getGroup
        Label noGroupDefLabel = new Label();
        mv.visitInsn(DUP);
        mv.visitJumpInsn(IFNULL, noGroupDefLabel);

        mv.visitMethodInsn(INVOKEVIRTUAL, GROUPDEF_INAME, "getId", "()I", false);

        // Switch on the group id
        mv.visitLookupSwitchInsn(unknownHashLabel, groupIds, groupIdLabels);

        // Cases for the group ids
        for (int i = 0; i < groupIds.length; i++) {
            mv.visitLabel(groupIdLabels[i]);
            mv.visitFrame(F_SAME, 0, null, 0, null);
            mv.visitJumpInsn(GOTO, labelsByGroupId.get(groupIds[i]));
        }

        mv.visitLabel(noGroupDefLabel);
        mv.visitFrame(F_SAME, 0, null, 0, null);
        mv.visitInsn(POP);

        // Throw exception if there is no match on class or group id
        mv.visitLabel(unknownGroupIdLabel);
        mv.visitFrame(F_SAME, 0, null, 0, null);
        mv.visitVarInsn(ALOAD, groupTypeVar);
        mv.visitMethodInsn(INVOKESTATIC, baseclassIName, "unknownGroupType",
                "(Ljava/lang/Object;)Ljava/lang/IllegalArgumentException;", false);
        mv.visitInsn(ATHROW);
    }

    // Generate the labeled calls to group writer methods
    for (ObjectHashCodeSwitchCase<Object> hashCase : casesByHashCode.values()) {
        for (ObjectSwitchCase<Object> classCase : hashCase.cases) {
            Object groupType = classCase.object;
            GroupDef group = schema.getGroup(groupType);
            String groupDescriptor = getTypeDescriptor(groupType, javaClassCodec);
            mv.visitLabel(classCase.label);
            mv.visitFrame(F_SAME, 0, null, 0, null);
            mv.visitVarInsn(ALOAD, 0); // this
            mv.visitVarInsn(ALOAD, 1); // out
            mv.visitVarInsn(ALOAD, 2); // obj
            if (javaClassCodec) {
                mv.visitTypeInsn(CHECKCAST, getTypeInternalName(groupType, javaClassCodec));
            }
            mv.visitMethodInsn(INVOKEVIRTUAL, genClassInternalName, "writeStaticGroupWithId_" + group.getName(),
                    "(Lcom/cinnober/msgcodec/io/ByteSink;" + groupDescriptor + ")V", false);
            mv.visitInsn(RETURN);
        }
    }

    mv.visitMaxs(4, nextVar);
    mv.visitEnd();
}

From source file:com.cinnober.msgcodec.blink.BaseByteCodeGenerator.java

License:Open Source License

protected void generateWriteStaticGroupForTypeWithId(Schema schema, ClassVisitor cv,
        String genClassInternalName, boolean javaClassCodec) {
    for (GroupDef group : schema.getGroups()) {
        Object groupType = group.getGroupType();
        String groupDescriptor = getTypeDescriptor(groupType, javaClassCodec);
        MethodVisitor mv = cv.visitMethod(ACC_PRIVATE, "writeStaticGroupWithId_" + group.getName(),
                "(Lcom/cinnober/msgcodec/io/ByteSink;" + groupDescriptor + ")V", null,
                new String[] { "java/io/IOException" });
        mv.visitCode();//  w w w .  j  a v  a 2  s. c  o  m
        int nextWriteidVar = 3;

        if (group.getId() != -1) {
            // write with id
            mv.visitVarInsn(ALOAD, 1); // out
            mv.visitLdcInsn(group.getId());
            mv.visitMethodInsn(INVOKESTATIC, blinkOutputIName, "writeUInt32",
                    "(Lcom/cinnober/msgcodec/io/ByteSink;I)V", false);
            mv.visitVarInsn(ALOAD, 0); // this
            mv.visitVarInsn(ALOAD, 1); // out
            mv.visitVarInsn(ALOAD, 2); // obj
            mv.visitMethodInsn(INVOKEVIRTUAL, genClassInternalName, "writeStaticGroup_" + group.getName(),
                    "(Lcom/cinnober/msgcodec/io/ByteSink;" + groupDescriptor + ")V", false);
            mv.visitInsn(RETURN);
        } else {
            // write with id
            mv.visitTypeInsn(NEW, "java/lang/IllegalArgumentException");
            mv.visitInsn(DUP);
            mv.visitLdcInsn("No group id");
            mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalArgumentException", "<init>",
                    "(Ljava/lang/String;)V", false);
            mv.visitInsn(ATHROW);
        }

        // end
        mv.visitMaxs(3, nextWriteidVar);
        mv.visitEnd();
    }
}

From source file:com.cinnober.msgcodec.blink.BaseByteCodeGenerator.java

License:Open Source License

protected void generateReadStaticGroupForType(final Schema schema, ClassVisitor cv,
        final String genClassInternalName, final boolean javaClassCodec) {
    for (final GroupDef group : schema.getGroups()) {
        Object groupType = group.getGroupType();
        String groupDescriptor = getTypeDescriptor(groupType, javaClassCodec);
        final MethodVisitor mv = cv.visitMethod(ACC_PRIVATE, "readStaticGroup_" + group.getName(),
                "(Lcom/cinnober/msgcodec/io/ByteSource;" + groupDescriptor + ")V", null,
                new String[] { "java/io/IOException" });
        mv.visitCode();/*  w  w w .ja v  a2 s .  c om*/
        final LocalVariable nextVar = new LocalVariable(3);

        // read fields of super group
        if (group.getSuperGroup() != null) {
            GroupDef superGroup = schema.getGroup(group.getSuperGroup());
            Object superGroupType = superGroup.getGroupType();
            String superGroupDescriptor = getTypeDescriptor(superGroupType, javaClassCodec);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitVarInsn(ALOAD, 1);
            mv.visitVarInsn(ALOAD, 2);
            mv.visitMethodInsn(INVOKEVIRTUAL, genClassInternalName, "readStaticGroup_" + superGroup.getName(),
                    "(Lcom/cinnober/msgcodec/io/ByteSource;" + superGroupDescriptor + ")V", false);
        }

        // fields
        for (final FieldDef field : group.getFields()) {
            final Class<?> javaClass = field.getJavaClass();

            Runnable readValue = () -> {
                Label tryStart = new Label();
                Label tryEnd = new Label();
                Label tryCatch = new Label();
                Label tryAfter = new Label();
                mv.visitTryCatchBlock(tryStart, tryEnd, tryCatch, "java/lang/Exception");

                mv.visitLabel(tryStart);
                mv.visitVarInsn(ALOAD, 1); // input stream
                generateDecodeValue(mv, 1, nextVar, field.isRequired(), field.getType(), javaClass,
                        field.getComponentJavaClass(), schema, genClassInternalName,
                        group.getName() + "_" + field.getName(), group.getName() + "." + field.getName(),
                        javaClassCodec);
                mv.visitLabel(tryEnd);
                mv.visitJumpInsn(GOTO, tryAfter);
                mv.visitLabel(tryCatch);
                int caughtExVar = nextVar.next();
                mv.visitVarInsn(ASTORE, caughtExVar);
                mv.visitTypeInsn(NEW, "com/cinnober/msgcodec/blink/FieldDecodeException");
                mv.visitInsn(DUP);
                mv.visitLdcInsn(field.getName());
                mv.visitVarInsn(ALOAD, caughtExVar);
                mv.visitMethodInsn(INVOKESPECIAL, "com/cinnober/msgcodec/blink/FieldDecodeException", "<init>",
                        "(Ljava/lang/String;Ljava/lang/Throwable;)V", false);
                mv.visitInsn(ATHROW);
                mv.visitLabel(tryAfter);
            };

            Accessor<?, ?> accessor = field.getAccessor();
            if (isPublicFieldAccessor(accessor)) {
                Field f = ((FieldAccessor) accessor).getField();
                mv.visitVarInsn(ALOAD, 2); // instance
                // value
                readValue.run();
                // store
                mv.visitFieldInsn(PUTFIELD, Type.getInternalName(f.getDeclaringClass()), f.getName(),
                        Type.getDescriptor(f.getType()));
            } else if (accessor.getClass() == CreateAccessor.class) {
                mv.visitVarInsn(ALOAD, 2); // instance

                Label tryStart = new Label();
                Label tryEnd = new Label();
                Label tryCatch = new Label();
                Label tryAfter = new Label();
                mv.visitTryCatchBlock(tryStart, tryEnd, tryCatch, "java/lang/Exception");

                mv.visitLabel(tryStart);
                mv.visitVarInsn(ALOAD, 1); // input stream

                generateDecodeDummy(mv, 1, nextVar, field.isRequired(), field.getType(), javaClass,
                        field.getComponentJavaClass(), schema, genClassInternalName,
                        group.getName() + "." + field.getName(), javaClassCodec);

                mv.visitInsn(POP);

                mv.visitLabel(tryEnd);
                mv.visitJumpInsn(GOTO, tryAfter);
                mv.visitLabel(tryCatch);
                int caughtExVar = nextVar.next();
                mv.visitVarInsn(ASTORE, caughtExVar);
                mv.visitTypeInsn(NEW, "com/cinnober/msgcodec/blink/FieldDecodeException");
                mv.visitInsn(DUP);
                mv.visitLdcInsn(field.getName());
                mv.visitVarInsn(ALOAD, caughtExVar);
                mv.visitMethodInsn(INVOKESPECIAL, "com/cinnober/msgcodec/blink/FieldDecodeException", "<init>",
                        "(Ljava/lang/String;Ljava/lang/Throwable;)V", false);
                mv.visitInsn(ATHROW);
                mv.visitLabel(tryAfter);

                mv.visitInsn(POP);
            } else {
                // accessor
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, genClassInternalName,
                        "accessor_" + group.getName() + "_" + field.getName(),
                        "Lcom/cinnober/msgcodec/Accessor;");
                // instance
                mv.visitVarInsn(ALOAD, 2); // instance
                // value
                readValue.run();
                if (javaClass.isPrimitive()) {
                    box(mv, javaClass);
                }
                // store
                mv.visitMethodInsn(INVOKEINTERFACE, "com/cinnober/msgcodec/Accessor", "setValue",
                        "(Ljava/lang/Object;Ljava/lang/Object;)V", true);
            }
        }

        mv.visitInsn(RETURN);
        mv.visitMaxs(6, nextVar.get());
        mv.visitEnd();
    }
}

From source file:com.cinnober.msgcodec.blink.BaseByteCodeGenerator.java

License:Open Source License

/**
 * Generate instructions to encode the specified value type.
 * The values on the stack are; the output stream and the value to be encoded.
 * After this call these values are expected to be consumed.
 *
 * @param mv the method visitor, open for code instructions.
 * @param outputStreamVar the variable instance that contains the output stream.
 * @param nextVar the next variable//from w w  w.j  a  v  a2s.c o  m
 * @param required true if the field is required, otherwise false.
 * @param type the field type
 * @param javaClass the field java class
 * @param componentJavaClass the field component java class, or null if not a sequence type
 * @param schema the protocol schema, not null
 * @param genClassInternalName the internal name of the generated class
 */
protected void generateEncodeValue(MethodVisitor mv, int outputStreamVar, LocalVariable nextVar,
        boolean required, TypeDef type, Class<?> javaClass, Class<?> componentJavaClass, Schema schema,
        String genClassInternalName, String fieldIdentifier, String debugValueLabel, boolean javaClassCodec) {

    type = schema.resolveToType(type, false);
    GroupDef refGroup = schema.resolveToGroup(type);

    if (javaClass.isPrimitive() && !required) {
        box(mv, javaClass);
    } else if (!javaClass.isPrimitive() && required) {
        mv.visitInsn(DUP);
        Label notNullLabel = new Label();
        mv.visitJumpInsn(IFNONNULL, notNullLabel);
        mv.visitInsn(POP); // output stream
        mv.visitLdcInsn(debugValueLabel);
        mv.visitMethodInsn(INVOKESTATIC, baseclassIName, "missingRequiredValue",
                "(Ljava/lang/String;)Ljava/lang/IllegalArgumentException;", false);
        mv.visitInsn(ATHROW);
        mv.visitLabel(notNullLabel);
        unbox(mv, javaClass);
    }
    switch (type.getType()) {
    case INT8:
        generateEncodeInt8Value(required, mv);
        break;
    case UINT8:
        generateEncodeUInt8Value(required, mv);
        break;
    case CHAR:
        generateEncodeCharacterValue(required, mv);
        break;
    case INT16:
        generateEncodeInt16Value(required, mv);
        break;
    case UINT16:
        generateEncodeUInt16Value(required, mv);
        break;
    case INT32:
        generateEncodeInt32Value(required, mv);
        break;
    case UINT32:
        generateEncodeUInt32Value(required, mv);
        break;
    case INT64:
        generateEncodeInt64Value(required, mv);
        break;
    case UINT64:
        generateEncodeUInt64Value(required, mv);
        break;
    case FLOAT32:
        generateEncodeFloat32Value(required, mv);
        break;
    case FLOAT64:
        generateEncodeFloat64Value(required, mv);
        break;
    case BIGINT:
        generateEncodeBigIntValue(required, mv);
        break;
    case DECIMAL:
        generateEncodeDecimalValue(required, mv);
        break;
    case BIGDECIMAL:
        generateEncodeBigDecimalValue(required, mv);
        break;
    case STRING:
        generateEncodeStringValue((TypeDef.StringUnicode) type, required, mv);
        break;
    case BINARY:
        generateEncodeBinaryValue((TypeDef.Binary) type, required, mv);
        break;
    case BOOLEAN:
        generateEncodeBooleanValue(required, mv);
        break;
    case ENUM:
        generateEncodeEnumValue((TypeDef.Enum) type, genClassInternalName, fieldIdentifier, nextVar, javaClass,
                required, mv, debugValueLabel);
        break;
    case TIME:
        generateEncodeTimeValue((TypeDef.Time) type, javaClass, required, mv);
        break;
    case SEQUENCE:
        generateEncodeSequenceValue(javaClass, nextVar, mv, required, outputStreamVar, componentJavaClass, type,
                schema, genClassInternalName, fieldIdentifier, debugValueLabel, javaClassCodec);
        break;
    case REFERENCE:
        generateEncodeRefValue(refGroup, required, nextVar, mv, genClassInternalName, outputStreamVar,
                (TypeDef.Reference) type, javaClassCodec);
        break;
    case DYNAMIC_REFERENCE:
        generateEncodeDynRefValue(nextVar, mv, required);
        break;
    default:
        throw new RuntimeException("Unhandled case: " + type.getType());
    }
}

From source file:com.cinnober.msgcodec.blink.BaseByteCodeGenerator.java

License:Open Source License

protected void generateEncodeTimeValue(TypeDef.Time type, Class<?> javaClass, boolean required,
        MethodVisitor mv) throws RuntimeException {
    if (javaClass == long.class || javaClass == Long.class) {
        generateEncodeInt64Value(required, mv);
    } else if (javaClass == int.class || javaClass == Integer.class) {
        generateEncodeInt32Value(required, mv);
    } else if (javaClass == Date.class) {

        Label nullLabel = new Label();
        Label endLabel = new Label();
        if (!required) {
            mv.visitInsn(DUP);/*from  ww w  .  j  ava  2  s  .c  o  m*/
            mv.visitJumpInsn(IFNULL, nullLabel);
        }

        // not null
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/util/Date", "getTime", "()J", false);
        // handle differences in UNIT and EPOCH
        long epochOffset = DateUtil.getEpochOffset(type.getEpoch());
        long timeInMillis = DateUtil.getTimeInMillis(type.getUnit());
        // wireTime = (dateTime - epochOffset) / timeUnitInMillis);
        if (epochOffset != 0) {
            mv.visitLdcInsn(epochOffset);
            mv.visitInsn(LSUB);
        }
        if (timeInMillis != 1) {
            mv.visitLdcInsn(timeInMillis);
            mv.visitInsn(LDIV);
        }
        box(mv, long.class);
        mv.visitMethodInsn(INVOKESTATIC, blinkOutputIName, "writeInt64Null",
                "(Lcom/cinnober/msgcodec/io/ByteSink;Ljava/lang/Long;)V", false);

        if (!required) {
            mv.visitJumpInsn(GOTO, endLabel);
            mv.visitLabel(nullLabel);
            mv.visitInsn(POP);
            mv.visitInsn(ACONST_NULL);
            mv.visitMethodInsn(INVOKESTATIC, blinkOutputIName, "writeInt64Null",
                    "(Lcom/cinnober/msgcodec/io/ByteSink;Ljava/lang/Long;)V", false);
            mv.visitLabel(endLabel);
        }
    } else {
        throw new IllegalArgumentException("Illegal time javaClass: " + javaClass);
    }
}

From source file:com.cinnober.msgcodec.blink.BaseByteCodeGenerator.java

License:Open Source License

protected void generateDecodeTimeValue(TypeDef.Time type, Class<?> javaClass, boolean required,
        MethodVisitor mv, LocalVariable nextVar) throws IllegalArgumentException {
    if (javaClass == long.class || javaClass == Long.class) {
        generateDecodeInt64Value(required, mv);
    } else if (javaClass == int.class || javaClass == Integer.class) {
        generateDecodeInt32Value(required, mv);
    } else if (javaClass == Date.class) {

        int timeVar = nextVar.next();
        nextVar.next(); // note: 2 variable slots
        Label endLabel = new Label();
        if (required) {
            generateDecodeInt64Value(true, mv);
        } else {/*from   w  w  w . j a  v  a 2s . c  o  m*/
            generateDecodeInt64Value(false, mv);
            mv.visitInsn(DUP);
            Label nonNullLabel = new Label();
            mv.visitJumpInsn(IFNONNULL, nonNullLabel);
            // null
            mv.visitTypeInsn(CHECKCAST, "java/util/Date");
            mv.visitJumpInsn(GOTO, endLabel);
            // not null
            mv.visitLabel(nonNullLabel);
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false);
        }

        mv.visitVarInsn(LSTORE, timeVar);
        mv.visitTypeInsn(NEW, "java/util/Date");
        mv.visitInsn(DUP);
        mv.visitVarInsn(LLOAD, timeVar);
        // handle differences in UNIT and EPOCH
        long epochOffset = DateUtil.getEpochOffset(type.getEpoch());
        long timeInMillis = DateUtil.getTimeInMillis(type.getUnit());
        // dateTime = wireTime * timeUnitInMillis + epochOffset;
        if (timeInMillis != 1) {
            mv.visitLdcInsn(timeInMillis);
            mv.visitInsn(LMUL);
        }
        if (epochOffset != 0) {
            mv.visitLdcInsn(epochOffset);
            mv.visitInsn(LADD);
        }

        mv.visitMethodInsn(INVOKESPECIAL, "java/util/Date", "<init>", "(J)V", false);

        if (!required) {
            // end
            mv.visitLabel(endLabel);
        }
    } else {
        throw new IllegalArgumentException("Illegal time javaClass: " + javaClass);
    }
}

From source file:com.cinnober.msgcodec.blink.NativeByteCodeGenerator.java

License:Open Source License

@Override
protected void generateWriteStaticGroupForTypeWithId(Schema schema, ClassVisitor cv,
        String genClassInternalName, boolean javaClassCodec) {
    for (GroupDef group : schema.getGroups()) {
        Object groupType = group.getGroupType();
        String groupDescriptor = getTypeDescriptor(groupType, javaClassCodec);
        MethodVisitor mv = cv.visitMethod(ACC_PRIVATE, "writeStaticGroupWithId_" + group.getName(),
                "(Lcom/cinnober/msgcodec/io/ByteSink;" + groupDescriptor + ")V", null,
                new String[] { "java/io/IOException" });
        mv.visitCode();//from w  w  w. j  ava2s  .c  o  m
        int nextWriteidVar = 3;

        if (group.getId() != -1) {
            // write with id
            mv.visitVarInsn(ALOAD, 1); // out
            mv.visitLdcInsn(group.getId() & 0xffffffffL);
            mv.visitMethodInsn(INVOKESTATIC, blinkOutputIName, "writeUInt64",
                    "(Lcom/cinnober/msgcodec/io/ByteSink;J)V", false);

            // add extension offset (four zero bytes)
            mv.visitVarInsn(ALOAD, 1); // out
            mv.visitInsn(ICONST_0);
            generateEncodeUInt32Value(true, mv);

            mv.visitVarInsn(ALOAD, 0); // this
            mv.visitVarInsn(ALOAD, 1); // out
            mv.visitVarInsn(ALOAD, 2); // obj
            mv.visitMethodInsn(INVOKEVIRTUAL, genClassInternalName, "writeStaticGroup_" + group.getName(),
                    "(Lcom/cinnober/msgcodec/io/ByteSink;" + groupDescriptor + ")V", false);
            mv.visitInsn(RETURN);
        } else {
            // write with id
            mv.visitTypeInsn(NEW, "java/lang/IllegalArgumentException");
            mv.visitInsn(DUP);
            mv.visitLdcInsn("No group id");
            mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalArgumentException", "<init>",
                    "(Ljava/lang/String;)V", false);
            mv.visitInsn(ATHROW);
        }

        // end
        mv.visitMaxs(3, nextWriteidVar);
        mv.visitEnd();
    }
}

From source file:com.cinnober.msgcodec.blink.NativeByteCodeGenerator.java

License:Open Source License

@Override
protected void generateEncodeBinaryValue(TypeDef.Binary type, boolean required, MethodVisitor mv) {
    if (Integer.compareUnsigned(type.getMaxSize(), 255) <= 0) {
        // inline
        mv.visitLdcInsn(type.getMaxSize());
        if (required) {
            mv.visitMethodInsn(INVOKESTATIC, blinkOutputIName, "writeInlineBinary",
                    "(Lcom/cinnober/msgcodec/io/ByteSink;[BI)V", false);
        } else {/*from   w  ww  . ja v  a 2  s  .  c o m*/
            mv.visitMethodInsn(INVOKESTATIC, blinkOutputIName, "writeInlineBinaryNull",
                    "(Lcom/cinnober/msgcodec/io/ByteSink;[BI)V", false);
        }
    } else {
        // data area
        // cast bytesink to ByteBuf, set position to data area, etc
        throw new UnsupportedOperationException("Not implemented yet"); // TODO: add support for data area
    }
}

From source file:com.cinnober.msgcodec.blink.NativeByteCodeGenerator.java

License:Open Source License

@Override
protected void generateEncodeStringValue(TypeDef.StringUnicode type, boolean required, MethodVisitor mv) {
    if (Integer.compareUnsigned(type.getMaxSize(), 255) <= 0) {
        // inline
        mv.visitLdcInsn(type.getMaxSize());
        if (required) {
            mv.visitMethodInsn(INVOKESTATIC, blinkOutputIName, "writeInlineStringUTF8",
                    "(Lcom/cinnober/msgcodec/io/ByteSink;Ljava/lang/String;I)V", false);
        } else {/*from ww w. j a  v  a 2  s .c om*/
            mv.visitMethodInsn(INVOKESTATIC, blinkOutputIName, "writeStringUTF8Null",
                    "(Lcom/cinnober/msgcodec/io/ByteSink;Ljava/lang/String;I)V", false);
        }
    } else {
        // data area
        throw new UnsupportedOperationException("Not implemented yet"); // TODO: add support for data area
    }
}