blob: 4aa43af9bc18c2b06541ed51c1bb97c7984b8443 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Intel, Mikhail Y. Fursov
*
*/
#ifndef PLATFORM_POSIX
#include <crtdbg.h>
#endif
#include "Type.h"
#include "Jitrino.h"
#include "VMInterface.h"
#include "EMInterface.h"
#include "Log.h"
#include "PMF.h"
#include "CompilationContext.h"
#include "JITInstanceContext.h"
#include "RuntimeInterface.h"
#include "jit_export.h"
#include "jit_export_jpda.h"
#include "open/types.h"
#define LOG_DOMAIN "jitrino"
#include "cxxlog.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "port_threadunsafe.h"
#if !defined(_IPF_) // No .JET on IPF yet
#define USE_FAST_PATH
#endif
#ifdef USE_FAST_PATH
#include "../../jet/jet.h"
#endif
namespace Jitrino {
//
// exported DLL functions for the DRL VM
//
////////////////////////////////////////////////////////
// Optional functions that don't have to be provided.
////////////////////////////////////////////////////////
#ifdef USE_FAST_PATH
static bool isJET(JIT_Handle jit)
{
JITInstanceContext* jitContext = Jitrino::getJITInstanceContext(jit);
return jitContext->isJet();
}
#endif
// Called once at the end of the constructor.
extern "C"
JITEXPORT void
JIT_init(JIT_Handle jit, const char* name, vm_adaptor_t adaptor)
{
std::string initMessage = std::string("Initializing Jitrino.") + name + " -> ";
std::string mode = "OPT";
#ifdef USE_FAST_PATH
if (JITInstanceContext::isNameReservedForJet(name)) mode = "JET";
#endif
initMessage = initMessage + mode + " compiler mode";
INFO(initMessage.c_str());
VMInterface::setVmAdapter(adaptor);
Jitrino::Init(jit, name);
#ifdef USE_FAST_PATH
Jet::setup(jit, name);
#endif
}
// Called once at the end of the destructor.
extern "C"
JITEXPORT void
JIT_deinit(JIT_Handle jit)
{
#ifdef USE_FAST_PATH
Jet::cleanup();
#endif
Jitrino::DeInit(jit);
}
extern "C"
JITEXPORT void
JIT_next_command_line_argument(JIT_Handle jit, const char *name,
const char *arg)
{
#ifdef USE_FAST_PATH
Jet::cmd_line_arg(jit, name, arg);
#endif
}
extern "C"
JITEXPORT void
JIT_set_profile_access_interface(JIT_Handle jit, EM_Handle em,
EM_ProfileAccessInterface* pc_interface)
{
JITInstanceContext* jitContext = Jitrino::getJITInstanceContext(jit);
MemoryManager& mm = Jitrino::getGlobalMM();
ProfilingInterface* pi = new (mm) ProfilingInterface(em, jit, pc_interface);
jitContext->setProfilingInterface(pi);
}
//Optional
extern "C"
JITEXPORT bool
JIT_enable_profiling(JIT_Handle jit, PC_Handle pc, EM_JIT_PC_Role role)
{
JITInstanceContext* jitContext = Jitrino::getJITInstanceContext(jit);
ProfilingInterface* pi = jitContext->getProfilingInterface();
return pi->enableProfiling(pc, role == EM_JIT_PROFILE_ROLE_GEN ?
JITProfilingRole_GEN: JITProfilingRole_USE);
}
extern "C"
JITEXPORT void
JIT_profile_notification_callback(JIT_Handle jit, PC_Handle pc, Method_Handle mh)
{
JITInstanceContext* jitContext = Jitrino::getJITInstanceContext(jit);
if (jitContext->isJet()) {
#ifdef USE_FAST_PATH
Jet::rt_profile_notification_callback(jit, pc, mh);
#endif
} //opt does not support counters patching today.
}
// Called if JIT registered itself to be notified when the method is
// recompiled
// Returns TRUE if any code was modified and FALSE otherwise
extern "C"
JITEXPORT Boolean
JIT_recompiled_method_callback(JIT_Handle jit,
Method_Handle recompiled_method,
void *callback_data)
{
MethodDesc methodDesc(recompiled_method, NULL);
bool res = Jitrino::getRuntimeInterface()->recompiledMethodEvent(&methodDesc,callback_data);
return (res ? TRUE : FALSE);
}
////////////////////////////////////////////////////////
// Required functions.
////////////////////////////////////////////////////////
extern "C"
JITEXPORT JIT_Result
JIT_compile_method_with_params(JIT_Handle jit, Compile_Handle compilation,
Method_Handle method_handle,
OpenMethodExecutionParams compilation_params)
{
MemoryManager memManager("JIT_compile_method.memManager");
JITInstanceContext* jitContext = Jitrino::getJITInstanceContext(jit);
assert(jitContext!= NULL);
TypeManager typeManager(memManager); typeManager.init();
CompilationInterface compilationInterface(compilation, method_handle, jit,
memManager, compilation_params, NULL, typeManager);
CompilationContext cs(memManager, &compilationInterface, jitContext);
compilationInterface.setCompilationContext(&cs);
static int method_seqnb = 0;
UNSAFE_REGION_START
// Non-atomic increment of compiled method counter,
// may affect accuracy of JIT logging but don't affect JIT functionality
int current_nb = method_seqnb++;
UNSAFE_REGION_END
MethodDesc* md = compilationInterface.getMethodToCompile();
const char* methodTypeName = md->getParentType()->getName();
const char* methodName = md->getName();
const char* methodSig = md->getSignatureString();
PMF::Pipeline* pipep = jitContext->getPMF().selectPipeline(methodTypeName, methodName, methodSig);
cs.setPipeline((HPipeline*)pipep);
LogStreams::current(jitContext).beginMethod(methodTypeName, methodName, methodSig, method_seqnb);
Str pipename = pipep->getName();
LogStream& info = LogStream::log(LogStream::INFO, (HPipeline*)pipep);
if (info.isEnabled()) {
info << "<" << current_nb << "\t"
<< jitContext->getJITName() << "." << pipename
<< "\tstart "
<< methodTypeName << "." << methodName << methodSig
<< "\tbyte code size=" << md->getByteCodeSize()
<< std::endl;
}
#ifdef _DEBUG
Jitrino::incCompilationRecursionLevel();
#endif
JIT_Result result;
#ifdef USE_FAST_PATH
if (isJET(jit))
result = Jet::compile_with_params(jit, compilation, method_handle,
compilation_params);
else
#endif // USE_FAST_PATH
result = Jitrino::CompileMethod(&cs) ? JIT_SUCCESS : JIT_FAILURE;
#ifdef _DEBUG
Jitrino::decCompilationRecursionLevel();
#endif
if (info.isEnabled()) {
info << current_nb << ">\t"
<< jitContext->getJITName() << "." << pipename
<< "\t end ";
//<< methodTypeName << "." << methodName << methodSig;
if (result == JIT_SUCCESS) {
unsigned size = md->getCodeBlockSize(0);
U_8* start = size ? md->getCodeBlockAddress(0) : 0;
info << "\tnative code size=" << size
<< " code range=[" << (void*)start << "," << (void*)(start+size) << "]";
}
else
info << "\tFAILURE";
info << std::endl;
}
LogStreams::current(jitContext).endMethod();
return result;
}
extern "C"
JITEXPORT OpenMethodExecutionParams JIT_get_exe_capabilities (JIT_Handle jit)
{
#ifdef USE_FAST_PATH
if (isJET(jit)) {
return Jet::get_exe_capabilities();
}
#endif // USE_FAST_PATH
static const OpenMethodExecutionParams compilation_capabilities = {
false, // exe_notify_method_entry
false, // exe_notify_method_exit
false, // exe_notify_field_access
false, // exe_notify_field_modification
false, // exe_notify_exception_throw
false, // exe_notify_exception_catch
false, // exe_notify_monitor_enter
false, // exe_notify_monitor_exit
false, // exe_notify_contended_monitor_enter
false, // exe_notify_contended_monitor_exit
false, // exe_do_method_inlining
false, // exe_do_code_mapping
false, // exe_do_local_var_mapping
false, // exe_insert_write_barriers
false, // exe_provide_access_to_this
false, // exe_restore_context_after_unwind
false, // exe_notify_compiled_method_load
};
return compilation_capabilities;
}
extern "C"
JITEXPORT void
JIT_unwind_stack_frame(JIT_Handle jit, Method_Handle method,
::JitFrameContext *context)
{
#ifdef _DEBUG
if(Log::cat_rt()->isEnabled())
Log::cat_rt()->out() << "UNWIND_STACK_FRAME(" << method << ")" << ::std::endl;
#endif
#ifdef USE_FAST_PATH
if (isJET(jit)) {
Jet::rt_unwind(jit, method, context);
return;
}
#endif
MethodDesc methodDesc(method, jit);
Jitrino::getRuntimeInterface()->unwindStack(&methodDesc, context, context->is_ip_past == FALSE);
}
extern "C"
JITEXPORT void
JIT_get_root_set_from_stack_frame(JIT_Handle jit, Method_Handle method,
GC_Enumeration_Handle enum_handle,
::JitFrameContext *context)
{
#ifdef _DEBUG
if(Log::cat_rt()->isEnabled())
Log::cat_rt()->out() << "GET_ROOT_SET_FROM_STACK_FRAME(" << method << ")" << ::std::endl;
#endif
#ifdef USE_FAST_PATH
if (isJET(jit)) {
Jet::rt_enum(jit, method, enum_handle, context);
return;
}
#endif
MethodDesc methodDesc(method, jit);
GCInterface gcInterface(enum_handle);
Jitrino::getRuntimeInterface()->getGCRootSet(&methodDesc, &gcInterface, context,
context->is_ip_past == FALSE);
}
extern "C"
JITEXPORT U_32
JIT_get_inline_depth(JIT_Handle jit, InlineInfoPtr ptr, U_32 offset)
{
if (Log::cat_rt()->isEnabled()) {
Log::cat_rt()->out() << "GET_INLINE_DEPTH()" << ::std::endl;
}
return Jitrino::getRuntimeInterface()->getInlineDepth(ptr, offset);
}
extern "C"
JITEXPORT Method_Handle
JIT_get_inlined_method(JIT_Handle jit, InlineInfoPtr ptr, U_32 offset,
U_32 inline_depth)
{
if (Log::cat_rt()->isEnabled()) {
Log::cat_rt()->out() << "GET_INLINED_METHOD()" << ::std::endl;
}
if (0 == inline_depth) {
assert(0 && "misused inline_depth, must be [1..max_depth]");
return 0;
}
return Jitrino::getRuntimeInterface()->getInlinedMethod(ptr, offset, inline_depth);
}
extern "C"
JITEXPORT uint16
JIT_get_inlined_bc(JIT_Handle jit, InlineInfoPtr ptr, U_32 offset, U_32 inline_depth)
{
if (Log::cat_rt()->isEnabled()) {
Log::cat_rt()->out() << "GET_INLINED_BC()" << ::std::endl;
}
if (0 == inline_depth) {
assert(0 && "misused inline_depth, must be [1..max_depth]");
return 0;
}
return Jitrino::getRuntimeInterface()->getInlinedBc(ptr, offset, inline_depth);
}
extern "C"
JITEXPORT void
JIT_fix_handler_context(JIT_Handle jit, Method_Handle method,
::JitFrameContext *context)
{
#ifdef _DEBUG
if(Log::cat_rt()->isEnabled())
Log::cat_rt()->out() << "FIX_HANDLER_CONTEXT(" << method << ")" << ::std::endl;
#endif
#ifdef USE_FAST_PATH
if (isJET(jit)) {
Jet::rt_fix_handler_context(jit, method, context);
return;
}
#endif
MethodDesc methodDesc(method, jit);
Jitrino::getRuntimeInterface()->fixHandlerContext(&methodDesc, context,
context->is_ip_past == FALSE);
}
extern "C"
JITEXPORT Boolean
JIT_is_soe_area
(JIT_Handle jit, Method_Handle method,
const ::JitFrameContext *context)
{
#ifdef USE_FAST_PATH
if (isJET(jit)) {
return Jet::rt_is_soe_area(jit, method, context);
}
#endif
MethodDesc methodDesc(method, jit);
return Jitrino::getRuntimeInterface()->isSOEArea(&methodDesc, context, context->is_ip_past == FALSE);
}
extern "C"
JITEXPORT void *
JIT_get_address_of_this(JIT_Handle jit, Method_Handle method,
const ::JitFrameContext *context)
{
#ifdef USE_FAST_PATH
if (isJET(jit)) {
return Jet::rt_get_address_of_this(jit, method, context);
}
#endif
MethodDesc methodDesc(method, jit);
return Jitrino::getRuntimeInterface()->getAddressOfThis(&methodDesc, context,
context->is_ip_past == FALSE);
}
extern "C"
JITEXPORT Boolean
JIT_supports_compressed_references(JIT_Handle jit)
{
#ifdef _EM64T_
return true;
#else
return false;
#endif
}
extern "C"
JITEXPORT void
JIT_get_root_set_for_thread_dump(JIT_Handle jit, Method_Handle method,
GC_Enumeration_Handle enum_handle,
::JitFrameContext *context)
{
if(Log::cat_rt()->isEnabled()) {
Log::cat_rt()->out() << "GET_ROOT_SET_FROM_STACK_FRAME(" << method << ")" << ::std::endl;
}
MethodDesc methodDesc(method, jit);
ThreadDumpEnumerator gcInterface;
Jitrino::getRuntimeInterface()->getGCRootSet(&methodDesc, &gcInterface, context,
context->is_ip_past == FALSE);
}
////////////////////////////////////////////////////////
// JVMTI support functions.
////////////////////////////////////////////////////////
extern "C"
JITEXPORT OpenExeJpdaError
get_native_location_for_bc(JIT_Handle jit, Method_Handle method,
uint16 bc_pc, NativeCodePtr *native_pc)
{
#ifdef USE_FAST_PATH
if (isJET(jit)) {
Jet::rt_bc2native(jit, method, bc_pc, native_pc);
return EXE_ERROR_NONE;
}
#endif
MethodDesc methDesc(method, jit);
POINTER_SIZE_INT* ncAddr = (POINTER_SIZE_INT*) native_pc;
if (Jitrino::getRuntimeInterface()->getNativeLocationForBc(&methDesc, bc_pc, ncAddr)) {
return EXE_ERROR_NONE;
}
return EXE_ERROR_UNSUPPORTED;
}
extern "C"
JITEXPORT OpenExeJpdaError
get_bc_location_for_native(JIT_Handle jit, Method_Handle method,
NativeCodePtr native_pc, uint16 *bc_pc)
{
#ifdef USE_FAST_PATH
if (isJET(jit)) {
Jet::rt_native2bc(jit, method, native_pc, bc_pc);
return EXE_ERROR_NONE;
}
#endif
MethodDesc methDesc(method, jit);
POINTER_SIZE_INT ncAddr = (POINTER_SIZE_INT) native_pc;
if (Jitrino::getRuntimeInterface()->getBcLocationForNative(&methDesc, ncAddr, bc_pc)) {
return EXE_ERROR_NONE;
}
return EXE_ERROR_INVALID_LOCATION;
}
extern "C"
JITEXPORT ::OpenExeJpdaError
get_local_var(JIT_Handle jit, Method_Handle method,
const ::JitFrameContext *context, uint16 var_num,
VM_Data_Type var_type, void *value_ptr)
{
#ifdef USE_FAST_PATH
if (isJET(jit)) {
return Jet::rt_get_local_var(jit, method, context, var_num, var_type,
value_ptr);
}
#endif
return EXE_ERROR_UNSUPPORTED;
}
extern "C"
JITEXPORT ::OpenExeJpdaError
set_local_var(JIT_Handle jit, Method_Handle method,
const ::JitFrameContext *context, uint16 var_num,
VM_Data_Type var_type, void *value_ptr)
{
#ifdef USE_FAST_PATH
if (isJET(jit)) {
return Jet::rt_set_local_var(jit, method, context, var_num, var_type,
value_ptr);
}
#endif
return EXE_ERROR_UNSUPPORTED;
}
} //namespace Jitrino