Search in sources :

Example 1 with Label

use of org.apache.beam.vendor.bytebuddy.v1_11_0.net.bytebuddy.jar.asm.Label in project curiostack by curioswitch.

the class DoParse method setRepeatedFieldValue.

/**
 * Returns the {@link StackManipulation} for setting the value of a normal repeated field.
 *
 * <p>Roughly equivalent to:
 *
 * <pre>{@code
 * ParseSupport.parseArrayStart(parser);
 * while (!ParseSupport.checkArrayEnd(parser)) {
 *   builder.addFoo(readValue());
 * }
 * }</pre>
 */
private StackManipulation setRepeatedFieldValue(ProtoFieldInfo info, Label beforeReadField, LocalVariables<LocalVariable> locals, Map<String, FieldDescription> fieldsByName, StackManipulation setSingleValue) {
    Label arrayStart = new Label();
    StackManipulation.Compound beforeRead = new StackManipulation.Compound(locals.load(LocalVariable.parser), ParseSupport_parseArrayStart, new SetJumpTargetLabel(arrayStart), locals.load(LocalVariable.parser), ParseSupport_throwIfRepeatedNull, locals.load(LocalVariable.parser), ParseSupport_checkArrayEnd, new IfTrue(beforeReadField));
    Label afterSet = new Label();
    StackManipulation.Compound setValueAndPrepareForNext = new StackManipulation.Compound(setSingleValue, Removal.SINGLE, new SetJumpTargetLabel(afterSet), locals.load(LocalVariable.parser), Parser_nextValue, Removal.SINGLE, new Goto(arrayStart));
    if (info.valueType() == Type.ENUM) {
        // We special-case enum since we may need to skip unknown values.
        return new StackManipulation.Compound(beforeRead, locals.load(LocalVariable.parser), readValue(info, fieldsByName, locals), locals.store(LocalVariable.intvalue), locals.load(LocalVariable.intvalue), IntegerConstant.forValue(-1), new IfEqual(int.class, afterSet), locals.load(LocalVariable.builder), locals.load(LocalVariable.intvalue), setValueAndPrepareForNext);
    } else {
        return new StackManipulation.Compound(beforeRead, locals.load(LocalVariable.builder), locals.load(LocalVariable.parser), readValue(info, fieldsByName, locals), setValueAndPrepareForNext);
    }
}
Also used : IfEqual(org.curioswitch.common.protobuf.json.bytebuddy.IfEqual) Goto(org.curioswitch.common.protobuf.json.bytebuddy.Goto) StackManipulation(net.bytebuddy.implementation.bytecode.StackManipulation) SetJumpTargetLabel(org.curioswitch.common.protobuf.json.bytebuddy.SetJumpTargetLabel) Label(net.bytebuddy.jar.asm.Label) SetJumpTargetLabel(org.curioswitch.common.protobuf.json.bytebuddy.SetJumpTargetLabel) IfTrue(org.curioswitch.common.protobuf.json.bytebuddy.IfTrue)

Example 2 with Label

use of org.apache.beam.vendor.bytebuddy.v1_11_0.net.bytebuddy.jar.asm.Label in project curiostack by curioswitch.

the class DoParse method apply.

@Override
public Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) {
    Map<String, FieldDescription> fieldsByName = CodeGenUtil.fieldsByName(implementationContext);
    List<FieldDescriptor> sortedFields = CodeGenUtil.sorted(descriptor.getFields());
    // Fields stored in order of number, so to get the highest number we take the last field.
    FieldDescriptor lastField = !sortedFields.isEmpty() ? sortedFields.get(sortedFields.size() - 1) : null;
    // Field numbers are 1 or greater so we will allocate the same size as the last field number
    // and subtract 1 when keeping track.
    int lastFieldNumber = lastField != null ? lastField.getNumber() : 0;
    int numFieldPresenceWords = lastFieldNumber / Integer.SIZE;
    if (lastFieldNumber % Integer.SIZE > 0) {
        numFieldPresenceWords++;
    }
    LocalVariable[] fieldPresenceVars = new LocalVariable[numFieldPresenceWords];
    for (int i = 0; i < numFieldPresenceWords; i++) {
        fieldPresenceVars[i] = new LocalVariable("setFieldBits" + i);
    }
    LocalVariable[] handles = Arrays.copyOf(LocalVariable.values(), LocalVariable.values().length + fieldPresenceVars.length);
    System.arraycopy(fieldPresenceVars, 0, handles, LocalVariable.values().length, fieldPresenceVars.length);
    LocalVariables.Builder<LocalVariable> localsBuilder = LocalVariables.builderForMethod(instrumentedMethod, handles).add(builderClass, LocalVariable.builder).add(String.class, LocalVariable.fieldName).add(int.class, LocalVariable.intvalue).add(int.class, LocalVariable.intMapKey).add(long.class, LocalVariable.longMapKey).add(boolean.class, LocalVariable.boolMapKey).add(String.class, LocalVariable.stringMapKey);
    for (LocalVariable fieldPresenceVar : fieldPresenceVars) {
        localsBuilder.add(int.class, fieldPresenceVar);
    }
    LocalVariables<LocalVariable> locals = localsBuilder.build();
    List<StackManipulation> stackManipulations = new ArrayList<>();
    Label beforeReadField = new Label();
    Label finished = new Label();
    // Initialize local variables for this method, e.g.,
    // void doMerge(JsonParser parser, int currentDepth, Message.Builder messageBuilder) {
    // T builder = (T) messageBuilder;
    // String fieldName = null;
    // Object fieldNumberUnboxed = null;
    // int fieldNumber = 0;
    // int setFieldBits0 = 0;
    // int setFieldBits1 = 0;
    // ...
    stackManipulations.addAll(Arrays.asList(locals.initialize(), locals.load(LocalVariable.messageBuilder), TypeCasting.to(new ForLoadedType(builderClass)), locals.store(LocalVariable.builder)));
    // Begins the loop that reads fields from the JSON, reading the field name and computing its
    // hash, e.g.,
    // ...
    // while (parser.nextValue() != ParseSupport.checkObjectEnd) {
    // fieldName = parser.getCurrentName();
    // fieldNumberUnboxed = FIELD_NUMBERS.get(fieldName):
    // if (fieldNumberUnboxed == null) {
    // ParseSupport.throwIfUnknownField(fieldName, descriptor.getFullName());
    // return
    // }
    // fieldNumber = (int) fieldNumberUnboxed;
    // ...
    stackManipulations.addAll(Arrays.asList(new SetJumpTargetLabel(beforeReadField), locals.load(LocalVariable.parser), Parser_nextValue, ParseSupport_checkObjectEnd, new IfTrue(finished), locals.load(LocalVariable.parser), Parser_getCurrentName, locals.store(LocalVariable.fieldName)));
    for (FieldDescriptor f : sortedFields) {
        Label afterNameCheck = new Label();
        Label afterField = new Label();
        ProtoFieldInfo field = new ProtoFieldInfo(f, prototype);
        int fieldNumberZeroBased = field.descriptor().getNumber() - 1;
        LocalVariable fieldPresenceVar = fieldPresenceVars[fieldNumberZeroBased / Integer.SIZE];
        int fieldPreserveVarBitIndex = fieldNumberZeroBased % Integer.SIZE;
        // if-statement for checking whether the current JSON field name matches this field, e.g.,
        // if (fieldName == String.intern(field.getName())
        // || fieldName == String.intern(field.getJsonName()) {
        // ...
        // } else if ...
        stackManipulations.addAll(Arrays.asList(locals.load(LocalVariable.fieldName), new TextConstant(field.descriptor().getJsonName()), new IfRefsEqual(afterNameCheck), locals.load(LocalVariable.fieldName), new TextConstant(field.descriptor().getName()), new IfRefsNotEqual(afterField), new SetJumpTargetLabel(afterNameCheck)));
        // Check whether we have already seen this field in the JSON, which is not allowed. e.g.,
        // setFieldBitsN = ParseSupport.throwIfFieldAlreadyWritten(
        // setFieldBitsN, 0x1 << field.getNumber() % 8);
        stackManipulations.addAll(Arrays.asList(locals.load(fieldPresenceVar), IntegerConstant.forValue(0x1 << fieldPreserveVarBitIndex), new TextConstant(field.descriptor().getFullName()), ParseSupport_throwIfFieldAlreadyWritten, locals.store(fieldPresenceVar)));
        // ParseSupport.throwIfOneofAlreadyWritten(builder.getSomeOneofCase(), field.getFullName());
        if (field.isInOneof()) {
            try {
                stackManipulations.addAll(Arrays.asList(locals.load(LocalVariable.parser), locals.load(LocalVariable.builder), invoke(builderClass.getDeclaredMethod(field.getOneOfCaseMethodName())), new TextConstant(field.descriptor().getFullName()), IntegerConstant.forValue(mustSkipNull(field.descriptor())), ParseSupport_throwIfOneofAlreadyWritten));
            } catch (NoSuchMethodException e) {
                throw new IllegalStateException("Could not find oneof case method.", e);
            }
        }
        // }
        if (mustSkipNull(field.descriptor())) {
            stackManipulations.addAll(Arrays.asList(locals.load(LocalVariable.parser), ParseSupport_checkNull, new IfTrue(beforeReadField)));
        }
        StackManipulation setValue = setFieldValue(field, beforeReadField, locals, fieldsByName);
        stackManipulations.add(setValue);
        stackManipulations.add(new SetJumpTargetLabel(afterField));
    }
    if (ignoringUnknownFields) {
        // If we found no corresponding field number, jump back to the beginning of the while loop.
        stackManipulations.add(new Goto(beforeReadField));
    } else {
        // If we found no corresponding field number, throw an exception.
        stackManipulations.addAll(Arrays.asList(locals.load(LocalVariable.fieldName), new TextConstant(descriptor.getFullName()), ParseSupport_throwIfUnknownField));
    }
    // End of the field processing while loop.
    stackManipulations.add(new SetJumpTargetLabel(finished));
    stackManipulations.add(MethodReturn.VOID);
    StackManipulation.Size operandStackSize = new StackManipulation.Compound(stackManipulations).apply(methodVisitor, implementationContext);
    return new Size(operandStackSize.getMaximalSize(), locals.stackSize());
}
Also used : StackManipulation(net.bytebuddy.implementation.bytecode.StackManipulation) ForLoadedType(net.bytebuddy.description.type.TypeDescription.ForLoadedType) ArrayList(java.util.ArrayList) SetJumpTargetLabel(org.curioswitch.common.protobuf.json.bytebuddy.SetJumpTargetLabel) Label(net.bytebuddy.jar.asm.Label) FieldDescriptor(com.google.protobuf.Descriptors.FieldDescriptor) IfRefsEqual(org.curioswitch.common.protobuf.json.bytebuddy.IfRefsEqual) Goto(org.curioswitch.common.protobuf.json.bytebuddy.Goto) IfRefsNotEqual(org.curioswitch.common.protobuf.json.bytebuddy.IfRefsNotEqual) TextConstant(net.bytebuddy.implementation.bytecode.constant.TextConstant) FieldDescription(net.bytebuddy.description.field.FieldDescription) SetJumpTargetLabel(org.curioswitch.common.protobuf.json.bytebuddy.SetJumpTargetLabel) IfTrue(org.curioswitch.common.protobuf.json.bytebuddy.IfTrue)

Example 3 with Label

use of org.apache.beam.vendor.bytebuddy.v1_11_0.net.bytebuddy.jar.asm.Label in project curiostack by curioswitch.

the class DoParse method setMapFieldValue.

/**
 * Returns the {@link StackManipulation} for setting the value of a map field.
 *
 * <p>Roughly equivalent to:
 *
 * <pre>{@code
 * ParseSupport.parseObjectStart(parser);
 * while (!ParseSupport.checkObjectEnd(parser.currentToken())) {
 *   builder.putFoo(readKey(), readValue());
 * }
 * }</pre>
 */
private StackManipulation setMapFieldValue(ProtoFieldInfo info, Label beforeReadField, LocalVariables<LocalVariable> locals, Map<String, FieldDescription> fieldsByName) {
    final StackManipulation setConcreteValue = invoke(info.setValueMethod());
    final StackManipulation setMapEntry;
    if (info.valueJavaType() == JavaType.MESSAGE) {
        setMapEntry = new StackManipulation.Compound(TypeCasting.to(new ForLoadedType(info.javaClass())), setConcreteValue);
    } else {
        setMapEntry = setConcreteValue;
    }
    Label mapStart = new Label();
    Label afterSet = new Label();
    StackManipulation.Compound beforeReadKey = new StackManipulation.Compound(locals.load(LocalVariable.parser), ParseSupport_parseObjectStart, new SetJumpTargetLabel(mapStart), locals.load(LocalVariable.parser), Parser_currentToken, ParseSupport_checkObjectEnd, new IfTrue(beforeReadField));
    StackManipulation.Compound setValueAndPrepareForNext = new StackManipulation.Compound(setMapEntry, Removal.SINGLE, new SetJumpTargetLabel(afterSet), locals.load(LocalVariable.parser), Parser_nextToken, Removal.SINGLE, new Goto(mapStart));
    if (info.valueType() == Type.ENUM) {
        // We special-case enum since we may need to skip unknown values.
        final LocalVariable keyVar;
        switch(info.mapKeyField().valueJavaType()) {
            case INT:
                keyVar = LocalVariable.intMapKey;
                break;
            case LONG:
                keyVar = LocalVariable.longMapKey;
                break;
            case BOOLEAN:
                keyVar = LocalVariable.boolMapKey;
                break;
            case STRING:
                keyVar = LocalVariable.stringMapKey;
                break;
            default:
                throw new IllegalArgumentException("Invalid map key type");
        }
        return new StackManipulation.Compound(beforeReadKey, locals.load(LocalVariable.parser), readValue(info.mapKeyField(), fieldsByName, locals), locals.store(keyVar), locals.load(LocalVariable.parser), Parser_nextToken, Removal.SINGLE, locals.load(LocalVariable.parser), readValue(info, fieldsByName, locals), locals.store(LocalVariable.intvalue), locals.load(LocalVariable.intvalue), IntegerConstant.forValue(-1), new IfEqual(int.class, afterSet), locals.load(LocalVariable.builder), locals.load(keyVar), locals.load(LocalVariable.intvalue), setValueAndPrepareForNext);
    } else {
        return new StackManipulation.Compound(beforeReadKey, locals.load(LocalVariable.builder), locals.load(LocalVariable.parser), readValue(info.mapKeyField(), fieldsByName, locals), locals.load(LocalVariable.parser), Parser_nextToken, Removal.SINGLE, locals.load(LocalVariable.parser), readValue(info, fieldsByName, locals), setValueAndPrepareForNext);
    }
}
Also used : IfEqual(org.curioswitch.common.protobuf.json.bytebuddy.IfEqual) Goto(org.curioswitch.common.protobuf.json.bytebuddy.Goto) StackManipulation(net.bytebuddy.implementation.bytecode.StackManipulation) ForLoadedType(net.bytebuddy.description.type.TypeDescription.ForLoadedType) SetJumpTargetLabel(org.curioswitch.common.protobuf.json.bytebuddy.SetJumpTargetLabel) Label(net.bytebuddy.jar.asm.Label) SetJumpTargetLabel(org.curioswitch.common.protobuf.json.bytebuddy.SetJumpTargetLabel) IfTrue(org.curioswitch.common.protobuf.json.bytebuddy.IfTrue)

Example 4 with Label

use of org.apache.beam.vendor.bytebuddy.v1_11_0.net.bytebuddy.jar.asm.Label in project hibernate-orm by hibernate.

the class FieldReaderAppender method apply.

@Override
public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext, MethodDescription instrumentedMethod) {
    TypeDescription dispatcherType = persistentField.getType().isPrimitive() ? persistentField.getType().asErasure() : TypeDescription.OBJECT;
    // if ( this.$$_hibernate_getInterceptor() != null )
    methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
    methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, managedCtClass.getInternalName(), EnhancerConstants.INTERCEPTOR_GETTER_NAME, Type.getMethodDescriptor(Type.getType(PersistentAttributeInterceptor.class)), false);
    Label skip = new Label();
    methodVisitor.visitJumpInsn(Opcodes.IFNULL, skip);
    // this (for field write)
    methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
    // this.$$_hibernate_getInterceptor();
    methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
    methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, managedCtClass.getInternalName(), EnhancerConstants.INTERCEPTOR_GETTER_NAME, Type.getMethodDescriptor(Type.getType(PersistentAttributeInterceptor.class)), false);
    // .readXXX( self, fieldName, field );
    methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
    methodVisitor.visitLdcInsn(persistentField.getName());
    methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
    fieldRead(methodVisitor);
    methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, Type.getInternalName(PersistentAttributeInterceptor.class), "read" + EnhancerImpl.capitalize(dispatcherType.getSimpleName()), Type.getMethodDescriptor(Type.getType(dispatcherType.getDescriptor()), Type.getType(Object.class), Type.getType(String.class), Type.getType(dispatcherType.getDescriptor())), true);
    // field = (cast) XXX
    if (!dispatcherType.isPrimitive()) {
        methodVisitor.visitTypeInsn(Opcodes.CHECKCAST, persistentField.getType().asErasure().getInternalName());
    }
    fieldWrite(methodVisitor);
    // end if
    methodVisitor.visitLabel(skip);
    if (implementationContext.getClassFileVersion().isAtLeast(ClassFileVersion.JAVA_V6)) {
        methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
    }
    // return field
    methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
    fieldRead(methodVisitor);
    methodVisitor.visitInsn(Type.getType(persistentField.getType().asErasure().getDescriptor()).getOpcode(Opcodes.IRETURN));
    return new Size(4 + persistentField.getType().getStackSize().getSize(), instrumentedMethod.getStackSize());
}
Also used : PersistentAttributeInterceptor(org.hibernate.engine.spi.PersistentAttributeInterceptor) Label(net.bytebuddy.jar.asm.Label) TypeDescription(net.bytebuddy.description.type.TypeDescription)

Example 5 with Label

use of org.apache.beam.vendor.bytebuddy.v1_11_0.net.bytebuddy.jar.asm.Label in project hibernate-orm by hibernate.

the class FieldWriterAppender method apply.

@Override
public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext, MethodDescription instrumentedMethod) {
    TypeDescription dispatcherType = persistentField.getType().isPrimitive() ? persistentField.getType().asErasure() : TypeDescription.OBJECT;
    // if ( this.$$_hibernate_getInterceptor() != null )
    methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
    methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, managedCtClass.getInternalName(), EnhancerConstants.INTERCEPTOR_GETTER_NAME, Type.getMethodDescriptor(Type.getType(PersistentAttributeInterceptor.class)), false);
    Label noInterceptor = new Label();
    methodVisitor.visitJumpInsn(Opcodes.IFNULL, noInterceptor);
    // this (for field write)
    methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
    // this.$$_hibernate_getInterceptor();
    methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
    methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, managedCtClass.getInternalName(), EnhancerConstants.INTERCEPTOR_GETTER_NAME, Type.getMethodDescriptor(Type.getType(PersistentAttributeInterceptor.class)), false);
    // .writeXXX( self, fieldName, field, arg1 );
    methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
    methodVisitor.visitLdcInsn(persistentField.getName());
    methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
    fieldRead(methodVisitor);
    methodVisitor.visitVarInsn(Type.getType(dispatcherType.getDescriptor()).getOpcode(Opcodes.ILOAD), 1);
    methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, Type.getInternalName(PersistentAttributeInterceptor.class), "write" + EnhancerImpl.capitalize(dispatcherType.getSimpleName()), Type.getMethodDescriptor(Type.getType(dispatcherType.getDescriptor()), Type.getType(Object.class), Type.getType(String.class), Type.getType(dispatcherType.getDescriptor()), Type.getType(dispatcherType.getDescriptor())), true);
    // arg1 = (cast) XXX
    if (!dispatcherType.isPrimitive()) {
        methodVisitor.visitTypeInsn(Opcodes.CHECKCAST, persistentField.getType().asErasure().getInternalName());
    }
    fieldWrite(methodVisitor);
    // return
    methodVisitor.visitInsn(Opcodes.RETURN);
    // else
    methodVisitor.visitLabel(noInterceptor);
    if (implementationContext.getClassFileVersion().isAtLeast(ClassFileVersion.JAVA_V6)) {
        methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
    }
    // this (for field write)
    methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
    // arg1 = (cast) XXX
    methodVisitor.visitVarInsn(Type.getType(dispatcherType.getDescriptor()).getOpcode(Opcodes.ILOAD), 1);
    if (!dispatcherType.isPrimitive()) {
        methodVisitor.visitTypeInsn(Opcodes.CHECKCAST, persistentField.getType().asErasure().getInternalName());
    }
    fieldWrite(methodVisitor);
    // return
    methodVisitor.visitInsn(Opcodes.RETURN);
    return new Size(4 + 2 * persistentField.getType().getStackSize().getSize(), instrumentedMethod.getStackSize());
}
Also used : PersistentAttributeInterceptor(org.hibernate.engine.spi.PersistentAttributeInterceptor) Label(net.bytebuddy.jar.asm.Label) TypeDescription(net.bytebuddy.description.type.TypeDescription)

Aggregations

Label (net.bytebuddy.jar.asm.Label)8 StackManipulation (net.bytebuddy.implementation.bytecode.StackManipulation)4 Goto (org.curioswitch.common.protobuf.json.bytebuddy.Goto)4 SetJumpTargetLabel (org.curioswitch.common.protobuf.json.bytebuddy.SetJumpTargetLabel)4 ForLoadedType (net.bytebuddy.description.type.TypeDescription.ForLoadedType)3 IfTrue (org.curioswitch.common.protobuf.json.bytebuddy.IfTrue)3 FieldDescriptor (com.google.protobuf.Descriptors.FieldDescriptor)2 ArrayList (java.util.ArrayList)2 FieldDescription (net.bytebuddy.description.field.FieldDescription)2 TypeDescription (net.bytebuddy.description.type.TypeDescription)2 IfEqual (org.curioswitch.common.protobuf.json.bytebuddy.IfEqual)2 PersistentAttributeInterceptor (org.hibernate.engine.spi.PersistentAttributeInterceptor)2 SerializableString (com.fasterxml.jackson.core.SerializableString)1 ByteString (com.google.protobuf.ByteString)1 Entry (java.util.Map.Entry)1 TextConstant (net.bytebuddy.implementation.bytecode.constant.TextConstant)1 IfFalse (org.curioswitch.common.protobuf.json.bytebuddy.IfFalse)1 IfRefsEqual (org.curioswitch.common.protobuf.json.bytebuddy.IfRefsEqual)1 IfRefsNotEqual (org.curioswitch.common.protobuf.json.bytebuddy.IfRefsNotEqual)1 EqualsHelper (org.hibernate.internal.util.compare.EqualsHelper)1