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 #ifdef COMPILER2
  42 int VectorSupport::vop2ideal(jint id, BasicType bt) {
  43   VectorOperation vop = (VectorOperation)id;
  44   switch (vop) {
  45     case VECTOR_OP_ADD: {
  46       switch (bt) {
  47         case T_BYTE:   // fall-through
  48         case T_SHORT:  // fall-through
  49         case T_INT:    return Op_AddI;
  50         case T_LONG:   return Op_AddL;
  51         case T_FLOAT:  return Op_AddF;
  52         case T_DOUBLE: return Op_AddD;
  53         default: fatal("ADD: %s", type2name(bt));
  54       }
  55       break;
  56     }
  57     case VECTOR_OP_SUB: {
  58       switch (bt) {
  59         case T_BYTE:   // fall-through
  60         case T_SHORT:  // fall-through
  61         case T_INT:    return Op_SubI;
  62         case T_LONG:   return Op_SubL;
  63         case T_FLOAT:  return Op_SubF;
  64         case T_DOUBLE: return Op_SubD;
  65         default: fatal("SUB: %s", type2name(bt));
  66       }
  67       break;
  68     }
  69     case VECTOR_OP_MUL: {
  70       switch (bt) {
  71         case T_BYTE:   // fall-through
  72         case T_SHORT:  // fall-through
  73         case T_INT:    return Op_MulI;
  74         case T_LONG:   return Op_MulL;
  75         case T_FLOAT:  return Op_MulF;
  76         case T_DOUBLE: return Op_MulD;
  77         default: fatal("MUL: %s", type2name(bt));
  78       }
  79       break;
  80     }
  81     case VECTOR_OP_DIV: {
  82       switch (bt) {
  83         case T_BYTE:   // fall-through
  84         case T_SHORT:  // fall-through
  85         case T_INT:    return Op_DivI;
  86         case T_LONG:   return Op_DivL;
  87         case T_FLOAT:  return Op_DivF;
  88         case T_DOUBLE: return Op_DivD;
  89         default: fatal("DIV: %s", type2name(bt));
  90       }
  91       break;
  92     }
  93     case VECTOR_OP_MIN: {
  94       switch (bt) {
  95         case T_BYTE:
  96         case T_SHORT:
  97         case T_INT:    return Op_MinI;
  98         case T_LONG:   return Op_MinL;
  99         case T_FLOAT:  return Op_MinF;
 100         case T_DOUBLE: return Op_MinD;
 101         default: fatal("MIN: %s", type2name(bt));
 102       }
 103       break;
 104     }
 105     case VECTOR_OP_MAX: {
 106       switch (bt) {
 107         case T_BYTE:
 108         case T_SHORT:
 109         case T_INT:    return Op_MaxI;
 110         case T_LONG:   return Op_MaxL;
 111         case T_FLOAT:  return Op_MaxF;
 112         case T_DOUBLE: return Op_MaxD;
 113         default: fatal("MAX: %s", type2name(bt));
 114       }
 115       break;
 116     }
 117     case VECTOR_OP_ABS: {
 118       switch (bt) {
 119         case T_BYTE:   // fall-through
 120         case T_SHORT:  // fall-through
 121         case T_INT:    return Op_AbsI;
 122         case T_LONG:   return Op_AbsL;
 123         case T_FLOAT:  return Op_AbsF;
 124         case T_DOUBLE: return Op_AbsD;
 125         default: fatal("ABS: %s", type2name(bt));
 126       }
 127       break;
 128     }
 129     case VECTOR_OP_NEG: {
 130       switch (bt) {
 131         case T_BYTE:   // fall-through
 132         case T_SHORT:  // fall-through
 133         case T_INT:    return Op_NegI;
 134         case T_FLOAT:  return Op_NegF;
 135         case T_DOUBLE: return Op_NegD;
 136         default: fatal("NEG: %s", type2name(bt));
 137       }
 138       break;
 139     }
 140     case VECTOR_OP_AND: {
 141       switch (bt) {
 142         case T_BYTE:   // fall-through
 143         case T_SHORT:  // fall-through
 144         case T_INT:    return Op_AndI;
 145         case T_LONG:   return Op_AndL;
 146         default: fatal("AND: %s", type2name(bt));
 147       }
 148       break;
 149     }
 150     case VECTOR_OP_OR: {
 151       switch (bt) {
 152         case T_BYTE:   // fall-through
 153         case T_SHORT:  // fall-through
 154         case T_INT:    return Op_OrI;
 155         case T_LONG:   return Op_OrL;
 156         default: fatal("OR: %s", type2name(bt));
 157       }
 158       break;
 159     }
 160     case VECTOR_OP_XOR: {
 161       switch (bt) {
 162         case T_BYTE:   // fall-through
 163         case T_SHORT:  // fall-through
 164         case T_INT:    return Op_XorI;
 165         case T_LONG:   return Op_XorL;
 166         default: fatal("XOR: %s", type2name(bt));
 167       }
 168       break;
 169     }
 170     case VECTOR_OP_SQRT: {
 171       switch (bt) {
 172         case T_FLOAT:  return Op_SqrtF;
 173         case T_DOUBLE: return Op_SqrtD;
 174         default: fatal("SQRT: %s", type2name(bt));
 175       }
 176       break;
 177     }
 178     case VECTOR_OP_NOT: {
 179       switch (bt) {
 180         case T_BYTE:   // fall-through
 181         case T_SHORT:  // fall-through
 182         case T_INT:    // fall-through
 183         case T_LONG:   return Op_Not;
 184         default: fatal("NOT: %s", type2name(bt));
 185       }
 186       break;
 187     }
 188     case VECTOR_OP_FMA: {
 189       switch (bt) {
 190         case T_FLOAT:  return Op_FmaF;
 191         case T_DOUBLE: return Op_FmaD;
 192         default: fatal("FMA: %s", type2name(bt));
 193       }
 194       break;
 195     }
 196     case VECTOR_OP_LSHIFT: {
 197       switch (bt) {
 198         case T_BYTE:   // fall-through
 199         case T_SHORT:  // fall-through
 200         case T_INT:  return Op_LShiftI;
 201         case T_LONG: return Op_LShiftL;
 202         default: fatal("LSHIFT: %s", type2name(bt));
 203       }
 204       break;
 205     }
 206     case VECTOR_OP_RSHIFT: {
 207       switch (bt) {
 208         case T_BYTE:   // fall-through
 209         case T_SHORT:  // fall-through
 210         case T_INT:  return Op_RShiftI;
 211         case T_LONG: return Op_RShiftL;
 212         default: fatal("RSHIFT: %s", type2name(bt));
 213       }
 214       break;
 215     }
 216     case VECTOR_OP_URSHIFT: {
 217       switch (bt) {
 218         case T_BYTE:  return Op_URShiftB;
 219         case T_SHORT: return Op_URShiftS;
 220         case T_INT:   return Op_URShiftI;
 221         case T_LONG:  return Op_URShiftL;
 222         default: fatal("URSHIFT: %s", type2name(bt));
 223       }
 224       break;
 225     }
 226     default: fatal("unknown op: %d", vop);
 227   }
 228   return 0; // Unimplemented
 229 }
 230 #endif // COMPILER2
 231 
 232 /**
 233  * Implementation of the jdk.internal.vm.vector.VectorSupport class
 234  */
 235 
 236 JVM_ENTRY(jint, VectorSupport_GetMaxLaneCount(JNIEnv *env, jclass vsclazz, jobject clazz)) {
 237 #ifdef COMPILER2
 238   oop mirror = JNIHandles::resolve_non_null(clazz);
 239   if (java_lang_Class::is_primitive(mirror)) {
 240     BasicType bt = java_lang_Class::primitive_type(mirror);
 241     return Matcher::max_vector_size(bt);
 242   }
 243 #endif // COMPILER2
 244   return -1;
 245 } JVM_END
 246 
 247 // JVM_RegisterVectorSupportMethods
 248 
 249 #define LANG "Ljava/lang/"
 250 #define CLS LANG "Class;"
 251 
 252 #define CC (char*)  /*cast a literal from (const char*)*/
 253 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
 254 
 255 static JNINativeMethod jdk_internal_vm_vector_VectorSupport_methods[] = {
 256     {CC "getMaxLaneCount",   CC "(" CLS ")I", FN_PTR(VectorSupport_GetMaxLaneCount)}
 257 };
 258 
 259 #undef CC
 260 #undef FN_PTR
 261 
 262 #undef LANG
 263 #undef CLS
 264 
 265 // This function is exported, used by NativeLookup.
 266 
 267 JVM_ENTRY(void, JVM_RegisterVectorSupportMethods(JNIEnv* env, jclass vsclass)) {
 268   ThreadToNativeFromVM ttnfv(thread);
 269 
 270   int ok = env->RegisterNatives(vsclass, jdk_internal_vm_vector_VectorSupport_methods, sizeof(jdk_internal_vm_vector_VectorSupport_methods)/sizeof(JNINativeMethod));
 271   guarantee(ok == 0, "register jdk.internal.vm.vector.VectorSupport natives");
 272 } JVM_END