Factor code stubs out of JITX86.
This commit is contained in:
parent
21f5400d9c
commit
111dd7eb68
@ -31,6 +31,7 @@ library = setup(builder.compiler.StaticLibrary('sourcepawn'))
|
||||
library.sources += [
|
||||
'api.cpp',
|
||||
'code-allocator.cpp',
|
||||
'code-stubs.cpp',
|
||||
'plugin-runtime.cpp',
|
||||
'compiled-function.cpp',
|
||||
'debug-trace.cpp',
|
||||
@ -40,7 +41,9 @@ library.sources += [
|
||||
'opcodes.cpp',
|
||||
'interpreter.cpp',
|
||||
'watchdog_timer.cpp',
|
||||
'x86/code-stubs-x86.cpp',
|
||||
'x86/jit_x86.cpp',
|
||||
'x86/x86-utils.cpp',
|
||||
'zlib/adler32.c',
|
||||
'zlib/compress.c',
|
||||
'zlib/crc32.c',
|
||||
|
@ -33,6 +33,7 @@
|
||||
#endif
|
||||
|
||||
#include <sourcemod_version.h>
|
||||
#include "code-stubs.h"
|
||||
|
||||
using namespace sp;
|
||||
using namespace SourcePawn;
|
||||
@ -298,13 +299,13 @@ return_error:
|
||||
SPVM_NATIVE_FUNC
|
||||
SourcePawnEngine2::CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData)
|
||||
{
|
||||
return g_Jit.CreateFakeNative(callback, pData);
|
||||
return Environment::get()->stubs()->CreateFakeNativeStub(callback, pData);
|
||||
}
|
||||
|
||||
void
|
||||
SourcePawnEngine2::DestroyFakeNative(SPVM_NATIVE_FUNC func)
|
||||
{
|
||||
g_Jit.DestroyFakeNative(func);
|
||||
return Environment::get()->FreeCode((void *)func);
|
||||
}
|
||||
|
||||
const char *
|
||||
|
41
sourcepawn/jit/code-stubs.cpp
Normal file
41
sourcepawn/jit/code-stubs.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
// vim: set sts=2 ts=8 sw=2 tw=99 et:
|
||||
//
|
||||
// Copyright (C) 2006-2015 AlliedModders LLC
|
||||
//
|
||||
// This file is part of SourcePawn. SourcePawn is free software: you can
|
||||
// redistribute it and/or modify it under the terms of the GNU General Public
|
||||
// License as published by the Free Software Foundation, either version 3 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// SourcePawn. If not, see http://www.gnu.org/licenses/.
|
||||
//
|
||||
#include "code-stubs.h"
|
||||
#include "environment.h"
|
||||
|
||||
using namespace sp;
|
||||
|
||||
CodeStubs::CodeStubs(Environment *env)
|
||||
: env_(env),
|
||||
invoke_stub_(nullptr),
|
||||
return_stub_(nullptr),
|
||||
timeout_stub_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
CodeStubs::Initialize()
|
||||
{
|
||||
if (!InitializeFeatureDetection())
|
||||
return false;
|
||||
if (!CompileInvokeStub())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CodeStubs::Shutdown()
|
||||
{
|
||||
if (invoke_stub_)
|
||||
env_->FreeCode(invoke_stub_);
|
||||
}
|
61
sourcepawn/jit/code-stubs.h
Normal file
61
sourcepawn/jit/code-stubs.h
Normal file
@ -0,0 +1,61 @@
|
||||
// vim: set sts=2 ts=8 sw=2 tw=99 et:
|
||||
//
|
||||
// Copyright (C) 2006-2015 AlliedModders LLC
|
||||
//
|
||||
// This file is part of SourcePawn. SourcePawn is free software: you can
|
||||
// redistribute it and/or modify it under the terms of the GNU General Public
|
||||
// License as published by the Free Software Foundation, either version 3 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// SourcePawn. If not, see http://www.gnu.org/licenses/.
|
||||
//
|
||||
#ifndef _include_sourcepawn_vm_code_stubs_h_
|
||||
#define _include_sourcepawn_vm_code_stubs_h_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sp_vm_api.h>
|
||||
|
||||
typedef struct sp_context_s sp_context_t;
|
||||
|
||||
namespace sp {
|
||||
|
||||
class Environment;
|
||||
|
||||
typedef int (*InvokeStubFn)(sp_context_t *ctx, uint8_t *memory, void *code);
|
||||
|
||||
class CodeStubs
|
||||
{
|
||||
public:
|
||||
CodeStubs(Environment *env);
|
||||
|
||||
public:
|
||||
bool Initialize();
|
||||
void Shutdown();
|
||||
|
||||
SPVM_NATIVE_FUNC CreateFakeNativeStub(SPVM_FAKENATIVE_FUNC callback, void *userData);
|
||||
|
||||
InvokeStubFn InvokeStub() const {
|
||||
return (InvokeStubFn)invoke_stub_;
|
||||
}
|
||||
void *ReturnStub() const {
|
||||
return return_stub_;
|
||||
}
|
||||
void *TimeoutStub() const {
|
||||
return return_stub_;
|
||||
}
|
||||
|
||||
private:
|
||||
bool InitializeFeatureDetection();
|
||||
bool CompileInvokeStub();
|
||||
|
||||
private:
|
||||
Environment *env_;
|
||||
void *invoke_stub_;
|
||||
void *return_stub_; // Owned by invoke_stub_.
|
||||
void *timeout_stub_; // Owned by invoke_stub_.
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // _include_sourcepawn_vm_code_stubs_h_
|
@ -15,6 +15,7 @@
|
||||
#include "watchdog_timer.h"
|
||||
#include "debug-trace.h"
|
||||
#include "api.h"
|
||||
#include "code-stubs.h"
|
||||
#include "watchdog_timer.h"
|
||||
|
||||
using namespace sp;
|
||||
@ -63,13 +64,14 @@ Environment::Initialize()
|
||||
{
|
||||
api_v1_ = new SourcePawnEngine();
|
||||
api_v2_ = new SourcePawnEngine2();
|
||||
code_stubs_ = new CodeStubs(this);
|
||||
watchdog_timer_ = new WatchdogTimer(this);
|
||||
|
||||
if ((code_pool_ = Knight::KE_CreateCodeCache()) == nullptr)
|
||||
return false;
|
||||
|
||||
// Safe to initialize JIT now that we have the code cache.
|
||||
if (!g_Jit.InitializeJIT())
|
||||
// Safe to initialize code now that we have the code cache.
|
||||
if (!code_stubs_->Initialize())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -79,7 +81,7 @@ void
|
||||
Environment::Shutdown()
|
||||
{
|
||||
watchdog_timer_->Shutdown();
|
||||
g_Jit.ShutdownJIT();
|
||||
code_stubs_->Shutdown();
|
||||
Knight::KE_DestroyCodeCache(code_pool_);
|
||||
|
||||
assert(sEnvironment == this);
|
||||
@ -208,7 +210,7 @@ Environment::PatchAllJumpsForTimeout()
|
||||
|
||||
for (size_t j = 0; j < fun->NumLoopEdges(); j++) {
|
||||
const LoopEdge &e = fun->GetLoopEdge(j);
|
||||
int32_t diff = intptr_t(g_Jit.TimeoutStub()) - intptr_t(base + e.offset);
|
||||
int32_t diff = intptr_t(code_stubs_->TimeoutStub()) - intptr_t(base + e.offset);
|
||||
*reinterpret_cast<int32_t *>(base + e.offset - 4) = diff;
|
||||
}
|
||||
}
|
||||
@ -232,3 +234,21 @@ Environment::UnpatchAllJumpsFromTimeout()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
Environment::Invoke(PluginRuntime *runtime, CompiledFunction *fn, cell_t *result)
|
||||
{
|
||||
sp_context_t *ctx = runtime->GetBaseContext()->GetCtx();
|
||||
|
||||
// Note that cip, hp, sp are saved and restored by Execute2().
|
||||
ctx->cip = fn->GetCodeOffset();
|
||||
|
||||
InvokeStubFn invoke = code_stubs_->InvokeStub();
|
||||
|
||||
EnterInvoke();
|
||||
int err = invoke(ctx, runtime->plugin()->memory, fn->GetEntryAddress());
|
||||
LeaveInvoke();
|
||||
|
||||
*result = ctx->rval;
|
||||
return err;
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ namespace sp {
|
||||
|
||||
using namespace SourcePawn;
|
||||
|
||||
class CodeStubs;
|
||||
class WatchdogTimer;
|
||||
|
||||
// An Environment encapsulates everything that's needed to load and run
|
||||
@ -61,6 +62,9 @@ class Environment : public ISourcePawnEnvironment
|
||||
// Allocate and free executable memory.
|
||||
void *AllocateCode(size_t size);
|
||||
void FreeCode(void *code);
|
||||
CodeStubs *stubs() {
|
||||
return code_stubs_;
|
||||
}
|
||||
|
||||
// Runtime management.
|
||||
void RegisterRuntime(PluginRuntime *rt);
|
||||
@ -70,6 +74,7 @@ class Environment : public ISourcePawnEnvironment
|
||||
ke::Mutex *lock() {
|
||||
return &mutex_;
|
||||
}
|
||||
int Invoke(PluginRuntime *runtime, CompiledFunction *fn, cell_t *result);
|
||||
|
||||
// Helpers.
|
||||
void SetProfiler(IProfilingTool *profiler) {
|
||||
@ -135,6 +140,8 @@ class Environment : public ISourcePawnEnvironment
|
||||
|
||||
uintptr_t frame_id_;
|
||||
uintptr_t invoke_depth_;
|
||||
|
||||
ke::AutoPtr<CodeStubs> code_stubs_;
|
||||
};
|
||||
|
||||
class EnterProfileScope
|
||||
|
@ -603,10 +603,10 @@ BaseContext::Execute2(IPluginFunction *function, const cell_t *params, unsigned
|
||||
m_CustomMsg = false;
|
||||
m_InExec = true;
|
||||
|
||||
/* Start the frame tracer */
|
||||
|
||||
if (Environment::get()->IsJitEnabled())
|
||||
ir = g_Jit.InvokeFunction(m_pRuntime, fn, result);
|
||||
// Enter the execution engine.
|
||||
Environment *env = Environment::get();
|
||||
if (env->IsJitEnabled())
|
||||
ir = env->Invoke(m_pRuntime, fn, result);
|
||||
else
|
||||
ir = Interpret(m_pRuntime, cfun->Public()->code_offs, result);
|
||||
|
||||
|
135
sourcepawn/jit/x86/code-stubs-x86.cpp
Normal file
135
sourcepawn/jit/x86/code-stubs-x86.cpp
Normal file
@ -0,0 +1,135 @@
|
||||
// vim: set sts=2 ts=8 sw=2 tw=99 et:
|
||||
//
|
||||
// Copyright (C) 2006-2015 AlliedModders LLC
|
||||
//
|
||||
// This file is part of SourcePawn. SourcePawn is free software: you can
|
||||
// redistribute it and/or modify it under the terms of the GNU General Public
|
||||
// License as published by the Free Software Foundation, either version 3 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// SourcePawn. If not, see http://www.gnu.org/licenses/.
|
||||
//
|
||||
#include <sp_vm_api.h>
|
||||
#include "code-stubs.h"
|
||||
#include "x86-utils.h"
|
||||
#include "jit_shared.h"
|
||||
#include "jit_x86.h"
|
||||
|
||||
using namespace sp;
|
||||
using namespace SourcePawn;
|
||||
|
||||
#define __ masm.
|
||||
|
||||
bool
|
||||
CodeStubs::InitializeFeatureDetection()
|
||||
{
|
||||
MacroAssemblerX86 masm;
|
||||
MacroAssemblerX86::GenerateFeatureDetection(masm);
|
||||
void *code = LinkCode(env_, masm);
|
||||
if (!code)
|
||||
return false;
|
||||
MacroAssemblerX86::RunFeatureDetection(code);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
CodeStubs::CompileInvokeStub()
|
||||
{
|
||||
AssemblerX86 masm;
|
||||
|
||||
__ push(ebp);
|
||||
__ movl(ebp, esp);
|
||||
|
||||
__ push(esi); // ebp - 4
|
||||
__ push(edi); // ebp - 8
|
||||
__ push(ebx); // ebp - 12
|
||||
__ push(esp); // ebp - 16
|
||||
|
||||
__ movl(ebx, Operand(ebp, 8 + 4 * 0));
|
||||
__ movl(eax, Operand(ebp, 8 + 4 * 1));
|
||||
__ movl(ecx, Operand(ebp, 8 + 4 * 2));
|
||||
|
||||
// Set up run-time registers.
|
||||
__ movl(edi, Operand(ebx, offsetof(sp_context_t, sp)));
|
||||
__ addl(edi, eax);
|
||||
__ movl(esi, eax);
|
||||
__ movl(ebx, edi);
|
||||
|
||||
// Align the stack.
|
||||
__ andl(esp, 0xfffffff0);
|
||||
|
||||
// Call into plugin (align the stack first).
|
||||
__ call(ecx);
|
||||
|
||||
// Get input context, store rval.
|
||||
__ movl(ecx, Operand(ebp, 8 + 4 * 0));
|
||||
__ movl(Operand(ecx, offsetof(sp_context_t, rval)), pri);
|
||||
|
||||
// Set no error.
|
||||
__ movl(eax, SP_ERROR_NONE);
|
||||
|
||||
// Store latest stk. If we have an error code, we'll jump directly to here,
|
||||
// so eax will already be set.
|
||||
Label ret;
|
||||
__ bind(&ret);
|
||||
__ subl(stk, dat);
|
||||
__ movl(Operand(ecx, offsetof(sp_context_t, sp)), stk);
|
||||
|
||||
// Restore stack.
|
||||
__ movl(esp, Operand(ebp, -16));
|
||||
|
||||
// Restore registers and gtfo.
|
||||
__ pop(ebx);
|
||||
__ pop(edi);
|
||||
__ pop(esi);
|
||||
__ pop(ebp);
|
||||
__ ret();
|
||||
|
||||
// The universal emergency return will jump to here.
|
||||
Label error;
|
||||
__ bind(&error);
|
||||
__ movl(ecx, Operand(ebp, 8 + 4 * 0)); // ret-path expects ecx = ctx
|
||||
__ jmp(&ret);
|
||||
|
||||
Label timeout;
|
||||
__ bind(&timeout);
|
||||
__ movl(eax, SP_ERROR_TIMEOUT);
|
||||
__ jmp(&error);
|
||||
|
||||
invoke_stub_ = LinkCode(env_, masm);
|
||||
if (!invoke_stub_)
|
||||
return false;
|
||||
|
||||
return_stub_ = reinterpret_cast<uint8_t *>(invoke_stub_) + error.offset();
|
||||
timeout_stub_ = reinterpret_cast<uint8_t *>(invoke_stub_) + timeout.offset();
|
||||
return true;
|
||||
}
|
||||
|
||||
SPVM_NATIVE_FUNC
|
||||
CodeStubs::CreateFakeNativeStub(SPVM_FAKENATIVE_FUNC callback, void *pData)
|
||||
{
|
||||
AssemblerX86 masm;
|
||||
|
||||
__ push(ebx);
|
||||
__ push(edi);
|
||||
__ push(esi);
|
||||
__ movl(edi, Operand(esp, 16)); // store ctx
|
||||
__ movl(esi, Operand(esp, 20)); // store params
|
||||
__ movl(ebx, esp);
|
||||
__ andl(esp, 0xfffffff0);
|
||||
__ subl(esp, 4);
|
||||
|
||||
__ push(intptr_t(pData));
|
||||
__ push(esi);
|
||||
__ push(edi);
|
||||
__ call(ExternalAddress((void *)callback));
|
||||
__ movl(esp, ebx);
|
||||
__ pop(esi);
|
||||
__ pop(edi);
|
||||
__ pop(ebx);
|
||||
__ ret();
|
||||
|
||||
return (SPVM_NATIVE_FUNC)LinkCode(env_, masm);
|
||||
}
|
@ -38,6 +38,8 @@
|
||||
#include "watchdog_timer.h"
|
||||
#include "interpreter.h"
|
||||
#include "environment.h"
|
||||
#include "code-stubs.h"
|
||||
#include "x86-utils.h"
|
||||
|
||||
using namespace sp;
|
||||
|
||||
@ -49,20 +51,6 @@ using namespace sp;
|
||||
|
||||
JITX86 g_Jit;
|
||||
|
||||
static inline uint8_t *
|
||||
LinkCode(AssemblerX86 &masm)
|
||||
{
|
||||
if (masm.outOfMemory())
|
||||
return NULL;
|
||||
|
||||
void *code = Environment::get()->AllocateCode(masm.length());
|
||||
if (!code)
|
||||
return NULL;
|
||||
|
||||
masm.emitToExecutableMemory(code);
|
||||
return reinterpret_cast<uint8_t *>(code);
|
||||
}
|
||||
|
||||
static inline ConditionCode
|
||||
OpToCondition(OPCODE op)
|
||||
{
|
||||
@ -299,7 +287,8 @@ CompileFromThunk(PluginRuntime *runtime, cell_t pcode_offs, void **addrp, char *
|
||||
}
|
||||
|
||||
Compiler::Compiler(PluginRuntime *rt, cell_t pcode_offs)
|
||||
: rt_(rt),
|
||||
: env_(Environment::get()),
|
||||
rt_(rt),
|
||||
plugin_(rt->plugin()),
|
||||
error_(SP_ERROR_NONE),
|
||||
pcode_start_(pcode_offs),
|
||||
@ -365,7 +354,7 @@ Compiler::emit(int *errp)
|
||||
emitCallThunks();
|
||||
emitErrorPaths();
|
||||
|
||||
uint8_t *code = LinkCode(masm);
|
||||
uint8_t *code = LinkCode(env_, masm);
|
||||
if (!code) {
|
||||
*errp = SP_ERROR_OUT_OF_MEMORY;
|
||||
return NULL;
|
||||
@ -1532,7 +1521,7 @@ Compiler::emitCallThunks()
|
||||
|
||||
__ bind(&error);
|
||||
__ movl(Operand(cipAddr()), thunk->pcode_offset);
|
||||
__ jmp(g_Jit.GetUniversalReturn());
|
||||
__ jmp(ExternalAddress(env_->stubs()->ReturnStub()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1727,7 +1716,7 @@ Compiler::emitErrorPath(Label *dest, int code)
|
||||
if (dest->used()) {
|
||||
__ bind(dest);
|
||||
__ movl(eax, code);
|
||||
__ jmp(g_Jit.GetUniversalReturn());
|
||||
__ jmp(ExternalAddress(env_->stubs()->ReturnStub()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1797,109 +1786,11 @@ Compiler::emitErrorPaths()
|
||||
__ bind(&extern_error_);
|
||||
__ movl(eax, intptr_t(rt_->GetBaseContext()->GetCtx()));
|
||||
__ movl(eax, Operand(eax, offsetof(sp_context_t, n_err)));
|
||||
__ jmp(g_Jit.GetUniversalReturn());
|
||||
__ jmp(ExternalAddress(env_->stubs()->ReturnStub()));
|
||||
}
|
||||
}
|
||||
|
||||
typedef int (*JIT_EXECUTE)(sp_context_t *ctx, uint8_t *memory, void *code);
|
||||
|
||||
static void *
|
||||
GenerateEntry(void **retp, void **timeoutp)
|
||||
{
|
||||
AssemblerX86 masm;
|
||||
|
||||
__ push(ebp);
|
||||
__ movl(ebp, esp);
|
||||
|
||||
__ push(esi); // ebp - 4
|
||||
__ push(edi); // ebp - 8
|
||||
__ push(ebx); // ebp - 12
|
||||
__ push(esp); // ebp - 16
|
||||
|
||||
__ movl(ebx, Operand(ebp, 8 + 4 * 0));
|
||||
__ movl(eax, Operand(ebp, 8 + 4 * 1));
|
||||
__ movl(ecx, Operand(ebp, 8 + 4 * 2));
|
||||
|
||||
// Set up run-time registers.
|
||||
__ movl(edi, Operand(ebx, offsetof(sp_context_t, sp)));
|
||||
__ addl(edi, eax);
|
||||
__ movl(esi, eax);
|
||||
__ movl(ebx, edi);
|
||||
|
||||
// Align the stack.
|
||||
__ andl(esp, 0xfffffff0);
|
||||
|
||||
// Call into plugin (align the stack first).
|
||||
__ call(ecx);
|
||||
|
||||
// Get input context, store rval.
|
||||
__ movl(ecx, Operand(ebp, 8 + 4 * 0));
|
||||
__ movl(Operand(ecx, offsetof(sp_context_t, rval)), pri);
|
||||
|
||||
// Set no error.
|
||||
__ movl(eax, SP_ERROR_NONE);
|
||||
|
||||
// Store latest stk. If we have an error code, we'll jump directly to here,
|
||||
// so eax will already be set.
|
||||
Label ret;
|
||||
__ bind(&ret);
|
||||
__ subl(stk, dat);
|
||||
__ movl(Operand(ecx, offsetof(sp_context_t, sp)), stk);
|
||||
|
||||
// Restore stack.
|
||||
__ movl(esp, Operand(ebp, -16));
|
||||
|
||||
// Restore registers and gtfo.
|
||||
__ pop(ebx);
|
||||
__ pop(edi);
|
||||
__ pop(esi);
|
||||
__ pop(ebp);
|
||||
__ ret();
|
||||
|
||||
// The universal emergency return will jump to here.
|
||||
Label error;
|
||||
__ bind(&error);
|
||||
__ movl(ecx, Operand(ebp, 8 + 4 * 0)); // ret-path expects ecx = ctx
|
||||
__ jmp(&ret);
|
||||
|
||||
Label timeout;
|
||||
__ bind(&timeout);
|
||||
__ movl(eax, SP_ERROR_TIMEOUT);
|
||||
__ jmp(&error);
|
||||
|
||||
void *code = LinkCode(masm);
|
||||
if (!code)
|
||||
return NULL;
|
||||
|
||||
*retp = reinterpret_cast<uint8_t *>(code) + error.offset();
|
||||
*timeoutp = reinterpret_cast<uint8_t *>(code) + timeout.offset();
|
||||
return code;
|
||||
}
|
||||
|
||||
JITX86::JITX86()
|
||||
{
|
||||
m_pJitEntry = NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
JITX86::InitializeJIT()
|
||||
{
|
||||
m_pJitEntry = GenerateEntry(&m_pJitReturn, &m_pJitTimeout);
|
||||
if (!m_pJitEntry)
|
||||
return false;
|
||||
|
||||
MacroAssemblerX86 masm;
|
||||
MacroAssemblerX86::GenerateFeatureDetection(masm);
|
||||
void *code = LinkCode(masm);
|
||||
if (!code)
|
||||
return false;
|
||||
MacroAssemblerX86::RunFeatureDetection(code);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
JITX86::ShutdownJIT()
|
||||
{
|
||||
}
|
||||
|
||||
@ -1918,55 +1809,3 @@ JITX86::CompileFunction(PluginRuntime *prt, cell_t pcode_offs, int *err)
|
||||
prt->AddJittedFunction(fun);
|
||||
return fun;
|
||||
}
|
||||
|
||||
SPVM_NATIVE_FUNC
|
||||
JITX86::CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData)
|
||||
{
|
||||
AssemblerX86 masm;
|
||||
|
||||
__ push(ebx);
|
||||
__ push(edi);
|
||||
__ push(esi);
|
||||
__ movl(edi, Operand(esp, 16)); // store ctx
|
||||
__ movl(esi, Operand(esp, 20)); // store params
|
||||
__ movl(ebx, esp);
|
||||
__ andl(esp, 0xfffffff0);
|
||||
__ subl(esp, 4);
|
||||
|
||||
__ push(intptr_t(pData));
|
||||
__ push(esi);
|
||||
__ push(edi);
|
||||
__ call(ExternalAddress((void *)callback));
|
||||
__ movl(esp, ebx);
|
||||
__ pop(esi);
|
||||
__ pop(edi);
|
||||
__ pop(ebx);
|
||||
__ ret();
|
||||
|
||||
return (SPVM_NATIVE_FUNC)LinkCode(masm);
|
||||
}
|
||||
|
||||
void
|
||||
JITX86::DestroyFakeNative(SPVM_NATIVE_FUNC func)
|
||||
{
|
||||
Environment::get()->FreeCode((void *)func);
|
||||
}
|
||||
|
||||
int
|
||||
JITX86::InvokeFunction(PluginRuntime *runtime, CompiledFunction *fn, cell_t *result)
|
||||
{
|
||||
sp_context_t *ctx = runtime->GetBaseContext()->GetCtx();
|
||||
|
||||
// Note that cip, hp, sp are saved and restored by Execute2().
|
||||
ctx->cip = fn->GetCodeOffset();
|
||||
|
||||
JIT_EXECUTE pfn = (JIT_EXECUTE)m_pJitEntry;
|
||||
|
||||
Environment::get()->EnterInvoke();
|
||||
int err = pfn(ctx, runtime->plugin()->memory, fn->GetEntryAddress());
|
||||
Environment::get()->LeaveInvoke();
|
||||
|
||||
*result = ctx->rval;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,10 @@
|
||||
|
||||
using namespace SourcePawn;
|
||||
|
||||
namespace sp {
|
||||
class Environment;
|
||||
}
|
||||
|
||||
#define JIT_INLINE_ERRORCHECKS (1<<0)
|
||||
#define JIT_INLINE_NATIVES (1<<1)
|
||||
#define STACK_MARGIN 64 //8 parameters of safety, I guess
|
||||
@ -101,6 +105,7 @@ class Compiler
|
||||
|
||||
private:
|
||||
AssemblerX86 masm;
|
||||
sp::Environment *env_;
|
||||
PluginRuntime *rt_;
|
||||
const sp_plugin_t *plugin_;
|
||||
int error_;
|
||||
@ -131,26 +136,7 @@ class JITX86
|
||||
JITX86();
|
||||
|
||||
public:
|
||||
bool InitializeJIT();
|
||||
void ShutdownJIT();
|
||||
SPVM_NATIVE_FUNC CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData);
|
||||
void DestroyFakeNative(SPVM_NATIVE_FUNC func);
|
||||
CompiledFunction *CompileFunction(PluginRuntime *runtime, cell_t pcode_offs, int *err);
|
||||
int InvokeFunction(PluginRuntime *runtime, CompiledFunction *fn, cell_t *result);
|
||||
|
||||
void *TimeoutStub() const {
|
||||
return m_pJitTimeout;
|
||||
}
|
||||
|
||||
public:
|
||||
ExternalAddress GetUniversalReturn() {
|
||||
return ExternalAddress(m_pJitReturn);
|
||||
}
|
||||
|
||||
private:
|
||||
void *m_pJitEntry; /* Entry function */
|
||||
void *m_pJitReturn; /* Universal return address */
|
||||
void *m_pJitTimeout; /* Universal timeout address */
|
||||
};
|
||||
|
||||
const Register pri = eax;
|
||||
|
30
sourcepawn/jit/x86/x86-utils.cpp
Normal file
30
sourcepawn/jit/x86/x86-utils.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
// vim: set sts=2 ts=8 sw=2 tw=99 et:
|
||||
//
|
||||
// Copyright (C) 2006-2015 AlliedModders LLC
|
||||
//
|
||||
// This file is part of SourcePawn. SourcePawn is free software: you can
|
||||
// redistribute it and/or modify it under the terms of the GNU General Public
|
||||
// License as published by the Free Software Foundation, either version 3 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// SourcePawn. If not, see http://www.gnu.org/licenses/.
|
||||
//
|
||||
#include "environment.h"
|
||||
#include "x86-utils.h"
|
||||
|
||||
using namespace sp;
|
||||
|
||||
uint8_t *
|
||||
sp::LinkCode(Environment *env, AssemblerX86 &masm)
|
||||
{
|
||||
if (masm.outOfMemory())
|
||||
return nullptr;
|
||||
|
||||
void *code = env->AllocateCode(masm.length());
|
||||
if (!code)
|
||||
return nullptr;
|
||||
|
||||
masm.emitToExecutableMemory(code);
|
||||
return reinterpret_cast<uint8_t *>(code);
|
||||
}
|
27
sourcepawn/jit/x86/x86-utils.h
Normal file
27
sourcepawn/jit/x86/x86-utils.h
Normal file
@ -0,0 +1,27 @@
|
||||
// vim: set sts=2 ts=8 sw=2 tw=99 et:
|
||||
//
|
||||
// Copyright (C) 2006-2015 AlliedModders LLC
|
||||
//
|
||||
// This file is part of SourcePawn. SourcePawn is free software: you can
|
||||
// redistribute it and/or modify it under the terms of the GNU General Public
|
||||
// License as published by the Free Software Foundation, either version 3 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// SourcePawn. If not, see http://www.gnu.org/licenses/.
|
||||
//
|
||||
#ifndef _include_sourcepawn_vm_x86_utils_h_
|
||||
#define _include_sourcepawn_vm_x86_utils_h_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <macro-assembler-x86.h>
|
||||
|
||||
namespace sp {
|
||||
|
||||
class Environment;
|
||||
|
||||
uint8_t *LinkCode(Environment *env, AssemblerX86 &masm);
|
||||
|
||||
}
|
||||
|
||||
#endif // _include_sourcepawn_vm_x86_utils_h_
|
Loading…
Reference in New Issue
Block a user