From 111dd7eb68039235de7d086deca8caa6288c272d Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 24 Feb 2015 01:12:23 -0800 Subject: [PATCH] Factor code stubs out of JITX86. --- sourcepawn/jit/AMBuilder | 3 + sourcepawn/jit/api.cpp | 5 +- sourcepawn/jit/code-stubs.cpp | 41 ++++++ sourcepawn/jit/code-stubs.h | 61 +++++++++ sourcepawn/jit/environment.cpp | 28 +++- sourcepawn/jit/environment.h | 7 + sourcepawn/jit/sp_vm_basecontext.cpp | 8 +- sourcepawn/jit/x86/code-stubs-x86.cpp | 135 ++++++++++++++++++++ sourcepawn/jit/x86/jit_x86.cpp | 177 ++------------------------ sourcepawn/jit/x86/jit_x86.h | 24 +--- sourcepawn/jit/x86/x86-utils.cpp | 30 +++++ sourcepawn/jit/x86/x86-utils.h | 27 ++++ 12 files changed, 348 insertions(+), 198 deletions(-) create mode 100644 sourcepawn/jit/code-stubs.cpp create mode 100644 sourcepawn/jit/code-stubs.h create mode 100644 sourcepawn/jit/x86/code-stubs-x86.cpp create mode 100644 sourcepawn/jit/x86/x86-utils.cpp create mode 100644 sourcepawn/jit/x86/x86-utils.h diff --git a/sourcepawn/jit/AMBuilder b/sourcepawn/jit/AMBuilder index b7db32ff..b96a3211 100644 --- a/sourcepawn/jit/AMBuilder +++ b/sourcepawn/jit/AMBuilder @@ -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', diff --git a/sourcepawn/jit/api.cpp b/sourcepawn/jit/api.cpp index 4b577d4d..6c9956d7 100644 --- a/sourcepawn/jit/api.cpp +++ b/sourcepawn/jit/api.cpp @@ -33,6 +33,7 @@ #endif #include +#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 * diff --git a/sourcepawn/jit/code-stubs.cpp b/sourcepawn/jit/code-stubs.cpp new file mode 100644 index 00000000..252685c7 --- /dev/null +++ b/sourcepawn/jit/code-stubs.cpp @@ -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_); +} diff --git a/sourcepawn/jit/code-stubs.h b/sourcepawn/jit/code-stubs.h new file mode 100644 index 00000000..093ec7aa --- /dev/null +++ b/sourcepawn/jit/code-stubs.h @@ -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 +#include + +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_ diff --git a/sourcepawn/jit/environment.cpp b/sourcepawn/jit/environment.cpp index ea779f96..7d6a50ea 100644 --- a/sourcepawn/jit/environment.cpp +++ b/sourcepawn/jit/environment.cpp @@ -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(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; +} diff --git a/sourcepawn/jit/environment.h b/sourcepawn/jit/environment.h index 40ddd46d..638a4b97 100644 --- a/sourcepawn/jit/environment.h +++ b/sourcepawn/jit/environment.h @@ -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 code_stubs_; }; class EnterProfileScope diff --git a/sourcepawn/jit/sp_vm_basecontext.cpp b/sourcepawn/jit/sp_vm_basecontext.cpp index 7f460a64..8d14d54b 100644 --- a/sourcepawn/jit/sp_vm_basecontext.cpp +++ b/sourcepawn/jit/sp_vm_basecontext.cpp @@ -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); diff --git a/sourcepawn/jit/x86/code-stubs-x86.cpp b/sourcepawn/jit/x86/code-stubs-x86.cpp new file mode 100644 index 00000000..2b7a4b94 --- /dev/null +++ b/sourcepawn/jit/x86/code-stubs-x86.cpp @@ -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 +#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(invoke_stub_) + error.offset(); + timeout_stub_ = reinterpret_cast(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); +} diff --git a/sourcepawn/jit/x86/jit_x86.cpp b/sourcepawn/jit/x86/jit_x86.cpp index 36f51247..5de146a3 100644 --- a/sourcepawn/jit/x86/jit_x86.cpp +++ b/sourcepawn/jit/x86/jit_x86.cpp @@ -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(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(code) + error.offset(); - *timeoutp = reinterpret_cast(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; -} - diff --git a/sourcepawn/jit/x86/jit_x86.h b/sourcepawn/jit/x86/jit_x86.h index cba9051e..ca5abb64 100644 --- a/sourcepawn/jit/x86/jit_x86.h +++ b/sourcepawn/jit/x86/jit_x86.h @@ -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; diff --git a/sourcepawn/jit/x86/x86-utils.cpp b/sourcepawn/jit/x86/x86-utils.cpp new file mode 100644 index 00000000..4d73903c --- /dev/null +++ b/sourcepawn/jit/x86/x86-utils.cpp @@ -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(code); +} diff --git a/sourcepawn/jit/x86/x86-utils.h b/sourcepawn/jit/x86/x86-utils.h new file mode 100644 index 00000000..02dc679c --- /dev/null +++ b/sourcepawn/jit/x86/x86-utils.h @@ -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 +#include + +namespace sp { + +class Environment; + +uint8_t *LinkCode(Environment *env, AssemblerX86 &masm); + +} + +#endif // _include_sourcepawn_vm_x86_utils_h_