use of dyvilx.tools.asm.Handle in project Dyvil by Dyvil.
the class PropertyReference method writeReference.
@Override
public void writeReference(MethodWriter writer, int lineNumber) throws BytecodeException {
StringBuilder desc = new StringBuilder().append('(');
if (this.receiver != null) {
this.receiver.writeExpression(writer, null);
this.receiver.getType().appendExtendedName(desc);
}
final IType methodType = this.getterMethod.getType();
final String getterName = this.getterMethod.getInternalName();
desc.append(')').append('L').append(ReferenceType.LazyFields.getInternalRef(methodType, "")).append(';');
final Handle getterHandle = this.getterMethod.toHandle();
final Handle setterHandle = this.setterMethod.toHandle();
writer.visitLineNumber(lineNumber);
writer.visitInvokeDynamicInsn(getterName, desc.toString(), BOOTSTRAP, getterHandle, setterHandle);
}
use of dyvilx.tools.asm.Handle in project Dyvil by Dyvil.
the class LambdaExpr method writeExpression.
@Override
public void writeExpression(MethodWriter writer, IType type) throws BytecodeException {
int handleType = this.getHandleType();
if (handleType == 0) {
handleType = ClassFormat.H_INVOKESTATIC;
if (this.captureHelper != null) {
if (this.captureHelper.isThisCaptured()) {
handleType = ClassFormat.H_INVOKESPECIAL;
}
this.captureHelper.writeCaptures(writer, this.lineNumber());
}
}
final String desc = this.getTargetDescriptor();
final String invokedName = this.method.getInternalName();
final String invokedType = this.getInvokeDescriptor();
final dyvilx.tools.asm.Type methodDescriptorType = dyvilx.tools.asm.Type.getMethodType(this.method.getDescriptor());
final dyvilx.tools.asm.Type lambdaDescriptorType = dyvilx.tools.asm.Type.getMethodType(this.getLambdaDescriptor());
final Handle handle = new Handle(handleType, this.owner, this.name, desc);
writer.visitLineNumber(this.lineNumber());
writer.visitInvokeDynamicInsn(invokedName, invokedType, BOOTSTRAP, methodDescriptorType, handle, lambdaDescriptorType);
if (type != null) {
this.type.writeCast(writer, type, this.lineNumber());
}
}
use of dyvilx.tools.asm.Handle in project Dyvil by Dyvil.
the class AbstractMethod method writeInvoke.
@Override
public void writeInvoke(MethodWriter writer, IValue receiver, ArgumentList arguments, ITypeContext typeContext, int lineNumber) throws BytecodeException {
if (this.typeParameters != null) {
this.typeParameters.writeArguments(writer, typeContext);
}
writer.visitLineNumber(lineNumber);
final int opcode;
final String mangledName = this.getInternalName();
final String descriptor = this.getDescriptor();
if (this.hasModifier(Modifiers.EXTENSION)) {
// extension method invocation
final Handle handle = new Handle(ClassFormat.H_INVOKESTATIC, this.enclosingClass.getInternalName(), mangledName, descriptor);
writer.visitInvokeDynamicInsn(mangledName, descriptor, EXTENSION_BSM, handle);
return;
}
final String owner;
final boolean isInterface;
if (receiver != null) {
final IType receiverType = receiver.getType();
if (receiver.isIgnoredClassAccess() && receiverType.hasTag(IType.TYPE_VAR)) {
// Dynamic invocation of a static method based on a type variable
writer.visitInvokeDynamicInsn(mangledName, descriptor.replace("(", "(Ljava/lang/Class;"), STATICVIRTUAL_BSM);
return;
}
if (receiver.valueTag() == IValue.SUPER) {
// Super-method invocation
opcode = Opcodes.INVOKESPECIAL;
owner = this.enclosingClass.getInternalName();
isInterface = this.enclosingClass.isInterface();
} else if (this.isStatic()) {
opcode = Opcodes.INVOKESTATIC;
owner = this.enclosingClass.getInternalName();
isInterface = this.enclosingClass.isInterface();
} else {
// bugfix: for non-static calls, we use the type of the receiver to avoid
// IllegalAccessExceptions on the owner class.
// Example: Calling length() on a StringBuilder object resolves to AbstractStringBuilder.length(),
// but AbstractStringBuilder is not accessible
final IClass receiverClass = receiverType.getTheClass();
opcode = this.getInvokeOpcode(receiverClass);
owner = receiverType.getInternalName();
isInterface = receiverClass.isInterface();
}
} else {
opcode = this.getInvokeOpcode();
owner = this.enclosingClass.getInternalName();
isInterface = this.enclosingClass.isInterface();
}
writer.visitMethodInsn(opcode, owner, mangledName, descriptor, isInterface);
}