/**
 * @file jvmpi_oprofile.cpp
 * JVMPI agent implementation to report jitted JVM code to OProfile
 *
 * @remark Copyright 2007 OProfile authors
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * @author Maynard Johnson
 *
 * Copyright IBM Corporation 2007
 *
 */

#include <iostream>
#include <map>
#include <string>
#include <cstring>
#include <stdexcept>
#include <cerrno>

extern "C" {
#include <stdint.h>
#include <jvmpi.h>
#include <opagent.h>
}

using namespace std;

static bool debug = false;
static op_agent_t agent_hdl;

class class_details {
public:
	string name;
	map<jmethodID, string> method_names;
	map<jmethodID, string> method_signatures;
};


static pthread_mutex_t class_map_mutex = PTHREAD_MUTEX_INITIALIZER;
static map <jobjectID, class_details> loaded_classes;

void class_load(JVMPI_Event * event)
{
	class_details cls;
	cls.name = event->u.class_load.class_name;
	JVMPI_Method * passed_methods = event->u.class_load.methods;
	for (int i = 0; i < event->u.class_load.num_methods;
	     i++, passed_methods++) {
		cls.method_names[passed_methods->method_id] =
			passed_methods->method_name;
		cls.method_signatures[passed_methods->method_id] =
			passed_methods->method_signature;
	}

	pthread_mutex_lock(&class_map_mutex);
	loaded_classes[event->u.class_load.class_id] = cls;
	pthread_mutex_unlock(&class_map_mutex);
}

void class_unload(JVMPI_Event * event)
{
	pthread_mutex_lock(&class_map_mutex);
	loaded_classes.erase(event->u.class_load.class_id);
	pthread_mutex_unlock(&class_map_mutex);
}

JVMPI_Interface * jvmpi;

void compiled_method_load(JVMPI_Event * event)
{
	jmethodID method = event->u.compiled_method_load.method_id;
	void * code_addr =  event->u.compiled_method_load.code_addr;
	jint code_size =  event->u.compiled_method_load.code_size;

	jvmpi->DisableGC();
	 /* Get the class of the method */
	jobjectID classID = jvmpi->GetMethodClass(method);
	jvmpi->EnableGC();

	pthread_mutex_lock(&class_map_mutex);
	map<jobjectID, class_details>::iterator iter =
		loaded_classes.find(classID);
	if (iter == loaded_classes.end()) {
		throw runtime_error("Error: Cannot find class for compiled"
				    " method\n");
	}

	class_details cls_info = ((class_details)iter->second);
	map<jmethodID, string>::iterator method_it =
		cls_info.method_names.find(method);
	if (method_it == cls_info.method_names.end()) {
		throw runtime_error("Error: Cannot find method name for "
				    "compiled method\n");
	}
	char const * method_name = method_it->second.c_str();
	method_it = cls_info.method_signatures.find(method);
	if (method_it == cls_info.method_signatures.end()) {
		throw runtime_error("Error: Cannot find method signature "
				    "for compiled method\n");
	}
	char const * method_signature = method_it->second.c_str();

	string const class_signature = "L" + cls_info.name + ";";
	pthread_mutex_unlock(&class_map_mutex);

	if (debug) {
		cerr << "load: class=" << class_signature << ", method ="
		     << method_name << ", method signature = "
		     << method_signature
		     << ", addr=" << code_addr << ", size="
		     << code_size << endl;
	}

	// produce a symbol name out of class name and method name
	int cnt = strlen(method_name) + strlen(class_signature.c_str()) +
		strlen(method_signature) + 2;
	char buf[cnt];
	strncpy(buf, class_signature.c_str(), cnt - 1);
	strncat(buf, method_name, cnt - strlen(buf) - 1);
	strncat(buf, method_signature, cnt - strlen(buf) - 1);
	if (op_write_native_code(agent_hdl, buf, (uint64_t) code_addr,
				 code_addr, code_size))
		perror("Error: op_write_native_code()");
}

void compiled_method_unload(JVMPI_Event * event)
{
	void * code_addr =  event->u.compiled_method_load.code_addr;
	if (debug) {
		cerr << "unload: addr="
			<< (unsigned long long) (uintptr_t) code_addr
			<< endl;
	}
	if (op_unload_native_code(agent_hdl, (uint64_t)code_addr))
		perror("Error: op_unload_native_code()");
}

void jvm_shutdown(JVMPI_Event * event)
{
	/* Checking event here is not really necessary; added only to silence
	 * the 'unused parameter' compiler warning.
	 */
	if (event)
		if (op_close_agent(agent_hdl))
			perror("Error: op_close_agent()");
}


void jvm_notify_event(JVMPI_Event * event)
{
	switch (event->event_type) {
	case JVMPI_EVENT_COMPILED_METHOD_LOAD:
		compiled_method_load(event);
		break;
	case JVMPI_EVENT_COMPILED_METHOD_UNLOAD:
		compiled_method_unload(event);
		break;
	case JVMPI_EVENT_JVM_SHUT_DOWN:
		jvm_shutdown(event);
		break;
	case JVMPI_EVENT_CLASS_LOAD:
		class_load(event);
		break;
	case JVMPI_EVENT_CLASS_UNLOAD:
		class_unload(event);
		break;
	default:
		break;
	}
}

extern "C" {
JNIEXPORT jint JNICALL JVM_OnLoad(JavaVM * jvm, char * options,
                                  void * reserved)
{
	int err;

	if (options && strstr(options, "version")) {
		cerr << "jvmpi_oprofile: current libopagent version "
				 << op_major_version() << "." << op_minor_version()
				 << endl;
		throw runtime_error("Exiting");
	}

	if (options && strstr(options, "debug=yes")) {
		debug = true;
		/* Add something braindead to silence the 'unused parameter'
		 * compiler warning.
		 */
		if (reserved)
			debug = true;
	}

	if (debug)
		cerr << "jvmpi_oprofile: agent activated" << endl;

	agent_hdl = op_open_agent();
	if (!agent_hdl) {
		perror("Error: op_open_agent()");
		throw runtime_error("Exiting");
	}

	/* The union below is used to avoid the 'dereferencing type-punned
	 * pointer will break strict-aliasing rules' compiler warning on the
	 * GetEnv call.
	 */
	union {
		JVMPI_Interface * jvmpi_ifc;
		void * jvmpi_ifc_ptr;
	} jvmpi_GetEnv_arg;
	err = jvm->GetEnv(&jvmpi_GetEnv_arg.jvmpi_ifc_ptr, JVMPI_VERSION_1);
	if (err < 0) {
		cerr << "GetEnv failed with rc=" << err << endl;
		throw runtime_error("Exiting");
	}
	jvmpi = jvmpi_GetEnv_arg.jvmpi_ifc;
	jvmpi->EnableEvent(JVMPI_EVENT_COMPILED_METHOD_LOAD, NULL);
	jvmpi->EnableEvent(JVMPI_EVENT_COMPILED_METHOD_UNLOAD, NULL);
	jvmpi->EnableEvent(JVMPI_EVENT_JVM_SHUT_DOWN, NULL);
	jvmpi->EnableEvent(JVMPI_EVENT_CLASS_LOAD, NULL);

	jvmpi->NotifyEvent = jvm_notify_event;
	return JNI_OK;
}
}
