static int CompileFromThunk(PluginRuntime *runtime, cell_t pcode_offs, void **addrp, char *pc) { // If the watchdog timer has declared a timeout, we must process it now, // and possibly refuse to compile, since otherwise we will compile a // function that is not patched for timeouts. if (!Environment::get()->watchdog()->HandleInterrupt()) return SP_ERROR_TIMEOUT; CompiledFunction *fn = runtime->GetJittedFunctionByOffset(pcode_offs); if (!fn) { int err; fn = CompileFunction(runtime, pcode_offs, &err); if (!fn) return err; } #if defined JIT_SPEW Environment::get()->debugger()->OnDebugSpew( "Patching thunk to %s::%s\n", runtime->plugin()->name, GetFunctionName(runtime->plugin(), pcode_offs)); #endif *addrp = fn->GetEntryAddress(); /* Right now, we always keep the code RWE */ *(intptr_t *)(pc - 4) = intptr_t(fn->GetEntryAddress()) - intptr_t(pc); return SP_ERROR_NONE; }
bool Compiler::emitCall() { cell_t offset = readCell(); // If this offset looks crappy, i.e. not aligned or out of bounds, we just // abort. if (offset % 4 != 0 || uint32_t(offset) >= rt_->code().length) { error_ = SP_ERROR_INSTRUCTION_PARAM; return false; } CompiledFunction *fun = rt_->GetJittedFunctionByOffset(offset); if (!fun) { // Need to emit a delayed thunk. CallThunk *thunk = new CallThunk(offset); __ call(&thunk->call); if (!thunks_.append(thunk)) return false; } else { // Function is already emitted, we can do a direct call. __ call(ExternalAddress(fun->GetEntryAddress())); } // Map the return address to the cip that started this call. emitCipMapping(op_cip_); return true; }
Value * CompiledFunction::code(Frame * frame) { CompiledFunction * function = NULL; frame->extract()(function); StringStreamT buffer; llvm::raw_os_ostream llvmBuffer(buffer); function->compiledValue(frame)->print(llvmBuffer); llvmBuffer.flush(); return new String(buffer.str()); }
cell_t FrameIterator::findCip() const { CompiledFunction *fn = runtime_->GetJittedFunctionByOffset(function_cip()); if (!fn) return 0; if (cip_ == kInvalidCip) { if (pc_) cip_ = fn->FindCipByPc(pc_); else cip_ = function_cip(); } return cip_; }
void Environment::UnpatchAllJumpsFromTimeout() { mutex_.AssertCurrentThreadOwns(); for (ke::InlineList<PluginRuntime>::iterator iter = runtimes_.begin(); iter != runtimes_.end(); iter++) { PluginRuntime *rt = *iter; for (size_t i = 0; i < rt->NumJitFunctions(); i++) { CompiledFunction *fun = rt->GetJitFunction(i); uint8_t *base = reinterpret_cast<uint8_t *>(fun->GetEntryAddress()); for (size_t j = 0; j < fun->NumLoopEdges(); j++) SwapLoopEdge(base, fun->GetLoopEdge(j)); } } }