MCPcopy Index your code
hub / github.com/clojure/clojure / maybeEmitFIAdapter

Method maybeEmitFIAdapter

src/jvm/clojure/lang/Compiler.java:1693–1747  ·  view source on GitHub ↗

If targetClass is FI and has an adaptable functional method Find fn invoker method matching adaptable method of FI Emit bytecode for (expr is emitted): if(expr instanceof IFn && !(expr instanceof FI)) invokeDynamic(targetMethod, fnInvokerImplMethod) Else emit nothing

(ObjExpr objx, GeneratorAdapter gen, Expr expr, Class targetClass)

Source from the content-addressed store, hash-verified

1691 * Else emit nothing
1692 */
1693 static boolean maybeEmitFIAdapter(ObjExpr objx, GeneratorAdapter gen, Expr expr, Class targetClass) {
1694 // Optimization:
1695 // if(expr instanceof QualifiedMethodExpr)
1696 // emitInvokeDynamic(targetMethod, QME method) // DON'T emit expr
1697
1698 java.lang.reflect.Method targetMethod = maybeFIMethod(targetClass);
1699 if (targetMethod == null)
1700 return false;
1701
1702 // compute fn invoker method
1703 int paramCount = targetMethod.getParameterCount();
1704 Class[] invokerParams = new Class[paramCount + 1];
1705 invokerParams[0] = IFn.class; // close over Ifn as first arg
1706 StringBuilder invokeMethodBuilder = new StringBuilder("invoke");
1707 for (int i = 0; i < paramCount; i++) {
1708 // FnInvokers only has prims for first 2 args
1709 invokerParams[i + 1] = paramCount <= 2 ? toInvokerParamType(targetMethod.getParameterTypes()[i]) : Object.class;
1710 invokeMethodBuilder.append(FnInvokers.encodeInvokerType(invokerParams[i + 1]));
1711 }
1712 // FnInvokers has prim returns for <= 2 params, only Object for higher
1713 Class retType = targetMethod.getReturnType();
1714 char invokerReturnCode = FnInvokers.encodeInvokerType(paramCount <= 2 ? retType : Object.class);
1715 invokeMethodBuilder.append(invokerReturnCode);
1716 String invokerMethodName = invokeMethodBuilder.toString();
1717
1718 // Emit adapter to fn invoker method
1719 Type samType = Type.getType(targetClass);
1720 Type ifnType = Type.getType(IFn.class);
1721 try {
1722 java.lang.reflect.Method fnInvokerMethod = FnInvokers.class.getMethod(invokerMethodName, invokerParams);
1723
1724 // if not (expr instanceof IFn), go to end label
1725 expr.emit(C.EXPRESSION, objx, gen);
1726 gen.dup();
1727 gen.instanceOf(ifnType);
1728 Label endLabel = gen.newLabel();
1729 gen.ifZCmp(Opcodes.IFEQ, endLabel);
1730
1731 // if (expr instanceof FI), go to end label
1732 gen.dup();
1733 gen.instanceOf(samType);
1734 gen.ifZCmp(Opcodes.IFNE, endLabel);
1735
1736 // else adapt fn invoker method as impl for target method
1737 emitInvokeDynamicAdapter(gen, targetClass, targetMethod, FnInvokers.class, fnInvokerMethod);
1738
1739 // end - checkcast that we have the target FI type
1740 gen.mark(endLabel);
1741 gen.checkCast(samType);
1742 return true;
1743 } catch (NoSuchMethodException e) {
1744 throw Util.sneakyThrow(e); // should never happen
1745 }
1746
1747 }
1748
1749 // LambdaMetafactory.metafactory() method handle for lambda bootstrap
1750 private static final Handle LMF_HANDLE =

Callers 2

emitTypedArgsMethod · 0.95
doEmitMethod · 0.95

Calls 15

maybeFIMethodMethod · 0.95
toInvokerParamTypeMethod · 0.95
encodeInvokerTypeMethod · 0.95
getTypeMethod · 0.95
sneakyThrowMethod · 0.95
appendMethod · 0.80
dupMethod · 0.80
instanceOfMethod · 0.80
newLabelMethod · 0.80
ifZCmpMethod · 0.80
markMethod · 0.80

Tested by

no test coverage detected