use of dyvilx.tools.asm.Label in project Dyvil by Dyvil.
the class CaseClasses method writeHashCode.
public static void writeHashCode(MethodWriter writer, IType type) throws BytecodeException {
if (type.isPrimitive()) {
switch(type.getTypecode()) {
case PrimitiveType.BOOLEAN_CODE:
{
// Write boolean hashing by using 1231 if the value is true and
// 1237 if the value is false
Label elseLabel = new Label();
Label endLabel = new Label();
// if
writer.visitJumpInsn(IFEQ, elseLabel);
// then
writer.visitLdcInsn(1231);
writer.visitJumpInsn(GOTO, endLabel);
// else
writer.visitLabel(elseLabel);
writer.visitLdcInsn(1237);
writer.visitLabel(endLabel);
return;
}
case PrimitiveType.BYTE_CODE:
return;
case PrimitiveType.SHORT_CODE:
return;
case PrimitiveType.CHAR_CODE:
return;
case PrimitiveType.INT_CODE:
return;
case PrimitiveType.LONG_CODE:
// Write a long hashing snippet by XORing the value by the value
// bit-shifted 32 bits to the right, and then converting the
// result to an integer. l1 = (int) (l ^ (l >>> 32))
writer.visitInsn(DUP2);
writer.visitLdcInsn(32);
writer.visitInsn(LUSHR);
writer.visitInsn(LOR);
writer.visitInsn(L2I);
return;
case PrimitiveType.FLOAT_CODE:
// Write a float hashing snippet using Float.floatToIntBits
writer.visitLineNumber(0);
writer.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "floatToIntBits", "(F)I", false);
return;
case PrimitiveType.DOUBLE_CODE:
// Write a double hashing snippet using Double.doubleToLongBits
// and long hashing
writer.visitLineNumber(0);
writer.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "doubleToLongBits", "(D)J", false);
writer.visitInsn(DUP2);
writer.visitLdcInsn(32);
writer.visitInsn(LUSHR);
writer.visitInsn(LOR);
writer.visitInsn(L2I);
return;
}
}
Label elseLabel = new Label();
Label endLabel = new Label();
// Write an Object hashing snippet
// if
writer.visitInsn(DUP);
writer.visitJumpInsn(IFNULL, elseLabel);
// then
writer.visitLineNumber(0);
final ArrayType arrayType = type.extract(ArrayType.class);
if (arrayType != null) {
writeArrayHashCode(writer, arrayType.getElementType());
} else {
writer.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "hashCode", "()I", false);
}
writer.visitJumpInsn(GOTO, endLabel);
// else
writer.visitLabel(elseLabel);
writer.visitInsn(POP);
writer.visitLdcInsn(0);
writer.visitLabel(endLabel);
}
use of dyvilx.tools.asm.Label in project Dyvil by Dyvil.
the class MatchExpr method generateBranched.
private void generateBranched(MethodWriter writer, Object frameType) throws BytecodeException {
final boolean expr = frameType != null;
final int localCount = writer.localCount();
final IType matchedType = this.matchedValue.getType();
final int varIndex = this.matchedValue.writeStore(writer, null);
final int localCountInner = writer.localCount();
Label elseLabel = new Label();
Label endLabel = new Label();
for (int i = 0; ; ) {
MatchCase c = this.cases[i];
IValue condition = c.condition;
c.pattern.writeJumpOnMismatch(writer, varIndex, elseLabel);
if (condition != null) {
condition.writeInvJump(writer, elseLabel);
}
this.writeAction(writer, expr, frameType, c.action);
writer.resetLocals(localCountInner);
if (!writer.hasReturn()) {
writer.visitJumpInsn(Opcodes.GOTO, endLabel);
}
writer.visitTargetLabel(elseLabel);
if (++i < this.caseCount) {
elseLabel = new Label();
} else {
break;
}
}
// MatchError
writer.visitLabel(elseLabel);
if (!this.exhaustive) {
this.writeMatchError(writer, varIndex, matchedType);
}
writer.visitLabel(endLabel);
writer.resetLocals(localCount);
}
use of dyvilx.tools.asm.Label in project Dyvil by Dyvil.
the class BooleanOperator method writeExpression.
protected static void writeExpression(MethodWriter writer, IValue value, IType type) {
final Label label = new Label();
final Label end = new Label();
// if (expr) {
value.writeInvJump(writer, label);
// true
writer.visitLdcInsn(1);
// }
writer.visitJumpInsn(Opcodes.GOTO, end);
// else {
writer.visitLabel(label);
// false
writer.visitLdcInsn(0);
// }
writer.visitLabel(end);
if (type != null) {
Types.BOOLEAN.writeCast(writer, type, value.lineNumber());
}
}
use of dyvilx.tools.asm.Label in project Dyvil by Dyvil.
the class CodeMethod method write.
@Override
public void write(ClassWriter writer) throws BytecodeException {
final boolean interfaceClass = this.enclosingClass.isInterface();
final long flags = ModifierUtil.getFlags(this);
final String ownerClassName = this.enclosingClass.getInternalName();
final String mangledName = this.getInternalName();
final String descriptor = this.getDescriptor();
final String signature = this.needsSignature() ? this.getSignature() : null;
final String[] exceptionTypes = this.getInternalExceptions();
MethodWriter methodWriter = new MethodWriterImpl(writer, writer.visitMethod(ModifierUtil.getJavaModifiers(flags), mangledName, descriptor, signature, exceptionTypes));
if (!this.isStatic()) {
methodWriter.setThisType(ownerClassName);
}
this.writeAnnotations(methodWriter, flags);
this.writeParameters(methodWriter);
final Label start = new Label();
final Label end = new Label();
if (this.value != null) {
methodWriter.visitCode();
methodWriter.visitLabel(start);
this.value.writeExpression(methodWriter, this.type);
methodWriter.visitLabel(end);
methodWriter.visitEnd(this.type);
} else if (this.hasModifier(Modifiers.STATIC | Modifiers.ABSTRACT)) {
// no value, but no abstract flag
methodWriter.visitCode();
methodWriter.visitTypeInsn(Opcodes.NEW, "java/lang/AbstractMethodError");
methodWriter.visitInsn(Opcodes.DUP);
methodWriter.visitLdcInsn(ClassFormat.internalToPackage(ownerClassName) + '.' + mangledName + descriptor);
methodWriter.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/AbstractMethodError", "<init>", "(Ljava/lang/String;)V", false);
methodWriter.visitInsn(Opcodes.ATHROW);
methodWriter.visitEnd(this.type);
}
if (!this.isStatic()) {
methodWriter.visitLocalVariable("this", 'L' + ownerClassName + ';', null, start, end, 0);
}
this.parameters.writeLocals(methodWriter, start, end);
if (this.overrideMethods == null) {
return;
}
final int lineNumber = this.lineNumber();
final int opcode = this.getInvokeOpcode();
final int bridgeModifiers = Modifiers.PUBLIC | Modifiers.SYNTHETIC | Modifiers.BRIDGE | (this.isStatic() ? Modifiers.STATIC : 0);
/*
* Contains entries in the format 'mangledName(paramTypes)returnType'
* Used to ensure unique bridge methods
*/
final Set<String> descriptors = new HashSet<>(1 + this.overrideMethods.size());
descriptors.add(mangledName + descriptor);
for (IMethod overrideMethod : this.overrideMethods) {
final String overrideDescriptor = overrideMethod.getDescriptor();
final String overrideMangledName = overrideMethod.getInternalName();
final String overrideEntry = overrideMangledName + overrideDescriptor;
// generated
if (descriptors.contains(overrideEntry)) {
continue;
}
descriptors.add(overrideEntry);
// Generate a bridge method
methodWriter = new MethodWriterImpl(writer, writer.visitMethod(bridgeModifiers, overrideMangledName, overrideDescriptor, null, exceptionTypes));
methodWriter.visitCode();
if (!this.isStatic()) {
methodWriter.setThisType(ownerClassName);
methodWriter.visitVarInsn(Opcodes.ALOAD, 0);
}
// Generate Parameters and load arguments
this.writeBridgeParameters(methodWriter, overrideMethod);
// Generate Type Parameters and load reified type arguments
this.writeBridgeTypeParameters(methodWriter, overrideMethod);
final IType overrideReturnType = overrideMethod.getType();
methodWriter.visitLineNumber(lineNumber);
methodWriter.visitMethodInsn(opcode, ownerClassName, mangledName, descriptor, interfaceClass);
this.type.writeCast(methodWriter, overrideReturnType, lineNumber);
methodWriter.visitInsn(overrideReturnType.getReturnOpcode());
methodWriter.visitEnd();
}
}
use of dyvilx.tools.asm.Label in project Dyvil by Dyvil.
the class OrPattern method writeJumpOnMismatch.
@Override
public void writeJumpOnMismatch(MethodWriter writer, int varIndex, Label target) throws BytecodeException {
final int locals = writer.localCount();
varIndex = Pattern.ensureVar(writer, varIndex);
final Label targetLabel = new Label();
this.left.writeJumpOnMatch(writer, varIndex, targetLabel);
writer.resetLocals(locals);
this.right.writeJumpOnMismatch(writer, varIndex, target);
writer.visitLabel(targetLabel);
writer.resetLocals(locals);
}
Aggregations