blob: 9cd3143893eb581e1f2d42b0b137c4d82ae8d935 [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
*
*/
#include "Jitrino.h"
#include "irmanager.h"
#include "FlowGraph.h"
#include "Log.h"
#include "CountWriters.h"
#include "XTimer.h"
#include "VMInterface.h"
#ifdef _WIN32
#pragma pack(push)
#include <windows.h>
#define vsnprintf _vsnprintf
#pragma pack(pop)
#else
#include <stdarg.h>
#include <sys/stat.h>
#include <sys/types.h>
#endif
#include "PlatformDependant.h"
#include "JITInstanceContext.h"
#include "PMF.h"
#include "PMFAction.h"
#include "RuntimeInterface_arch.h"
#include <ostream>
namespace Jitrino {
// the JIT runtime interface
RuntimeInterface* Jitrino::runtimeInterface = NULL;
JITInstances* Jitrino::jitInstances = NULL;
struct Jitrino::Flags Jitrino::flags;
static TlsKey recursionKey = 0;
// some demo parameters
bool print_hashtable_info = false;
char which_char = 'a';
// read in some flags to test mechanism
bool initialized_parameters = false;
void initialize_parameters(CompilationContext* compilationContext, MethodDesc &md)
{
// BCMap Info Required
compilationContext->getVMCompilationInterface()->setBCMapInfoRequired(true);
// do onetime things
if (!initialized_parameters) {
initialized_parameters = true;
}
}
MemoryManager* Jitrino::global_mm = 0;
static CountWriter* countWriter = 0;
static CountTime globalTimer("total-compilation time");
static SummTimes summtimes("action times");
void Jitrino::crash (const char* msg)
{
std::cerr << std::endl << "Jitrino crashed" << std::endl;
if (msg != 0)
std::cerr << msg << std::endl;
exit(11);
}
void crash (const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
char buff[1024];
vsnprintf(buff, sizeof(buff), fmt, args);
std::cerr << buff;
exit(11);
}
bool Jitrino::Init(JIT_Handle jh, const char* name)
{
//check for duplicate initialization
JITInstanceContext* jitInstance = getJITInstanceContext(jh);
if (jitInstance!=NULL) {
assert(0);
return false;
}
// check if jitName is already in use
if (jitInstances) {
for (JITInstances::const_iterator it = jitInstances->begin(), end = jitInstances->end(); it!=end; ++it) {
JITInstanceContext* jitContext = *it;
if (jitContext->getJITName() == name) {
assert(0);
return false;
}
}
}else {
global_mm = new MemoryManager("Jitrino::Init.global_mm");
#if defined(_IPF_)
runtimeInterface = new IPF::RuntimeInterface;
flags.codegen = CG_IPF;
#else
runtimeInterface = new Ia32::RuntimeInterface;
flags.codegen = CG_IA32;
#endif
jitInstances = new (*global_mm) JITInstances(*global_mm);
flags.time=false;
recursionKey = Tls::allocKey();
}
jitInstance = new (*global_mm) JITInstanceContext(*global_mm, jh, name);
jitInstances->push_back(jitInstance);
jitInstance->getPMF().init(jitInstances->size() == 1);
if (countWriter == 0 && jitInstance->getPMF().getBoolArg(0, "time", false)) {
countWriter = new CountWriterFile(0);
XTimer::initialize(true);
}
return true;
}
void Jitrino::DeInit(JIT_Handle jh)
{
JITInstanceContext* jitInstance = getJITInstanceContext(jh);
if (jitInstance==NULL) {
assert(0);
return;
}
if (countWriter != 0) {
jitInstance->getPMF().summTimes(summtimes);
}
jitInstance->getPMF().deinit();
killJITInstanceContext(jitInstance);
if (jitInstances->empty()) {
if (countWriter != 0) {
delete countWriter;
countWriter = 0;
}
}
}
class FalseSessionAction: public SessionAction {
public:
virtual void run () {getCompilationContext()->setCompilationFailed(true);}
};
static ActionFactory<FalseSessionAction> _false("false");
class LockMethodSessionAction : public SessionAction {
public:
virtual void run () {
CompilationContext* cc = getCompilationContext();
CompilationInterface* ci = cc->getVMCompilationInterface();
ci->lockMethodData();
MethodDesc* methDesc = ci->getMethodToCompile();
if (methDesc->getCodeBlockSize(0) > 0 || methDesc->getCodeBlockSize(1) > 0){
cc->setCompilationFinished(true);
ci->unlockMethodData();
}
}
};
static ActionFactory<LockMethodSessionAction> _lock_method("lock_method");
class UnlockMethodSessionAction : public SessionAction {
public:
virtual void run () {
getCompilationContext()->getVMCompilationInterface()->unlockMethodData();
}
};
static ActionFactory<UnlockMethodSessionAction> _unlock_method("unlock_method");
void runPipeline(CompilationContext* c) {
globalTimer.start();
PMF::PipelineIterator pit((PMF::Pipeline*)c->getPipeline());
while (pit.next()) {
SessionAction* sa = pit.getSessionAction();
sa->setCompilationContext(c);
c->setCurrentSessionAction(sa);
c->stageId++;
sa->start();
sa->run();
sa->stop();
c->setCurrentSessionAction(0);
if (c->isCompilationFailed() || c->isCompilationFinished()) {
break;
}
}
globalTimer.stop();
}
bool compileMethod(CompilationContext* cc) {
if(Jitrino::flags.skip) {
return false;
}
runPipeline(cc);
bool success = !cc->isCompilationFailed();
return success;
}
bool Jitrino::CompileMethod(CompilationContext* cc) {
CompilationInterface* compilationInterface = cc->getVMCompilationInterface();
bool success = false;
MethodDesc& methodDesc = *compilationInterface->getMethodToCompile();
initialize_parameters(cc, methodDesc);
if (methodDesc.getByteCodeSize() <= 0) {
Log::out() << " ... Skipping because of 0 byte codes ..." << ::std::endl;
assert(0);
} else {
success = compileMethod(cc);
}
return success;
}
JITInstanceContext* Jitrino::getJITInstanceContext(JIT_Handle jitHandle) {
if (jitInstances)
for (JITInstances::const_iterator it = jitInstances->begin(), end = jitInstances->end(); it!=end; ++it) {
JITInstanceContext* jit= *it;
if (jit->getJitHandle() == jitHandle) {
return jit;
}
}
return NULL;
}
void Jitrino::killJITInstanceContext(JITInstanceContext* jit) {
for (JITInstances::iterator it = jitInstances->begin(), end = jitInstances->end(); it!=end; ++it) {
if (*it == jit) {
jitInstances->erase(it);
return;
}
}
}
int Jitrino::getCompilationRecursionLevel() {
return (int)(POINTER_SIZE_INT)Tls::get(recursionKey);
}
void Jitrino::incCompilationRecursionLevel() {
int recursion = (int)(POINTER_SIZE_INT)Tls::get(recursionKey);
Tls::put(recursionKey, (void*)(POINTER_SIZE_INT)(recursion+1));
}
void Jitrino::decCompilationRecursionLevel() {
int recursion = (int)(POINTER_SIZE_INT)Tls::get(recursionKey);
Tls::put(recursionKey, (void*)(POINTER_SIZE_INT)(recursion-1));
}
} //namespace Jitrino
/*--------------------------------------------------------------------
* DllMain definition (Windows only) - DLL entry point function which
* is called whenever a new thread/process which executes the DLL code
* is started/terminated.
* Currently it is used to notify log system only.
*--------------------------------------------------------------------
*/
#if defined(_WIN32) || defined(_WIN64)
extern "C" bool __stdcall DllMain(void *dll_handle, U_32 reason, void *reserved) {
switch (reason) {
case DLL_PROCESS_ATTACH:
// allocate a TLS index.
// fall through, the new process creates a new thread
case DLL_THREAD_ATTACH:
// notify interested parties (only one now)
break;
case DLL_THREAD_DETACH:
// notify interested parties (only one now)
Jitrino::Tls::threadDetach();
break;
case DLL_PROCESS_DETACH:
// notify interested parties (only one now)
// release the TLS index
Jitrino::Tls::threadDetach();
break;
default:
break;
}
return TRUE;
}
#endif // defined(_WIN32) || defined(_WIN64)