src/jdk/internal/dynalink/beans/BeanLinker.java

changeset 1239
e1146c9cc758
parent 963
e2497b11a021
child 1490
d85f981c8cf8
     1.1 --- a/src/jdk/internal/dynalink/beans/BeanLinker.java	Fri Jan 30 15:03:56 2015 +0100
     1.2 +++ b/src/jdk/internal/dynalink/beans/BeanLinker.java	Thu Feb 12 16:43:33 2015 +0100
     1.3 @@ -165,6 +165,10 @@
     1.4      private static MethodHandle LIST_GUARD = Guards.getInstanceOfGuard(List.class);
     1.5      private static MethodHandle MAP_GUARD = Guards.getInstanceOfGuard(Map.class);
     1.6  
     1.7 +    private enum CollectionType {
     1.8 +        ARRAY, LIST, MAP
     1.9 +    };
    1.10 +
    1.11      private GuardedInvocationComponent getElementGetter(final CallSiteDescriptor callSiteDescriptor,
    1.12              final LinkerServices linkerServices, final List<String> operations) throws Exception {
    1.13          final MethodType callSiteType = callSiteDescriptor.getMethodType();
    1.14 @@ -178,27 +182,27 @@
    1.15          // Note that for arrays and lists, using LinkerServices.asType() will ensure that any language specific linkers
    1.16          // in use will get a chance to perform any (if there's any) implicit conversion to integer for the indices.
    1.17          final GuardedInvocationComponent gic;
    1.18 -        final boolean isMap;
    1.19 +        final CollectionType collectionType;
    1.20          if(declaredType.isArray()) {
    1.21 -            gic = new GuardedInvocationComponent(MethodHandles.arrayElementGetter(declaredType));
    1.22 -            isMap = false;
    1.23 +            gic = createInternalFilteredGuardedInvocationComponent(MethodHandles.arrayElementGetter(declaredType), linkerServices);
    1.24 +            collectionType = CollectionType.ARRAY;
    1.25          } else if(List.class.isAssignableFrom(declaredType)) {
    1.26 -            gic = new GuardedInvocationComponent(GET_LIST_ELEMENT);
    1.27 -            isMap = false;
    1.28 +            gic = createInternalFilteredGuardedInvocationComponent(GET_LIST_ELEMENT, linkerServices);
    1.29 +            collectionType = CollectionType.LIST;
    1.30          } else if(Map.class.isAssignableFrom(declaredType)) {
    1.31 -            gic = new GuardedInvocationComponent(GET_MAP_ELEMENT);
    1.32 -            isMap = true;
    1.33 +            gic = createInternalFilteredGuardedInvocationComponent(GET_MAP_ELEMENT, linkerServices);
    1.34 +            collectionType = CollectionType.MAP;
    1.35          } else if(clazz.isArray()) {
    1.36 -            gic = getClassGuardedInvocationComponent(MethodHandles.arrayElementGetter(clazz), callSiteType);
    1.37 -            isMap = false;
    1.38 +            gic = getClassGuardedInvocationComponent(linkerServices.filterInternalObjects(MethodHandles.arrayElementGetter(clazz)), callSiteType);
    1.39 +            collectionType = CollectionType.ARRAY;
    1.40          } else if(List.class.isAssignableFrom(clazz)) {
    1.41 -            gic = new GuardedInvocationComponent(GET_LIST_ELEMENT, Guards.asType(LIST_GUARD, callSiteType), List.class,
    1.42 -                    ValidationType.INSTANCE_OF);
    1.43 -            isMap = false;
    1.44 +            gic = createInternalFilteredGuardedInvocationComponent(GET_LIST_ELEMENT, Guards.asType(LIST_GUARD, callSiteType), List.class, ValidationType.INSTANCE_OF,
    1.45 +                    linkerServices);
    1.46 +            collectionType = CollectionType.LIST;
    1.47          } else if(Map.class.isAssignableFrom(clazz)) {
    1.48 -            gic = new GuardedInvocationComponent(GET_MAP_ELEMENT, Guards.asType(MAP_GUARD, callSiteType), Map.class,
    1.49 -                    ValidationType.INSTANCE_OF);
    1.50 -            isMap = true;
    1.51 +            gic = createInternalFilteredGuardedInvocationComponent(GET_MAP_ELEMENT, Guards.asType(MAP_GUARD, callSiteType), Map.class, ValidationType.INSTANCE_OF,
    1.52 +                    linkerServices);
    1.53 +            collectionType = CollectionType.MAP;
    1.54          } else {
    1.55              // Can't retrieve elements for objects that are neither arrays, nor list, nor maps.
    1.56              return nextComponent;
    1.57 @@ -208,7 +212,7 @@
    1.58          final String fixedKey = getFixedKey(callSiteDescriptor);
    1.59          // Convert the key to a number if we're working with a list or array
    1.60          final Object typedFixedKey;
    1.61 -        if(!isMap && fixedKey != null) {
    1.62 +        if(collectionType != CollectionType.MAP && fixedKey != null) {
    1.63              typedFixedKey = convertKeyToInteger(fixedKey, linkerServices);
    1.64              if(typedFixedKey == null) {
    1.65                  // key is not numeric, it can never succeed
    1.66 @@ -227,15 +231,21 @@
    1.67          }
    1.68  
    1.69          final MethodHandle checkGuard;
    1.70 -        if(invocation == GET_LIST_ELEMENT) {
    1.71 +        switch(collectionType) {
    1.72 +        case LIST:
    1.73              checkGuard = convertArgToInt(RANGE_CHECK_LIST, linkerServices, callSiteDescriptor);
    1.74 -        } else if(invocation == GET_MAP_ELEMENT) {
    1.75 +            break;
    1.76 +        case MAP:
    1.77              // TODO: A more complex solution could be devised for maps, one where we do a get() first, and fold it
    1.78              // into a GWT that tests if it returned null, and if it did, do another GWT with containsKey()
    1.79              // that returns constant null (on true), or falls back to next component (on false)
    1.80 -            checkGuard = CONTAINS_MAP;
    1.81 -        } else {
    1.82 +            checkGuard = linkerServices.filterInternalObjects(CONTAINS_MAP);
    1.83 +            break;
    1.84 +        case ARRAY:
    1.85              checkGuard = convertArgToInt(RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor);
    1.86 +            break;
    1.87 +        default:
    1.88 +            throw new AssertionError();
    1.89          }
    1.90          final MethodPair matchedInvocations = matchReturnTypes(binder.bind(invocation),
    1.91                  nextComponent.getGuardedInvocation().getInvocation());
    1.92 @@ -243,6 +253,18 @@
    1.93                  gic.getValidatorClass(), gic.getValidationType());
    1.94      }
    1.95  
    1.96 +    private static GuardedInvocationComponent createInternalFilteredGuardedInvocationComponent(
    1.97 +            final MethodHandle invocation, final LinkerServices linkerServices) {
    1.98 +        return new GuardedInvocationComponent(linkerServices.filterInternalObjects(invocation));
    1.99 +    }
   1.100 +
   1.101 +    private static GuardedInvocationComponent createInternalFilteredGuardedInvocationComponent(
   1.102 +            final MethodHandle invocation, final MethodHandle guard, final Class<?> validatorClass,
   1.103 +            final ValidationType validationType, final LinkerServices linkerServices) {
   1.104 +        return new GuardedInvocationComponent(linkerServices.filterInternalObjects(invocation), guard,
   1.105 +                validatorClass, validationType);
   1.106 +    }
   1.107 +
   1.108      private static String getFixedKey(final CallSiteDescriptor callSiteDescriptor) {
   1.109          return callSiteDescriptor.getNameTokenCount() == 2 ? null : callSiteDescriptor.getNameToken(
   1.110                  CallSiteDescriptor.NAME_OPERAND);
   1.111 @@ -381,37 +403,38 @@
   1.112          // dealing with an array, or a list or map, but hey...
   1.113          // Note that for arrays and lists, using LinkerServices.asType() will ensure that any language specific linkers
   1.114          // in use will get a chance to perform any (if there's any) implicit conversion to integer for the indices.
   1.115 -        final boolean isMap;
   1.116 +        final CollectionType collectionType;
   1.117          if(declaredType.isArray()) {
   1.118 -            gic = new GuardedInvocationComponent(MethodHandles.arrayElementSetter(declaredType));
   1.119 -            isMap = false;
   1.120 +            gic = createInternalFilteredGuardedInvocationComponent(MethodHandles.arrayElementSetter(declaredType), linkerServices);
   1.121 +            collectionType = CollectionType.ARRAY;
   1.122          } else if(List.class.isAssignableFrom(declaredType)) {
   1.123 -            gic = new GuardedInvocationComponent(SET_LIST_ELEMENT);
   1.124 -            isMap = false;
   1.125 +            gic = createInternalFilteredGuardedInvocationComponent(SET_LIST_ELEMENT, linkerServices);
   1.126 +            collectionType = CollectionType.LIST;
   1.127          } else if(Map.class.isAssignableFrom(declaredType)) {
   1.128 -            gic = new GuardedInvocationComponent(PUT_MAP_ELEMENT);
   1.129 -            isMap = true;
   1.130 +            gic = createInternalFilteredGuardedInvocationComponent(PUT_MAP_ELEMENT, linkerServices);
   1.131 +            collectionType = CollectionType.MAP;
   1.132          } else if(clazz.isArray()) {
   1.133 -            gic = getClassGuardedInvocationComponent(MethodHandles.arrayElementSetter(clazz), callSiteType);
   1.134 -            isMap = false;
   1.135 +            gic = getClassGuardedInvocationComponent(linkerServices.filterInternalObjects(
   1.136 +                    MethodHandles.arrayElementSetter(clazz)), callSiteType);
   1.137 +            collectionType = CollectionType.ARRAY;
   1.138          } else if(List.class.isAssignableFrom(clazz)) {
   1.139 -            gic = new GuardedInvocationComponent(SET_LIST_ELEMENT, Guards.asType(LIST_GUARD, callSiteType), List.class,
   1.140 -                    ValidationType.INSTANCE_OF);
   1.141 -            isMap = false;
   1.142 +            gic = createInternalFilteredGuardedInvocationComponent(SET_LIST_ELEMENT, Guards.asType(LIST_GUARD, callSiteType), List.class, ValidationType.INSTANCE_OF,
   1.143 +                    linkerServices);
   1.144 +            collectionType = CollectionType.LIST;
   1.145          } else if(Map.class.isAssignableFrom(clazz)) {
   1.146 -            gic = new GuardedInvocationComponent(PUT_MAP_ELEMENT, Guards.asType(MAP_GUARD, callSiteType), Map.class,
   1.147 -                    ValidationType.INSTANCE_OF);
   1.148 -            isMap = true;
   1.149 +            gic = createInternalFilteredGuardedInvocationComponent(PUT_MAP_ELEMENT, Guards.asType(MAP_GUARD, callSiteType),
   1.150 +                    Map.class, ValidationType.INSTANCE_OF, linkerServices);
   1.151 +            collectionType = CollectionType.MAP;
   1.152          } else {
   1.153              // Can't set elements for objects that are neither arrays, nor list, nor maps.
   1.154              gic = null;
   1.155 -            isMap = false;
   1.156 +            collectionType = null;
   1.157          }
   1.158  
   1.159          // In contrast to, say, getElementGetter, we only compute the nextComponent if the target object is not a map,
   1.160          // as maps will always succeed in setting the element and will never need to fall back to the next component
   1.161          // operation.
   1.162 -        final GuardedInvocationComponent nextComponent = isMap ? null : getGuardedInvocationComponent(
   1.163 +        final GuardedInvocationComponent nextComponent = collectionType == CollectionType.MAP ? null : getGuardedInvocationComponent(
   1.164                  callSiteDescriptor, linkerServices, operations);
   1.165          if(gic == null) {
   1.166              return nextComponent;
   1.167 @@ -421,7 +444,7 @@
   1.168          final String fixedKey = getFixedKey(callSiteDescriptor);
   1.169          // Convert the key to a number if we're working with a list or array
   1.170          final Object typedFixedKey;
   1.171 -        if(!isMap && fixedKey != null) {
   1.172 +        if(collectionType != CollectionType.MAP && fixedKey != null) {
   1.173              typedFixedKey = convertKeyToInteger(fixedKey, linkerServices);
   1.174              if(typedFixedKey == null) {
   1.175                  // key is not numeric, it can never succeed
   1.176 @@ -439,7 +462,8 @@
   1.177              return gic.replaceInvocation(binder.bind(invocation));
   1.178          }
   1.179  
   1.180 -        final MethodHandle checkGuard = convertArgToInt(invocation == SET_LIST_ELEMENT ? RANGE_CHECK_LIST :
   1.181 +        assert collectionType == CollectionType.LIST || collectionType == CollectionType.ARRAY;
   1.182 +        final MethodHandle checkGuard = convertArgToInt(collectionType == CollectionType.LIST ? RANGE_CHECK_LIST :
   1.183              RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor);
   1.184          final MethodPair matchedInvocations = matchReturnTypes(binder.bind(invocation),
   1.185                  nextComponent.getGuardedInvocation().getInvocation());

mercurial