nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/AbstractJavaLinker.java
changeset 34979 03b189baa361
parent 34978 e753c4c9f96f
child 37379 e9c85d2b1fcc
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/AbstractJavaLinker.java	Thu Jan 14 13:22:58 2016 +0100
+++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/AbstractJavaLinker.java	Thu Jan 14 13:24:03 2016 +0100
@@ -349,31 +349,52 @@
             throws Exception {
         final CallSiteDescriptor callSiteDescriptor = request.getCallSiteDescriptor();
 
+        final MissingMemberHandlerFactory missingMemberHandlerFactory;
+        final LinkerServices directLinkerServices;
+        if (linkerServices instanceof LinkerServicesWithMissingMemberHandlerFactory) {
+            final LinkerServicesWithMissingMemberHandlerFactory lswmmhf = ((LinkerServicesWithMissingMemberHandlerFactory)linkerServices);
+            missingMemberHandlerFactory = lswmmhf.missingMemberHandlerFactory;
+            directLinkerServices = lswmmhf.linkerServices;
+        } else {
+            missingMemberHandlerFactory = null;
+            directLinkerServices = linkerServices;
+        }
+
         // Handle NamedOperation(CALL_METHOD, name) separately
         final Operation operation = callSiteDescriptor.getOperation();
         if (operation instanceof NamedOperation) {
             final NamedOperation namedOperation = (NamedOperation)operation;
             if (namedOperation.getBaseOperation() == StandardOperation.CALL_METHOD) {
-                return createGuardedDynamicMethodInvocation(callSiteDescriptor,
-                        linkerServices, namedOperation.getName().toString(), methods);
+                final GuardedInvocation inv =
+                        createGuardedDynamicMethodInvocation(callSiteDescriptor,
+                        directLinkerServices, namedOperation.getName().toString(), methods);
+                if (inv == null) {
+                    return createNoSuchMemberHandler(missingMemberHandlerFactory,
+                            request, directLinkerServices).getGuardedInvocation();
+                }
+                return inv;
             }
         }
 
         final GuardedInvocationComponent gic = getGuardedInvocationComponent(
-                new ComponentLinkRequest(request, linkerServices));
+                new ComponentLinkRequest(request, directLinkerServices,
+                        missingMemberHandlerFactory));
         return gic != null ? gic.getGuardedInvocation() : null;
     }
 
     static final class ComponentLinkRequest {
         final LinkRequest linkRequest;
         final LinkerServices linkerServices;
+        final MissingMemberHandlerFactory missingMemberHandlerFactory;
         final List<Operation> operations;
         final Object name;
 
         ComponentLinkRequest(final LinkRequest linkRequest,
-                final LinkerServices linkerServices) {
+                final LinkerServices linkerServices,
+                final MissingMemberHandlerFactory missingMemberHandlerFactory) {
             this.linkRequest = linkRequest;
             this.linkerServices = linkerServices;
+            this.missingMemberHandlerFactory = missingMemberHandlerFactory;
             final Operation operation = linkRequest.getCallSiteDescriptor().getOperation();
             this.operations = Arrays.asList(
                     CompositeOperation.getOperations(
@@ -383,9 +404,11 @@
 
         private ComponentLinkRequest(final LinkRequest linkRequest,
                 final LinkerServices linkerServices,
+                final MissingMemberHandlerFactory missingMemberHandlerFactory,
                 final List<Operation> operations, final Object name) {
             this.linkRequest = linkRequest;
             this.linkerServices = linkerServices;
+            this.missingMemberHandlerFactory = missingMemberHandlerFactory;
             this.operations = operations;
             this.name = name;
         }
@@ -396,6 +419,7 @@
 
         ComponentLinkRequest popOperations() {
             return new ComponentLinkRequest(linkRequest, linkerServices,
+                    missingMemberHandlerFactory,
                     operations.subList(1, operations.size()), name);
         }
     }
@@ -416,7 +440,8 @@
 
     GuardedInvocationComponent getNextComponent(final ComponentLinkRequest req) throws Exception {
         if (req.operations.isEmpty()) {
-            return null;
+            return createNoSuchMemberHandler(req.missingMemberHandlerFactory,
+                    req.linkRequest, req.linkerServices);
         }
         final GuardedInvocationComponent gic = getGuardedInvocationComponent(req);
         if (gic != null) {
@@ -425,6 +450,22 @@
         return getNextComponent(req.popOperations());
     }
 
+    private GuardedInvocationComponent createNoSuchMemberHandler(
+            final MissingMemberHandlerFactory missingMemberHandlerFactory,
+            final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception {
+        if (missingMemberHandlerFactory == null) {
+            return null;
+        }
+        final MethodHandle handler = missingMemberHandlerFactory.createMissingMemberHandler(linkRequest, linkerServices);
+        if (handler == null) {
+            return null;
+        }
+        final MethodType type = linkRequest.getCallSiteDescriptor().getMethodType();
+        // The returned handler is allowed to differ in return type.
+        assert handler.type().changeReturnType(type.returnType()).equals(type);
+        return getClassGuardedInvocationComponent(handler, type);
+    }
+
     static final <T> List<T> pop(final List<T> l) {
         return l.subList(1, l.size());
     }