1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/jfr/writers/jfrJavaEventWriter.cpp Mon Aug 12 18:30:40 2019 +0300 1.3 @@ -0,0 +1,249 @@ 1.4 +/* 1.5 + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +#include "precompiled.hpp" 1.29 +#include "jni.h" 1.30 +#include "classfile/symbolTable.hpp" 1.31 +#include "classfile/systemDictionary.hpp" 1.32 +#include "classfile/vmSymbols.hpp" 1.33 +#include "jfr/jni/jfrJavaSupport.hpp" 1.34 +#include "jfr/recorder/storage/jfrStorage.hpp" 1.35 +#include "jfr/support/jfrThreadId.hpp" 1.36 +#include "jfr/utilities/jfrTypes.hpp" 1.37 +#include "jfr/writers/jfrJavaEventWriter.hpp" 1.38 +#include "oops/instanceKlass.hpp" 1.39 +#include "oops/oop.inline.hpp" 1.40 +#include "runtime/fieldDescriptor.hpp" 1.41 +#include "runtime/handles.hpp" 1.42 +#include "runtime/jniHandles.hpp" 1.43 +#include "runtime/thread.inline.hpp" 1.44 + 1.45 +static int start_pos_offset = invalid_offset; 1.46 +static int start_pos_address_offset = invalid_offset; 1.47 +static int current_pos_offset = invalid_offset; 1.48 +static int max_pos_offset = invalid_offset; 1.49 +static int max_event_size_offset = invalid_offset; 1.50 +static int notified_offset = invalid_offset; 1.51 +static int thread_id_offset = invalid_offset; 1.52 +static int valid_offset = invalid_offset; 1.53 + 1.54 +static bool find_field(InstanceKlass* ik, 1.55 + Symbol* name_symbol, 1.56 + Symbol* signature_symbol, 1.57 + fieldDescriptor* fd, 1.58 + bool is_static = false, 1.59 + bool allow_super = false) { 1.60 + if (allow_super || is_static) { 1.61 + return ik->find_field(name_symbol, signature_symbol, is_static, fd) != NULL; 1.62 + } else { 1.63 + return ik->find_local_field(name_symbol, signature_symbol, fd); 1.64 + } 1.65 +} 1.66 + 1.67 +static void compute_offset(int &dest_offset, 1.68 + Klass* klass, 1.69 + Symbol* name_symbol, 1.70 + Symbol* signature_symbol, 1.71 + bool is_static = false, bool allow_super = false) { 1.72 + fieldDescriptor fd; 1.73 + InstanceKlass* ik = InstanceKlass::cast(klass); 1.74 + if (!find_field(ik, name_symbol, signature_symbol, &fd, is_static, allow_super)) { 1.75 + assert(false, "invariant"); 1.76 + } 1.77 + dest_offset = fd.offset(); 1.78 +} 1.79 + 1.80 +static bool setup_event_writer_offsets(TRAPS) { 1.81 + const char class_name[] = "jdk/jfr/internal/EventWriter"; 1.82 + Symbol* const k_sym = SymbolTable::lookup(class_name, sizeof class_name - 1, CHECK_false); 1.83 + assert(k_sym != NULL, "invariant"); 1.84 + Klass* klass = SystemDictionary::resolve_or_fail(k_sym, true, CHECK_false); 1.85 + assert(klass != NULL, "invariant"); 1.86 + 1.87 + const char start_pos_name[] = "startPosition"; 1.88 + Symbol* const start_pos_sym = SymbolTable::lookup(start_pos_name, sizeof start_pos_name - 1, CHECK_false); 1.89 + assert(start_pos_sym != NULL, "invariant"); 1.90 + assert(invalid_offset == start_pos_offset, "invariant"); 1.91 + compute_offset(start_pos_offset, klass, start_pos_sym, vmSymbols::long_signature()); 1.92 + assert(start_pos_offset != invalid_offset, "invariant"); 1.93 + 1.94 + const char start_pos_address_name[] = "startPositionAddress"; 1.95 + Symbol* const start_pos_address_sym = SymbolTable::lookup(start_pos_address_name, sizeof start_pos_address_name - 1, CHECK_false); 1.96 + assert(start_pos_address_sym != NULL, "invariant"); 1.97 + assert(invalid_offset == start_pos_address_offset, "invariant"); 1.98 + compute_offset(start_pos_address_offset, klass, start_pos_address_sym, vmSymbols::long_signature()); 1.99 + assert(start_pos_address_offset != invalid_offset, "invariant"); 1.100 + 1.101 + const char event_pos_name[] = "currentPosition"; 1.102 + Symbol* const event_pos_sym = SymbolTable::lookup(event_pos_name, sizeof event_pos_name - 1, CHECK_false); 1.103 + assert(event_pos_sym != NULL, "invariant"); 1.104 + assert(invalid_offset == current_pos_offset, "invariant"); 1.105 + compute_offset(current_pos_offset, klass, event_pos_sym,vmSymbols::long_signature()); 1.106 + assert(current_pos_offset != invalid_offset, "invariant"); 1.107 + 1.108 + const char max_pos_name[] = "maxPosition"; 1.109 + Symbol* const max_pos_sym = SymbolTable::lookup(max_pos_name, sizeof max_pos_name - 1, CHECK_false); 1.110 + assert(max_pos_sym != NULL, "invariant"); 1.111 + assert(invalid_offset == max_pos_offset, "invariant"); 1.112 + compute_offset(max_pos_offset, klass, max_pos_sym, vmSymbols::long_signature()); 1.113 + assert(max_pos_offset != invalid_offset, "invariant"); 1.114 + 1.115 + const char max_event_size_name[] = "maxEventSize"; 1.116 + Symbol* const max_event_size_sym = SymbolTable::lookup(max_event_size_name, sizeof max_event_size_name - 1, CHECK_false); 1.117 + assert (max_event_size_sym != NULL, "invariant"); 1.118 + assert(invalid_offset == max_event_size_offset, "invariant"); 1.119 + compute_offset(max_event_size_offset, klass, max_event_size_sym, vmSymbols::int_signature()); 1.120 + assert(max_event_size_offset != invalid_offset, "invariant"); 1.121 + 1.122 + const char notified_name[] = "notified"; 1.123 + Symbol* const notified_sym = SymbolTable::lookup(notified_name, sizeof notified_name - 1, CHECK_false); 1.124 + assert (notified_sym != NULL, "invariant"); 1.125 + assert(invalid_offset == notified_offset, "invariant"); 1.126 + compute_offset(notified_offset, klass, notified_sym, vmSymbols::bool_signature()); 1.127 + assert(notified_offset != invalid_offset, "invariant"); 1.128 + 1.129 + const char valid_name[] = "valid"; 1.130 + Symbol* const valid_sym = SymbolTable::lookup(valid_name, sizeof valid_name - 1, CHECK_false); 1.131 + assert (valid_sym != NULL, "invariant"); 1.132 + assert(invalid_offset == valid_offset, "invariant"); 1.133 + compute_offset(valid_offset, klass, valid_sym, vmSymbols::bool_signature()); 1.134 + assert(valid_offset != invalid_offset, "invariant"); 1.135 + return true; 1.136 +} 1.137 + 1.138 +bool JfrJavaEventWriter::has_required_classes(TRAPS) { 1.139 + const char class_name[] = "jdk/jfr/internal/EventWriter"; 1.140 + Symbol* const k_sym = SymbolTable::lookup(class_name, sizeof class_name - 1, CHECK_false); 1.141 + Klass* klass = SystemDictionary::resolve_or_null(k_sym, CHECK_false); 1.142 + return (klass != NULL); 1.143 +} 1.144 + 1.145 +bool JfrJavaEventWriter::initialize() { 1.146 + static bool initialized = false; 1.147 + if (!initialized) { 1.148 + Thread* thread = Thread::current(); 1.149 + initialized = setup_event_writer_offsets(thread); 1.150 + } 1.151 + return initialized; 1.152 +} 1.153 + 1.154 +jboolean JfrJavaEventWriter::flush(jobject writer, jint used, jint requested, JavaThread* jt) { 1.155 + DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(jt)); 1.156 + assert(writer != NULL, "invariant"); 1.157 + oop const w = JNIHandles::resolve_non_null(writer); 1.158 + assert(w != NULL, "invariant"); 1.159 + JfrBuffer* const current = jt->jfr_thread_local()->java_buffer(); 1.160 + assert(current != NULL, "invariant"); 1.161 + JfrBuffer* const buffer = JfrStorage::flush(current, used, requested, false, jt); 1.162 + assert(buffer != NULL, "invariant"); 1.163 + // "validity" is contextually defined here to mean 1.164 + // that some memory location was provided that is 1.165 + // large enough to accommodate the "requested size". 1.166 + const bool is_valid = buffer->free_size() >= (size_t)(used + requested); 1.167 + u1* const new_current_position = is_valid ? buffer->pos() + used : buffer->pos(); 1.168 + w->long_field_put(start_pos_offset, (jlong)buffer->pos()); 1.169 + w->long_field_put(current_pos_offset, (jlong)new_current_position); 1.170 + // only update java writer if underlying memory changed 1.171 + if (buffer != current) { 1.172 + w->long_field_put(start_pos_address_offset, (jlong)buffer->pos_address()); 1.173 + w->long_field_put(max_pos_offset, (jlong)buffer->end()); 1.174 + } 1.175 + if (!is_valid) { 1.176 + // mark writer as invalid for this write attempt 1.177 + w->release_bool_field_put(valid_offset, JNI_FALSE); 1.178 + return JNI_FALSE; 1.179 + } 1.180 + // An exclusive use of a leased buffer is treated equivalent to 1.181 + // holding a system resource. As such, it should be released as soon as possible. 1.182 + // Returning true here signals that the thread will need to call flush again 1.183 + // on EventWriter.endEvent() and that flush will return the lease. 1.184 + return buffer->lease() ? JNI_TRUE : JNI_FALSE; 1.185 +} 1.186 + 1.187 +class JfrJavaEventWriterNotificationClosure : public ThreadClosure { 1.188 + public: 1.189 + void do_thread(Thread* t) { 1.190 + if (t->is_Java_thread()) { 1.191 + JfrJavaEventWriter::notify((JavaThread*)t); 1.192 + } 1.193 + } 1.194 +}; 1.195 + 1.196 +void JfrJavaEventWriter::notify() { 1.197 + assert(SafepointSynchronize::is_at_safepoint(), "invariant"); 1.198 + JfrJavaEventWriterNotificationClosure closure; 1.199 + Threads::threads_do(&closure); 1.200 +} 1.201 + 1.202 +void JfrJavaEventWriter::notify(JavaThread* jt) { 1.203 + assert(jt != NULL, "invariant"); 1.204 + assert(SafepointSynchronize::is_at_safepoint(), "invariant"); 1.205 + if (jt->jfr_thread_local()->has_java_event_writer()) { 1.206 + oop buffer_writer = JNIHandles::resolve_non_null(jt->jfr_thread_local()->java_event_writer()); 1.207 + assert(buffer_writer != NULL, "invariant"); 1.208 + buffer_writer->release_bool_field_put(notified_offset, JNI_TRUE); 1.209 + } 1.210 +} 1.211 + 1.212 +static jobject create_new_event_writer(JfrBuffer* buffer, TRAPS) { 1.213 + assert(buffer != NULL, "invariant"); 1.214 + DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD)); 1.215 + HandleMark hm(THREAD); 1.216 + static const char klass[] = "jdk/jfr/internal/EventWriter"; 1.217 + static const char method[] = "<init>"; 1.218 + static const char signature[] = "(JJJJZ)V"; 1.219 + JavaValue result(T_OBJECT); 1.220 + JfrJavaArguments args(&result, klass, method, signature, CHECK_NULL); 1.221 + // parameters 1.222 + args.push_long((jlong)buffer->pos()); 1.223 + args.push_long((jlong)buffer->end()); 1.224 + args.push_long((jlong)buffer->pos_address()); 1.225 + args.push_long((jlong)JFR_THREAD_ID(THREAD)); 1.226 + args.push_int((int)JNI_TRUE); 1.227 + JfrJavaSupport::new_object_global_ref(&args, CHECK_NULL); 1.228 + return result.get_jobject(); 1.229 +} 1.230 + 1.231 +jobject JfrJavaEventWriter::event_writer(Thread* t) { 1.232 + DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(t)); 1.233 + JfrThreadLocal* const tl = t->jfr_thread_local(); 1.234 + assert(tl->shelved_buffer() == NULL, "invariant"); 1.235 + return tl->java_event_writer(); 1.236 +} 1.237 + 1.238 +jobject JfrJavaEventWriter::new_event_writer(TRAPS) { 1.239 + DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD)); 1.240 + assert(event_writer(THREAD) == NULL, "invariant"); 1.241 + JfrThreadLocal* const tl = THREAD->jfr_thread_local(); 1.242 + assert(!tl->has_java_buffer(), "invariant"); 1.243 + JfrBuffer* const buffer = tl->java_buffer(); 1.244 + if (buffer == NULL) { 1.245 + JfrJavaSupport::throw_out_of_memory_error("OOME for thread local buffer", THREAD); 1.246 + return NULL; 1.247 + } 1.248 + jobject java_event_writer = create_new_event_writer(buffer, CHECK_NULL); 1.249 + tl->set_java_event_writer(java_event_writer); 1.250 + assert(tl->has_java_event_writer(), "invariant"); 1.251 + return java_event_writer; 1.252 +}