1 /* 2 * Copyright (c) 2022, Red Hat, Inc. 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 "gc/shared/collectedHeap.hpp" 30 #include "oops/arrayOop.hpp" 31 #include "oops/instanceKlass.inline.hpp" 32 #include "oops/oop.inline.hpp" 33 #include "oops/oopsHierarchy.hpp" 34 #include "runtime/interfaceSupport.inline.hpp" 35 #include "runtime/jniHandles.inline.hpp" 36 #include "runtime/os.hpp" 37 #include "runtime/orderAccess.hpp" 38 #include "utilities/macros.hpp" 39 40 #include OS_CPU_HEADER_INLINE(os) 41 42 /** 43 * Implementation of the net.shipilev.Magic 44 */ 45 46 JVM_ENTRY(static jlong, NetShipilevMagic_timestamp(JNIEnv *env, jclass cls)) { 47 #if defined(X86) && !defined(ZERO) 48 return os::rdtsc(); 49 #else 50 return -1; 51 #endif 52 } JVM_END 53 54 JVM_ENTRY(static jlong, NetShipilevMagic_timestamp_serial(JNIEnv *env, jclass cls)) { 55 #if defined(X86) && !defined(ZERO) 56 // Rely on rdtscp intrinsic to make the right thing 57 // serialization-wise. In these fallback/interpreter paths, 58 // just bite the bullet and do the fence. 59 OrderAccess::fence(); 60 return os::rdtsc(); 61 #else 62 return -1; 63 #endif 64 } JVM_END 65 66 JVM_ENTRY(jlong, NetShipilevMagic_sizeOf(JNIEnv *env, jclass cls, jobject obj)) 67 assert(obj != NULL, "object must not be NULL"); 68 69 oop o = JNIHandles::resolve_non_null(obj); 70 return o->size()*HeapWordSize; 71 JVM_END 72 73 JVM_ENTRY(jlong, NetShipilevMagic_addressOf(JNIEnv *env, jclass cls, jobject obj)) 74 assert(obj != NULL, "object must not be NULL"); 75 76 oop o = JNIHandles::resolve_non_null(obj); 77 return cast_from_oop<jlong>(o); 78 JVM_END 79 80 JVM_ENTRY(jlong, NetShipilevMagic_fieldOffsetOf(JNIEnv *env, jclass cls, jobject field)) 81 assert(field != NULL, "field must not be NULL"); 82 83 oop f = JNIHandles::resolve_non_null(field); 84 oop m = java_lang_reflect_Field::clazz(f); 85 Klass* k = java_lang_Class::as_Klass(m); 86 int slot = java_lang_reflect_Field::slot(f); 87 88 return InstanceKlass::cast(k)->field_offset(slot); 89 JVM_END 90 91 JVM_ENTRY(jlong, NetShipilevMagic_fieldSizeOf(JNIEnv *env, jclass cls, jobject field)) 92 assert(field != NULL, "field must not be NULL"); 93 94 oop f = JNIHandles::resolve_non_null(field); 95 oop m = java_lang_reflect_Field::clazz(f); 96 Klass* k = java_lang_Class::as_Klass(m); 97 int slot = java_lang_reflect_Field::slot(f); 98 99 Symbol* sig = InstanceKlass::cast(k)->field_signature(slot); 100 switch (sig->char_at(0)) { 101 case JVM_SIGNATURE_CLASS : 102 case JVM_SIGNATURE_ARRAY : return type2aelembytes(T_OBJECT); 103 case JVM_SIGNATURE_BYTE : return type2aelembytes(T_BYTE); 104 case JVM_SIGNATURE_CHAR : return type2aelembytes(T_CHAR); 105 case JVM_SIGNATURE_FLOAT : return type2aelembytes(T_FLOAT); 106 case JVM_SIGNATURE_DOUBLE : return type2aelembytes(T_DOUBLE); 107 case JVM_SIGNATURE_INT : return type2aelembytes(T_INT); 108 case JVM_SIGNATURE_LONG : return type2aelembytes(T_LONG); 109 case JVM_SIGNATURE_SHORT : return type2aelembytes(T_SHORT); 110 case JVM_SIGNATURE_BOOLEAN : return type2aelembytes(T_BOOLEAN); 111 } 112 113 ShouldNotReachHere(); 114 return 0; 115 JVM_END 116 117 class GetReferencedObjectsClosure : public BasicOopIterateClosure { 118 private: 119 objArrayOopDesc* const _result; 120 int _count; 121 public: 122 GetReferencedObjectsClosure(objArrayOopDesc* result) : _result(result), _count(0) {} 123 124 template <typename T> void do_oop_nv(T* p) { 125 oop o = HeapAccess<>::oop_load(p); 126 if (!CompressedOops::is_null(o)) { 127 _result->obj_at_put(_count++, o); 128 } 129 } 130 131 int count() { return _count; } 132 133 virtual void do_oop(oop* p) { do_oop_nv(p); } 134 virtual void do_oop(narrowOop* p) { do_oop_nv(p); } 135 136 // Don't use the oop verification code in the oop_oop_iterate framework. 137 debug_only(virtual bool should_verify_oops() { return false; }) 138 }; 139 140 JVM_ENTRY(jint, NetShipilevMagic_getReferencedObjects(JNIEnv *env, jclass cls, jobject obj_ref, jobjectArray ref_buf_ref)) 141 oop obj = JNIHandles::resolve_non_null(obj_ref); 142 objArrayOop ref_buf = objArrayOop(JNIHandles::resolve_non_null(ref_buf_ref)); 143 144 assert(Universe::heap()->is_in(obj), "object should be in heap: " PTR_FORMAT, p2i(obj)); 145 assert(Universe::heap()->is_in(ref_buf), "ref buf should be in heap: " PTR_FORMAT, p2i(ref_buf)); 146 147 InstanceKlass* k = InstanceKlass::cast(obj->klass()); 148 149 int count = 0; 150 { 151 InstanceKlass* ik = k; 152 while (ik != NULL) { 153 count += ik->nonstatic_oop_field_count(); 154 ik = ik->superklass(); 155 } 156 } 157 158 if (count == 0) { 159 return 0; 160 } 161 162 if (count > ref_buf->length()) { 163 return -1; 164 } 165 166 GetReferencedObjectsClosure cl(ref_buf); 167 168 #ifdef _LP64 169 if (UseCompressedOops) { 170 k->oop_oop_iterate<narrowOop>(obj, &cl); 171 } else 172 #endif 173 { 174 k->oop_oop_iterate<oop>(obj, &cl); 175 } 176 177 return cl.count(); 178 JVM_END 179 180 /// JVM_RegisterUnsafeMethods 181 182 #define CC (char*) /*cast a literal from (const char*)*/ 183 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) 184 185 #define LANG "Ljava/lang/" 186 187 #define OBJ LANG "Object;" 188 #define CLS LANG "Class;" 189 #define FLD LANG "reflect/Field;" 190 191 static JNINativeMethod net_shipilev_Magic_methods[] = { 192 {CC "timestamp", CC "()J", FN_PTR(NetShipilevMagic_timestamp)}, 193 {CC "timestampSerial", CC "()J", FN_PTR(NetShipilevMagic_timestamp_serial)}, 194 {CC "sizeOf0", CC "(" OBJ ")J", FN_PTR(NetShipilevMagic_sizeOf)}, 195 {CC "addressOf0", CC "(" OBJ ")J", FN_PTR(NetShipilevMagic_addressOf)}, 196 {CC "getReferencedObjects", CC "(" OBJ "[" OBJ ")I", FN_PTR(NetShipilevMagic_getReferencedObjects)}, 197 {CC "fieldOffsetOf0", CC "(" FLD ")J", FN_PTR(NetShipilevMagic_fieldOffsetOf)}, 198 {CC "fieldSizeOf0", CC "(" FLD ")J", FN_PTR(NetShipilevMagic_fieldSizeOf)}, 199 }; 200 201 #undef LANG 202 #undef OBJ 203 #undef CLS 204 #undef FLD 205 206 #undef CC 207 #undef FN_PTR 208 209 JVM_ENTRY(void, JVM_RegisterNetShipilevMagicMethods(JNIEnv *env, jclass cls)) { 210 ThreadToNativeFromVM ttnfv(thread); 211 212 int ok = env->RegisterNatives(cls, net_shipilev_Magic_methods, sizeof(net_shipilev_Magic_methods)/sizeof(JNINativeMethod)); 213 guarantee(ok == 0, "register net.shipilev.Magic natives"); 214 } JVM_END