1.1 --- a/src/share/vm/prims/methodHandles.cpp Thu May 12 10:33:17 2011 -0700 1.2 +++ b/src/share/vm/prims/methodHandles.cpp Thu May 12 14:04:48 2011 -0700 1.3 @@ -1099,6 +1099,14 @@ 1.4 return Klass::cast(SystemDictionary::Object_klass())->java_mirror(); 1.5 } 1.6 1.7 +bool MethodHandles::is_float_fixed_reinterpretation_cast(BasicType src, BasicType dst) { 1.8 + if (src == T_FLOAT) return dst == T_INT; 1.9 + if (src == T_INT) return dst == T_FLOAT; 1.10 + if (src == T_DOUBLE) return dst == T_LONG; 1.11 + if (src == T_LONG) return dst == T_DOUBLE; 1.12 + return false; 1.13 +} 1.14 + 1.15 bool MethodHandles::same_basic_type_for_arguments(BasicType src, 1.16 BasicType dst, 1.17 bool raw, 1.18 @@ -1125,10 +1133,8 @@ 1.19 return true; // remaining case: byte fits in short 1.20 } 1.21 // allow float/fixed reinterpretation casts 1.22 - if (src == T_FLOAT) return dst == T_INT; 1.23 - if (src == T_INT) return dst == T_FLOAT; 1.24 - if (src == T_DOUBLE) return dst == T_LONG; 1.25 - if (src == T_LONG) return dst == T_DOUBLE; 1.26 + if (is_float_fixed_reinterpretation_cast(src, dst)) 1.27 + return true; 1.28 return false; 1.29 } 1.30 1.31 @@ -1399,7 +1405,7 @@ 1.32 int argnum, 1.33 bool raw) { 1.34 const char* err = NULL; 1.35 - bool for_return = (argnum < 0); 1.36 + const bool for_return = (argnum < 0); 1.37 1.38 // just in case: 1.39 if (src_type == T_ARRAY) src_type = T_OBJECT; 1.40 @@ -1408,17 +1414,17 @@ 1.41 // Produce some nice messages if VerifyMethodHandles is turned on: 1.42 if (!same_basic_type_for_arguments(src_type, dst_type, raw, for_return)) { 1.43 if (src_type == T_OBJECT) { 1.44 - if (raw && dst_type == T_INT && is_always_null_type(src_klass)) 1.45 - return NULL; // OK to convert a null pointer to a garbage int 1.46 - err = ((argnum >= 0) 1.47 + if (raw && is_java_primitive(dst_type)) 1.48 + return NULL; // ref-to-prim discards ref and returns zero 1.49 + err = (!for_return 1.50 ? "type mismatch: passing a %s for method argument #%d, which expects primitive %s" 1.51 : "type mismatch: returning a %s, but caller expects primitive %s"); 1.52 } else if (dst_type == T_OBJECT) { 1.53 - err = ((argnum >= 0) 1.54 + err = (!for_return 1.55 ? "type mismatch: passing a primitive %s for method argument #%d, which expects %s" 1.56 : "type mismatch: returning a primitive %s, but caller expects %s"); 1.57 } else { 1.58 - err = ((argnum >= 0) 1.59 + err = (!for_return 1.60 ? "type mismatch: passing a %s for method argument #%d, which expects %s" 1.61 : "type mismatch: returning a %s, but caller expects %s"); 1.62 } 1.63 @@ -1427,11 +1433,11 @@ 1.64 if (!class_cast_needed(dst_klass, src_klass)) { 1.65 if (raw) 1.66 return NULL; // reverse cast is OK; the MH target is trusted to enforce it 1.67 - err = ((argnum >= 0) 1.68 + err = (!for_return 1.69 ? "cast required: passing a %s for method argument #%d, which expects %s" 1.70 : "cast required: returning a %s, but caller expects %s"); 1.71 } else { 1.72 - err = ((argnum >= 0) 1.73 + err = (!for_return 1.74 ? "reference mismatch: passing a %s for method argument #%d, which expects %s" 1.75 : "reference mismatch: returning a %s, but caller expects %s"); 1.76 } 1.77 @@ -1452,7 +1458,7 @@ 1.78 1.79 size_t msglen = strlen(err) + strlen(src_name) + strlen(dst_name) + (argnum < 10 ? 1 : 11); 1.80 char* msg = NEW_RESOURCE_ARRAY(char, msglen + 1); 1.81 - if (argnum >= 0) { 1.82 + if (!for_return) { 1.83 assert(strstr(err, "%d") != NULL, ""); 1.84 jio_snprintf(msg, msglen, err, src_name, argnum, dst_name); 1.85 } else { 1.86 @@ -2180,9 +2186,10 @@ 1.87 } 1.88 1.89 void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnum, TRAPS) { 1.90 - int argslot = java_lang_invoke_AdapterMethodHandle::vmargslot(mh()); 1.91 - jint conversion = java_lang_invoke_AdapterMethodHandle::conversion(mh()); 1.92 - jint conv_op = adapter_conversion_op(conversion); 1.93 + Handle argument = java_lang_invoke_AdapterMethodHandle::argument(mh()); 1.94 + int argslot = java_lang_invoke_AdapterMethodHandle::vmargslot(mh()); 1.95 + jint conversion = java_lang_invoke_AdapterMethodHandle::conversion(mh()); 1.96 + jint conv_op = adapter_conversion_op(conversion); 1.97 1.98 // adjust the adapter code to the internal EntryKind enumeration: 1.99 EntryKind ek_orig = adapter_entry_kind(conv_op); 1.100 @@ -2241,7 +2248,7 @@ 1.101 } else if (src == T_DOUBLE && dest == T_FLOAT) { 1.102 ek_opt = _adapter_opt_d2f; 1.103 } else { 1.104 - assert(false, ""); 1.105 + goto throw_not_impl; // runs user code, hence could block 1.106 } 1.107 break; 1.108 case 1 *4+ 2: 1.109 @@ -2250,11 +2257,11 @@ 1.110 } else if (src == T_FLOAT && dest == T_DOUBLE) { 1.111 ek_opt = _adapter_opt_f2d; 1.112 } else { 1.113 - assert(false, ""); 1.114 + goto throw_not_impl; // runs user code, hence could block 1.115 } 1.116 break; 1.117 default: 1.118 - assert(false, ""); 1.119 + goto throw_not_impl; // runs user code, hence could block 1.120 break; 1.121 } 1.122 } 1.123 @@ -2271,7 +2278,7 @@ 1.124 ek_opt = _adapter_opt_unboxl; 1.125 break; 1.126 default: 1.127 - assert(false, ""); 1.128 + goto throw_not_impl; 1.129 break; 1.130 } 1.131 } 1.132 @@ -2284,6 +2291,9 @@ 1.133 vminfo = argslot; 1.134 ek_opt = _adapter_opt_collect_ref; 1.135 ensure_vmlayout_field(target, CHECK); 1.136 + // for MethodHandleWalk: 1.137 + if (java_lang_invoke_AdapterMethodHandle::is_instance(argument())) 1.138 + ensure_vmlayout_field(argument, CHECK); 1.139 if (!OptimizeMethodHandles) break; 1.140 switch (type2size[src]) { 1.141 case 1: 1.142 @@ -2311,7 +2321,7 @@ 1.143 ek_opt = _adapter_opt_collect_2_ref; 1.144 break; 1.145 default: 1.146 - assert(false, ""); 1.147 + goto throw_not_impl; 1.148 break; 1.149 } 1.150 } 1.151 @@ -2335,7 +2345,7 @@ 1.152 rotate > 0 ? _adapter_opt_rot_2_up : _adapter_opt_rot_2_down); 1.153 break; 1.154 default: 1.155 - assert(false, ""); 1.156 + goto throw_not_impl; 1.157 break; 1.158 } 1.159 } 1.160 @@ -2402,12 +2412,11 @@ 1.161 case _adapter_collect_args: 1.162 { 1.163 assert(UseRicochetFrames, "else don't come here"); 1.164 - int elem_slots = argument_slot_count( 1.165 - java_lang_invoke_MethodHandle::type( 1.166 - java_lang_invoke_AdapterMethodHandle::argument(mh()) ) ); 1.167 + int elem_slots = argument_slot_count(java_lang_invoke_MethodHandle::type(argument())); 1.168 // vminfo will be the location to insert the return value 1.169 vminfo = argslot; 1.170 ensure_vmlayout_field(target, CHECK); 1.171 + ensure_vmlayout_field(argument, CHECK); 1.172 1.173 // general case: 1.174 switch (dest) { 1.175 @@ -2472,12 +2481,11 @@ 1.176 case _adapter_fold_args: 1.177 { 1.178 assert(UseRicochetFrames, "else don't come here"); 1.179 - int elem_slots = argument_slot_count( 1.180 - java_lang_invoke_MethodHandle::type( 1.181 - java_lang_invoke_AdapterMethodHandle::argument(mh()) ) ); 1.182 + int elem_slots = argument_slot_count(java_lang_invoke_MethodHandle::type(argument())); 1.183 // vminfo will be the location to insert the return value 1.184 vminfo = argslot + elem_slots; 1.185 ensure_vmlayout_field(target, CHECK); 1.186 + ensure_vmlayout_field(argument, CHECK); 1.187 1.188 switch (dest) { 1.189 default : if (!is_subword_type(dest)) goto throw_not_impl; 1.190 @@ -2527,15 +2535,31 @@ 1.191 break; 1.192 } 1.193 1.194 - if (err != NULL && (vminfo & CONV_VMINFO_MASK) != vminfo) { 1.195 + if (err == NULL && (vminfo & CONV_VMINFO_MASK) != vminfo) { 1.196 // should not happen, since vminfo is used to encode arg/slot indexes < 255 1.197 err = "vminfo overflow"; 1.198 } 1.199 1.200 - if (err != NULL && !have_entry(ek_opt)) { 1.201 + if (err == NULL && !have_entry(ek_opt)) { 1.202 err = "adapter stub for this kind of method handle is missing"; 1.203 } 1.204 1.205 + if (err == NULL && ek_opt == ek_orig) { 1.206 + switch (ek_opt) { 1.207 + case _adapter_prim_to_prim: 1.208 + case _adapter_ref_to_prim: 1.209 + case _adapter_prim_to_ref: 1.210 + case _adapter_swap_args: 1.211 + case _adapter_rot_args: 1.212 + case _adapter_collect_args: 1.213 + case _adapter_fold_args: 1.214 + case _adapter_spread_args: 1.215 + // should be handled completely by optimized cases; see above 1.216 + err = "init_AdapterMethodHandle should not issue this"; 1.217 + break; 1.218 + } 1.219 + } 1.220 + 1.221 if (err != NULL) { 1.222 throw_InternalError_for_bad_conversion(conversion, err, THREAD); 1.223 return;