All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.chains_project.collector.util.ByteBuddyHelper Maven / Gradle / Ivy

package io.github.chains_project.collector.util;

import java.util.ArrayList;
import java.util.List;
import net.bytebuddy.ClassFileVersion;
import net.bytebuddy.dynamic.TargetType;
import net.bytebuddy.dynamic.scaffold.TypeInitializer.None;
import net.bytebuddy.implementation.Implementation.Context.Disabled.Factory;
import net.bytebuddy.implementation.Implementation.Context.ExtractableView;
import net.bytebuddy.implementation.Implementation.Context.FrameGeneration;
import net.bytebuddy.implementation.auxiliary.AuxiliaryType.NamingStrategy.Enumerating;
import net.bytebuddy.implementation.bytecode.StackManipulation;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.MethodNode;

public class ByteBuddyHelper {

    private static final ExtractableView BYTE_BUDDY_CONTEXT = Factory.INSTANCE.make(
            TargetType.DESCRIPTION,
            new Enumerating("F"),
            None.INSTANCE,
            ClassFileVersion.JAVA_V17,
            ClassFileVersion.JAVA_V17,
            FrameGeneration.DISABLED);

    /**
     * Applies a stack manipulation and adds the resulting instructions.
     *
     * @param method the method to add it to
     * @param insertAfter the node to insert it after
     * @param manipulation the stack manipulation to apply
     * @param insertPosition the insertion position
     * @return the new current instruction
     */
    public static AbstractInsnNode applyStackManipulation(
            MethodNode method,
            AbstractInsnNode insertAfter,
            StackManipulation manipulation,
            InsertPosition insertPosition) {
        int sizeBefore = method.instructions.size();

        manipulation.apply(method, BYTE_BUDDY_CONTEXT);

        List newNodes = new ArrayList<>();
        for (int i = sizeBefore; i < method.instructions.size(); i++) {
            AbstractInsnNode e = method.instructions.get(i);
            newNodes.add(e);
        }
        newNodes.forEach(it -> method.instructions.remove(it));

        AbstractInsnNode current = insertAfter;
        for (int i = 0; i < newNodes.size(); i++) {
            AbstractInsnNode newNode = newNodes.get(i);
            if (i == 0 && insertPosition == InsertPosition.BEFORE) {
                method.instructions.insertBefore(current, newNode);
            } else {
                method.instructions.insert(current, newNode);
            }
            current = newNode;
        }

        return insertPosition == InsertPosition.BEFORE ? insertAfter : current;
    }

    public enum InsertPosition {
        BEFORE,
        AFTER,
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy