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