use of 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 static 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();
return new StackManipulation.Compound(locals.load(LocalVariable.parser), ParseSupport_parseObjectStart, new SetJumpTargetLabel(mapStart), locals.load(LocalVariable.parser), Parser_currentToken, ParseSupport_checkObjectEnd, new IfTrue(beforeReadField), 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), setMapEntry, Removal.SINGLE, locals.load(LocalVariable.parser), Parser_nextToken, Removal.SINGLE, new Goto(mapStart));
}
use of 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);
// Fields stored in order of number, so to get the highest number we take the last field.
FieldDescriptor lastField = Iterables.getLast(descriptor.getFields(), 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++;
}
List<LocalVariable> fieldPresenceVars = new ArrayList<>();
for (int i = 0; i < numFieldPresenceWords; i++) {
fieldPresenceVars.add(new LocalVariable("setFieldBits" + i));
}
LocalVariables.Builder<LocalVariable> localsBuilder = LocalVariables.builderForMethod(instrumentedMethod, ObjectArrays.concat(LocalVariable.values(), Iterables.toArray(fieldPresenceVars, LocalVariable.class), LocalVariable.class)).add(builderClass, LocalVariable.builder).add(String.class, LocalVariable.fieldName);
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 : descriptor.getFields()) {
Label afterNameCheck = new Label();
Label afterField = new Label();
ProtoFieldInfo field = new ProtoFieldInfo(f, prototype);
int fieldNumberZeroBased = field.descriptor().getNumber() - 1;
LocalVariable fieldPresenceVar = fieldPresenceVars.get(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.builder), invoke(builderClass.getDeclaredMethod(field.getOneOfCaseMethodName())), new TextConstant(field.descriptor().getFullName()), 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());
}
use of 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());
}
use of 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());
}
use of net.bytebuddy.jar.asm.Label in project hibernate-orm by hibernate.
the class InlineDirtyCheckingHandler method apply.
@Override
public Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) {
// if (arg != field) {
methodVisitor.visitVarInsn(Type.getType(persistentField.getType().asErasure().getDescriptor()).getOpcode(Opcodes.ILOAD), 1);
methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
if (persistentField.getDeclaringType().asErasure().equals(managedCtClass)) {
methodVisitor.visitFieldInsn(Opcodes.GETFIELD, persistentField.getDeclaringType().asErasure().getInternalName(), persistentField.getName(), persistentField.getDescriptor());
} else {
methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, persistentField.getDeclaringType().asErasure().getInternalName(), EnhancerConstants.PERSISTENT_FIELD_READER_PREFIX + persistentField.getName(), Type.getMethodDescriptor(Type.getType(persistentField.getDescriptor())), false);
}
int branchCode;
if (persistentField.getType().isPrimitive()) {
if (persistentField.getType().represents(long.class)) {
methodVisitor.visitInsn(Opcodes.LCMP);
} else if (persistentField.getType().represents(float.class)) {
methodVisitor.visitInsn(Opcodes.FCMPL);
} else if (persistentField.getType().represents(double.class)) {
methodVisitor.visitInsn(Opcodes.DCMPL);
} else {
methodVisitor.visitInsn(Opcodes.ISUB);
}
branchCode = Opcodes.IFEQ;
} else {
methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(EqualsHelper.class), "areEqual", Type.getMethodDescriptor(Type.getType(boolean.class), Type.getType(Object.class), Type.getType(Object.class)), false);
branchCode = Opcodes.IFNE;
}
Label skip = new Label();
methodVisitor.visitJumpInsn(branchCode, skip);
// this.$$_hibernate_trackChange(fieldName)
methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
methodVisitor.visitLdcInsn(persistentField.getName());
methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, managedCtClass.getInternalName(), EnhancerConstants.TRACKER_CHANGER_NAME, Type.getMethodDescriptor(Type.getType(void.class), Type.getType(String.class)), false);
// }
methodVisitor.visitLabel(skip);
if (implementationContext.getClassFileVersion().isAtLeast(ClassFileVersion.JAVA_V6)) {
methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
}
return new Size(1 + 2 * persistentField.getType().asErasure().getStackSize().getSize(), instrumentedMethod.getStackSize());
}
Aggregations