changeset 1597:2247904a107c

8144917: Prepare AbstractJavaLinker/BeanLinker codebase for missing member implementation Reviewed-by: mhaupt, sundar
author attila
date Thu, 14 Jan 2016 13:22:58 +0100
parents da61004610e3
children 30c3bcdb762c
files src/jdk.dynalink/share/classes/jdk/dynalink/beans/AbstractJavaLinker.java src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeanLinker.java src/jdk.dynalink/share/classes/jdk/dynalink/beans/StaticClassLinker.java
diffstat 3 files changed, 154 insertions(+), 110 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/AbstractJavaLinker.java	Thu Jan 14 15:35:43 2016 +0530
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/AbstractJavaLinker.java	Thu Jan 14 13:22:58 2016 +0100
@@ -359,45 +359,70 @@
             }
         }
 
-        List<Operation> operations = Arrays.asList(
-                CompositeOperation.getOperations(
-                        NamedOperation.getBaseOperation(operation)));
-        final Object name = NamedOperation.getName(operation);
+        final GuardedInvocationComponent gic = getGuardedInvocationComponent(
+                new ComponentLinkRequest(request, linkerServices));
+        return gic != null ? gic.getGuardedInvocation() : null;
+    }
 
-        while(!operations.isEmpty()) {
-            final GuardedInvocationComponent gic =
-                    getGuardedInvocationComponent(callSiteDescriptor,
-                            linkerServices, operations, name);
-            if(gic != null) {
-                return gic.getGuardedInvocation();
+    static final class ComponentLinkRequest {
+        final LinkRequest linkRequest;
+        final LinkerServices linkerServices;
+        final List<Operation> operations;
+        final Object name;
+
+        ComponentLinkRequest(final LinkRequest linkRequest,
+                final LinkerServices linkerServices) {
+            this.linkRequest = linkRequest;
+            this.linkerServices = linkerServices;
+            final Operation operation = linkRequest.getCallSiteDescriptor().getOperation();
+            this.operations = Arrays.asList(
+                    CompositeOperation.getOperations(
+                            NamedOperation.getBaseOperation(operation)));
+            this.name = NamedOperation.getName(operation);
+        }
+
+        private ComponentLinkRequest(final LinkRequest linkRequest,
+                final LinkerServices linkerServices,
+                final List<Operation> operations, final Object name) {
+            this.linkRequest = linkRequest;
+            this.linkerServices = linkerServices;
+            this.operations = operations;
+            this.name = name;
+        }
+
+        CallSiteDescriptor getDescriptor() {
+            return linkRequest.getCallSiteDescriptor();
+        }
+
+        ComponentLinkRequest popOperations() {
+            return new ComponentLinkRequest(linkRequest, linkerServices,
+                    operations.subList(1, operations.size()), name);
+        }
+    }
+
+    protected GuardedInvocationComponent getGuardedInvocationComponent(final ComponentLinkRequest req)
+    throws Exception {
+        final Operation op = req.operations.get(0);
+        if (op instanceof StandardOperation) {
+            switch((StandardOperation)op) {
+            case GET_PROPERTY: return getPropertyGetter(req.popOperations());
+            case SET_PROPERTY: return getPropertySetter(req.popOperations());
+            case GET_METHOD: return getMethodGetter(req.popOperations());
+            default:
             }
-            operations = pop(operations);
         }
         return null;
     }
 
-    protected GuardedInvocationComponent getGuardedInvocationComponent(
-            final CallSiteDescriptor callSiteDescriptor,
-            final LinkerServices linkerServices,
-            final List<Operation> operations, final Object name)
-    throws Exception {
-        if(operations.isEmpty()) {
+    GuardedInvocationComponent getNextComponent(final ComponentLinkRequest req) throws Exception {
+        if (req.operations.isEmpty()) {
             return null;
         }
-        final Operation op = operations.get(0);
-        // Either GET_PROPERTY:name(this) or GET_PROPERTY(this, name)
-        if(op == StandardOperation.GET_PROPERTY) {
-            return getPropertyGetter(callSiteDescriptor, linkerServices, pop(operations), name);
+        final GuardedInvocationComponent gic = getGuardedInvocationComponent(req);
+        if (gic != null) {
+            return gic;
         }
-        // Either SET_PROPERTY:name(this, value) or SET_PROPERTY(this, name, value)
-        if(op == StandardOperation.SET_PROPERTY) {
-            return getPropertySetter(callSiteDescriptor, linkerServices, pop(operations), name);
-        }
-        // Either GET_METHOD:name(this), or GET_METHOD(this, name)
-        if(op == StandardOperation.GET_METHOD) {
-            return getMethodGetter(callSiteDescriptor, linkerServices, pop(operations), name);
-        }
-        return null;
+        return getNextComponent(req.popOperations());
     }
 
     static final <T> List<T> pop(final List<T> l) {
@@ -483,16 +508,15 @@
     private static final MethodHandle CONSTANT_NULL_DROP_METHOD_HANDLE = MethodHandles.dropArguments(
             MethodHandles.constant(Object.class, null), 0, MethodHandle.class);
 
-    private GuardedInvocationComponent getPropertySetter(final CallSiteDescriptor callSiteDescriptor,
-            final LinkerServices linkerServices, final List<Operation> operations, final Object name) throws Exception {
-        if (name == null) {
-            return getUnnamedPropertySetter(callSiteDescriptor, linkerServices, operations);
+    private GuardedInvocationComponent getPropertySetter(final ComponentLinkRequest req) throws Exception {
+        if (req.name == null) {
+            return getUnnamedPropertySetter(req);
         }
-        return getNamedPropertySetter(callSiteDescriptor, linkerServices, operations, name);
+        return getNamedPropertySetter(req);
     }
 
-    private GuardedInvocationComponent getUnnamedPropertySetter(final CallSiteDescriptor callSiteDescriptor,
-            final LinkerServices linkerServices, final List<Operation> operations) throws Exception {
+    private GuardedInvocationComponent getUnnamedPropertySetter(final ComponentLinkRequest req) throws Exception {
+        final CallSiteDescriptor callSiteDescriptor = req.getDescriptor();
         // Must have three arguments: target object, property name, and property value.
         assertParameterCount(callSiteDescriptor, 3);
 
@@ -501,6 +525,7 @@
         // invoked, we'll conservatively presume Object return type. The one exception is void return.
         final MethodType origType = callSiteDescriptor.getMethodType();
         final MethodType type = origType.returnType() == void.class ? origType : origType.changeReturnType(Object.class);
+        final LinkerServices linkerServices = req.linkerServices;
 
         // What's below is basically:
         //   foldArguments(guardWithTest(isNotNull, invoke, null|nextComponent.invocation),
@@ -527,11 +552,10 @@
         // Handle to invoke the setter, dropping unnecessary fold arguments R(MethodHandle, O, N, V)
         final MethodHandle invokeHandleFolded = MethodHandles.dropArguments(invokeHandle, 2, type.parameterType(
                 1));
-        final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor,
-                linkerServices, operations, null);
+        final GuardedInvocationComponent nextComponent = getNextComponent(req);
 
         final MethodHandle fallbackFolded;
-        if(nextComponent == null) {
+        if (nextComponent == null) {
             // Object(MethodHandle)->Object(MethodHandle, O, N, V); returns constant null
             fallbackFolded = MethodHandles.dropArguments(CONSTANT_NULL_DROP_METHOD_HANDLE, 1,
                     type.parameterList()).asType(type.insertParameterTypes(0, MethodHandle.class));
@@ -551,19 +575,19 @@
         return nextComponent.compose(compositeSetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS);
     }
 
-    private GuardedInvocationComponent getNamedPropertySetter(final CallSiteDescriptor callSiteDescriptor,
-            final LinkerServices linkerServices, final List<Operation> operations, final Object name) throws Exception {
+    private GuardedInvocationComponent getNamedPropertySetter(final ComponentLinkRequest req) throws Exception {
+        final CallSiteDescriptor callSiteDescriptor = req.getDescriptor();
         // Must have two arguments: target object and property value
         assertParameterCount(callSiteDescriptor, 2);
-        final GuardedInvocation gi = createGuardedDynamicMethodInvocation(callSiteDescriptor, linkerServices,
-                name.toString(), propertySetters);
+        final GuardedInvocation gi = createGuardedDynamicMethodInvocation(callSiteDescriptor, req.linkerServices,
+                req.name.toString(), propertySetters);
         // If we have a property setter with this name, this composite operation will always stop here
         if(gi != null) {
             return new GuardedInvocationComponent(gi, clazz, ValidationType.EXACT_CLASS);
         }
         // If we don't have a property setter with this name, always fall back to the next operation in the
         // composite (if any)
-        return getGuardedInvocationComponent(callSiteDescriptor, linkerServices, operations, name);
+        return getNextComponent(req);
     }
 
     private static final Lookup privateLookup = new Lookup(MethodHandles.lookup());
@@ -576,20 +600,18 @@
             "getTarget", MethodType.methodType(MethodHandle.class, CallSiteDescriptor.class, LinkerServices.class));
     private static final MethodHandle GETTER_INVOKER = MethodHandles.invoker(MethodType.methodType(Object.class, Object.class));
 
-    private GuardedInvocationComponent getPropertyGetter(final CallSiteDescriptor callSiteDescriptor,
-            final LinkerServices linkerServices, final List<Operation> ops, final Object name) throws Exception {
-        if (name == null) {
-            return getUnnamedPropertyGetter(callSiteDescriptor, linkerServices, ops);
+    private GuardedInvocationComponent getPropertyGetter(final ComponentLinkRequest req) throws Exception {
+        if (req.name == null) {
+            return getUnnamedPropertyGetter(req);
         }
-
-        return getNamedPropertyGetter(callSiteDescriptor, linkerServices, ops, name);
+        return getNamedPropertyGetter(req);
     }
 
-    private GuardedInvocationComponent getUnnamedPropertyGetter(final CallSiteDescriptor callSiteDescriptor,
-            final LinkerServices linkerServices, final List<Operation> ops) throws Exception {
+    private GuardedInvocationComponent getUnnamedPropertyGetter(final ComponentLinkRequest req) throws Exception {
         // Since we can't know what kind of a getter we'll get back on different invocations, we'll just
         // conservatively presume Object. Note we can't just coerce to a narrower call site type as the linking
         // runtime might not allow coercing at that call site.
+        final CallSiteDescriptor callSiteDescriptor = req.getDescriptor();
         final MethodType type = callSiteDescriptor.getMethodType().changeReturnType(Object.class);
         // Must have exactly two arguments: receiver and name
         assertParameterCount(callSiteDescriptor, 2);
@@ -600,6 +622,7 @@
         // AnnotatedDynamicMethod; if it is non-null, invoke its "handle" field, otherwise either return null,
         // or delegate to next component's invocation.
 
+        final LinkerServices linkerServices = req.linkerServices;
         final MethodHandle typedGetter = linkerServices.asType(getPropertyGetterHandle, type.changeReturnType(
                 AnnotatedDynamicMethod.class));
         final MethodHandle callSiteBoundMethodGetter = MethodHandles.insertArguments(
@@ -613,8 +636,7 @@
         // Object(AnnotatedDynamicMethod, T0)->Object(AnnotatedDynamicMethod, T0, T1)
         final MethodHandle invokeHandleFolded = MethodHandles.dropArguments(invokeHandleTyped, 2,
                 type.parameterType(1));
-        final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor,
-                linkerServices, ops, null);
+        final GuardedInvocationComponent nextComponent = getNextComponent(req);
 
         final MethodHandle fallbackFolded;
         if(nextComponent == null) {
@@ -639,17 +661,17 @@
         return nextComponent.compose(compositeGetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS);
     }
 
-    private GuardedInvocationComponent getNamedPropertyGetter(final CallSiteDescriptor callSiteDescriptor,
-            final LinkerServices linkerServices, final List<Operation> ops, final Object name) throws Exception {
+    private GuardedInvocationComponent getNamedPropertyGetter(final ComponentLinkRequest req) throws Exception {
+        final CallSiteDescriptor callSiteDescriptor = req.getDescriptor();
         // Must have exactly one argument: receiver
         assertParameterCount(callSiteDescriptor, 1);
         // Fixed name
-        final AnnotatedDynamicMethod annGetter = propertyGetters.get(name.toString());
+        final AnnotatedDynamicMethod annGetter = propertyGetters.get(req.name.toString());
         if(annGetter == null) {
             // We have no such property, always delegate to the next component operation
-            return getGuardedInvocationComponent(callSiteDescriptor, linkerServices, ops, name);
+            return getNextComponent(req);
         }
-        final MethodHandle getter = annGetter.getInvocation(callSiteDescriptor, linkerServices);
+        final MethodHandle getter = annGetter.getInvocation(req);
         // NOTE: since property getters (not field getters!) are no-arg, we don't have to worry about them being
         // overloaded in a subclass. Therefore, we can discover the most abstract superclass that has the
         // method, and use that as the guard with Guards.isInstance() for a more stably linked call site. If
@@ -686,28 +708,27 @@
             MethodType.methodType(boolean.class, Object.class));
     private static final MethodHandle OBJECT_IDENTITY = MethodHandles.identity(Object.class);
 
-    private GuardedInvocationComponent getMethodGetter(final CallSiteDescriptor callSiteDescriptor,
-            final LinkerServices linkerServices, final List<Operation> ops, final Object name) throws Exception {
+    private GuardedInvocationComponent getMethodGetter(final ComponentLinkRequest req) throws Exception {
+        if (req.name == null) {
+            return getUnnamedMethodGetter(req);
+        }
+        return getNamedMethodGetter(req);
+    }
+
+    private static MethodType getMethodGetterType(final ComponentLinkRequest req) {
         // The created method handle will always return a DynamicMethod (or null), but since we don't want that type to
         // be visible outside of this linker, declare it to return Object.
-        final MethodType type = callSiteDescriptor.getMethodType().changeReturnType(Object.class);
-        if (name == null) {
-            return getUnnamedMethodGetter(callSiteDescriptor, linkerServices, ops, type);
-        }
-
-        return getNamedMethodGetter(callSiteDescriptor, linkerServices, ops, name, type);
+        return req.getDescriptor().getMethodType().changeReturnType(Object.class);
     }
 
-    private GuardedInvocationComponent getUnnamedMethodGetter(final CallSiteDescriptor callSiteDescriptor,
-            final LinkerServices linkerServices, final List<Operation> ops, final MethodType type) throws Exception {
+    private GuardedInvocationComponent getUnnamedMethodGetter(final ComponentLinkRequest req) throws Exception {
         // Must have exactly two arguments: receiver and name
-        assertParameterCount(callSiteDescriptor, 2);
-        final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor,
-                linkerServices, ops, null);
-        if(nextComponent == null || !InternalTypeUtilities.areAssignable(DynamicMethod.class,
-                nextComponent.getGuardedInvocation().getInvocation().type().returnType())) {
-            // No next component operation, or it can never produce a dynamic method; just return a component
-            // for this operation.
+        assertParameterCount(req.getDescriptor(), 2);
+        final GuardedInvocationComponent nextComponent = getNextComponent(req);
+        final LinkerServices linkerServices = req.linkerServices;
+        final MethodType type = getMethodGetterType(req);
+        if(nextComponent == null) {
+            // No next component operation; just return a component for this operation.
             return getClassGuardedInvocationComponent(linkerServices.asType(getDynamicMethod, type), type);
         }
 
@@ -728,25 +749,28 @@
         final MethodHandle nextCombinedInvocation = MethodHandles.dropArguments(nextComponentInvocation, 0,
                 Object.class);
         // Assemble it all into a fold(guard(isNotNull, identity, nextInvocation), get)
+        // Note that nextCombinedInvocation needs to have its return type changed to Object
         final MethodHandle compositeGetter = MethodHandles.foldArguments(MethodHandles.guardWithTest(
-                IS_DYNAMIC_METHOD, returnMethodHandle, nextCombinedInvocation), typedGetter);
+                IS_DYNAMIC_METHOD, returnMethodHandle,
+                nextCombinedInvocation.asType(nextCombinedInvocation.type().changeReturnType(Object.class))),
+                typedGetter);
 
         return nextComponent.compose(compositeGetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS);
     }
 
-    private GuardedInvocationComponent getNamedMethodGetter(final CallSiteDescriptor callSiteDescriptor,
-            final LinkerServices linkerServices, final List<Operation> ops, final Object name, final MethodType type)
+    private GuardedInvocationComponent getNamedMethodGetter(final ComponentLinkRequest req)
             throws Exception {
         // Must have exactly one argument: receiver
-        assertParameterCount(callSiteDescriptor, 1);
-        final DynamicMethod method = getDynamicMethod(name.toString());
+        assertParameterCount(req.getDescriptor(), 1);
+        final DynamicMethod method = getDynamicMethod(req.name.toString());
         if(method == null) {
             // We have no such method, always delegate to the next component
-            return getGuardedInvocationComponent(callSiteDescriptor, linkerServices, ops, name);
+            return getNextComponent(req);
         }
         // No delegation to the next component of the composite operation; if we have a method with that name,
         // we'll always return it at this point.
-        return getClassGuardedInvocationComponent(linkerServices.asType(MethodHandles.dropArguments(
+        final MethodType type = getMethodGetterType(req);
+        return getClassGuardedInvocationComponent(req.linkerServices.asType(MethodHandles.dropArguments(
                 MethodHandles.constant(Object.class, method), 0, type.parameterType(0)), type), type);
     }
 
@@ -876,8 +900,8 @@
             this.validationType = validationType;
         }
 
-        MethodHandle getInvocation(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices) {
-            return method.getInvocation(callSiteDescriptor, linkerServices);
+        MethodHandle getInvocation(final ComponentLinkRequest req) {
+            return method.getInvocation(req.getDescriptor(), req.linkerServices);
         }
 
         @SuppressWarnings("unused")
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeanLinker.java	Thu Jan 14 15:35:43 2016 +0530
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeanLinker.java	Thu Jan 14 13:22:58 2016 +0100
@@ -129,25 +129,21 @@
     }
 
     @Override
-    protected GuardedInvocationComponent getGuardedInvocationComponent(final CallSiteDescriptor callSiteDescriptor,
-            final LinkerServices linkerServices, final List<Operation> operations, final Object name) throws Exception {
-        final GuardedInvocationComponent superGic = super.getGuardedInvocationComponent(callSiteDescriptor,
-                linkerServices, operations, name);
+    protected GuardedInvocationComponent getGuardedInvocationComponent(final ComponentLinkRequest req) throws Exception {
+        final GuardedInvocationComponent superGic = super.getGuardedInvocationComponent(req);
         if(superGic != null) {
             return superGic;
         }
-        if(operations.isEmpty()) {
-            return null;
-        }
-        final Operation op = operations.get(0);
-        if(op == StandardOperation.GET_ELEMENT) {
-            return getElementGetter(callSiteDescriptor, linkerServices, pop(operations), name);
-        }
-        if(op == StandardOperation.SET_ELEMENT) {
-            return getElementSetter(callSiteDescriptor, linkerServices, pop(operations), name);
-        }
-        if(op == StandardOperation.GET_LENGTH) {
-            return getLengthGetter(callSiteDescriptor);
+        if (!req.operations.isEmpty()) {
+            final Operation op = req.operations.get(0);
+            if (op instanceof StandardOperation) {
+                switch ((StandardOperation)op) {
+                case GET_ELEMENT: return getElementGetter(req.popOperations());
+                case SET_ELEMENT: return getElementSetter(req.popOperations());
+                case GET_LENGTH:  return getLengthGetter(req.getDescriptor());
+                default:
+                }
+            }
         }
         return null;
     }
@@ -170,12 +166,12 @@
         ARRAY, LIST, MAP
     };
 
-    private GuardedInvocationComponent getElementGetter(final CallSiteDescriptor callSiteDescriptor,
-            final LinkerServices linkerServices, final List<Operation> operations, final Object name) throws Exception {
+    private GuardedInvocationComponent getElementGetter(final ComponentLinkRequest req) throws Exception {
+        final CallSiteDescriptor callSiteDescriptor = req.getDescriptor();
+        final LinkerServices linkerServices = req.linkerServices;
         final MethodType callSiteType = callSiteDescriptor.getMethodType();
         final Class<?> declaredType = callSiteType.parameterType(0);
-        final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor,
-                linkerServices, operations, name);
+        final GuardedInvocationComponent nextComponent = getNextComponent(req);
 
         // If declared type of receiver at the call site is already an array, a list or map, bind without guard. Thing
         // is, it'd be quite stupid of a call site creator to go though invokedynamic when it knows in advance they're
@@ -211,6 +207,7 @@
 
         // Convert the key to a number if we're working with a list or array
         final Object typedName;
+        final Object name = req.name;
         if(collectionType != CollectionType.MAP && name != null) {
             typedName = convertKeyToInteger(name, linkerServices);
             if(typedName == null) {
@@ -399,8 +396,9 @@
     private static final MethodHandle PUT_MAP_ELEMENT = Lookup.PUBLIC.findVirtual(Map.class, "put",
             MethodType.methodType(Object.class, Object.class, Object.class));
 
-    private GuardedInvocationComponent getElementSetter(final CallSiteDescriptor callSiteDescriptor,
-            final LinkerServices linkerServices, final List<Operation> operations, final Object name) throws Exception {
+    private GuardedInvocationComponent getElementSetter(final ComponentLinkRequest req) throws Exception {
+        final CallSiteDescriptor callSiteDescriptor = req.getDescriptor();
+        final LinkerServices linkerServices = req.linkerServices;
         final MethodType callSiteType = callSiteDescriptor.getMethodType();
         final Class<?> declaredType = callSiteType.parameterType(0);
 
@@ -441,14 +439,14 @@
         // In contrast to, say, getElementGetter, we only compute the nextComponent if the target object is not a map,
         // as maps will always succeed in setting the element and will never need to fall back to the next component
         // operation.
-        final GuardedInvocationComponent nextComponent = collectionType == CollectionType.MAP ? null : getGuardedInvocationComponent(
-                callSiteDescriptor, linkerServices, operations, name);
+        final GuardedInvocationComponent nextComponent = collectionType == CollectionType.MAP ? null : getNextComponent(req);
         if(gic == null) {
             return nextComponent;
         }
 
         // Convert the key to a number if we're working with a list or array
         final Object typedName;
+        final Object name = req.name;
         if(collectionType != CollectionType.MAP && name != null) {
             typedName = convertKeyToInteger(name, linkerServices);
             if(typedName == null) {
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/StaticClassLinker.java	Thu Jan 14 15:35:43 2016 +0530
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/StaticClassLinker.java	Thu Jan 14 13:22:58 2016 +0100
@@ -91,6 +91,7 @@
 import java.util.Set;
 import jdk.dynalink.CallSiteDescriptor;
 import jdk.dynalink.NamedOperation;
+import jdk.dynalink.Operation;
 import jdk.dynalink.StandardOperation;
 import jdk.dynalink.beans.GuardedInvocationComponent.ValidationType;
 import jdk.dynalink.linker.GuardedInvocation;
@@ -162,6 +163,27 @@
         }
 
         @Override
+        protected GuardedInvocationComponent getGuardedInvocationComponent(final ComponentLinkRequest req) throws Exception {
+            final GuardedInvocationComponent superGic = super.getGuardedInvocationComponent(req);
+            if (superGic != null) {
+                return superGic;
+            }
+            if (!req.operations.isEmpty()) {
+                final Operation op = req.operations.get(0);
+                if (op instanceof StandardOperation) {
+                    switch ((StandardOperation)op) {
+                    case GET_ELEMENT:
+                    case SET_ELEMENT:
+                        // StaticClass doesn't behave as a collection
+                        return getNextComponent(req.popOperations());
+                    default:
+                    }
+                }
+            }
+            return null;
+        }
+
+        @Override
         SingleDynamicMethod getConstructorMethod(final String signature) {
             return constructor != null? constructor.getMethodForExactParamTypes(signature) : null;
         }