package st.gravel.support.jvm.runtime; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles.Lookup; import java.lang.invoke.MethodType; import st.gravel.support.compiler.ast.BlockInliner; import st.gravel.support.compiler.ast.MethodMapping; import st.gravel.support.compiler.ast.MethodNode; import st.gravel.support.compiler.ast.Node; import st.gravel.support.compiler.ast.Reference; import st.gravel.support.compiler.jvm.BlockSendArgument; import st.gravel.support.compiler.jvm.JVMDefinedObjectType; import st.gravel.support.compiler.jvm.JVMNonPrimitiveType; import st.gravel.support.jvm.Block1; public class LiteralBlockSendCallSite extends PolymorphicCallSite { private final BlockSendArgument[] astConstants; private final String[] copiedArgumentNames; public static BaseCallSite newInstance(Lookup lookup, MethodType type, String selector, BlockSendArgument[] astConstants, String[] copiedArgumentNames) { BaseCallSite callsite = new LiteralBlockSendCallSite(lookup, type, selector, astConstants, copiedArgumentNames); BaseCallSite.register(callsite); return callsite; } private LiteralBlockSendCallSite(Lookup lookup, MethodType type, String selector, BlockSendArgument[] astConstants, String[] copiedArgumentNames) { super(lookup, type, selector); this.astConstants = astConstants; this.copiedArgumentNames = copiedArgumentNames; } @Override protected MethodHandle findMethodForNil() { MethodMapping methodMapping = ImageBootstrapper.systemMapping .methodMappingForNil_(selector); if (methodMapping == null) { return createDNUHandleForNil(); } MethodNode methodNode = methodMapping.methodNode(); return inlineBlocks(methodNode, ImageBootstrapper.systemMapping .nilClassMapping().reference(), JVMDefinedObjectType.factory.object()); } @Override protected MethodHandle findMethod(Class receiverClass) { MethodMapping methodMapping = ImageBootstrapper.systemMapping .methodMappingFor_methodName_(receiverClass, selector); if (methodMapping == null) { return createDNUHandle(receiverClass).asType(type); } MethodNode methodNode = methodMapping .methodNode(); return inlineBlocks(methodNode, ImageBootstrapper.systemMapping .classMappingForJavaClass_(receiverClass).reference(), (JVMNonPrimitiveType) ImageBootstrapper.systemMapping.compilerTools().jvmTypeForClass_(receiverClass)); } private MethodHandle createDNUHandleForNil() { throw new RuntimeException("niy"); } private MethodHandle createDNUHandle(Class receiverClass) { throw new RuntimeException("niy"); } private MethodHandle inlineBlocks(MethodNode methodNode, Reference receiverReference, JVMNonPrimitiveType selfType) { BlockInliner blockInliner = BlockInliner.factory .methodNode_astConstants_systemMapping_copiedArgumentNames_selfType_receiverReference_( methodNode, astConstants, ImageBootstrapper.systemMapping, copiedArgumentNames, selfType , receiverReference); if (!isOptimizable(methodNode)) { return blockInliner.buildNonOptimized(); } return blockInliner.build(); } private boolean isOptimizable(MethodNode methodNode) { Block1<Boolean, Node> _aBlock = new Block1<Boolean, Node>() { @Override public Boolean value_(Node arg1) { return arg1.isSuperNode(); } }; return !(methodNode.allNodesContains_(_aBlock )); } }