blob: f8fad2d728f928e875d50e9419ae59b684c92179 [file] [log] [blame]
#ifdef SERVICE
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/Target/TargetJITInfo.h"
#include "../lib/ExecutionEngine/JIT/JIT.h"
#include "JavaThread.h"
#include "JavaJIT.h"
#include "Jnjvm.h"
#include "mvm/VirtualMachine.h"
#include "mvm/Threads/Cond.h"
#include "mvm/Threads/Locks.h"
#include "mvm/JIT.h"
#include "signal.h"
#include "execinfo.h"
using namespace jnjvm;
static void* StackTrace[256];
// PrintStackTrace - In the case of a program crash or fault, print out a stack
// trace so that the user has an indication of why and where we died.
//
// On glibc systems we have the 'backtrace' function, which works nicely, but
// doesn't demangle symbols.
static void PrintStackTrace() {
// Use backtrace() to output a backtrace on Linux systems with glibc.
int depth = backtrace(StackTrace, 256);
backtrace_symbols_fd(StackTrace, depth, STDERR_FILENO);
}
static void throwStoppedBundleException() {
void** addr = (void**)__builtin_frame_address(0);
fprintf(stderr, "in stopped %p\n", addr);
JavaJIT::printBacktrace();
PrintStackTrace();
fprintf(stderr, "OK\n");
JavaThread* th = JavaThread::get();
th->throwException(th->ServiceException);
}
static JnjvmClassLoader* stoppedBundle;
static mvm::LockNormal lock;
static mvm::Cond cond;
static mvm::Thread* initiator;
#if defined(__MACH__) && !defined(__i386__)
#define FRAME_IP(fp) (fp[2])
#else
#define FRAME_IP(fp) (fp[1])
#endif
void terminationHandler(int) {
void** addr = (void**)__builtin_frame_address(0);
void* baseSP = mvm::Thread::get()->baseSP;
while (addr && addr < baseSP && addr < addr[0]) {
addr = (void**)addr[0];
void** ptr = (void**)FRAME_IP(addr);
JavaMethod* meth = JavaJIT::IPToJavaMethod(ptr);
if (meth) {
if (meth->classDef->classLoader == stoppedBundle) {
fprintf(stderr, "Je change %p!\n", FRAME_IP(addr));
JavaJIT::printBacktrace();
FRAME_IP(addr) = (void**)(uintptr_t)throwStoppedBundleException;
}
}
}
addr = (void**)__builtin_frame_address(0);
while (addr && addr < baseSP && addr < addr[0]) {
addr = (void**)addr[0];
void** ptr = (void**)FRAME_IP(addr);
JavaMethod* meth = JavaJIT::IPToJavaMethod(ptr);
if (meth) {
if (meth->classDef->classLoader != stoppedBundle) {
JavaThread* th = JavaThread::get();
th->lock.lock();
th->interruptFlag = 1;
// here we could also raise a signal for interrupting I/O
if (th->state == JavaThread::StateWaiting) {
th->state = JavaThread::StateInterrupted;
th->varcond.signal();
}
th->lock.unlock();
}
break;
}
}
if (mvm::Thread::get() != initiator) {
lock.lock();
while (stoppedBundle)
cond.wait(&lock);
lock.unlock();
} else {
fprintf(stderr, "Je suis l'initiateur, je quitte\n");
}
}
void Jnjvm::stopService() {
JnjvmClassLoader* bundle = (JnjvmClassLoader*)CU;
bundle->getIsolate()->status = 1;
stoppedBundle = bundle;
mvm::Thread* th = mvm::Thread::get();
th->MyVM->memoryLimit = ~0;
initiator = th;
fprintf(stderr, "I am %p\n", th);
for(mvm::Thread* cur = (mvm::Thread*)th->next(); cur != th;
cur = (mvm::Thread*)cur->next()) {
mvm::VirtualMachine* executingVM = cur->MyVM;
assert(executingVM && "Thread with no VM!");
fprintf(stderr, "Killing th %p\n", cur);
uint32 res = cur->kill(SIGUSR1);
assert(res == 0);
}
fprintf(stderr, "Doing it\n");
// I have to do it too!
terminationHandler(0);
fprintf(stderr, "OK! bon ben moi je m'en vais\n");
/*
llvm::TargetJITInfo& TJI = ((llvm::JIT*)mvm::MvmModule::executionEngine)->getJITInfo();
for (ClassMap::iterator i = bundle->getClasses()->map.begin(), e = bundle->getClasses()->map.end();
i!= e; ++i) {
Class* cl = i->second->asClass();
if (cl) {
for (uint32 i = 0; i < cl->nbVirtualMethods; ++i) {
if (cl->virtualMethods[i].code) {
TJI.replaceMachineCodeForFunction(cl->virtualMethods[i].code, (void*)(uintptr_t)throwStoppedBundleException);
}
}
for (uint32 i = 0; i < cl->nbStaticMethods; ++i) {
if (cl->staticMethods[i].code) {
TJI.replaceMachineCodeForFunction(cl->staticMethods[i].code, (void*)(uintptr_t)throwStoppedBundleException);
}
}
}
}
stoppedBundle = 0;
cond.broadcast();*/
}
#endif