--- /dev/null 2016-10-25 08:46:44.038854975 +0200
+++ new/src/share/vm/evtrace/traceJavaBridge.cpp 2016-10-25 10:40:14.123780799 +0200
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ *
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see .
+ *
+ */
+
+#include "evtrace/traceJavaBridge.hpp"
+
+#include "evtrace/traceBuffer.hpp"
+#include "evtrace/traceBufferQueue.hpp"
+#include "evtrace/traceEvents.hpp"
+#include "evtrace/traceWriter.hpp"
+#include "evtrace/traceReaderThread.hpp"
+
+#include "prims/jni.h"
+#include "runtime/interfaceSupport.hpp"
+#include "runtime/javaCalls.hpp"
+
+#define TEVT_ENTRY(result_type, header) \
+ JVM_ENTRY(result_type, header)
+
+#define TEVT_END JVM_END
+
+TEVT_ENTRY(jobject, TEvT_DequeueBuffer(JNIEnv *env, jobject self, jlong queue_handle, const jboolean should_block))
+ TraceBufferQueue *queue = (TraceBufferQueue *) queue_handle;
+
+ TraceBuffer *buffer;
+
+ if (thread->is_TraceReader_thread()) {
+ // we do this to avoid interrupting the thread at a bad time
+ ((TraceReaderThread *) thread)->set_is_polling_queue(true);
+ }
+ jlong delay = 4;
+ for (;;) {
+ buffer = queue->try_dequeue();
+ if (buffer != NULL || !should_block || !TraceManager::is_initialized()) {
+ break;
+ }
+
+ os::sleep(thread, delay, true);
+ if (delay <= 64) {
+ delay = 2 * delay;
+ }
+ }
+ if (thread->is_TraceReader_thread()) {
+ ((TraceReaderThread *) thread)->set_is_polling_queue(false);
+ }
+
+ jobject bufobj = NULL;
+ if (buffer != NULL) {
+ ThreadToNativeFromVM ttn(thread);
+
+ jlong handle = (jlong) ((uintptr_t) buffer); // sign extension paranoia
+ size_t length = buffer->filled_size();
+ jobject bytebuf = env->NewDirectByteBuffer(buffer->data, length);
+ jclass clazz = env->FindClass("sun/evtracing/TraceBuffer");
+ jmethodID method = env->GetMethodID(clazz, "", "(JLjava/nio/ByteBuffer;J)V");
+ assert(method != NULL, "must be successful");
+ bufobj = env->NewObject(clazz, method, handle, bytebuf, buffer->owner_id);
+ assert(bufobj != NULL, "must succeed");
+ }
+ return bufobj;
+TEVT_END
+
+TEVT_ENTRY(void, TEvT_EnqueueBuffer(JNIEnv *env, jobject self, jlong queue_handle, jlong buffer_handle))
+ TraceBufferQueue *queue = (TraceBufferQueue *) queue_handle;
+ queue->enqueue((TraceBuffer *) buffer_handle);
+TEVT_END
+
+TEVT_ENTRY(void, TEvT_ResetAndEnqueueBuffer(JNIEnv *env, jobject self, jlong queue_handle, jlong buffer_handle))
+ TraceBuffer *buffer = (TraceBuffer *) buffer_handle;
+ buffer->reset();
+ TraceBufferQueue *queue = (TraceBufferQueue *) queue_handle;
+ queue->enqueue((TraceBuffer *) buffer_handle);
+TEVT_END
+
+TEVT_ENTRY(void, TEvT_FreeBuffer(JNIEnv *env, jobject self, jlong buffer_handle))
+ TraceBuffer *buffer = (TraceBuffer *) buffer_handle;
+ TraceManager::free_buffer(buffer);
+TEVT_END
+
+TEVT_ENTRY(jlong, TEvT_QueueCount(JNIEnv *env, jobject self, jlong queue_handle))
+ TraceBufferQueue *queue = (TraceBufferQueue *) queue_handle;
+ return (jlong) queue->count();TEVT_END
+
+TEVT_ENTRY(void, TEvT_WriteGroupEvent(JNIEnv *env, jobject self, jlong park_global_seq_begin_ref, jobject source))
+ TraceEvents::write_group(thread, park_global_seq_begin_ref, instanceOop(JNIHandles::resolve_non_null(source)));
+TEVT_END
+
+TEVT_ENTRY(jstring, TEvT_GetConfiguration(JNIEnv *env, jobject self))
+ jstring config = NULL;
+ if (EventTracingConfiguration != NULL && EventTracingConfiguration[0] != '\0') {
+ ThreadToNativeFromVM ttn(thread);
+ config = env->NewStringUTF(EventTracingConfiguration);
+ }
+ return config;
+TEVT_END
+
+TEVT_ENTRY(void, TEvT_PutNativeStatistics(JNIEnv *env, jobject self, jobject map))
+ JavaTraceStatistics jts(env, thread, instanceHandle(instanceOop(JNIHandles::resolve_non_null(map))), CHECK);
+ TraceManager::write_stats(&jts);
+TEVT_END
+
+JavaTraceStatistics::JavaTraceStatistics(JNIEnv* env, JavaThread* thread, instanceHandle map, TRAPS)
+: _env(env),
+ THREAD(THREAD),
+ _hashmap_obj(map)
+{
+}
+
+void JavaTraceStatistics::add_entry(const char* name, jdouble value) {
+ assert(name != NULL, "must not be NULL");
+
+ // assume utf8 string to save native transition required by java_lang_String::create_from_platform_dependent_str
+ Handle name_str = java_lang_String::create_from_str(name, CHECK);
+ oop value_oop = java_lang_boxing_object::create(T_DOUBLE, (jvalue*) &value, CHECK);
+ Handle value_handle(THREAD, value_oop);
+
+ JavaValue result(T_OBJECT);
+ JavaCalls::call_virtual(&result,
+ _hashmap_obj,
+ _hashmap_obj->klass(),
+ vmSymbols::put_name(),
+ vmSymbols::object_object_object_signature(),
+ name_str,
+ value_handle,
+ CHECK);
+}
+
+TEVT_ENTRY(void, TEvT_ResetNativeStatistics(JNIEnv *env, jobject self))
+ TraceManager::reset_stats();
+TEVT_END
+
+TEVT_ENTRY(void, TEvT_ResetNativeMetadata(JNIEnv *env, jobject self))
+ TraceManager::reset_metadata();
+TEVT_END
+
+TEVT_ENTRY(void, TEvT_ReclaimBuffers(JNIEnv *env, jobject self, jboolean wait_until_processed))
+ TraceManager::reclaim_buffers_in_safepoint(wait_until_processed);
+TEVT_END
+
+#define CC (char*) /*cast a literal from (const char*)*/
+#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
+
+static JNINativeMethod tevtmethods[] = {
+ {CC"dequeueBuffer", CC"(JZ)Lsun/evtracing/TraceBuffer;", FN_PTR(TEvT_DequeueBuffer)},
+ {CC"enqueueBuffer", CC"(JJ)V", FN_PTR(TEvT_EnqueueBuffer)},
+ {CC"resetAndEnqueueBuffer", CC"(JJ)V", FN_PTR(TEvT_ResetAndEnqueueBuffer)},
+ {CC"freeBuffer", CC"(J)V", FN_PTR(TEvT_FreeBuffer)},
+ {CC"queueCount", CC"(J)J", FN_PTR(TEvT_QueueCount) },
+ {CC"writeGroupEvent", CC"(JLjava/lang/Object;)V", FN_PTR(TEvT_WriteGroupEvent)},
+ {CC"getConfiguration", CC"()Ljava/lang/String;", FN_PTR(TEvT_GetConfiguration)},
+ {CC"putNativeStatistics", CC"(Ljava/util/Map;)V", FN_PTR(TEvT_PutNativeStatistics)},
+ {CC"resetNativeStatistics", CC"()V", FN_PTR(TEvT_ResetNativeStatistics)},
+ {CC"resetNativeMetadata", CC"()V", FN_PTR(TEvT_ResetNativeMetadata)},
+ {CC"reclaimBuffers", CC"(Z)V", FN_PTR(TEvT_ReclaimBuffers)},
+};
+
+JVM_ENTRY(jboolean, JVM_RegisterEventTracingMethods(JNIEnv* env, jclass tevtclass))
+ if (EnableEventTracing) {
+ ThreadToNativeFromVM ttnfv(thread);
+ int ok = env->RegisterNatives(tevtclass, tevtmethods, sizeof(tevtmethods) / sizeof(JNINativeMethod));
+ guarantee(ok == 0, "register event tracing natives");
+ }
+ return EnableEventTracing;
+JVM_END