1 /* 2 * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "precompiled.hpp" 26 #include "jni.h" 27 #include "jvm.h" 28 #include "classfile/javaClasses.inline.hpp" 29 #include "code/location.hpp" 30 #include "prims/vectorSupport.hpp" 31 #include "runtime/fieldDescriptor.inline.hpp" 32 #include "runtime/handles.inline.hpp" 33 #include "runtime/interfaceSupport.inline.hpp" 34 #include "runtime/jniHandles.inline.hpp" 35 #include "runtime/stackValue.hpp" 36 37 #ifdef COMPILER2 38 #include "opto/matcher.hpp" // Matcher::max_vector_size(BasicType) 39 #endif // COMPILER2 40 41 bool VectorSupport::is_vector(Klass* klass) { 42 return klass->is_subclass_of(SystemDictionary::vector_VectorPayload_klass()); 43 } 44 45 bool VectorSupport::is_vector_mask(Klass* klass) { 46 return klass->is_subclass_of(SystemDictionary::vector_VectorMask_klass()); 47 } 48 49 bool VectorSupport::is_vector_shuffle(Klass* klass) { 50 return klass->is_subclass_of(SystemDictionary::vector_VectorShuffle_klass()); 51 } 52 53 BasicType VectorSupport::klass2bt(InstanceKlass* ik) { 54 assert(ik->is_subclass_of(SystemDictionary::vector_VectorPayload_klass()), "%s not a VectorPayload", ik->name()->as_C_string()); 55 fieldDescriptor fd; // find_field initializes fd if found 56 // static final Class<?> ETYPE; 57 Klass* holder = ik->find_field(vmSymbols::ETYPE_name(), vmSymbols::class_signature(), &fd); 58 59 assert(holder != NULL, "sanity"); 60 assert(fd.is_static(), ""); 61 assert(fd.offset() > 0, ""); 62 63 if (is_vector_shuffle(ik)) { 64 return T_BYTE; 65 } else { // vector and mask 66 oop value = ik->java_mirror()->obj_field(fd.offset()); 67 BasicType elem_bt = java_lang_Class::as_BasicType(value); 68 return elem_bt; 69 } 70 } 71 72 jint VectorSupport::klass2length(InstanceKlass* ik) { 73 fieldDescriptor fd; // find_field initializes fd if found 74 // static final int VLENGTH; 75 Klass* holder = ik->find_field(vmSymbols::VLENGTH_name(), vmSymbols::int_signature(), &fd); 76 77 assert(holder != NULL, "sanity"); 78 assert(fd.is_static(), ""); 79 assert(fd.offset() > 0, ""); 80 81 jint vlen = ik->java_mirror()->int_field(fd.offset()); 82 assert(vlen > 0, ""); 83 return vlen; 84 } 85 86 void VectorSupport::init_vector_array(typeArrayOop arr, BasicType elem_bt, int num_elem, address value_addr) { 87 int elem_size = type2aelembytes(elem_bt); 88 for (int i = 0; i < num_elem; i++) { 89 switch (elem_bt) { 90 case T_BYTE: { 91 jbyte elem_value = *(jbyte*) (value_addr + i * elem_size); 92 arr->byte_at_put(i, elem_value); 93 break; 94 } 95 case T_SHORT: { 96 jshort elem_value = *(jshort*) (value_addr + i * elem_size); 97 arr->short_at_put(i, elem_value); 98 break; 99 } 100 case T_INT: { 101 jint elem_value = *(jint*) (value_addr + i * elem_size); 102 arr->int_at_put(i, elem_value); 103 break; 104 } 105 case T_LONG: { 106 jlong elem_value = *(jlong*) (value_addr + i * elem_size); 107 arr->long_at_put(i, elem_value); 108 break; 109 } 110 case T_FLOAT: { 111 jfloat elem_value = *(jfloat*) (value_addr + i * elem_size); 112 arr->float_at_put(i, elem_value); 113 break; 114 } 115 case T_DOUBLE: { 116 jdouble elem_value = *(jdouble*) (value_addr + i * elem_size); 117 arr->double_at_put(i, elem_value); 118 break; 119 } 120 default: 121 fatal("unsupported: %s", type2name(elem_bt)); 122 } 123 } 124 } 125 126 void VectorSupport::init_mask_array(typeArrayOop arr, BasicType elem_bt, int num_elem, address value_addr) { 127 int elem_size = type2aelembytes(elem_bt); 128 129 for (int i = 0; i < num_elem; i++) { 130 switch (elem_bt) { 131 case T_BYTE: { 132 jbyte elem_value = *(jbyte*) (value_addr + i * elem_size); 133 arr->bool_at_put(i, elem_value != 0); 134 break; 135 } 136 case T_SHORT: { 137 jshort elem_value = *(jshort*) (value_addr + i * elem_size); 138 arr->bool_at_put(i, elem_value != 0); 139 break; 140 } 141 case T_INT: // fall-through 142 case T_FLOAT: { 143 jint elem_value = *(jint*) (value_addr + i * elem_size); 144 arr->bool_at_put(i, elem_value != 0); 145 break; 146 } 147 case T_LONG: // fall-through 148 case T_DOUBLE: { 149 jlong elem_value = *(jlong*) (value_addr + i * elem_size); 150 arr->bool_at_put(i, elem_value != 0); 151 break; 152 } 153 default: 154 fatal("unsupported: %s", type2name(elem_bt)); 155 } 156 } 157 } 158 159 oop VectorSupport::allocate_vector_payload_helper(InstanceKlass* ik, BasicType elem_bt, int num_elem, address value_addr, TRAPS) { 160 161 bool is_mask = is_vector_mask(ik); 162 163 // On-heap vector values are represented as primitive arrays. 164 TypeArrayKlass* tak = TypeArrayKlass::cast(Universe::typeArrayKlassObj(is_mask ? T_BOOLEAN : elem_bt)); 165 166 typeArrayOop arr = tak->allocate(num_elem, CHECK_NULL); // safepoint 167 168 if (is_mask) { 169 init_mask_array(arr, elem_bt, num_elem, value_addr); 170 } else { 171 init_vector_array(arr, elem_bt, num_elem, value_addr); 172 } 173 return arr; 174 } 175 176 oop VectorSupport::allocate_vector(InstanceKlass* ik, frame* fr, RegisterMap* reg_map, ObjectValue* ov, TRAPS) { 177 assert(is_vector(ik), "%s not a vector", ik->name()->as_C_string()); 178 assert(ov->field_size() == 1, "%s not a vector", ik->name()->as_C_string()); 179 180 // Vector value in an aligned adjacent tuple (1, 2, 4, 8, or 16 slots). 181 LocationValue* loc_value = ov->field_at(0)->as_LocationValue(); 182 183 BasicType elem_bt = klass2bt(ik); 184 int num_elem = klass2length(ik); 185 186 Handle vbox = ik->allocate_instance_handle(CHECK_NULL); 187 188 Location loc = loc_value->location(); 189 190 oop payload = NULL; 191 if (loc.type() == Location::vector) { 192 address value_addr = loc.is_register() 193 // Value was in a callee-save register 194 ? reg_map->location(VMRegImpl::as_VMReg(loc.register_number())) 195 // Else value was directly saved on the stack. The frame's original stack pointer, 196 // before any extension by its callee (due to Compiler1 linkage on SPARC), must be used. 197 : ((address)fr->unextended_sp()) + loc.stack_offset(); 198 payload = allocate_vector_payload_helper(ik, elem_bt, num_elem, value_addr, CHECK_NULL); // safepoint 199 } else { 200 // assert(false, "interesting"); 201 StackValue* value = StackValue::create_stack_value(fr, reg_map, loc_value); 202 payload = value->get_obj()(); 203 } 204 vector_VectorPayload::set_payload(vbox(), payload); 205 return vbox(); 206 } 207 208 #ifdef COMPILER2 209 int VectorSupport::vop2ideal(jint id, BasicType bt) { 210 VectorOperation vop = (VectorOperation)id; 211 switch (vop) { 212 case VECTOR_OP_ADD: { 213 switch (bt) { 214 case T_BYTE: // fall-through 215 case T_SHORT: // fall-through 216 case T_INT: return Op_AddI; 217 case T_LONG: return Op_AddL; 218 case T_FLOAT: return Op_AddF; 219 case T_DOUBLE: return Op_AddD; 220 default: fatal("ADD: %s", type2name(bt)); 221 } 222 break; 223 } 224 case VECTOR_OP_SUB: { 225 switch (bt) { 226 case T_BYTE: // fall-through 227 case T_SHORT: // fall-through 228 case T_INT: return Op_SubI; 229 case T_LONG: return Op_SubL; 230 case T_FLOAT: return Op_SubF; 231 case T_DOUBLE: return Op_SubD; 232 default: fatal("SUB: %s", type2name(bt)); 233 } 234 break; 235 } 236 case VECTOR_OP_MUL: { 237 switch (bt) { 238 case T_BYTE: // fall-through 239 case T_SHORT: // fall-through 240 case T_INT: return Op_MulI; 241 case T_LONG: return Op_MulL; 242 case T_FLOAT: return Op_MulF; 243 case T_DOUBLE: return Op_MulD; 244 default: fatal("MUL: %s", type2name(bt)); 245 } 246 break; 247 } 248 case VECTOR_OP_DIV: { 249 switch (bt) { 250 case T_BYTE: // fall-through 251 case T_SHORT: // fall-through 252 case T_INT: return Op_DivI; 253 case T_LONG: return Op_DivL; 254 case T_FLOAT: return Op_DivF; 255 case T_DOUBLE: return Op_DivD; 256 default: fatal("DIV: %s", type2name(bt)); 257 } 258 break; 259 } 260 case VECTOR_OP_MIN: { 261 switch (bt) { 262 case T_BYTE: 263 case T_SHORT: 264 case T_INT: return Op_MinI; 265 case T_LONG: return Op_MinL; 266 case T_FLOAT: return Op_MinF; 267 case T_DOUBLE: return Op_MinD; 268 default: fatal("MIN: %s", type2name(bt)); 269 } 270 break; 271 } 272 case VECTOR_OP_MAX: { 273 switch (bt) { 274 case T_BYTE: 275 case T_SHORT: 276 case T_INT: return Op_MaxI; 277 case T_LONG: return Op_MaxL; 278 case T_FLOAT: return Op_MaxF; 279 case T_DOUBLE: return Op_MaxD; 280 default: fatal("MAX: %s", type2name(bt)); 281 } 282 break; 283 } 284 case VECTOR_OP_ABS: { 285 switch (bt) { 286 case T_BYTE: // fall-through 287 case T_SHORT: // fall-through 288 case T_INT: return Op_AbsI; 289 case T_LONG: return Op_AbsL; 290 case T_FLOAT: return Op_AbsF; 291 case T_DOUBLE: return Op_AbsD; 292 default: fatal("ABS: %s", type2name(bt)); 293 } 294 break; 295 } 296 case VECTOR_OP_NEG: { 297 switch (bt) { 298 case T_BYTE: // fall-through 299 case T_SHORT: // fall-through 300 case T_INT: return Op_NegI; 301 case T_FLOAT: return Op_NegF; 302 case T_DOUBLE: return Op_NegD; 303 default: fatal("NEG: %s", type2name(bt)); 304 } 305 break; 306 } 307 case VECTOR_OP_AND: { 308 switch (bt) { 309 case T_BYTE: // fall-through 310 case T_SHORT: // fall-through 311 case T_INT: return Op_AndI; 312 case T_LONG: return Op_AndL; 313 default: fatal("AND: %s", type2name(bt)); 314 } 315 break; 316 } 317 case VECTOR_OP_OR: { 318 switch (bt) { 319 case T_BYTE: // fall-through 320 case T_SHORT: // fall-through 321 case T_INT: return Op_OrI; 322 case T_LONG: return Op_OrL; 323 default: fatal("OR: %s", type2name(bt)); 324 } 325 break; 326 } 327 case VECTOR_OP_XOR: { 328 switch (bt) { 329 case T_BYTE: // fall-through 330 case T_SHORT: // fall-through 331 case T_INT: return Op_XorI; 332 case T_LONG: return Op_XorL; 333 default: fatal("XOR: %s", type2name(bt)); 334 } 335 break; 336 } 337 case VECTOR_OP_SQRT: { 338 switch (bt) { 339 case T_FLOAT: return Op_SqrtF; 340 case T_DOUBLE: return Op_SqrtD; 341 default: fatal("SQRT: %s", type2name(bt)); 342 } 343 break; 344 } 345 case VECTOR_OP_NOT: { 346 switch (bt) { 347 case T_BYTE: // fall-through 348 case T_SHORT: // fall-through 349 case T_INT: // fall-through 350 case T_LONG: return Op_Not; 351 default: fatal("NOT: %s", type2name(bt)); 352 } 353 break; 354 } 355 case VECTOR_OP_FMA: { 356 switch (bt) { 357 case T_FLOAT: return Op_FmaF; 358 case T_DOUBLE: return Op_FmaD; 359 default: fatal("FMA: %s", type2name(bt)); 360 } 361 break; 362 } 363 case VECTOR_OP_LSHIFT: { 364 switch (bt) { 365 case T_BYTE: // fall-through 366 case T_SHORT: // fall-through 367 case T_INT: return Op_LShiftI; 368 case T_LONG: return Op_LShiftL; 369 default: fatal("LSHIFT: %s", type2name(bt)); 370 } 371 break; 372 } 373 case VECTOR_OP_RSHIFT: { 374 switch (bt) { 375 case T_BYTE: // fall-through 376 case T_SHORT: // fall-through 377 case T_INT: return Op_RShiftI; 378 case T_LONG: return Op_RShiftL; 379 default: fatal("RSHIFT: %s", type2name(bt)); 380 } 381 break; 382 } 383 case VECTOR_OP_URSHIFT: { 384 switch (bt) { 385 case T_BYTE: return Op_URShiftB; 386 case T_SHORT: return Op_URShiftS; 387 case T_INT: return Op_URShiftI; 388 case T_LONG: return Op_URShiftL; 389 default: fatal("URSHIFT: %s", type2name(bt)); 390 } 391 break; 392 } 393 default: fatal("unknown op: %d", vop); 394 } 395 return 0; // Unimplemented 396 } 397 #endif // COMPILER2 398 399 /** 400 * Implementation of the jdk.internal.vm.vector.VectorSupport class 401 */ 402 403 JVM_ENTRY(jint, VectorSupport_GetMaxLaneCount(JNIEnv *env, jclass vsclazz, jobject clazz)) { 404 #ifdef COMPILER2 405 oop mirror = JNIHandles::resolve_non_null(clazz); 406 if (java_lang_Class::is_primitive(mirror)) { 407 BasicType bt = java_lang_Class::primitive_type(mirror); 408 return Matcher::max_vector_size(bt); 409 } 410 #endif // COMPILER2 411 return -1; 412 } JVM_END 413 414 // JVM_RegisterVectorSupportMethods 415 416 #define LANG "Ljava/lang/" 417 #define CLS LANG "Class;" 418 419 #define CC (char*) /*cast a literal from (const char*)*/ 420 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) 421 422 static JNINativeMethod jdk_internal_vm_vector_VectorSupport_methods[] = { 423 {CC "getMaxLaneCount", CC "(" CLS ")I", FN_PTR(VectorSupport_GetMaxLaneCount)} 424 }; 425 426 #undef CC 427 #undef FN_PTR 428 429 #undef LANG 430 #undef CLS 431 432 // This function is exported, used by NativeLookup. 433 434 JVM_ENTRY(void, JVM_RegisterVectorSupportMethods(JNIEnv* env, jclass vsclass)) { 435 ThreadToNativeFromVM ttnfv(thread); 436 437 int ok = env->RegisterNatives(vsclass, jdk_internal_vm_vector_VectorSupport_methods, sizeof(jdk_internal_vm_vector_VectorSupport_methods)/sizeof(JNINativeMethod)); 438 guarantee(ok == 0, "register jdk.internal.vm.vector.VectorSupport natives"); 439 } JVM_END