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

org.qbicc.plugin.reflection.VarHandleResolvingBasicBlockBuilder Maven / Gradle / Ivy

There is a newer version: 0.77.0
Show newest version
package org.qbicc.plugin.reflection;

import static org.qbicc.plugin.reflection.Reflection.erase;

import java.util.List;

import org.qbicc.context.ClassContext;
import org.qbicc.context.CompilationContext;
import org.qbicc.graph.BasicBlockBuilder;
import org.qbicc.graph.DelegatingBasicBlockBuilder;
import org.qbicc.graph.Value;
import org.qbicc.graph.ValueHandle;
import org.qbicc.type.descriptor.BaseTypeDescriptor;
import org.qbicc.type.descriptor.ClassTypeDescriptor;
import org.qbicc.type.descriptor.MethodDescriptor;
import org.qbicc.type.descriptor.TypeDescriptor;

/**
 * A basic block builder which resolves signature-polymorphic {@code VarHandle} invocations to their
 * canonical variants; specifically, converting the return type as needed.
 */
public final class VarHandleResolvingBasicBlockBuilder extends DelegatingBasicBlockBuilder {
    private final CompilationContext ctxt;

    public VarHandleResolvingBasicBlockBuilder(CompilationContext ctxt, BasicBlockBuilder delegate) {
        super(delegate);
        this.ctxt = ctxt;
    }

    @Override
    public ValueHandle virtualMethodOf(Value instance, TypeDescriptor owner, String name, MethodDescriptor descriptor) {
        if (owner instanceof ClassTypeDescriptor ctd && ctd.packageAndClassNameEquals("java/lang/invoke", "VarHandle")) {
            return super.virtualMethodOf(instance, owner, name, translate(name, descriptor));
        }
        return super.virtualMethodOf(instance, owner, name, descriptor);
    }

    @Override
    public ValueHandle exactMethodOf(Value instance, TypeDescriptor owner, String name, MethodDescriptor descriptor) {
        if (owner instanceof ClassTypeDescriptor ctd && ctd.packageAndClassNameEquals("java/lang/invoke", "VarHandle")) {
            return super.exactMethodOf(instance, owner, name, translate(name, descriptor));
        }
        return super.exactMethodOf(instance, owner, name, descriptor);
    }

    private MethodDescriptor translate(String name, MethodDescriptor descriptor) {
        ClassContext classContext = ctxt.getBootstrapClassContext();
        TypeDescriptor retType = descriptor.getReturnType();
        MethodDescriptor erased = erase(classContext, descriptor);
        List erasedParamTypes = erased.getParameterTypes();
        int paramCnt = erasedParamTypes.size();
        TypeDescriptor fixedRetType;
        // transform all special methods
        switch (name) {
            // CAS always returns {@code boolean}
            case "compareAndSet":
            case "weakCompareAndSetPlain":
            case "weakCompareAndSet":
            case "weakCompareAndSetAcquire":
            case "weakCompareAndSetRelease":
                fixedRetType = BaseTypeDescriptor.Z;
                break;

            // set always returns {@code void}
            case "set":
            case "setVolatile":
            case "setRelease":
            case "setOpaque":
                fixedRetType = retType;
                break;

            // get always returns *whatever the type is*; we can't really infer it though!
            case "get":
            case "getVolatile":
            case "getAcquire":
            case "getOpaque":
                fixedRetType = retType;
                break;

            // compare-and-exchange and read-modify-write returns the erased type of its input
            case "compareAndExchange":
            case "compareAndExchangeAcquire":
            case "compareAndExchangeRelease":
            case "getAndSet":
            case "getAndSetAcquire":
            case "getAndSetRelease":
            case "getAndAdd":
            case "getAndAddAcquire":
            case "getAndAddRelease":
            case "getAndBitwiseOr":
            case "getAndBitwiseOrAcquire":
            case "getAndBitwiseOrRelease":
            case "getAndBitwiseAnd":
            case "getAndBitwiseAndAcquire":
            case "getAndBitwiseAndRelease":
            case "getAndBitwiseXor":
            case "getAndBitwiseXorAcquire":
            case "getAndBitwiseXorRelease":
                fixedRetType = erasedParamTypes.get(paramCnt - 1);
                break;

            default:
                return descriptor;
        }
        if (retType == BaseTypeDescriptor.V) {
            return MethodDescriptor.synthesize(classContext, fixedRetType, erasedParamTypes);
        } else {
            // use the original return type even if it's narrower (because we will need the cast from the generated method)
            return MethodDescriptor.synthesize(classContext, retType, erasedParamTypes);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy