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());