diff --git a/core/DebugReporter.cpp b/core/DebugReporter.cpp
index d86fa111..ed8a6bd2 100644
--- a/core/DebugReporter.cpp
+++ b/core/DebugReporter.cpp
@@ -36,11 +36,6 @@
DebugReport g_DbgReporter;
-/* I'm really lazy. This should probably be exported to ISourcePawnEngine someday,
- * but we need to make sure the JIT will deal with the version bump.
- */
-extern const char *GetSourcePawnErrorMessage(int error);
-
void DebugReport::OnSourceModAllInitialized()
{
g_pSourcePawn->SetDebugListener(this);
@@ -56,7 +51,7 @@ void DebugReport::GenerateError(IPluginContext *ctx, cell_t func_idx, int err, c
va_end(ap);
const char *plname = g_PluginSys.FindPluginByContext(ctx->GetContext())->GetFilename();
- const char *error = GetSourcePawnErrorMessage(err);
+ const char *error = g_pSourcePawn2->GetErrorString(err);
if (error)
{
@@ -91,7 +86,7 @@ void DebugReport::GenerateCodeError(IPluginContext *pContext, uint32_t code_addr
va_end(ap);
const char *plname = g_PluginSys.FindPluginByContext(pContext->GetContext())->GetFilename();
- const char *error = GetSourcePawnErrorMessage(err);
+ const char *error = g_pSourcePawn2->GetErrorString(err);
if (error)
{
diff --git a/core/Makefile b/core/Makefile
index ef2e9d9e..b31c3e2d 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -29,12 +29,8 @@ OBJECTS += smn_admin.cpp smn_bitbuffer.cpp smn_console.cpp smn_core.cpp \
smn_adt_trie.cpp smn_hudtext.cpp smn_adt_stack.cpp smn_nextmap.cpp
OBJECTS += systems/ExtensionSys.cpp systems/ForwardSys.cpp systems/HandleSys.cpp \
systems/LibrarySys.cpp systems/PluginInfoDatabase.cpp systems/PluginSys.cpp \
- systems/ShareSys.cpp vm/sp_vm_basecontext.cpp vm/sp_vm_engine.cpp \
- vm/sp_vm_function.cpp
+ systems/ShareSys.cpp
OBJECTS += thread/ThreadWorker.cpp thread/BaseWorker.cpp thread/PosixThreads.cpp ThreadSupport.cpp
-OBJECTS += zlib/adler32.c zlib/compress.c zlib/crc32.c zlib/deflate.c zlib/gzio.c \
- zlib/infback.c zlib/inffast.c zlib/inflate.c zlib/inftrees.c zlib/trees.c \
- zlib/uncompr.c zlib/zutil.c
##############################################
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
@@ -103,13 +99,9 @@ ifeq "$(GCC_VERSION)" "4"
CPPFLAGS += $(CPP_GCC4_FLAGS)
endif
-OBJ_LINUX := $(OBJECTS:%vm_engine.cpp=$(BIN_DIR)/%vm_engine.o)
-OBJ_LINUX := $(OBJ_LINUX:%.cpp=$(BIN_DIR)/%.o)
+OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o)
OBJ_LINUX := $(OBJ_LINUX:%.c=$(BIN_DIR)/%.o)
-$(BIN_DIR)/%vm_engine.o: %vm_engine.cpp
- $(CPP) $(INCLUDE_SM16) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
-
$(BIN_DIR)/%.o: %.cpp
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
@@ -118,8 +110,6 @@ $(BIN_DIR)/%.o: %.c
all: check
mkdir -p $(BIN_DIR)/systems
- mkdir -p $(BIN_DIR)/vm
- mkdir -p $(BIN_DIR)/zlib
mkdir -p $(BIN_DIR)/thread
ln -sf $(SRCDS)/bin/vstdlib_i486.so vstdlib_i486.so;
ln -sf $(SRCDS)/bin/tier0_i486.so tier0_i486.so;
@@ -142,7 +132,5 @@ default: all
clean: check
rm -rf $(BIN_DIR)/*.o
rm -rf $(BIN_DIR)/systems/*.o
- rm -rf $(BIN_DIR)/zlib/*.o
- rm -rf $(BIN_DIR)/vm/*.o
rm -rf $(BIN_DIR)/thread/*.o
rm -rf $(BIN_DIR)/$(BINARY)
diff --git a/core/msvc8/sourcemod_mm.vcproj b/core/msvc8/sourcemod_mm.vcproj
index a935712f..fcfc7357 100644
--- a/core/msvc8/sourcemod_mm.vcproj
+++ b/core/msvc8/sourcemod_mm.vcproj
@@ -1358,204 +1358,26 @@
Name="SourcePawn"
UniqueIdentifier="{C3C3DC6E-E392-4916-B893-7ACB92192DE0}"
>
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
GetVMName(), g_pVM->GetVersionString());
- ConsolePrint(" JIT Settings: %s", g_pVM->GetCPUOptimizations());
+ ConsolePrint(" SourcePawn Engine: %s (build %s)", g_pSourcePawn2->GetEngineName(), g_pSourcePawn2->GetVersionString());
+ ConsolePrint(" SourcePawn API: v1 = %d, v2 = %d", g_pSourcePawn->GetEngineAPIVersion(), g_pSourcePawn2->GetAPIVersion());
ConsolePrint(" Compiled on: %s %s", __DATE__, __TIME__);
ConsolePrint(" http://www.sourcemod.net/");
}
diff --git a/core/smn_console.cpp b/core/smn_console.cpp
index c635a339..7dded75e 100644
--- a/core/smn_console.cpp
+++ b/core/smn_console.cpp
@@ -833,7 +833,7 @@ static cell_t sm_ServerCommand(IPluginContext *pContext, const cell_t *params)
char buffer[1024];
size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1);
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
}
@@ -854,7 +854,7 @@ static cell_t sm_InsertServerCommand(IPluginContext *pContext, const cell_t *par
char buffer[1024];
size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1);
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
}
@@ -894,7 +894,7 @@ static cell_t sm_ClientCommand(IPluginContext *pContext, const cell_t *params)
char buffer[256];
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
}
@@ -921,7 +921,7 @@ static cell_t FakeClientCommand(IPluginContext *pContext, const cell_t *params)
char buffer[256];
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
}
@@ -948,7 +948,7 @@ static cell_t FakeClientCommandEx(IPluginContext *pContext, const cell_t *params
char buffer[256];
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
}
@@ -966,7 +966,7 @@ static cell_t ReplyToCommand(IPluginContext *pContext, const cell_t *params)
char buffer[1024];
size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 2);
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
}
diff --git a/core/smn_core.cpp b/core/smn_core.cpp
index 78d18ebd..84692bca 100644
--- a/core/smn_core.cpp
+++ b/core/smn_core.cpp
@@ -130,7 +130,7 @@ static cell_t ThrowError(IPluginContext *pContext, const cell_t *params)
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
- if (pContext->GetContext()->n_err == SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() == SP_ERROR_NONE)
{
pContext->ThrowNativeErrorEx(SP_ERROR_ABORTED, "%s", buffer);
}
@@ -387,7 +387,7 @@ static cell_t SetFailState(IPluginContext *pContext, const cell_t *params)
char buffer[2048];
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
pPlugin->SetErrorState(Plugin_Error, "%s", str);
return pContext->ThrowNativeErrorEx(SP_ERROR_ABORTED, "Formatting error (%s)", str);
@@ -455,7 +455,7 @@ static cell_t MarkNativeAsOptional(IPluginContext *pContext, const cell_t *param
{
char *name;
uint32_t idx;
- sp_context_t *ctx = pContext->GetContext();
+ sp_native_t *native;
pContext->LocalToString(params[1], &name);
if (pContext->FindNativeByName(name, &idx) != SP_ERROR_NONE)
@@ -464,7 +464,9 @@ static cell_t MarkNativeAsOptional(IPluginContext *pContext, const cell_t *param
return 0;
}
- ctx->natives[idx].flags |= SP_NTVFLAG_OPTIONAL;
+ pContext->GetNativeByIndex(idx, &native);
+
+ native->flags |= SP_NTVFLAG_OPTIONAL;
return 1;
}
@@ -505,7 +507,7 @@ static cell_t sm_LogAction(IPluginContext *pContext, const cell_t *params)
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 3);
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
}
@@ -535,7 +537,7 @@ static cell_t LogToFile(IPluginContext *pContext, const cell_t *params)
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
fclose(fp);
return 0;
@@ -568,7 +570,7 @@ static cell_t LogToFileEx(IPluginContext *pContext, const cell_t *params)
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
fclose(fp);
return 0;
diff --git a/core/smn_fakenatives.cpp b/core/smn_fakenatives.cpp
index 5e1fd71b..f5c3c24c 100644
--- a/core/smn_fakenatives.cpp
+++ b/core/smn_fakenatives.cpp
@@ -54,8 +54,7 @@ cell_t FakeNativeRouter(IPluginContext *pContext, const cell_t *params, void *pD
}
/* Check if the native is paused */
- sp_context_t *pNativeCtx = native->ctx->GetContext();
- if ((pNativeCtx->flags & SPFLAG_PLUGIN_PAUSED) == SPFLAG_PLUGIN_PAUSED)
+ if (native->ctx->GetRuntime()->IsPaused())
{
return pContext->ThrowNativeError("Plugin owning this native is currently paused.");
}
@@ -90,7 +89,7 @@ cell_t FakeNativeRouter(IPluginContext *pContext, const cell_t *params, void *pD
int error;
if ((error=native->call->Execute(&result)) != SP_ERROR_NONE)
{
- if (pContext->GetContext()->n_err == SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() == SP_ERROR_NONE)
{
pContext->ThrowNativeErrorEx(error, "Error encountered while processing a dynamic native");
}
@@ -146,7 +145,7 @@ static cell_t ThrowNativeError(IPluginContext *pContext, const cell_t *params)
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
s_curcaller->ThrowNativeError("Error encountered while processing a dynamic native");
} else {
@@ -434,7 +433,7 @@ static cell_t FormatNativeString(IPluginContext *pContext, const cell_t *params)
pContext->LocalToPhysAddr(params[5], &addr);
*addr = (cell_t)written;
- return s_curcaller->GetContext()->n_err;
+ return s_curcaller->GetLastNativeError();
}
//tee hee
diff --git a/core/smn_filesystem.cpp b/core/smn_filesystem.cpp
index 9870d6a6..74f3aa8c 100644
--- a/core/smn_filesystem.cpp
+++ b/core/smn_filesystem.cpp
@@ -573,7 +573,7 @@ static cell_t sm_LogToGame(IPluginContext *pContext, const cell_t *params)
char buffer[1024];
size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
}
@@ -599,7 +599,7 @@ static cell_t sm_LogMessage(IPluginContext *pContext, const cell_t *params)
char buffer[1024];
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
}
@@ -617,7 +617,7 @@ static cell_t sm_LogError(IPluginContext *pContext, const cell_t *params)
char buffer[1024];
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
}
@@ -670,7 +670,7 @@ static cell_t sm_LogToOpenFile(IPluginContext *pContext, const cell_t *params)
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
}
@@ -701,7 +701,7 @@ static cell_t sm_LogToOpenFileEx(IPluginContext *pContext, const cell_t *params)
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
}
diff --git a/core/smn_halflife.cpp b/core/smn_halflife.cpp
index d34d6732..40590d94 100644
--- a/core/smn_halflife.cpp
+++ b/core/smn_halflife.cpp
@@ -289,7 +289,7 @@ static cell_t PrintToChat(IPluginContext *pContext, const cell_t *params)
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
/* Check for an error before printing to the client */
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
}
@@ -323,7 +323,7 @@ static cell_t PrintCenterText(IPluginContext *pContext, const cell_t *params)
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
/* Check for an error before printing to the client */
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
}
@@ -357,7 +357,7 @@ static cell_t PrintHintText(IPluginContext *pContext, const cell_t *params)
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
/* Check for an error before printing to the client */
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
}
diff --git a/core/smn_hudtext.cpp b/core/smn_hudtext.cpp
index 01426830..a5d98769 100644
--- a/core/smn_hudtext.cpp
+++ b/core/smn_hudtext.cpp
@@ -371,7 +371,7 @@ static cell_t ShowSyncHudText(IPluginContext *pContext, const cell_t *params)
}
g_SourceMod.FormatString(message_buffer, sizeof(message_buffer), pContext, params, 3);
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
}
@@ -443,7 +443,7 @@ static cell_t ShowHudText(IPluginContext *pContext, const cell_t *params)
}
g_SourceMod.FormatString(message_buffer, sizeof(message_buffer), pContext, params, 3);
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
}
diff --git a/core/smn_player.cpp b/core/smn_player.cpp
index ed185f09..33b5b826 100644
--- a/core/smn_player.cpp
+++ b/core/smn_player.cpp
@@ -1000,7 +1000,7 @@ static cell_t _ShowActivity(IPluginContext *pContext,
g_SourceMod.SetGlobalTarget(client);
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
}
@@ -1015,7 +1015,7 @@ static cell_t _ShowActivity(IPluginContext *pContext,
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
}
@@ -1054,7 +1054,7 @@ static cell_t _ShowActivity(IPluginContext *pContext,
}
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
}
@@ -1078,7 +1078,7 @@ static cell_t _ShowActivity(IPluginContext *pContext,
}
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
}
@@ -1123,7 +1123,7 @@ static cell_t _ShowActivity2(IPluginContext *pContext,
g_SourceMod.SetGlobalTarget(client);
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
}
@@ -1152,7 +1152,7 @@ static cell_t _ShowActivity2(IPluginContext *pContext,
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
}
@@ -1191,7 +1191,7 @@ static cell_t _ShowActivity2(IPluginContext *pContext,
}
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
}
@@ -1215,7 +1215,7 @@ static cell_t _ShowActivity2(IPluginContext *pContext,
}
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
}
@@ -1286,7 +1286,7 @@ static cell_t KickClient(IPluginContext *pContext, const cell_t *params)
char buffer[256];
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
}
@@ -1332,7 +1332,7 @@ static cell_t KickClientEx(IPluginContext *pContext, const cell_t *params)
char buffer[256];
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
- if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ if (pContext->GetLastNativeError() != SP_ERROR_NONE)
{
return 0;
}
diff --git a/core/smn_string.cpp b/core/smn_string.cpp
index e9d7b647..f9ba1140 100644
--- a/core/smn_string.cpp
+++ b/core/smn_string.cpp
@@ -233,8 +233,7 @@ static cell_t sm_vformat(IPluginContext *pContext, const cell_t *params)
int vargPos = static_cast(params[4]);
/* Get the parent parameter array */
- sp_context_t *ctx = pContext->GetContext();
- cell_t *local_params = (cell_t *)(ctx->memory + ctx->frm + (2 * sizeof(cell_t)));
+ cell_t *local_params = pContext->GetLocalParams();
cell_t max = local_params[0];
if (vargPos > (int)max + 1)
diff --git a/core/sourcemod.cpp b/core/sourcemod.cpp
index 8cf5fbbd..52e6f3aa 100644
--- a/core/sourcemod.cpp
+++ b/core/sourcemod.cpp
@@ -33,7 +33,6 @@
#include "sourcemod.h"
#include "sourcemm_api.h"
#include "systems/LibrarySys.h"
-#include "vm/sp_vm_engine.h"
#include
#include "PluginSys.h"
#include "ShareSys.h"
@@ -47,27 +46,26 @@
#include "ForwardSys.h"
#include "TimerSys.h"
#include "GameConfigs.h"
+#include "DebugReporter.h"
+#include "Profiler.h"
SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool);
SH_DECL_HOOK0_void(IServerGameDLL, LevelShutdown, SH_NOATTRIB, false);
SH_DECL_HOOK1_void(IServerGameDLL, GameFrame, SH_NOATTRIB, false, bool);
SH_DECL_HOOK1_void(IVEngineServer, ServerCommand, SH_NOATTRIB, false, const char *);
-SourcePawnEngine g_SourcePawn;
SourceModBase g_SourceMod;
ILibrary *g_pJIT = NULL;
SourceHook::String g_BaseDir;
-ISourcePawnEngine *g_pSourcePawn = &g_SourcePawn;
-IVirtualMachine *g_pVM;
+ISourcePawnEngine *g_pSourcePawn = NULL;
+ISourcePawnEngine2 *g_pSourcePawn2 = NULL;
IdentityToken_t *g_pCoreIdent = NULL;
IForward *g_pOnMapEnd = NULL;
bool g_Loaded = false;
-typedef int (*GIVEENGINEPOINTER)(ISourcePawnEngine *);
-typedef int (*GIVEENGINEPOINTER2)(ISourcePawnEngine *, unsigned int api_version);
-typedef unsigned int (*GETEXPORTCOUNT)();
-typedef IVirtualMachine *(*GETEXPORT)(unsigned int);
+typedef ISourcePawnEngine *(*GET_SP_V1)();
+typedef ISourcePawnEngine2 *(*GET_SP_V2)();
typedef void (*NOTIFYSHUTDOWN)();
void ShutdownJIT()
@@ -165,105 +163,34 @@ bool SourceModBase::InitializeSourceMod(char *error, size_t maxlength, bool late
return false;
}
- int err;
-
- GIVEENGINEPOINTER2 jit_init2 = (GIVEENGINEPOINTER2)g_pJIT->GetSymbolAddress("GiveEnginePointer2");
- if (!jit_init2)
- {
- GIVEENGINEPOINTER jit_init = (GIVEENGINEPOINTER)g_pJIT->GetSymbolAddress("GiveEnginePointer");
- if (!jit_init)
- {
- ShutdownJIT();
- if (error && maxlength)
- {
- snprintf(error, maxlength, "Failed to find GiveEnginePointer in JIT!");
- }
- return false;
- }
+ GET_SP_V1 getv1 = (GET_SP_V1)g_pJIT->GetSymbolAddress("GetSourcePawnEngine1");
+ GET_SP_V2 getv2 = (GET_SP_V2)g_pJIT->GetSymbolAddress("GetSourcePawnEngine2");
- if ((err=jit_init(g_pSourcePawn)) != 0)
- {
- ShutdownJIT();
- if (error && maxlength)
- {
- snprintf(error, maxlength, "GiveEnginePointer returned %d in the JIT", err);
- }
- return false;
- }
- }
- else
+ if (getv1 == NULL)
{
- /* On version bumps, we should check for older versions as well, if the new version fails.
- * We can then check the exports to see if any VM versions will be sufficient.
- */
- if ((err=jit_init2(g_pSourcePawn, SOURCEPAWN_ENGINE_API_VERSION)) != SP_ERROR_NONE)
- {
- ShutdownJIT();
- if (error && maxlength)
- {
- snprintf(error, maxlength, "JIT incompatible with SourceMod version");
- }
- return false;
- }
- }
-
- GETEXPORTCOUNT jit_getnum = (GETEXPORTCOUNT)g_pJIT->GetSymbolAddress("GetExportCount");
- GETEXPORT jit_get = (GETEXPORT)g_pJIT->GetSymbolAddress("GetExport");
- if (!jit_get)
- {
- ShutdownJIT();
if (error && maxlength)
{
- snprintf(error, maxlength, "JIT is missing a necessary export!");
+ snprintf(error, maxlength, "JIT is too old; upgrade SourceMod");
}
+ ShutdownJIT();
return false;
}
-
- unsigned int num = jit_getnum();
- if (!num)
+ else if (getv2 == NULL)
{
- ShutdownJIT();
if (error && maxlength)
{
- snprintf(error, maxlength, "JIT did not export any virtual machines!");
+ snprintf(error, maxlength, "JIT is too old; upgrade SourceMod");
}
- return false;
- }
-
- unsigned int api_version;
- for (unsigned int i=0; iAlso refuse anything < 3 because we need fake natives.
- * Also refuse anything < 7 because we need the new sp_native definition.
- */
- api_version = g_pVM->GetAPIVersion();
- if (api_version < 7 || api_version > SOURCEPAWN_VM_API_VERSION)
- {
- if (error && maxlength)
- {
- snprintf(error, maxlength, "JIT is not a compatible version");
- }
- g_pVM = NULL;
- continue;
- }
- break;
- }
-
- if (!g_pVM)
- {
ShutdownJIT();
return false;
}
+ g_pSourcePawn = getv1();
+ g_pSourcePawn2 = getv2();
+
+ g_pSourcePawn2->SetDebugListener(&g_DbgReporter);
+ g_pSourcePawn2->SetProfiler(&g_Profiler);
+
/* Hook this now so we can detect startup without calling StartSourceMod() */
SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelInit, gamedll, this, &SourceModBase::LevelInit, false);
@@ -663,7 +590,7 @@ ISourcePawnEngine *SourceModBase::GetScriptingEngine()
IVirtualMachine *SourceModBase::GetScriptingVM()
{
- return g_pVM;
+ return NULL;
}
void SourceModBase::AllPluginsLoaded()
diff --git a/core/systems/HandleSys.cpp b/core/systems/HandleSys.cpp
index 897a5ff9..71b41fa9 100644
--- a/core/systems/HandleSys.cpp
+++ b/core/systems/HandleSys.cpp
@@ -990,7 +990,7 @@ bool HandleSystem::TryAndFreeSomeHandles()
g_Logger.LogFatal("[SM] Reloading plugin to free %d handles.", highest_handle_count);
g_Logger.LogFatal("[SM] Contact the author(s) of this plugin to correct this error.", highest_handle_count);
- highest_owner->GetContext()->n_err = SP_ERROR_MEMACCESS;
+ highest_owner->GetBaseContext()->ThrowNativeErrorEx(SP_ERROR_MEMACCESS, "Memory leak");
return g_PluginSys.UnloadPlugin(highest_owner);
}
diff --git a/core/systems/PluginSys.cpp b/core/systems/PluginSys.cpp
index bf6c7e0e..c9196d68 100644
--- a/core/systems/PluginSys.cpp
+++ b/core/systems/PluginSys.cpp
@@ -58,7 +58,7 @@ CPlugin::CPlugin(const char *file)
m_type = PluginType_Private;
m_status = Plugin_Uncompiled;
m_serial = ++MySerial;
- m_plugin = NULL;
+ m_pRuntime = NULL;
m_errormsg[256] = '\0';
snprintf(m_filename, sizeof(m_filename), "%s", file);
m_handle = 0;
@@ -82,27 +82,12 @@ CPlugin::~CPlugin()
g_ShareSys.DestroyIdentity(m_ident);
}
- if (m_ctx.base)
+ if (m_pRuntime != NULL)
{
- delete m_ctx.base;
- m_ctx.base = NULL;
- }
- if (m_ctx.ctx)
- {
- m_ctx.vm->FreeContext(m_ctx.ctx);
- m_ctx.ctx = NULL;
- }
- if (m_ctx.co)
- {
- m_ctx.vm->AbortCompilation(m_ctx.co);
- m_ctx.co = NULL;
+ delete m_pRuntime;
+ m_pRuntime = NULL;
}
- if (m_plugin)
- {
- g_pSourcePawn->FreeFromMemory(m_plugin);
- m_plugin = NULL;
- }
if (m_pProps)
{
sm_trie_destroy(m_pProps);
@@ -125,7 +110,8 @@ void CPlugin::InitIdentity()
{
m_ident = g_ShareSys.CreateIdentity(g_PluginIdent, this);
m_handle = g_HandleSys.CreateHandle(g_PluginType, this, g_PluginSys.GetIdentity(), g_PluginSys.GetIdentity(), NULL);
- m_ctx.base->SetIdentity(m_ident);
+ m_pRuntime->GetDefaultContext()->SetKey(1, m_ident);
+ m_pRuntime->GetDefaultContext()->SetKey(2, (IPlugin *)this);
}
}
@@ -157,37 +143,6 @@ unsigned int CPlugin::CalcMemUsage()
base_size += (*i).size();
}
- if (m_plugin != NULL)
- {
- base_size += sizeof(sp_plugin_t);
- base_size += m_plugin->data_size;
- base_size += m_plugin->pcode_size;
- base_size += (m_plugin->info.natives_num * sizeof(sp_file_natives_t));
- base_size += (m_plugin->info.publics_num * sizeof(sp_file_publics_t));
- base_size += (m_plugin->info.pubvars_num * sizeof(sp_file_pubvars_t));
- base_size += (m_plugin->debug.files_num * sizeof(sp_fdbg_file_t));
- base_size += (m_plugin->debug.lines_num * sizeof(sp_fdbg_line_t));
- base_size += (m_plugin->debug.syms_num * sizeof(sp_fdbg_symbol_t));
- /* We can't get strtab size, oh well. */
- }
-
- if (m_ctx.base != NULL)
- {
- base_size += sizeof(BaseContext);
- base_size += m_ctx.base->GetPublicsNum() * sizeof(CFunction);
- }
- if (m_ctx.ctx != NULL)
- {
- base_size += m_ctx.ctx->mem_size;
- base_size += (m_plugin->debug.files_num * sizeof(sp_debug_file_t));
- base_size += (m_plugin->debug.lines_num * sizeof(sp_debug_line_t));
- base_size += (m_plugin->debug.syms_num * sizeof(sp_debug_symbol_t));
- base_size += (m_plugin->info.pubvars_num * sizeof(sp_pubvar_t));
- base_size += (m_plugin->info.publics_num * sizeof(sp_public_t));
- base_size += (m_plugin->info.natives_num * sizeof(sp_native_t));
- /* We also don't know the JIT code size, oh well. */
- }
-
return base_size;
}
@@ -214,23 +169,6 @@ CPlugin *CPlugin::CreatePlugin(const char *file, char *error, size_t maxlength)
return pPlugin;
}
- int err;
- sp_plugin_t *pl = g_pSourcePawn->LoadFromFilePointer(fp, &err);
- if (pl == NULL)
- {
- fclose(fp);
- if (error)
- {
- snprintf(error, maxlength, "Error %d while parsing plugin", err);
- }
- pPlugin->m_status = Plugin_BadLoad;
- return pPlugin;
- }
-
- fclose(fp);
-
- pPlugin->m_plugin = pl;
-
return pPlugin;
}
@@ -251,69 +189,9 @@ bool CPlugin::SetProperty(const char *prop, void *ptr)
return sm_trie_insert(m_pProps, prop, ptr);
}
-ICompilation *CPlugin::StartMyCompile(IVirtualMachine *vm)
+IPluginRuntime *CPlugin::GetRuntime()
{
- if (!m_plugin)
- {
- return NULL;
- }
-
- /* :NOTICE: We will eventually need to change these natives
- * for swapping in new contexts
- */
- if (m_ctx.co || m_ctx.ctx)
- {
- return NULL;
- }
-
- m_status = Plugin_Uncompiled;
-
- m_ctx.vm = vm;
- m_ctx.co = vm->StartCompilation(m_plugin);
-
- return m_ctx.co;
-}
-
-void CPlugin::CancelMyCompile()
-{
- if (!m_ctx.co)
- {
- return;
- }
-
- m_ctx.vm->AbortCompilation(m_ctx.co);
- m_ctx.co = NULL;
- m_ctx.vm = NULL;
-}
-
-bool CPlugin::FinishMyCompile(char *error, size_t maxlength)
-{
- if (!m_ctx.co)
- {
- return false;
- }
-
- int err;
- m_ctx.ctx = m_ctx.vm->CompileToContext(m_ctx.co, &err);
- if (!m_ctx.ctx)
- {
- memset(&m_ctx, 0, sizeof(m_ctx));
- if (error)
- {
- snprintf(error, maxlength, "JIT failed to compile (error %d)", err);
- }
- return false;
- }
-
- m_ctx.base = new BaseContext(m_ctx.ctx);
- m_ctx.ctx->user[SM_CONTEXTVAR_MYSELF] = (void *)this;
-
- m_status = Plugin_Created;
- m_ctx.co = NULL;
-
- UpdateInfo();
-
- return true;
+ return m_pRuntime;
}
void CPlugin::SetErrorState(PluginStatus status, const char *error_fmt, ...)
@@ -332,9 +210,9 @@ void CPlugin::SetErrorState(PluginStatus status, const char *error_fmt, ...)
vsnprintf(m_errormsg, sizeof(m_errormsg), error_fmt, ap);
va_end(ap);
- if (m_ctx.ctx)
+ if (m_pRuntime != NULL)
{
- m_ctx.ctx->flags |= SPFLAG_PLUGIN_PAUSED;
+ m_pRuntime->SetPauseState(true);
}
}
@@ -415,7 +293,7 @@ void CPlugin::Call_OnPluginStart()
m_status = Plugin_Running;
cell_t result;
- IPluginFunction *pFunction = m_ctx.base->GetFunctionByName("OnPluginStart");
+ IPluginFunction *pFunction = m_pRuntime->GetFunctionByName("OnPluginStart");
if (!pFunction)
{
return;
@@ -436,7 +314,7 @@ void CPlugin::Call_OnPluginEnd()
}
cell_t result;
- IPluginFunction *pFunction = m_ctx.base->GetFunctionByName("OnPluginEnd");
+ IPluginFunction *pFunction = m_pRuntime->GetFunctionByName("OnPluginEnd");
if (!pFunction)
{
return;
@@ -460,7 +338,7 @@ void CPlugin::Call_OnAllPluginsLoaded()
m_bGotAllLoaded = true;
cell_t result;
- IPluginFunction *pFunction = m_ctx.base->GetFunctionByName("OnAllPluginsLoaded");
+ IPluginFunction *pFunction = m_pRuntime->GetFunctionByName("OnAllPluginsLoaded");
if (pFunction != NULL)
{
pFunction->Execute(&result);
@@ -468,7 +346,7 @@ void CPlugin::Call_OnAllPluginsLoaded()
if (g_OnMapStarted)
{
- if ((pFunction = m_ctx.base->GetFunctionByName("OnMapStart")) != NULL)
+ if ((pFunction = m_pRuntime->GetFunctionByName("OnMapStart")) != NULL)
{
pFunction->Execute(NULL);
}
@@ -491,7 +369,7 @@ bool CPlugin::Call_AskPluginLoad(char *error, size_t maxlength)
int err;
cell_t result;
- IPluginFunction *pFunction = m_ctx.base->GetFunctionByName("AskPluginLoad");
+ IPluginFunction *pFunction = m_pRuntime->GetFunctionByName("AskPluginLoad");
if (!pFunction)
{
@@ -515,19 +393,24 @@ bool CPlugin::Call_AskPluginLoad(char *error, size_t maxlength)
return true;
}
-const sp_plugin_t *CPlugin::GetPluginStructure()
+void *CPlugin::GetPluginStructure()
{
- return m_plugin;
+ return NULL;
}
IPluginContext *CPlugin::GetBaseContext()
{
- return m_ctx.base;
+ if (m_pRuntime == NULL)
+ {
+ return NULL;
+ }
+
+ return m_pRuntime->GetDefaultContext();
}
sp_context_t *CPlugin::GetContext()
{
- return m_ctx.ctx;
+ return NULL;
}
const char *CPlugin::GetFilename()
@@ -557,12 +440,12 @@ PluginStatus CPlugin::GetStatus()
bool CPlugin::IsDebugging()
{
- if (!m_ctx.ctx)
+ if (m_pRuntime == NULL)
{
return false;
}
- return ((m_ctx.ctx->flags & SP_FLAG_DEBUG) == SP_FLAG_DEBUG);
+ return m_pRuntime->IsDebugging();
}
void CPlugin::LibraryActions(bool dropping)
@@ -590,7 +473,7 @@ bool CPlugin::SetPauseState(bool paused)
LibraryActions(true);
}
- IPluginFunction *pFunction = m_ctx.base->GetFunctionByName("OnPluginPauseChange");
+ IPluginFunction *pFunction = m_pRuntime->GetFunctionByName("OnPluginPauseChange");
if (pFunction)
{
cell_t result;
@@ -601,10 +484,10 @@ bool CPlugin::SetPauseState(bool paused)
if (paused)
{
m_status = Plugin_Paused;
- m_ctx.ctx->flags |= SPFLAG_PLUGIN_PAUSED;
+ m_pRuntime->SetPauseState(true);
} else {
m_status = Plugin_Running;
- m_ctx.ctx->flags &= ~SPFLAG_PLUGIN_PAUSED;
+ m_pRuntime->SetPauseState(false);
}
g_PluginSys._SetPauseState(this, paused);
@@ -652,8 +535,9 @@ bool CPlugin::ToggleDebugMode(bool debug, char *error, size_t maxlength)
return false;
}
- ICompilation *co = g_pVM->StartCompilation(m_ctx.ctx->plugin);
- if (!g_pVM->SetCompilationOption(co, "debug", (debug) ? "1" : "0"))
+ ICompilation *co = g_pSourcePawn2->StartCompilation();
+
+ if (!co->SetOption("debug", (debug) ? "1" : "0"))
{
if (error)
{
@@ -662,32 +546,7 @@ bool CPlugin::ToggleDebugMode(bool debug, char *error, size_t maxlength)
return false;
}
- sp_context_t *new_ctx = g_pVM->CompileToContext(co, &err);
-
- if (new_ctx)
- {
- memcpy(new_ctx->memory, m_ctx.ctx->memory, m_ctx.ctx->mem_size);
- new_ctx->hp = m_ctx.ctx->hp;
- new_ctx->sp = m_ctx.ctx->sp;
- new_ctx->frm = m_ctx.ctx->frm;
- new_ctx->dbreak = m_ctx.ctx->dbreak;
- new_ctx->context = m_ctx.ctx->context;
- memcpy(new_ctx->user, m_ctx.ctx->user, sizeof(m_ctx.ctx->user));
-
- uint32_t nativeCount = m_plugin->info.natives_num;
- for (uint32_t i=0; inatives[i].pfn = m_ctx.ctx->natives[i].pfn;
- new_ctx->natives[i].status = m_ctx.ctx->natives[i].status;
- }
-
- g_pVM->FreeContext(m_ctx.ctx);
- m_ctx.ctx = new_ctx;
- m_ctx.base->SetContext(new_ctx);
-
- UpdateInfo();
- }
- else
+ if ((err = m_pRuntime->ApplyCompilationOptions(co)) != SP_ERROR_NONE)
{
if (error)
{
@@ -696,6 +555,8 @@ bool CPlugin::ToggleDebugMode(bool debug, char *error, size_t maxlength)
return false;
}
+ UpdateInfo();
+
return true;
}
@@ -741,7 +602,7 @@ IPhraseCollection *CPlugin::GetPhrases()
void CPlugin::DependencyDropped(CPlugin *pOwner)
{
- if (!m_ctx.ctx)
+ if (!m_pRuntime)
{
return;
}
@@ -771,12 +632,12 @@ void CPlugin::DependencyDropped(CPlugin *pOwner)
{
pNative = (*iter);
/* Find this native! */
- if (m_ctx.base->FindNativeByName(pNative->name, &idx) != SP_ERROR_NONE)
+ if (m_pRuntime->FindNativeByName(pNative->name, &idx) != SP_ERROR_NONE)
{
continue;
}
/* Unbind it */
- m_ctx.base->GetNativeByIndex(idx, &native);
+ m_pRuntime->GetNativeByIndex(idx, &native);
native->pfn = NULL;
native->status = SP_NATIVE_UNBOUND;
unbound++;
@@ -1047,6 +908,7 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool de
return LoadRes_NeverLoad;
}
+ int err;
bool no_load = false;
PluginSettings *pset;
unsigned int setcount = m_PluginInfo.GetSettingsNum();
@@ -1102,7 +964,7 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool de
if (pPlugin->m_status == Plugin_Uncompiled)
{
- co = pPlugin->StartMyCompile(g_pVM);
+ co = g_pSourcePawn2->StartCompilation();
}
for (unsigned int i=0; iSetCompilationOption(co, key, val))
+ if ((err = co->SetOption(key, val)) == SP_ERROR_NONE)
{
if (error)
{
snprintf(error, maxlength, "Unable to set JIT option (key \"%s\") (value \"%s\")", key, val);
}
- pPlugin->CancelMyCompile();
+ co->Abort();
co = NULL;
break;
}
@@ -1137,10 +999,25 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool de
}
/* Do the actual compiling */
- if (co)
+ if (co != NULL)
{
- pPlugin->FinishMyCompile(error, maxlength);
- co = NULL;
+ char fullpath[PLATFORM_MAX_PATH];
+ g_SourceMod.BuildPath(Path_SM, fullpath, sizeof(fullpath), "plugins/%s", pPlugin->m_filename);
+
+ pPlugin->m_pRuntime = g_pSourcePawn2->LoadPlugin(co, fullpath, &err);
+ if (pPlugin->m_pRuntime == NULL)
+ {
+ snprintf(error,
+ maxlength,
+ "Unable to load plugin (error %d: %s)",
+ err,
+ g_pSourcePawn2->GetErrorString(err));
+ }
+ else
+ {
+ pPlugin->UpdateInfo();
+ pPlugin->m_status = Plugin_Created;
+ }
}
/* Get the status */
@@ -1321,7 +1198,7 @@ bool CPluginManager::FindOrRequirePluginDeps(CPlugin *pPlugin, char *error, size
{
cell_t res;
pFunc->Execute(&res);
- if (pPlugin->GetContext()->n_err != SP_ERROR_NONE)
+ if (pPlugin->GetBaseContext()->GetLastNativeError() != SP_ERROR_NONE)
{
if (error)
{
@@ -1448,7 +1325,7 @@ bool CPluginManager::LoadOrRequireExtensions(CPlugin *pPlugin, unsigned int pass
{
cell_t res;
pFunc->Execute(&res);
- if (pPlugin->GetContext()->n_err != SP_ERROR_NONE)
+ if (pPlugin->GetBaseContext()->GetLastNativeError() != SP_ERROR_NONE)
{
if (error)
{
@@ -1615,9 +1492,9 @@ void CPluginManager::TryRefreshDependencies(CPlugin *pPlugin)
{
/* If we got here, all natives are okay again! */
pPlugin->m_status = Plugin_Running;
- if ((pPlugin->m_ctx.ctx->flags & SPFLAG_PLUGIN_PAUSED) == SPFLAG_PLUGIN_PAUSED)
+ if (pPlugin->m_pRuntime->IsPaused())
{
- pPlugin->m_ctx.ctx->flags &= ~SPFLAG_PLUGIN_PAUSED;
+ pPlugin->m_pRuntime->SetPauseState(false);
_SetPauseState(pPlugin, false);
}
}
@@ -1687,8 +1564,22 @@ bool CPluginManager::UnloadPlugin(IPlugin *plugin)
IPlugin *CPluginManager::FindPluginByContext(const sp_context_t *ctx)
{
- IPlugin *pl = (IPlugin *)ctx->user[SM_CONTEXTVAR_MYSELF];
- return pl;
+ IPlugin *pPlugin;
+ IPluginContext *pContext;
+
+ pContext = reinterpret_cast(const_cast(ctx));
+
+ if (pContext->GetKey(2, (void **)&pPlugin))
+ {
+ return pPlugin;
+ }
+
+ return NULL;
+}
+
+CPlugin *CPluginManager::GetPluginByCtx(const sp_context_t *ctx)
+{
+ return (CPlugin *)FindPluginByContext(ctx);
}
unsigned int CPluginManager::GetPluginCount()
diff --git a/core/systems/PluginSys.h b/core/systems/PluginSys.h
index 7e79871a..1bb41141 100644
--- a/core/systems/PluginSys.h
+++ b/core/systems/PluginSys.h
@@ -43,7 +43,6 @@
#include
#include
#include "sm_globals.h"
-#include "vm/sp_vm_basecontext.h"
#include "PluginInfoDatabase.h"
#include "sm_trie.h"
#include "sourcemod.h"
@@ -109,19 +108,6 @@ using namespace SourceHook;
* 7. Once all plugins are deemed to be loaded, OnPluginStart() is called
*/
-#define SM_CONTEXTVAR_MYSELF 0
-
-struct ContextPair
-{
- ContextPair() : base(NULL), ctx(NULL), co(NULL)
- {
- };
- BaseContext *base;
- sp_context_t *ctx;
- ICompilation *co;
- IVirtualMachine *vm;
-};
-
enum LoadRes
{
LoadRes_Successful,
@@ -152,18 +138,19 @@ public:
PluginType GetType();
SourcePawn::IPluginContext *GetBaseContext();
sp_context_t *GetContext();
- const sm_plugininfo_t *GetPublicInfo();
+ void *GetPluginStructure();
const char *GetFilename();
bool IsDebugging();
PluginStatus GetStatus();
+ const sm_plugininfo_t *GetPublicInfo();
bool SetPauseState(bool paused);
unsigned int GetSerial();
- const sp_plugin_t *GetPluginStructure();
IdentityToken_t *GetIdentity();
unsigned int CalcMemUsage();
bool SetProperty(const char *prop, void *ptr);
bool GetProperty(const char *prop, void **ptr, bool remove=false);
void DropEverything();
+ SourcePawn::IPluginRuntime *GetRuntime();
public:
/**
* Creates a plugin object with default values.
@@ -174,16 +161,6 @@ public:
*/
static CPlugin *CreatePlugin(const char *file, char *error, size_t maxlength);
public:
- /**
- * Starts the initial compilation of a plugin.
- * Returns false if another compilation exists or there is a current context set.
- */
- ICompilation *StartMyCompile(IVirtualMachine *vm);
- /**
- * Finalizes a compilation. If error buffer is NULL, the error is saved locally.
- */
- bool FinishMyCompile(char *error, size_t maxlength);
- void CancelMyCompile();
/**
* Sets an error state on the plugin
@@ -267,13 +244,11 @@ protected:
void SetTimeStamp(time_t t);
void DependencyDropped(CPlugin *pOwner);
private:
- ContextPair m_ctx;
PluginType m_type;
char m_filename[PLATFORM_MAX_PATH];
PluginStatus m_status;
unsigned int m_serial;
sm_plugininfo_t m_info;
- sp_plugin_t *m_plugin;
char m_errormsg[256];
time_t m_LastAccess;
IdentityToken_t *m_ident;
@@ -289,6 +264,8 @@ private:
bool m_bGotAllLoaded;
int m_FileVersion;
char m_DateTime[256];
+ IPluginRuntime *m_pRuntime;
+ IPluginContext *m_pContext;
};
class CPluginManager :
@@ -382,10 +359,7 @@ public:
/**
* Internal version of FindPluginByContext()
*/
- inline CPlugin *GetPluginByCtx(const sp_context_t *ctx)
- {
- return reinterpret_cast(ctx->user[SM_CONTEXTVAR_MYSELF]);
- }
+ CPlugin *GetPluginByCtx(const sp_context_t *ctx);
/**
* Gets status text for a status code
diff --git a/core/systems/ShareSys.cpp b/core/systems/ShareSys.cpp
index 391a9c7c..3d04f7fa 100644
--- a/core/systems/ShareSys.cpp
+++ b/core/systems/ShareSys.cpp
@@ -488,7 +488,7 @@ NativeEntry *ShareSystem::AddFakeNative(IPluginFunction *pFunc, const char *name
pFake = new FakeNative;
- if ((gate = g_pVM->CreateFakeNative(func, pFake)) == NULL)
+ if ((gate = g_pSourcePawn2->CreateFakeNative(func, pFake)) == NULL)
{
delete pFake;
return NULL;
diff --git a/core/vm/sp_vm_basecontext.cpp b/core/vm/sp_vm_basecontext.cpp
deleted file mode 100644
index b963d523..00000000
--- a/core/vm/sp_vm_basecontext.cpp
+++ /dev/null
@@ -1,1120 +0,0 @@
-/**
- * vim: set ts=4 :
- * =============================================================================
- * SourcePawn
- * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
- * =============================================================================
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, version 3.0, as published by the
- * Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see .
- *
- * As a special exception, AlliedModders LLC gives you permission to link the
- * code of this program (as well as its derivative works) to "Half-Life 2," the
- * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
- * by the Valve Corporation. You must obey the GNU General Public License in
- * all respects for all other code used. Additionally, AlliedModders LLC grants
- * this exception to all derivative works. AlliedModders LLC defines further
- * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
- * or .
- *
- * Version: $Id$
- */
-
-#include
-#include
-#include
-#include
-#include "sp_vm_api.h"
-#include "sp_vm_basecontext.h"
-#include "sp_vm_engine.h"
-
-#ifdef SOURCEMOD_BUILD
-#include "Logger.h"
-#include "DebugReporter.h"
-#endif
-
-using namespace SourcePawn;
-
-extern SourcePawnEngine g_SourcePawn;
-
-#define CELLBOUNDMAX (INT_MAX/sizeof(cell_t))
-#define STACKMARGIN ((cell_t)(16*sizeof(cell_t)))
-
-int GlobalDebugBreak(sp_context_t *ctx, uint32_t frm, uint32_t cip)
-{
- g_SourcePawn.RunTracer(ctx, frm, cip);
-
- return SP_ERROR_NONE;
-}
-
-BaseContext::BaseContext(sp_context_t *_ctx)
-{
- ctx = _ctx;
- ctx->context = this;
- ctx->dbreak = GlobalDebugBreak;
-
- if (ctx->prof_flags != 0)
- {
- ctx->profiler = sm_profiler;
- }
-
- m_InExec = false;
- m_CustomMsg = false;
- m_funcsnum = ctx->vmbase->FunctionCount(ctx);
-#if 0
- m_priv_funcs = NULL;
-#endif
- m_pub_funcs = NULL;
-
-#if 0
- /**
- * Note: Since the m_plugin member will never change,
- * it is safe to assume the function count will never change
- */
- if (m_funcsnum && m_priv_funcs == NULL)
- {
- m_priv_funcs = new CFunction *[m_funcsnum];
- memset(m_priv_funcs, 0, sizeof(CFunction *) * m_funcsnum);
- } else {
- m_priv_funcs = NULL;
- }
-#endif
-
- if (ctx->plugin->info.publics_num && m_pub_funcs == NULL)
- {
- m_pub_funcs = new CFunction *[ctx->plugin->info.publics_num];
- memset(m_pub_funcs, 0, sizeof(CFunction *) * ctx->plugin->info.publics_num);
- } else {
- m_pub_funcs = NULL;
- }
-
- /* Initialize the null references */
- uint32_t index;
- if (FindPubvarByName("NULL_VECTOR", &index) == SP_ERROR_NONE)
- {
- sp_pubvar_t *pubvar;
- GetPubvarByIndex(index, &pubvar);
- m_pNullVec = pubvar->offs;
- } else {
- m_pNullVec = NULL;
- }
-
- if (FindPubvarByName("NULL_STRING", &index) == SP_ERROR_NONE)
- {
- sp_pubvar_t *pubvar;
- GetPubvarByIndex(index, &pubvar);
- m_pNullString = pubvar->offs;
- } else {
- m_pNullString = NULL;
- }
-}
-
-void BaseContext::FlushFunctionCache()
-{
- if (m_pub_funcs)
- {
- for (uint32_t i=0; iplugin->info.publics_num; i++)
- {
- delete m_pub_funcs[i];
- m_pub_funcs[i] = NULL;
- }
- }
-
-#if 0
- if (m_priv_funcs)
- {
- for (unsigned int i=0; iplugin->info.publics_num; i++)
- {
- if (!m_pub_funcs[i])
- {
- continue;
- }
- if (GetPublicByIndex(i, &pub) != SP_ERROR_NONE)
- {
- continue;
- }
- m_pub_funcs[i]->Set(pub->code_offs, this, pub->funcid, i);
- }
- }
-
-#if 0
- if (m_priv_funcs)
- {
- for (unsigned int i=0; i
- }
- }
-#endif
-}
-
-BaseContext::~BaseContext()
-{
- FlushFunctionCache();
- delete [] m_pub_funcs;
- m_pub_funcs = NULL;
-#if 0
- delete [] m_priv_funcs;
- m_priv_funcs = NULL;
-#endif
-}
-
-void BaseContext::SetContext(sp_context_t *_ctx)
-{
- if (!_ctx)
- {
- return;
- }
-
- ctx = _ctx;
- ctx->context = this;
- ctx->dbreak = GlobalDebugBreak;
-
- if (ctx->prof_flags != 0)
- {
- ctx->profiler = sm_profiler;
- }
-
- RefreshFunctionCache();
-}
-
-IVirtualMachine *BaseContext::GetVirtualMachine()
-{
- return (IVirtualMachine *)ctx->vmbase;
-}
-
-sp_context_t *BaseContext::GetContext()
-{
- return ctx;
-}
-
-bool BaseContext::IsDebugging()
-{
- return (ctx->flags & SPFLAG_PLUGIN_DEBUG);
-}
-
-int BaseContext::SetDebugBreak(SPVM_DEBUGBREAK newpfn, SPVM_DEBUGBREAK *oldpfn)
-{
- if (!IsDebugging())
- {
- return SP_ERROR_NOTDEBUGGING;
- }
-
- *oldpfn = ctx->dbreak;
- ctx->dbreak = newpfn;
-
- return SP_ERROR_NONE;
-}
-
-IPluginDebugInfo *BaseContext::GetDebugInfo()
-{
- if (!IsDebugging())
- {
- return NULL;
- }
- return this;
-}
-
-int BaseContext::Execute(uint32_t code_addr, cell_t *result)
-{
- if ((ctx->flags & SPFLAG_PLUGIN_PAUSED) == SPFLAG_PLUGIN_PAUSED)
- {
- return SP_ERROR_NOT_RUNNABLE;
- }
-
- /* tada, prevent a crash */
- cell_t _ignore_result;
- if (!result)
- {
- result = &_ignore_result;
- }
-
- IVirtualMachine *vm = (IVirtualMachine *)ctx->vmbase;
-
- uint32_t pushcount = ctx->pushcount;
- int err;
-
- if ((err = PushCell(pushcount++)) != SP_ERROR_NONE)
- {
-#if defined SOURCEMOD_BUILD
- g_DbgReporter.GenerateCodeError(this, code_addr, err, "Stack error; cannot complete execution!");
-#endif
- return SP_ERROR_NOT_RUNNABLE;
- }
- ctx->pushcount = 0;
-
- cell_t save_sp = ctx->sp + (pushcount * sizeof(cell_t));
- cell_t save_hp = ctx->hp;
- uint32_t n_idx = ctx->n_idx;
-
- bool wasExec = m_InExec;
-
- /* Clear the error state, if any */
- ctx->n_err = SP_ERROR_NONE;
- ctx->n_idx = 0;
- m_InExec = true;
- m_MsgCache[0] = '\0';
- m_CustomMsg = false;
-
- g_SourcePawn.PushTracer(ctx);
-
- err = vm->ContextExecute(ctx, code_addr, result);
-
- m_InExec = wasExec;
-
- /**
- * :TODO: Calling from a plugin in here will erase the cached message...
- * Should that be documented?
- */
- g_SourcePawn.PopTracer(err, m_CustomMsg ? m_MsgCache : NULL);
-
-#if defined SOURCEMOD_BUILD
- if (err == SP_ERROR_NONE)
- {
- if (ctx->sp != save_sp)
- {
- g_DbgReporter.GenerateCodeError(this,
- code_addr,
- SP_ERROR_STACKLEAK,
- "Stack leak detected: sp:%d should be %d!",
- ctx->sp,
- save_sp);
- }
- if (ctx->hp != save_hp)
- {
- g_DbgReporter.GenerateCodeError(this,
- code_addr,
- SP_ERROR_HEAPLEAK,
- "Heap leak detected: sp:%d should be %d!",
- ctx->hp,
- save_hp);
- }
- }
-#endif
-
- if (err != SP_ERROR_NONE)
- {
- ctx->sp = save_sp;
- ctx->hp = save_hp;
- }
-
- ctx->n_idx = n_idx;
- ctx->n_err = SP_ERROR_NONE;
- m_MsgCache[0] = '\0';
- m_CustomMsg = false;
-
- return err;
-}
-
-void BaseContext::SetErrorMessage(const char *msg, va_list ap)
-{
- m_CustomMsg = true;
-
- vsnprintf(m_MsgCache, sizeof(m_MsgCache), msg, ap);
-}
-
-cell_t BaseContext::ThrowNativeErrorEx(int error, const char *msg, ...)
-{
- if (!m_InExec)
- {
- return 0;
- }
-
- ctx->n_err = error;
-
- if (msg)
- {
- va_list ap;
- va_start(ap, msg);
- SetErrorMessage(msg, ap);
- va_end(ap);
- }
-
- return 0;
-}
-
-cell_t BaseContext::ThrowNativeError(const char *msg, ...)
-{
- if (!m_InExec)
- {
- return 0;
- }
-
- ctx->n_err = SP_ERROR_NATIVE;
-
- if (msg)
- {
- va_list ap;
- va_start(ap, msg);
- SetErrorMessage(msg, ap);
- va_end(ap);
- }
-
- return 0;
-}
-
-int BaseContext::HeapAlloc(unsigned int cells, cell_t *local_addr, cell_t **phys_addr)
-{
- cell_t *addr;
- ucell_t realmem;
-
-#if 0
- if (cells > CELLBOUNDMAX)
- {
- return SP_ERROR_ARAM;
- }
-#else
- assert(cells < CELLBOUNDMAX);
-#endif
-
- realmem = cells * sizeof(cell_t);
-
- /**
- * Check if the space between the heap and stack is sufficient.
- */
- if ((cell_t)(ctx->sp - ctx->hp - realmem) < STACKMARGIN)
- {
- return SP_ERROR_HEAPLOW;
- }
-
- addr = (cell_t *)(ctx->memory + ctx->hp);
- /* store size of allocation in cells */
- *addr = (cell_t)cells;
- addr++;
- ctx->hp += sizeof(cell_t);
-
- *local_addr = ctx->hp;
-
- if (phys_addr)
- {
- *phys_addr = addr;
- }
-
- ctx->hp += realmem;
-
- return SP_ERROR_NONE;
-}
-
-int BaseContext::HeapPop(cell_t local_addr)
-{
- cell_t cellcount;
- cell_t *addr;
-
- /* check the bounds of this address */
- local_addr -= sizeof(cell_t);
- if (local_addr < ctx->heap_base || local_addr >= ctx->sp)
- {
- return SP_ERROR_INVALID_ADDRESS;
- }
-
- addr = (cell_t *)(ctx->memory + local_addr);
- cellcount = (*addr) * sizeof(cell_t);
- /* check if this memory count looks valid */
- if ((signed)(ctx->hp - cellcount - sizeof(cell_t)) != local_addr)
- {
- return SP_ERROR_INVALID_ADDRESS;
- }
-
- ctx->hp = local_addr;
-
- return SP_ERROR_NONE;
-}
-
-
-int BaseContext::HeapRelease(cell_t local_addr)
-{
- if (local_addr < ctx->heap_base)
- {
- return SP_ERROR_INVALID_ADDRESS;
- }
-
- ctx->hp = local_addr - sizeof(cell_t);
-
- return SP_ERROR_NONE;
-}
-
-int BaseContext::FindNativeByName(const char *name, uint32_t *index)
-{
- int high;
-
- high = ctx->plugin->info.natives_num - 1;
-
- for (uint32_t i=0; iplugin->info.natives_num; i++)
- {
- if (strcmp(ctx->natives[i].name, name) == 0)
- {
- if (index)
- {
- *index = i;
- }
- return SP_ERROR_NONE;
- }
- }
-
- return SP_ERROR_NOT_FOUND;
-}
-
-int BaseContext::GetNativeByIndex(uint32_t index, sp_native_t **native)
-{
- if (index >= ctx->plugin->info.natives_num)
- {
- return SP_ERROR_INDEX;
- }
-
- if (native)
- {
- *native = &(ctx->natives[index]);
- }
-
- return SP_ERROR_NONE;
-}
-
-
-uint32_t BaseContext::GetNativesNum()
-{
- return ctx->plugin->info.natives_num;
-}
-
-int BaseContext::FindPublicByName(const char *name, uint32_t *index)
-{
- int diff, high, low;
- uint32_t mid;
-
- high = ctx->plugin->info.publics_num - 1;
- low = 0;
-
- while (low <= high)
- {
- mid = (low + high) / 2;
- diff = strcmp(ctx->publics[mid].name, name);
- if (diff == 0)
- {
- if (index)
- {
- *index = mid;
- }
- return SP_ERROR_NONE;
- } else if (diff < 0) {
- low = mid + 1;
- } else {
- high = mid - 1;
- }
- }
-
- return SP_ERROR_NOT_FOUND;
-}
-
-int BaseContext::GetPublicByIndex(uint32_t index, sp_public_t **pblic)
-{
- if (index >= ctx->plugin->info.publics_num)
- {
- return SP_ERROR_INDEX;
- }
-
- if (pblic)
- {
- *pblic = &(ctx->publics[index]);
- }
-
- return SP_ERROR_NONE;
-}
-
-uint32_t BaseContext::GetPublicsNum()
-{
- return ctx->plugin->info.publics_num;
-}
-
-int BaseContext::GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar)
-{
- if (index >= ctx->plugin->info.pubvars_num)
- {
- return SP_ERROR_INDEX;
- }
-
- if (pubvar)
- {
- *pubvar = &(ctx->pubvars[index]);
- }
-
- return SP_ERROR_NONE;
-}
-
-int BaseContext::FindPubvarByName(const char *name, uint32_t *index)
-{
- int diff, high, low;
- uint32_t mid;
-
- high = ctx->plugin->info.pubvars_num - 1;
- low = 0;
-
- while (low <= high)
- {
- mid = (low + high) / 2;
- diff = strcmp(ctx->pubvars[mid].name, name);
- if (diff == 0)
- {
- if (index)
- {
- *index = mid;
- }
- return SP_ERROR_NONE;
- } else if (diff < 0) {
- low = mid + 1;
- } else {
- high = mid - 1;
- }
- }
-
- return SP_ERROR_NOT_FOUND;
-}
-
-int BaseContext::GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr)
-{
- if (index >= ctx->plugin->info.pubvars_num)
- {
- return SP_ERROR_INDEX;
- }
-
- *local_addr = ctx->plugin->info.pubvars[index].address;
- *phys_addr = ctx->pubvars[index].offs;
-
- return SP_ERROR_NONE;
-}
-
-uint32_t BaseContext::GetPubVarsNum()
-{
- return ctx->plugin->info.pubvars_num;
-}
-
-int BaseContext::BindNatives(const sp_nativeinfo_t *natives, unsigned int num, int overwrite)
-{
- uint32_t i, j, max;
-
- max = ctx->plugin->info.natives_num;
-
- for (i=0; inatives[i].status == SP_NATIVE_BOUND) && !overwrite)
- {
- continue;
- }
-
- for (j=0; (natives[j].name) && (!num || jnatives[i].name, natives[j].name))
- {
- ctx->natives[i].pfn = natives[j].func;
- ctx->natives[i].status = SP_NATIVE_BOUND;
- }
- }
- }
-
- return SP_ERROR_NONE;
-}
-
-int BaseContext::BindNative(const sp_nativeinfo_t *native)
-{
- uint32_t index;
- int err;
-
- if ((err = FindNativeByName(native->name, &index)) != SP_ERROR_NONE)
- {
- return err;
- }
-
- ctx->natives[index].pfn = native->func;
- ctx->natives[index].status = SP_NATIVE_BOUND;
-
- return SP_ERROR_NONE;
-}
-
-int BaseContext::BindNativeToIndex(uint32_t index, SPVM_NATIVE_FUNC func)
-{
- int err;
- sp_native_t *native;
-
- if ((err = GetNativeByIndex(index, &native)) != SP_ERROR_NONE)
- {
- return err;
- }
-
- ctx->natives[index].pfn = func;
- ctx->natives[index].status = SP_NATIVE_BOUND;
-
- return SP_ERROR_NONE;
-}
-
-int BaseContext::BindNativeToAny(SPVM_NATIVE_FUNC native)
-{
- uint32_t nativesnum, i;
-
- nativesnum = ctx->plugin->info.natives_num;
-
- for (i=0; inatives[i].status == SP_NATIVE_UNBOUND)
- {
- ctx->natives[i].pfn = native;
- ctx->natives[i].status = SP_NATIVE_BOUND;
- }
- }
-
- return SP_ERROR_NONE;
-}
-
-int BaseContext::LocalToPhysAddr(cell_t local_addr, cell_t **phys_addr)
-{
- if (((local_addr >= ctx->hp) && (local_addr < ctx->sp)) || (local_addr < 0) || ((ucell_t)local_addr >= ctx->mem_size))
- {
- return SP_ERROR_INVALID_ADDRESS;
- }
-
- if (phys_addr)
- {
- *phys_addr = (cell_t *)(ctx->memory + local_addr);
- }
-
- return SP_ERROR_NONE;
-}
-
-int BaseContext::PushCell(cell_t value)
-{
- if ((ctx->hp + STACKMARGIN) > (cell_t)(ctx->sp - sizeof(cell_t)))
- {
- return SP_ERROR_STACKLOW;
- }
-
- ctx->sp -= sizeof(cell_t);
- *(cell_t *)(ctx->memory + ctx->sp) = value;
- ctx->pushcount++;
-
- return SP_ERROR_NONE;
-}
-
-int BaseContext::PushCellsFromArray(cell_t array[], unsigned int numcells)
-{
- unsigned int i;
- int err;
-
- for (i=0; isp += (cell_t)(i * sizeof(cell_t));
- ctx->pushcount -= i;
- return err;
- }
- }
-
- return SP_ERROR_NONE;
-}
-
-int BaseContext::PushCellArray(cell_t *local_addr, cell_t **phys_addr, cell_t array[], unsigned int numcells)
-{
- cell_t *ph_addr;
- int err;
-
- if ((err = HeapAlloc(numcells, local_addr, &ph_addr)) != SP_ERROR_NONE)
- {
- return err;
- }
-
- memcpy(ph_addr, array, numcells * sizeof(cell_t));
-
- if ((err = PushCell(*local_addr)) != SP_ERROR_NONE)
- {
- HeapRelease(*local_addr);
- return err;
- }
-
- if (phys_addr)
- {
- *phys_addr = ph_addr;
- }
-
- return SP_ERROR_NONE;
-}
-
-int BaseContext::LocalToString(cell_t local_addr, char **addr)
-{
- if (((local_addr >= ctx->hp) && (local_addr < ctx->sp)) || (local_addr < 0) || ((ucell_t)local_addr >= ctx->mem_size))
- {
- return SP_ERROR_INVALID_ADDRESS;
- }
- *addr = (char *)(ctx->memory + local_addr);
-
- return SP_ERROR_NONE;
-}
-
-int BaseContext::PushString(cell_t *local_addr, char **phys_addr, const char *string)
-{
- char *ph_addr;
- int err;
- unsigned int len, numcells = ((len=strlen(string)) + sizeof(cell_t)) / sizeof(cell_t);
-
- if ((err = HeapAlloc(numcells, local_addr, (cell_t **)&ph_addr)) != SP_ERROR_NONE)
- {
- return err;
- }
-
- memcpy(ph_addr, string, len);
- ph_addr[len] = '\0';
-
- if ((err = PushCell(*local_addr)) != SP_ERROR_NONE)
- {
- HeapRelease(*local_addr);
- return err;
- }
-
- if (phys_addr)
- {
- *phys_addr = ph_addr;
- }
-
- return SP_ERROR_NONE;
-}
-
-int BaseContext::StringToLocal(cell_t local_addr, size_t bytes, const char *source)
-{
- char *dest;
- size_t len;
-
- if (((local_addr >= ctx->hp) && (local_addr < ctx->sp)) || (local_addr < 0) || ((ucell_t)local_addr >= ctx->mem_size))
- {
- return SP_ERROR_INVALID_ADDRESS;
- }
-
- if (bytes == 0)
- {
- return SP_ERROR_NONE;
- }
-
- len = strlen(source);
- dest = (char *)(ctx->memory + local_addr);
-
- if (len >= bytes)
- {
- len = bytes - 1;
- }
-
- memmove(dest, source, len);
- dest[len] = '\0';
-
- return SP_ERROR_NONE;
-}
-
-inline int __CheckValidChar(char *c)
-{
- int count;
- int bytecount = 0;
-
- for (count=1; (*c & 0xC0) == 0x80; count++)
- {
- c--;
- }
-
- switch (*c & 0xF0)
- {
- case 0xC0:
- case 0xD0:
- {
- bytecount = 2;
- break;
- }
- case 0xE0:
- {
- bytecount = 3;
- break;
- }
- case 0xF0:
- {
- bytecount = 4;
- break;
- }
- }
-
- if (bytecount != count)
- {
- return count;
- }
-
- return 0;
-}
-
-int BaseContext::StringToLocalUTF8(cell_t local_addr, size_t maxbytes, const char *source, size_t *wrtnbytes)
-{
- char *dest;
- size_t len;
- bool needtocheck = false;
-
- if (((local_addr >= ctx->hp) && (local_addr < ctx->sp)) || (local_addr < 0) || ((ucell_t)local_addr >= ctx->mem_size))
- {
- return SP_ERROR_INVALID_ADDRESS;
- }
-
- if (maxbytes == 0)
- {
- return SP_ERROR_NONE;
- }
-
- len = strlen(source);
- dest = (char *)(ctx->memory + local_addr);
-
- if ((size_t)len >= maxbytes)
- {
- len = maxbytes - 1;
- needtocheck = true;
- }
-
- memmove(dest, source, len);
- if ((dest[len-1] & 1<<7) && needtocheck)
- {
- len -= __CheckValidChar(dest+len-1);
- }
- dest[len] = '\0';
-
- if (wrtnbytes)
- {
- *wrtnbytes = len;
- }
-
- return SP_ERROR_NONE;
-}
-
-#define USHR(x) ((unsigned int)(x)>>1)
-
-int BaseContext::LookupFile(ucell_t addr, const char **filename)
-{
- int high, low, mid;
-
- high = ctx->plugin->debug.files_num;
- low = -1;
-
- while (high - low > 1)
- {
- mid = USHR(low + high);
- if (ctx->files[mid].addr <= addr)
- {
- low = mid;
- } else {
- high = mid;
- }
- }
-
- if (low == -1)
- {
- return SP_ERROR_NOT_FOUND;
- }
-
- *filename = ctx->files[low].name;
-
- return SP_ERROR_NONE;
-}
-
-int BaseContext::LookupFunction(ucell_t addr, const char **name)
-{
- uint32_t iter, max = ctx->plugin->debug.syms_num;
-
- for (iter=0; itersymbols[iter].sym->ident == SP_SYM_FUNCTION)
- && (ctx->symbols[iter].codestart <= addr)
- && (ctx->symbols[iter].codeend > addr))
- {
- break;
- }
- }
-
- if (iter >= max)
- {
- return SP_ERROR_NOT_FOUND;
- }
-
- *name = ctx->symbols[iter].name;
-
- return SP_ERROR_NONE;
-}
-
-int BaseContext::LookupLine(ucell_t addr, uint32_t *line)
-{
- int high, low, mid;
-
- high = ctx->plugin->debug.lines_num;
- low = -1;
-
- while (high - low > 1)
- {
- mid = USHR(low + high);
- if (ctx->lines[mid].addr <= addr)
- {
- low = mid;
- } else {
- high = mid;
- }
- }
-
- if (low == -1)
- {
- return SP_ERROR_NOT_FOUND;
- }
-
- /* Since the CIP occurs BEFORE the line, we have to add one */
- *line = ctx->lines[low].line + 1;
-
- return SP_ERROR_NONE;
-}
-
-IPluginFunction *BaseContext::GetFunctionById(funcid_t func_id)
-{
- CFunction *pFunc = NULL;
-
- if (func_id & 1)
- {
- func_id >>= 1;
- if (func_id >= ctx->plugin->info.publics_num)
- {
- return NULL;
- }
- pFunc = m_pub_funcs[func_id];
- if (!pFunc)
- {
- m_pub_funcs[func_id] = new CFunction(ctx->publics[func_id].code_offs,
- this,
- ctx->publics[func_id].funcid,
- func_id);
- pFunc = m_pub_funcs[func_id];
- }
- else if (pFunc->IsInvalidated())
- {
- pFunc->Set(ctx->publics[func_id].code_offs,
- this,
- ctx->publics[func_id].funcid,
- func_id);
- }
- } else {
- /* :TODO: currently not used */
-#if 0
- func_id >>= 1;
- unsigned int index;
- if (!g_pVM->FunctionLookup(ctx, func_id, &index))
- {
- return NULL;
- }
- pFunc = m_priv_funcs[func_id];
- if (!pFunc)
- {
- m_priv_funcs[func_id] = new CFunction(save, this);
- pFunc = m_priv_funcs[func_id];
- }
-#endif
- }
-
- return pFunc;
-}
-
-IPluginFunction *BaseContext::GetFunctionByName(const char *public_name)
-{
- uint32_t index;
-
- if (FindPublicByName(public_name, &index) != SP_ERROR_NONE)
- {
- return NULL;
- }
-
- CFunction *pFunc = m_pub_funcs[index];
- if (!pFunc)
- {
- sp_public_t *pub = NULL;
- GetPublicByIndex(index, &pub);
- if (pub)
- {
- m_pub_funcs[index] = new CFunction(pub->code_offs, this, pub->funcid, index);
- }
- pFunc = m_pub_funcs[index];
- }
- else if (pFunc->IsInvalidated())
- {
- sp_public_t *pub = NULL;
- GetPublicByIndex(index, &pub);
- if (pub)
- {
- pFunc->Set(pub->code_offs, this, pub->funcid, index);
- }
- else
- {
- pFunc = NULL;
- }
- }
-
- return pFunc;
-}
-
-int BaseContext::LocalToStringNULL(cell_t local_addr, char **addr)
-{
- int err;
- if ((err = LocalToString(local_addr, addr)) != SP_ERROR_NONE)
- {
- return err;
- }
-
- if ((cell_t *)*addr == m_pNullString)
- {
- *addr = NULL;
- }
-
- return SP_ERROR_NONE;
-}
-
-#if defined SOURCEMOD_BUILD
-SourceMod::IdentityToken_t *BaseContext::GetIdentity()
-{
- return m_pToken;
-}
-
-void BaseContext::SetIdentity(SourceMod::IdentityToken_t *token)
-{
- m_pToken = token;
-}
-
-cell_t *BaseContext::GetNullRef(SP_NULL_TYPE type)
-{
- if (type == SP_NULL_VECTOR)
- {
- return m_pNullVec;
- }
-
- return NULL;
-}
-#endif
-
-bool BaseContext::IsInExec()
-{
- return m_InExec;
-}
diff --git a/core/vm/sp_vm_basecontext.h b/core/vm/sp_vm_basecontext.h
deleted file mode 100644
index 4b58937e..00000000
--- a/core/vm/sp_vm_basecontext.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/**
- * vim: set ts=4 :
- * =============================================================================
- * SourcePawn
- * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
- * =============================================================================
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, version 3.0, as published by the
- * Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see .
- *
- * As a special exception, AlliedModders LLC gives you permission to link the
- * code of this program (as well as its derivative works) to "Half-Life 2," the
- * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
- * by the Valve Corporation. You must obey the GNU General Public License in
- * all respects for all other code used. Additionally, AlliedModders LLC grants
- * this exception to all derivative works. AlliedModders LLC defines further
- * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
- * or .
- *
- * Version: $Id$
- */
-
-#ifndef _INCLUDE_SOURCEPAWN_BASECONTEXT_H_
-#define _INCLUDE_SOURCEPAWN_BASECONTEXT_H_
-
-#include "sp_vm_api.h"
-#include "sp_vm_function.h"
-
-/**
- * :TODO: Make functions allocate as a lump instead of individual allocations!
- */
-
-extern IProfiler *sm_profiler;
-
-namespace SourcePawn
-{
- class BaseContext :
- public IPluginContext,
- public IPluginDebugInfo
- {
- public:
- BaseContext(sp_context_t *ctx);
- ~BaseContext();
- public: //IPluginContext
- IVirtualMachine *GetVirtualMachine();
- sp_context_t *GetContext();
- bool IsDebugging();
- int SetDebugBreak(SPVM_DEBUGBREAK newpfn, SPVM_DEBUGBREAK *oldpfn);
- IPluginDebugInfo *GetDebugInfo();
- int HeapAlloc(unsigned int cells, cell_t *local_addr, cell_t **phys_addr);
- int HeapPop(cell_t local_addr);
- int HeapRelease(cell_t local_addr);
- int FindNativeByName(const char *name, uint32_t *index);
- int GetNativeByIndex(uint32_t index, sp_native_t **native);
- uint32_t GetNativesNum();
- int FindPublicByName(const char *name, uint32_t *index);
- int GetPublicByIndex(uint32_t index, sp_public_t **publicptr);
- uint32_t GetPublicsNum();
- int GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar);
- int FindPubvarByName(const char *name, uint32_t *index);
- int GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr);
- uint32_t GetPubVarsNum();
- int LocalToPhysAddr(cell_t local_addr, cell_t **phys_addr);
- int LocalToString(cell_t local_addr, char **addr);
- int StringToLocal(cell_t local_addr, size_t chars, const char *source);
- int StringToLocalUTF8(cell_t local_addr, size_t maxbytes, const char *source, size_t *wrtnbytes);
- int PushCell(cell_t value);
- int PushCellArray(cell_t *local_addr, cell_t **phys_addr, cell_t array[], unsigned int numcells);
- int PushString(cell_t *local_addr, char **phys_addr, const char *string);
- int PushCellsFromArray(cell_t array[], unsigned int numcells);
- int BindNatives(const sp_nativeinfo_t *natives, unsigned int num, int overwrite);
- int BindNative(const sp_nativeinfo_t *native);
- int BindNativeToAny(SPVM_NATIVE_FUNC native);
- int Execute(uint32_t code_addr, cell_t *result);
- cell_t ThrowNativeErrorEx(int error, const char *msg, ...);
- cell_t ThrowNativeError(const char *msg, ...);
- IPluginFunction *GetFunctionByName(const char *public_name);
- IPluginFunction *GetFunctionById(funcid_t func_id);
-#if defined SOURCEMOD_BUILD
- SourceMod::IdentityToken_t *GetIdentity();
- void SetIdentity(SourceMod::IdentityToken_t *token);
- cell_t *GetNullRef(SP_NULL_TYPE type);
- int LocalToStringNULL(cell_t local_addr, char **addr);
-#endif
- int BindNativeToIndex(uint32_t index, SPVM_NATIVE_FUNC native);
- public: //IPluginDebugInfo
- int LookupFile(ucell_t addr, const char **filename);
- int LookupFunction(ucell_t addr, const char **name);
- int LookupLine(ucell_t addr, uint32_t *line);
- public:
- void SetContext(sp_context_t *_ctx);
- bool IsInExec();
- private:
- void SetErrorMessage(const char *msg, va_list ap);
- void FlushFunctionCache();
- void RefreshFunctionCache();
- private:
- sp_context_t *ctx;
-#if defined SOURCEMOD_BUILD
- SourceMod::IdentityToken_t *m_pToken;
- cell_t *m_pNullVec;
- cell_t *m_pNullString;
-#endif
- char m_MsgCache[1024];
- bool m_CustomMsg;
- bool m_InExec;
- unsigned int m_funcsnum;
-#if 0
- CFunction **m_priv_funcs;
-#endif
- CFunction **m_pub_funcs;
- };
-};
-
-#endif //_INCLUDE_SOURCEPAWN_BASECONTEXT_H_
diff --git a/public/IPluginSys.h b/public/IPluginSys.h
index c6dd0313..6c0d9d46 100644
--- a/public/IPluginSys.h
+++ b/public/IPluginSys.h
@@ -109,25 +109,25 @@ namespace SourceMod
virtual PluginType GetType() =0;
/**
- * @brief Returns the current API context being used in the plugin.
+ * @brief Returns the IPluginRuntime::GetDefaultContext() value.
*
* @return Pointer to an IPluginContext, or NULL if not loaded.
*/
virtual SourcePawn::IPluginContext *GetBaseContext() =0;
/**
- * @brief Returns the context structure being used in the plugin.
+ * @brief Deprecated, returns NULL.
*
- * @return Pointer to an sp_context_t, or NULL if not loaded.
+ * @return NULL.
*/
virtual sp_context_t *GetContext() =0;
/**
- * @brief Returns the plugin file structure.
+ * @brief Deprecated, returns NULL.
*
- * @return Pointer to an sp_plugin_t, or NULL if not loaded.
+ * @return NULL.
*/
- virtual const sp_plugin_t *GetPluginStructure() =0;
+ virtual void *GetPluginStructure() =0;
/**
* @brief Returns information about the plugin by reference.
@@ -189,6 +189,13 @@ namespace SourceMod
* @return True if the property existed, false otherwise.
*/
virtual bool GetProperty(const char *prop, void **ptr, bool remove=false) =0;
+
+ /**
+ * @brief Returns the runtime representing this plugin.
+ *
+ * @return IPluginRuntime pointer, or NULL if not loaded.
+ */
+ virtual SourcePawn::IPluginRuntime *GetRuntime() =0;
};
diff --git a/public/ISourceMod.h b/public/ISourceMod.h
index 80fa1d05..e9ec4ac9 100644
--- a/public/ISourceMod.h
+++ b/public/ISourceMod.h
@@ -203,9 +203,9 @@ namespace SourceMod
virtual SourcePawn::ISourcePawnEngine *GetScriptingEngine() =0;
/**
- * @brief Returns the JIT interface.
+ * @brief Deprecated, do not use.
*
- * @return A pointer to the JIT interface.
+ * @return NULL.
*/
virtual SourcePawn::IVirtualMachine *GetScriptingVM() =0;
diff --git a/public/sourcepawn/sp_vm_api.h b/public/sourcepawn/sp_vm_api.h
index ee9db35a..6de6f6ee 100644
--- a/public/sourcepawn/sp_vm_api.h
+++ b/public/sourcepawn/sp_vm_api.h
@@ -41,10 +41,8 @@
#include "sp_vm_types.h"
/** SourcePawn Engine API Version */
-#define SOURCEPAWN_ENGINE_API_VERSION 3
-
-/** SourcePawn VM API Version */
-#define SOURCEPAWN_VM_API_VERSION 7
+#define SOURCEPAWN_ENGINE_API_VERSION 4
+#define SOURCEPAWN_ENGINE2_API_VERSION 1
#if !defined SOURCEMOD_BUILD
#define SOURCEMOD_BUILD
@@ -57,6 +55,9 @@ namespace SourceMod
};
#endif
+struct sp_context_s;
+typedef struct sp_context_s sp_context_t;
+
namespace SourcePawn
{
class IVirtualMachine;
@@ -185,7 +186,8 @@ namespace SourcePawn
{
public:
/**
- * @brief Executes the forward, resets the pushed parameter list, and performs any copybacks.
+ * @brief Executes the function, resets the pushed parameter list, and
+ * performs any copybacks.
*
* @param result Pointer to store return value in.
* @return Error code, if any.
@@ -206,9 +208,9 @@ namespace SourcePawn
virtual int CallFunction(const cell_t *params, unsigned int num_params, cell_t *result) =0;
/**
- * @brief Returns which plugin this function belongs to.
+ * @brief Deprecated, do not use.
*
- * @return IPluginContext pointer to parent plugin.
+ * @return GetDefaultContext() of parent runtime.
*/
virtual IPluginContext *GetParentContext() =0;
@@ -227,6 +229,37 @@ namespace SourcePawn
* @return Function id.
*/
virtual funcid_t GetFunctionID() =0;
+
+ /**
+ * @brief Executes the forward, resets the pushed parameter list, and
+ * performs any copybacks.
+ *
+ * Note: A function can only be executed given a runtime it was created in.
+ *
+ * @param ctx Context to execute the function in.
+ * @param result Pointer to store return value in.
+ * @return Error code, if any.
+ */
+ virtual int Execute2(IPluginContext *ctx, cell_t *result) =0;
+
+ /**
+ * @brief Executes the function with the given parameter array.
+ * Parameters are read in forward order (i.e. index 0 is parameter #1)
+ * NOTE: You will get an error if you attempt to use CallFunction() with
+ * previously pushed parameters.
+ *
+ * Note: A function can only be executed given a runtime it was created in.
+ *
+ * @param ctx Context to execute the function in.
+ * @param params Array of cell parameters.
+ * @param num_params Number of parameters to push.
+ * @param result Pointer to store result of function on return.
+ * @return SourcePawn error code (if any).
+ */
+ virtual int CallFunction2(IPluginContext *ctx,
+ const cell_t *params,
+ unsigned int num_params,
+ cell_t *result) =0;
};
@@ -262,43 +295,38 @@ namespace SourcePawn
};
/**
- * @brief Interface to managing a context at runtime.
+ * @brief Represents a JIT compilation or plugin loading options.
*/
- class IPluginContext
+ class ICompilation
{
public:
- /** Virtual destructor */
- virtual ~IPluginContext() { };
+ /**
+ * @brief Sets a compilation option.
+ *
+ * @param key Option name.
+ * @param val Option value.
+ * @return True on success, false on failure.
+ */
+ virtual bool SetOption(const char *key, const char *val) =0;
+
+ /**
+ * @brief Aborts the compilation and destroys this object.
+ */
+ virtual void Abort() =0;
+ };
+
+ /**
+ * @brief Interface to managing a runtime plugin.
+ */
+ class IPluginRuntime
+ {
public:
- /**
- * @brief Returns the parent IVirtualMachine.
- *
- * @return Parent virtual machine pointer.
- */
- virtual IVirtualMachine *GetVirtualMachine() =0;
-
/**
- * @brief Returns the child sp_context_t structure.
- *
- * @return Child sp_context_t structure.
+ * @brief Virtual destructor (you may call delete).
*/
- virtual sp_context_t *GetContext() =0;
-
- /**
- * @brief Returns true if the plugin is in debug mode.
- *
- * @return True if in debug mode, false otherwise.
- */
- virtual bool IsDebugging() =0;
-
- /**
- * @brief Installs a debug break and returns the old one, if any.
- * This will fail if the plugin is not debugging.
- *
- * @param newpfn New function pointer.
- * @param oldpfn Pointer to retrieve old function pointer.
- */
- virtual int SetDebugBreak(SPVM_DEBUGBREAK newpfn, SPVM_DEBUGBREAK *oldpfn) =0;
+ virtual ~IPluginRuntime()
+ {
+ }
/**
* @brief Returns debug info.
@@ -307,39 +335,6 @@ namespace SourcePawn
*/
virtual IPluginDebugInfo *GetDebugInfo() =0;
- /**
- * @brief Allocates memory on the secondary stack of a plugin.
- * Note that although called a heap, it is in fact a stack.
- *
- * @param cells Number of cells to allocate.
- * @param local_addr Will be filled with data offset to heap.
- * @param phys_addr Physical address to heap memory.
- */
- virtual int HeapAlloc(unsigned int cells, cell_t *local_addr, cell_t **phys_addr) =0;
-
- /**
- * @brief Pops a heap address off the heap stack. Use this to free memory allocated with
- * SP_HeapAlloc().
- * Note that in SourcePawn, the heap is in fact a bottom-up stack. Deallocations
- * with this native should be performed in precisely the REVERSE order.
- *
- * @param local_addr Local address to free.
- */
- virtual int HeapPop(cell_t local_addr) =0;
-
- /**
- * @brief Releases a heap address using a different method than SP_HeapPop().
- * This allows you to release in any order. However, if you allocate N
- * objects, release only some of them, then begin allocating again,
- * you cannot go back and starting freeing the originals.
- * In other words, for each chain of allocations, if you start deallocating,
- * then allocating more in a chain, you must only deallocate from the current
- * allocation chain. This is basically HeapPop() except on a larger scale.
- *
- * @param local_addr Local address to free.
- */
- virtual int HeapRelease(cell_t local_addr) =0;
-
/**
* @brief Finds a native by name.
*
@@ -419,7 +414,227 @@ namespace SourcePawn
virtual uint32_t GetPubVarsNum() =0;
/**
- * @brief Round-about method of converting a plugin reference to a physical address
+ * @brief Returns a function by name.
+ *
+ * @param public_name Name of the function.
+ * @return A new IPluginFunction pointer, NULL if not found.
+ */
+ virtual IPluginFunction *GetFunctionByName(const char *public_name) =0;
+
+ /**
+ * @brief Returns a function by its id.
+ *
+ * @param func_id Function ID.
+ * @return A new IPluginFunction pointer, NULL if not found.
+ */
+ virtual IPluginFunction *GetFunctionById(funcid_t func_id) =0;
+
+ /**
+ * @brief Returns the default context. The default context
+ * should not be destroyed.
+ *
+ * @return Default context pointer.
+ */
+ virtual IPluginContext *GetDefaultContext() =0;
+
+ /**
+ * @brief Returns true if the plugin is in debug mode.
+ *
+ * @return True if in debug mode, false otherwise.
+ */
+ virtual bool IsDebugging() =0;
+
+ /**
+ * @brief Applies new compilation/runtime settings to the runtime code.
+ *
+ * The compilation object is destroyed once this function completes.
+ *
+ * @return Error code (SP_ERROR_NONE on success).
+ */
+ virtual int ApplyCompilationOptions(ICompilation *co) =0;
+
+ /**
+ * @brief Sets whether or not the plugin is paused (cannot be run).
+ *
+ * @param pause Pause state.
+ */
+ virtual void SetPauseState(bool paused) =0;
+
+ /**
+ * @brief Returns whether or not the plugin is paused (runnable).
+ *
+ * @return Pause state (true = paused, false = not).
+ */
+ virtual bool IsPaused() =0;
+
+ /**
+ * @brief Returns the estimated memory usage of this plugin.
+ *
+ * @return Memory usage, in bytes.
+ */
+ virtual size_t GetMemUsage() =0;
+ };
+
+ /**
+ * @brief Interface to managing a context at runtime.
+ */
+ class IPluginContext
+ {
+ public:
+ /** Virtual destructor */
+ virtual ~IPluginContext() { };
+ public:
+ /**
+ * @brief Deprecated, does nothing.
+ *
+ * @return NULL.
+ */
+ virtual IVirtualMachine *GetVirtualMachine() =0;
+
+ /**
+ * @brief Deprecated, do not use.
+ *
+ * Returns the pointer of this object, casted to an opaque structure.
+ *
+ * @return Returns this.
+ */
+ virtual sp_context_t *GetContext() =0;
+
+ /**
+ * @brief Returns true if the plugin is in debug mode.
+ *
+ * @return True if in debug mode, false otherwise.
+ */
+ virtual bool IsDebugging() =0;
+
+ /**
+ * @brief Deprecated, does nothing.
+ *
+ * @param newpfn Unused.
+ * @param oldpfn Unused.
+ */
+ virtual int SetDebugBreak(void *newpfn, void *oldpfn) =0;
+
+ /**
+ * @brief Deprecated, do not use.
+ *
+ * @return NULL.
+ */
+ virtual IPluginDebugInfo *GetDebugInfo() =0;
+
+ /**
+ * @brief Allocates memory on the secondary stack of a plugin.
+ * Note that although called a heap, it is in fact a stack.
+ *
+ * @param cells Number of cells to allocate.
+ * @param local_addr Will be filled with data offset to heap.
+ * @param phys_addr Physical address to heap memory.
+ */
+ virtual int HeapAlloc(unsigned int cells, cell_t *local_addr, cell_t **phys_addr) =0;
+
+ /**
+ * @brief Pops a heap address off the heap stack. Use this to free memory allocated with
+ * SP_HeapAlloc().
+ * Note that in SourcePawn, the heap is in fact a bottom-up stack. Deallocations
+ * with this native should be performed in precisely the REVERSE order.
+ *
+ * @param local_addr Local address to free.
+ */
+ virtual int HeapPop(cell_t local_addr) =0;
+
+ /**
+ * @brief Releases a heap address using a different method than SP_HeapPop().
+ * This allows you to release in any order. However, if you allocate N
+ * objects, release only some of them, then begin allocating again,
+ * you cannot go back and starting freeing the originals.
+ * In other words, for each chain of allocations, if you start deallocating,
+ * then allocating more in a chain, you must only deallocate from the current
+ * allocation chain. This is basically HeapPop() except on a larger scale.
+ *
+ * @param local_addr Local address to free.
+ */
+ virtual int HeapRelease(cell_t local_addr) =0;
+
+ /**
+ * @brief Deprecated, use IPluginRuntime instead.
+ *
+ * @param name Name of native.
+ * @param index Optionally filled with native index number.
+ */
+ virtual int FindNativeByName(const char *name, uint32_t *index) =0;
+
+ /**
+ * @brief Deprecated, use IPluginRuntime instead.
+ *
+ * @param index Index number of native.
+ * @param native Optionally filled with pointer to native structure.
+ */
+ virtual int GetNativeByIndex(uint32_t index, sp_native_t **native) =0;
+
+ /**
+ * @brief Deprecated, use IPluginRuntime instead.
+ *
+ * @return Filled with the number of natives.
+ */
+ virtual uint32_t GetNativesNum() =0;
+
+ /**
+ * @brief Deprecated, use IPluginRuntime instead.
+ *
+ * @param name Name of public
+ * @param index Optionally filled with public index number.
+ */
+ virtual int FindPublicByName(const char *name, uint32_t *index) =0;
+
+ /**
+ * @brief Deprecated, use IPluginRuntime instead.
+ *
+ * @param index Public function index number.
+ * @param publicptr Optionally filled with pointer to public structure.
+ */
+ virtual int GetPublicByIndex(uint32_t index, sp_public_t **publicptr) =0;
+
+ /**
+ * @brief Deprecated, use IPluginRuntime instead.
+ *
+ * @return Filled with the number of public functions.
+ */
+ virtual uint32_t GetPublicsNum() =0;
+
+ /**
+ * @brief Deprecated, use IPluginRuntime instead.
+ *
+ * @param index Public variable index number.
+ * @param pubvar Optionally filled with pointer to pubvar structure.
+ */
+ virtual int GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar) =0;
+
+ /**
+ * @brief Deprecated, use IPluginRuntime instead.
+ *
+ * @param name Name of pubvar
+ * @param index Optionally filled with pubvar index number.
+ */
+ virtual int FindPubvarByName(const char *name, uint32_t *index) =0;
+
+ /**
+ * @brief Deprecated, use IPluginRuntime instead.
+ *
+ * @param index Index of public variable.
+ * @param local_addr Address to store local address in.
+ * @param phys_addr Address to store physically relocated in.
+ */
+ virtual int GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr) =0;
+
+ /**
+ * @brief Deprecated, use IPluginRuntime instead.
+ *
+ * @return Number of public variables.
+ */
+ virtual uint32_t GetPubVarsNum() =0;
+
+ /**
+ * @brief Converts a plugin reference to a physical address
*
* @param local_addr Local address in plugin.
* @param phys_addr Optionally filled with relocated physical address.
@@ -445,8 +660,8 @@ namespace SourcePawn
/**
* @brief Converts a physical UTF-8 string to a local address.
- * This function is the same as the ANSI version, except it will copy the maximum number of characters possible
- * without accidentally chopping a multi-byte character.
+ * This function is the same as the ANSI version, except it will copy the maximum number
+ * of characters possible without accidentally chopping a multi-byte character.
*
* @param local_addr Local address in plugin.
* @param maxbytes Number of bytes to write, including NULL terminator.
@@ -459,48 +674,41 @@ namespace SourcePawn
size_t *wrtnbytes) =0;
/**
- * @brief Pushes a cell onto the stack. Increases the parameter count by one.
+ * @brief Deprecated, does nothing.
*
- * @param value Cell value.
+ * @param value Unused.
*/
virtual int PushCell(cell_t value) =0;
/**
- * @brief Pushes an array of cells onto the stack. Increases the parameter count by one.
- * If the function returns an error it will fail entirely, releasing anything allocated in the process.
- * Note that this does not release the heap, so you should release it after
- * calling Execute().
+ * @brief Deprecated, does nothing.
*
- * @param local_addr Filled with local address to release.
- * @param phys_addr Optionally filled with physical address of new array.
- * @param array Cell array to copy.
- * @param numcells Number of cells in the array to copy.
+ * @param local_addr Unused.
+ * @param phys_addr Unused.
+ * @param array Unused.
+ * @param numcells Unused.
*/
virtual int PushCellArray(cell_t *local_addr, cell_t **phys_addr, cell_t array[], unsigned int numcells) =0;
/**
- * @brief Pushes a string onto the stack (by reference) and increases the parameter count by one.
- * Note that this does not release the heap, so you should release it after
- * calling Execute().
+ * @brief Deprecated, does nothing.
*
- * @param local_addr Filled with local address to release.
- * @param phys_addr Optionally filled with physical address of new array.
- * @param string Source string to push.
+ * @param local_addr Unused.
+ * @param phys_addr Unused.
+ * @param string Unused.
*/
virtual int PushString(cell_t *local_addr, char **phys_addr, const char *string) =0;
/**
- * @brief Individually pushes each cell of an array of cells onto the stack. Increases the
- * parameter count by the number of cells pushed.
- * If the function returns an error it will fail entirely, releasing anything allocated in the process.
+ * @brief Deprecated, does nothing.
*
- * @param array Array of cells to read from.
- * @param numcells Number of cells to read.
+ * @param array Unused.
+ * @param numcells Unused.
*/
virtual int PushCellsFromArray(cell_t array[], unsigned int numcells) =0;
/**
- * @brief Deprecated; do not use.
+ * @brief Deprecated, does nothing.
*
* @param natives Deprecated; do not use.
* @param num Deprecated; do not use.
@@ -509,25 +717,25 @@ namespace SourcePawn
virtual int BindNatives(const sp_nativeinfo_t *natives, unsigned int num, int overwrite) =0;
/**
- * @brief Deprecated; do not use.
+ * @brief Deprecated, does nothing.
*
* @param native Deprecated; do not use.
*/
virtual int BindNative(const sp_nativeinfo_t *native) =0;
/**
- * @brief Binds a single native to any non-registered native.
+ * @brief Deprecated, does nothing.
*
- * @param native Native to bind.
+ * @param native Unused.
*/
virtual int BindNativeToAny(SPVM_NATIVE_FUNC native) =0;
/**
- * @brief Executes a function ID located in this context.
+ * @brief Deprecated, does nothing.
*
- * @param code_addr Address to execute at.
- * @param result Pointer to store the return value (required).
- * @return Error code (if any) from the VM.
+ * @param code_addr Unused.
+ * @param result Unused.
+ * @return SP_ERROR_ABORTED.
*/
virtual int Execute(uint32_t code_addr, cell_t *result) =0;
@@ -566,10 +774,10 @@ namespace SourcePawn
*/
virtual IPluginFunction *GetFunctionById(funcid_t func_id) =0;
-#if defined SOURCEMOD_BUILD
/**
* @brief Returns the identity token for this context.
- * Note: This is a helper function for native calls and the Handle System.
+ *
+ * Note: This is a compatibility shim and is the same as GetKey(1).
*
* @return Identity token.
*/
@@ -592,7 +800,6 @@ namespace SourcePawn
* @param addr Destination output pointer.
*/
virtual int LocalToStringNULL(cell_t local_addr, char **addr) =0;
-#endif
/**
* @brief Deprecated; do not use.
@@ -608,6 +815,67 @@ namespace SourcePawn
* @return True if in exec, false otherwise.
*/
virtual bool IsInExec() =0;
+
+ /**
+ * @brief Returns the parent runtime of a context.
+ *
+ * @return Parent runtime.
+ */
+ virtual IPluginRuntime *GetRuntime() =0;
+
+ /**
+ * @brief Executes a function in the context. The function must be
+ * a member of the context's parent runtime.
+ *
+ * @param function Function.
+ * @param params Parameters.
+ * @param num_params Number of parameters in the parameter array.
+ * @param result Optional pointer to store the result on success.
+ * @return Error code.
+ */
+ virtual int Execute2(IPluginFunction *function,
+ const cell_t *params,
+ unsigned int num_params,
+ cell_t *result) =0;
+
+ /**
+ * @brief Returns whether a context is in an error state.
+ *
+ * This should only be used inside natives to determine whether
+ * a prior call failed.
+ */
+ virtual int GetLastNativeError() =0;
+
+ /**
+ * @brief Returns the local parameter stack, starting from the
+ * cell that contains the number of parameters passed.
+ *
+ * Local parameters are the parameters passed to the function
+ * from which a native was called (and thus this can only be
+ * called inside a native).
+ *
+ * @return Parameter stack.
+ */
+ virtual cell_t *GetLocalParams() =0;
+
+ /**
+ * @brief Sets a local "key" that can be used for fast lookup.
+ *
+ * Only the "owner" of the context should be setting this.
+ *
+ * @param key Key number (values allowed: 1 through 4).
+ * @param value Pointer value.
+ */
+ virtual void SetKey(int k, void *value) =0;
+
+ /**
+ * @brief Retrieves a previously set "key."
+ *
+ * @param key Key number (values allowed: 1 through 4).
+ * @param value Pointer to store value.
+ * @return True on success, false on failure.
+ */
+ virtual bool GetKey(int k, void **value) =0;
};
@@ -748,6 +1016,9 @@ namespace SourcePawn
virtual void OnCallbackEnd(int serial) =0;
};
+ struct sp_plugin_s;
+ typedef struct sp_plugin_s sp_plugin_t;
+
/**
* @brief Contains helper functions used by VMs and the host app
*/
@@ -755,30 +1026,29 @@ namespace SourcePawn
{
public:
/**
- * @brief Loads a named file from a file pointer.
- * Note: Using this means the memory will be allocated by the VM.
+ * @brief Deprecated, do not use.
*
- * @param fp File pointer. May be at any offset. Not closed on return.
- * @param err Optional error code pointer.
- * @return A new plugin structure.
+ * @param fp Unused.
+ * @param err Unused.
+ * @return NULL.
*/
virtual sp_plugin_t *LoadFromFilePointer(FILE *fp, int *err) =0;
/**
- * @brief Loads a file from a base memory address.
+ * @brief Deprecated, do not use,
*
- * @param base Base address of the plugin's memory region.
- * @param plugin If NULL, a new plugin pointer is returned.
- * Otherwise, the passed pointer is used.
- * @param err Optional error code pointer.
- * @return The resulting plugin pointer.
+ * @param base Unused.
+ * @param plugin Unused.
+ * @param err Unused.
+ * @return NULL.
*/
virtual sp_plugin_t *LoadFromMemory(void *base, sp_plugin_t *plugin, int *err) =0;
/**
- * Frees all of the memory associated with a plugin file.
- * If allocated using SP_LoadFromMemory, the base and plugin pointer
- * itself are not freed (so this may end up doing nothing).
+ * @brief Deprecated, do not use.
+ *
+ * @param plugin Unused.
+ * @return SP_ERROR_ABORTED.
*/
virtual int FreeFromMemory(sp_plugin_t *plugin) =0;
@@ -826,9 +1096,9 @@ namespace SourcePawn
virtual IDebugListener *SetDebugListener(IDebugListener *listener) =0;
/**
- * @brief Returns the number of plugins on the call stack.
+ * @brief Deprecated, do not use.
*
- * @return Number of contexts in the call stack.
+ * @return 0.
*/
virtual unsigned int GetContextCallCount() =0;
@@ -869,103 +1139,23 @@ namespace SourcePawn
virtual void FreePageMemory(void *ptr) =0;
};
-
- /**
- * @brief Dummy class for encapsulating private compilation data.
- */
- class ICompilation
- {
- public:
- /** Virtual destructor */
- virtual ~ICompilation() { };
- };
-
-
/**
* @brief Outlines the interface a Virtual Machine (JIT) must expose
*/
- class IVirtualMachine
+ class ISourcePawnEngine2
{
public:
/**
- * @brief Returns the current API version.
+ * @brief Returns the second engine API version.
+ *
+ * @return API version.
*/
virtual unsigned int GetAPIVersion() =0;
/**
* @brief Returns the string name of a VM implementation.
*/
- virtual const char *GetVMName() =0;
-
- /**
- * @brief Begins a new compilation
- *
- * @param plugin Pointer to a plugin structure.
- * @return New compilation pointer.
- */
- virtual ICompilation *StartCompilation(sp_plugin_t *plugin) =0;
-
- /**
- * @brief Sets a compilation option.
- *
- * @param co Pointer to a compilation.
- * @param key Option key name.
- * @param val Option value string.
- * @return True if option could be set, false otherwise.
- */
- virtual bool SetCompilationOption(ICompilation *co, const char *key, const char *val) =0;
-
- /**
- * @brief Finalizes a compilation into a new sp_context_t.
- * Note: This will free the ICompilation pointer.
- *
- * @param co Compilation pointer.
- * @param err Filled with error code on exit.
- * @return New plugin context.
- */
- virtual sp_context_t *CompileToContext(ICompilation *co, int *err) =0;
-
- /**
- * @brief Aborts a compilation and frees the ICompilation pointer.
- *
- * @param co Compilation pointer.
- */
- virtual void AbortCompilation(ICompilation *co) =0;
-
- /**
- * @brief Frees any internal variable usage on a context.
- *
- * @param ctx Context structure pointer.
- */
- virtual void FreeContext(sp_context_t *ctx) =0;
-
- /**
- * @brief Calls the "execute" function on a context.
- *
- * @param ctx Executes a function in a context.
- * @param code_addr Index into the code section.
- * @param result Pointer to store result into.
- * @return Error code (if any).
- */
- virtual int ContextExecute(sp_context_t *ctx, uint32_t code_addr, cell_t *result) =0;
-
- /**
- * @brief Given a context and a code address, returns the index of the function.
- *
- * @param ctx Context to search.
- * @param code_addr Index into the code section.
- * @param result Pointer to store result into.
- * @return True if code index is valid, false otherwise.
- */
- virtual bool FunctionLookup(const sp_context_t *ctx, uint32_t code_addr, unsigned int *result) =0;
-
- /**
- * @brief Returns the number of functions defined in the context.
- *
- * @param ctx Context to search.
- * @return Number of functions.
- */
- virtual unsigned int FunctionCount(const sp_context_t *ctx) =0;
+ virtual const char *GetEngineName() =0;
/**
* @brief Returns a version string.
@@ -975,21 +1165,24 @@ namespace SourcePawn
virtual const char *GetVersionString() =0;
/**
- * @brief Returns a string describing optimizations.
+ * @brief Creates a new compilation options object.
*
- * @return String describing CPU specific optimizations.
+ * @return Compilation options object.
*/
- virtual const char *GetCPUOptimizations() =0;
+ virtual ICompilation *StartCompilation() =0;
/**
- * @brief Given a context and a p-code address, returns the index of the function.
+ * @brief Loads a plugin from disk.
+ *
+ * If a compilation object is supplied, it is destroyed upon
+ * the function's return.
*
- * @param ctx Context to search.
- * @param code_addr Index into the p-code section.
- * @param result Pointer to store result into.
- * @return True if code index is valid, false otherwise.
+ * @param co Compilation options, or NULL for defaults.
+ * @param file Path to the file to compile.
+ * @param err Error code (filled on failure); required.
+ * @return New runtime pointer, or NULL on failure.
*/
- virtual bool FunctionPLookup(const sp_context_t *ctx, uint32_t code_addr, unsigned int *result) =0;
+ virtual IPluginRuntime *LoadPlugin(ICompilation *co, const char *file, int *err) =0;
/**
* @brief Creates a fake native and binds it to a general callback function.
@@ -1006,6 +1199,32 @@ namespace SourcePawn
* @param func Pointer to the fake native created by CreateFakeNative.
*/
virtual void DestroyFakeNative(SPVM_NATIVE_FUNC func) =0;
+
+ /**
+ * @brief Sets the debug listener. This should only be called once.
+ * If called successively (using manual chaining), only the last function should
+ * attempt to call back into the same plugin. Otherwise, globally cached states
+ * can be accidentally overwritten.
+ *
+ * @param listener Pointer to an IDebugListener.
+ * @return Old IDebugListener, or NULL if none.
+ */
+ virtual IDebugListener *SetDebugListener(IDebugListener *listener) =0;
+
+ /**
+ * @brief Sets the global profiler.
+ *
+ * @param profiler Profiler pointer.
+ */
+ virtual void SetProfiler(IProfiler *profiler) =0;
+
+ /**
+ * @brief Returns the string representation of an error message.
+ *
+ * @param err Error code.
+ * @return Error string, or NULL if not found.
+ */
+ virtual const char *GetErrorString(int err) =0;
};
};
diff --git a/public/sourcepawn/sp_vm_base.h b/public/sourcepawn/sp_vm_base.h
index e94b18cb..dfcba8a8 100644
--- a/public/sourcepawn/sp_vm_base.h
+++ b/public/sourcepawn/sp_vm_base.h
@@ -47,8 +47,5 @@
#define EXPORT_LINK extern "C" __attribute__((visibility("default")))
#endif
-/** No longer used */
-typedef SourcePawn::IVirtualMachine *(*SP_GETVM_FUNC)(SourcePawn::ISourcePawnEngine *);
-
#endif //_INCLUDE_SOURCEPAWN_VM_BASE_H_
diff --git a/public/sourcepawn/sp_vm_types.h b/public/sourcepawn/sp_vm_types.h
index 4eb57fd6..32fdedee 100644
--- a/public/sourcepawn/sp_vm_types.h
+++ b/public/sourcepawn/sp_vm_types.h
@@ -92,56 +92,6 @@ typedef uint32_t funcid_t; /**< Function index code */
*** binary.
**********************************************/
-/**
- * @brief Information about the core plugin tables. These may or may not be present!
- */
-typedef struct sp_plugin_infotab_s
-{
- const char *stringbase; /**< base of string table */
- uint32_t publics_num; /**< number of publics */
- sp_file_publics_t *publics; /**< public table */
- uint32_t natives_num; /**< number of natives */
- sp_file_natives_t *natives; /**< native table */
- uint32_t pubvars_num; /**< number of pubvars */
- sp_file_pubvars_t *pubvars; /**< pubvars table */
-} sp_plugin_infotab_t;
-
-/**
- * @brief Information about the plugin's debug tables. These are all present if one is present.
- */
-typedef struct sp_plugin_debug_s
-{
- const char *stringbase; /**< base of string table */
- uint32_t files_num; /**< number of files */
- sp_fdbg_file_t *files; /**< files table */
- uint32_t lines_num; /**< number of lines */
- sp_fdbg_line_t *lines; /**< lines table */
- uint32_t syms_num; /**< number of symbols */
- sp_fdbg_symbol_t *symbols; /**< symbol table */
-} sp_plugin_debug_t;
-
-#define SP_FA_SELF_EXTERNAL (1<<0) /**< Allocation of structure is external */
-#define SP_FA_BASE_EXTERNAL (1<<1) /**< Allocation of base is external */
-
-/**
- * @brief The rebased memory format of a plugin. This differs from the on-disk structure
- * to ensure that the format is properly read.
- */
-typedef struct sp_plugin_s
-{
- uint8_t *base; /**< Base of memory for this plugin. */
- uint8_t *pcode; /**< P-Code of plugin */
- uint32_t pcode_size; /**< Size of p-code */
- uint8_t *data; /**< Data/memory layout */
- uint32_t data_size; /**< Size of data */
- uint32_t memory; /**< Required memory space */
- uint16_t flags; /**< Code flags */
- uint32_t allocflags; /**< Allocation flags */
- sp_plugin_infotab_t info; /**< Base info table */
- sp_plugin_debug_t debug; /**< Debug info table */
-} sp_plugin_t;
-
-
namespace SourcePawn
{
class IPluginContext;
@@ -251,51 +201,7 @@ typedef struct sp_debug_symbol_s
sp_fdbg_symbol_t *sym; /**< Pointer to original symbol */
} sp_debug_symbol_t;
-/**
- * Breaks into a debugger
- * Params:
- * [0] - plugin context
- * [1] - frm
- * [2] - cip
- */
-typedef int (*SPVM_DEBUGBREAK)(struct sp_context_s *, uint32_t, uint32_t);
-
-#define SPFLAG_PLUGIN_DEBUG (1<<0) /**< plugin is in debug mode */
-#define SPFLAG_PLUGIN_PAUSED (1<<1) /**< plugin is "paused" (blocked from executing) */
-
-/**
- * @brief This is the heart of the VM. It contains all of the runtime
- * information about a plugin context. Note that user[0..3] can be used for any user based pointers.
- * However, vm[0..3] should not be touched, as it is reserved for the VM.
- */
-typedef struct sp_context_s
-{
- void *codebase; /**< Base of generated code and memory */
- sp_plugin_t *plugin; /**< Pointer back to parent information */
- SourcePawn::IPluginContext *context; /**< Pointer to IPluginContext */
- SourcePawn::IVirtualMachine *vmbase; /**< Pointer to IVirtualMachine */
- void *user[4]; /**< User specific pointers */
- void *vm[4]; /**< VM specific pointers */
- uint32_t flags; /**< Compilation flags */
- SPVM_DEBUGBREAK dbreak; /**< Debug break function */
- uint8_t *memory; /**< Data chunk */
- ucell_t mem_size; /**< Total memory size; */
- cell_t data_size; /**< Data chunk size, always starts at 0 */
- cell_t heap_base; /**< Where the heap starts */
- cell_t hp; /**< Heap pointer */
- cell_t sp; /**< Stack pointer */
- cell_t frm; /**< Frame pointer */
- uint32_t pushcount; /**< Push count */
- int32_t n_err; /**< Error code set by a native */
- uint32_t n_idx; /**< Current native index being executed */
- sp_public_t *publics; /**< Public functions table */
- sp_pubvar_t *pubvars; /**< Public variables table */
- sp_native_t *natives; /**< Natives table */
- sp_debug_file_t *files; /**< Files */
- sp_debug_line_t *lines; /**< Lines */
- sp_debug_symbol_t *symbols; /**< Symbols */
- SourcePawn::IProfiler *profiler; /**< Pointer to IProfiler */
- uint32_t prof_flags; /**< Profiling flags */
-} sp_context_t;
+//#define SPFLAG_PLUGIN_DEBUG (1<<0) /**< plugin is in debug mode */
+//#define SPFLAG_PLUGIN_PAUSED (1<<1) /**< plugin is "paused" (blocked from executing) */
#endif //_INCLUDE_SOURCEPAWN_VM_TYPES_H
diff --git a/sourcepawn/jit/BaseRuntime.cpp b/sourcepawn/jit/BaseRuntime.cpp
new file mode 100644
index 00000000..3d7cc402
--- /dev/null
+++ b/sourcepawn/jit/BaseRuntime.cpp
@@ -0,0 +1,357 @@
+#include
+#include
+#include
+#include "BaseRuntime.h"
+#include "sp_vm_engine.h"
+#include "x86/jit_x86.h"
+#include "sp_vm_basecontext.h"
+#include "engine2.h"
+
+using namespace SourcePawn;
+
+int GlobalDebugBreak(BaseContext *ctx, uint32_t frm, uint32_t cip)
+{
+ g_engine1.RunTracer(ctx, frm, cip);
+
+ return SP_ERROR_NONE;
+}
+
+BaseRuntime::BaseRuntime(sp_plugin_t *pl) : m_Debug(pl), m_pPlugin(pl)
+{
+ m_pCtx = new BaseContext(this);
+
+ if (m_pPlugin->info.publics_num > 0)
+ {
+ m_PubFuncs = new CFunction *[m_pPlugin->info.publics_num];
+ memset(m_PubFuncs, 0, sizeof(CFunction *) * m_pPlugin->info.publics_num);
+ }
+ else
+ {
+ m_PubFuncs = NULL;
+ }
+
+ m_pPlugin->dbreak = GlobalDebugBreak;
+ m_pPlugin->profiler = g_engine2.GetProfiler();
+}
+
+BaseRuntime::~BaseRuntime()
+{
+ for (uint32_t i = 0; i < m_pPlugin->info.publics_num; i++)
+ {
+ delete m_PubFuncs[i];
+ m_PubFuncs[i] = NULL;
+ }
+ delete [] m_PubFuncs;
+
+ ClearCompile();
+
+ free(m_pPlugin->base);
+ delete [] m_pPlugin->memory;
+ delete m_pPlugin;
+}
+
+void BaseRuntime::ClearCompile()
+{
+ g_Jit1.FreeContextVars(m_pCtx->GetCtx());
+ g_Jit1.FreePluginVars(m_pPlugin);
+}
+
+int BaseRuntime::FindNativeByName(const char *name, uint32_t *index)
+{
+ int high;
+
+ high = m_pPlugin->info.natives_num - 1;
+
+ for (uint32_t i=0; iinfo.natives_num; i++)
+ {
+ if (strcmp(m_pPlugin->natives[i].name, name) == 0)
+ {
+ if (index)
+ {
+ *index = i;
+ }
+ return SP_ERROR_NONE;
+ }
+ }
+
+ return SP_ERROR_NOT_FOUND;
+}
+
+int BaseRuntime::GetNativeByIndex(uint32_t index, sp_native_t **native)
+{
+ if (index >= m_pPlugin->info.natives_num)
+ {
+ return SP_ERROR_INDEX;
+ }
+
+ if (native)
+ {
+ *native = &(m_pPlugin->natives[index]);
+ }
+
+ return SP_ERROR_NONE;
+}
+
+
+uint32_t BaseRuntime::GetNativesNum()
+{
+ return m_pPlugin->info.natives_num;
+}
+
+int BaseRuntime::FindPublicByName(const char *name, uint32_t *index)
+{
+ int diff, high, low;
+ uint32_t mid;
+
+ high = m_pPlugin->info.publics_num - 1;
+ low = 0;
+
+ while (low <= high)
+ {
+ mid = (low + high) / 2;
+ diff = strcmp(m_pPlugin->publics[mid].name, name);
+ if (diff == 0)
+ {
+ if (index)
+ {
+ *index = mid;
+ }
+ return SP_ERROR_NONE;
+ } else if (diff < 0) {
+ low = mid + 1;
+ } else {
+ high = mid - 1;
+ }
+ }
+
+ return SP_ERROR_NOT_FOUND;
+}
+
+int BaseRuntime::GetPublicByIndex(uint32_t index, sp_public_t **pblic)
+{
+ if (index >= m_pPlugin->info.publics_num)
+ {
+ return SP_ERROR_INDEX;
+ }
+
+ if (pblic)
+ {
+ *pblic = &(m_pPlugin->publics[index]);
+ }
+
+ return SP_ERROR_NONE;
+}
+
+uint32_t BaseRuntime::GetPublicsNum()
+{
+ return m_pPlugin->info.publics_num;
+}
+
+int BaseRuntime::GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar)
+{
+ if (index >= m_pPlugin->info.pubvars_num)
+ {
+ return SP_ERROR_INDEX;
+ }
+
+ if (pubvar)
+ {
+ *pubvar = &(m_pPlugin->pubvars[index]);
+ }
+
+ return SP_ERROR_NONE;
+}
+
+int BaseRuntime::FindPubvarByName(const char *name, uint32_t *index)
+{
+ int diff, high, low;
+ uint32_t mid;
+
+ high = m_pPlugin->info.pubvars_num - 1;
+ low = 0;
+
+ while (low <= high)
+ {
+ mid = (low + high) / 2;
+ diff = strcmp(m_pPlugin->pubvars[mid].name, name);
+ if (diff == 0)
+ {
+ if (index)
+ {
+ *index = mid;
+ }
+ return SP_ERROR_NONE;
+ } else if (diff < 0) {
+ low = mid + 1;
+ } else {
+ high = mid - 1;
+ }
+ }
+
+ return SP_ERROR_NOT_FOUND;
+}
+
+int BaseRuntime::GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr)
+{
+ if (index >= m_pPlugin->info.pubvars_num)
+ {
+ return SP_ERROR_INDEX;
+ }
+
+ *local_addr = m_pPlugin->info.pubvars[index].address;
+ *phys_addr = m_pPlugin->pubvars[index].offs;
+
+ return SP_ERROR_NONE;
+}
+
+uint32_t BaseRuntime::GetPubVarsNum()
+{
+ return m_pPlugin->info.pubvars_num;
+}
+
+IPluginContext *BaseRuntime::GetDefaultContext()
+{
+ return m_pCtx;
+}
+
+IPluginDebugInfo *BaseRuntime::GetDebugInfo()
+{
+ if (!IsDebugging())
+ {
+ return NULL;
+ }
+
+ return &m_Debug;
+}
+
+void BaseRuntime::RefreshFunctionCache()
+{
+ if (m_PubFuncs != NULL)
+ {
+ sp_public_t *pub;
+ for (uint32_t i = 0; i < m_pPlugin->info.publics_num; i++)
+ {
+ if (m_PubFuncs[i] == NULL)
+ {
+ continue;
+ }
+ if (GetPublicByIndex(i, &pub) != SP_ERROR_NONE)
+ {
+ continue;
+ }
+ m_PubFuncs[i]->Set(pub->code_offs, this, (i << 1) | 1, i);
+ }
+ }
+
+}
+
+IPluginFunction *BaseRuntime::GetFunctionById(funcid_t func_id)
+{
+ CFunction *pFunc = NULL;
+
+ if (func_id & 1)
+ {
+ func_id >>= 1;
+ if (func_id >= m_pPlugin->info.publics_num)
+ {
+ return NULL;
+ }
+ pFunc = m_PubFuncs[func_id];
+ if (!pFunc)
+ {
+ m_PubFuncs[func_id] = new CFunction(m_pPlugin->publics[func_id].code_offs,
+ this,
+ (func_id << 1) | 1,
+ func_id);
+ pFunc = m_PubFuncs[func_id];
+ }
+ else if (pFunc->IsInvalidated())
+ {
+ pFunc->Set(m_pPlugin->publics[func_id].code_offs,
+ this,
+ (func_id << 1) | 1,
+ func_id);
+ }
+ }
+
+ return pFunc;
+}
+
+IPluginFunction *BaseRuntime::GetFunctionByName(const char *public_name)
+{
+ uint32_t index;
+
+ if (FindPublicByName(public_name, &index) != SP_ERROR_NONE)
+ {
+ return NULL;
+ }
+
+ CFunction *pFunc = m_PubFuncs[index];
+ if (!pFunc)
+ {
+ sp_public_t *pub = NULL;
+ GetPublicByIndex(index, &pub);
+ if (pub)
+ {
+ m_PubFuncs[index] = new CFunction(pub->code_offs, this, (index << 1) | 1, index);
+ }
+ pFunc = m_PubFuncs[index];
+ }
+ else if (pFunc->IsInvalidated())
+ {
+ sp_public_t *pub = NULL;
+ GetPublicByIndex(index, &pub);
+ if (pub)
+ {
+ pFunc->Set(pub->code_offs, this, (index << 1) | 1, index);
+ }
+ else
+ {
+ pFunc = NULL;
+ }
+ }
+
+ return pFunc;
+}
+
+bool BaseRuntime::IsDebugging()
+{
+ return ((m_pPlugin->run_flags & SPFLAG_PLUGIN_DEBUG) == SPFLAG_PLUGIN_DEBUG);
+}
+
+void BaseRuntime::SetPauseState(bool paused)
+{
+ if (paused)
+ {
+ m_pPlugin->run_flags |= SPFLAG_PLUGIN_PAUSED;
+ }
+ else
+ {
+ m_pPlugin->run_flags &= ~SPFLAG_PLUGIN_PAUSED;
+ }
+}
+
+bool BaseRuntime::IsPaused()
+{
+ return ((m_pPlugin->run_flags & SPFLAG_PLUGIN_PAUSED) == SPFLAG_PLUGIN_PAUSED);
+}
+
+size_t BaseRuntime::GetMemUsage()
+{
+ size_t mem = 0;
+
+ mem += sizeof(this);
+ mem += sizeof(sp_plugin_t);
+ mem += sizeof(BaseContext);
+ mem += m_pPlugin->base_size;
+ mem += m_pPlugin->jit_codesize;
+ mem += m_pPlugin->jit_memsize;
+
+ return mem;
+}
+
+BaseContext *BaseRuntime::GetBaseContext()
+{
+ return m_pCtx;
+}
+
diff --git a/sourcepawn/jit/BaseRuntime.h b/sourcepawn/jit/BaseRuntime.h
new file mode 100644
index 00000000..5ff75601
--- /dev/null
+++ b/sourcepawn/jit/BaseRuntime.h
@@ -0,0 +1,60 @@
+#ifndef _INCLUDE_SOURCEPAWN_JIT_RUNTIME_H_
+#define _INCLUDE_SOURCEPAWN_JIT_RUNTIME_H_
+
+#include
+#include "jit_shared.h"
+#include "sp_vm_function.h"
+
+class BaseContext;
+
+class DebugInfo : public IPluginDebugInfo
+{
+public:
+ DebugInfo(sp_plugin_t *plugin);
+public:
+ int LookupFile(ucell_t addr, const char **filename);
+ int LookupFunction(ucell_t addr, const char **name);
+ int LookupLine(ucell_t addr, uint32_t *line);
+private:
+ sp_plugin_t *m_pPlugin;
+};
+
+/* Jit wants fast access to this so we expose things as public */
+class BaseRuntime : public SourcePawn::IPluginRuntime
+{
+public:
+ BaseRuntime(sp_plugin_t *pl);
+ ~BaseRuntime();
+public:
+ virtual bool IsDebugging();
+ virtual IPluginDebugInfo *GetDebugInfo();
+ virtual int FindNativeByName(const char *name, uint32_t *index);
+ virtual int GetNativeByIndex(uint32_t index, sp_native_t **native);
+ virtual uint32_t GetNativesNum();
+ virtual int FindPublicByName(const char *name, uint32_t *index);
+ virtual int GetPublicByIndex(uint32_t index, sp_public_t **publicptr);
+ virtual uint32_t GetPublicsNum();
+ virtual int GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar);
+ virtual int FindPubvarByName(const char *name, uint32_t *index);
+ virtual int GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr);
+ virtual uint32_t GetPubVarsNum();
+ virtual IPluginFunction *GetFunctionByName(const char *public_name);
+ virtual IPluginFunction *GetFunctionById(funcid_t func_id);
+ virtual IPluginContext *GetDefaultContext();
+ virtual int ApplyCompilationOptions(ICompilation *co);
+ virtual void SetPauseState(bool paused);
+ virtual bool IsPaused();
+ virtual size_t GetMemUsage();
+public:
+ BaseContext *GetBaseContext();
+private:
+ void ClearCompile();
+ void RefreshFunctionCache();
+public:
+ DebugInfo m_Debug;
+ sp_plugin_t *m_pPlugin;
+ BaseContext *m_pCtx;
+ CFunction **m_PubFuncs;
+};
+
+#endif //_INCLUDE_SOURCEPAWN_JIT_RUNTIME_H_
diff --git a/sourcepawn/jit/x86/Makefile b/sourcepawn/jit/Makefile
similarity index 70%
rename from sourcepawn/jit/x86/Makefile
rename to sourcepawn/jit/Makefile
index d8966966..fdc1358b 100644
--- a/sourcepawn/jit/x86/Makefile
+++ b/sourcepawn/jit/Makefile
@@ -1,7 +1,8 @@
# (C)2004-2008 SourceMod Development Team
# Makefile written by David "BAILOPAN" Anderson
-SMSDK = ../../..
+SMSDK = ../..
+SOURCEHOOK = ../../../sourcemm-1.6/sourcehook
#####################################
### EDIT BELOW FOR OTHER PROJECTS ###
@@ -9,7 +10,26 @@ SMSDK = ../../..
PROJECT = sourcepawn.jit.x86
-OBJECTS = dll_exports.cpp jit_x86.cpp opcode_helpers.cpp
+OBJECTS = dll_exports.cpp \
+ x86/jit_x86.cpp \
+ x86/opcode_helpers.cpp \
+ sp_vm_basecontext.cpp \
+ sp_vm_engine.cpp \
+ sp_vm_function.cpp \
+ engine2.cpp \
+ BaseRuntime.cpp \
+ zlib/adler32.c \
+ zlib/compress.c \
+ zlib/crc32.c \
+ zlib/deflate.c \
+ zlib/gzio.c \
+ zlib/infback.c \
+ zlib/inffast.c \
+ zlib/inflate.c \
+ zlib/inftrees.c \
+ zlib/trees.c \
+ zlib/uncompr.c \
+ zlib/zutil.c
##############################################
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
@@ -24,7 +44,7 @@ CPP = gcc-4.1
LINK = -static-libgcc
INCLUDE = -I. -I.. -I$(SMSDK)/public -I$(SMSDK)/public/jit -I$(SMSDK)/public/jit/x86 \
- -I$(SMSDK)/public/sourcepawn
+ -I$(SMSDK)/public/sourcepawn -I$(SOURCEHOOK)
CFLAGS += -D_LINUX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \
-D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -DHAVE_STDINT_H \
@@ -52,12 +72,17 @@ endif
BINARY = $(PROJECT).so
OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o)
+OBJ_LINUX := $(OBJ_LINUX:%.c=$(BIN_DIR)/%.o)
+
+$(BIN_DIR)/%.o: %.c
+ $(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
$(BIN_DIR)/%.o: %.cpp
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
all:
- mkdir -p $(BIN_DIR)
+ mkdir -p $(BIN_DIR)/x86
+ mkdir -p $(BIN_DIR)/zlib
$(MAKE) -f Makefile jit
jit: $(OBJ_LINUX)
diff --git a/sourcepawn/jit/x86/dll_exports.cpp b/sourcepawn/jit/dll_exports.cpp
similarity index 71%
rename from sourcepawn/jit/x86/dll_exports.cpp
rename to sourcepawn/jit/dll_exports.cpp
index 522eabe3..91a80743 100644
--- a/sourcepawn/jit/x86/dll_exports.cpp
+++ b/sourcepawn/jit/dll_exports.cpp
@@ -31,44 +31,21 @@
#include
#include
-#include "jit_x86.h"
+#include "x86/jit_x86.h"
#include "dll_exports.h"
+#include "sp_vm_engine.h"
+#include "engine2.h"
-SourcePawn::ISourcePawnEngine *engine = NULL;
-JITX86 g_jit;
+SourcePawnEngine2 g_engine2;
-EXPORTFUNC int GiveEnginePointer2(SourcePawn::ISourcePawnEngine *engine_p, unsigned int api_version)
+EXPORTFUNC ISourcePawnEngine *GetSourcePawnEngine1()
{
- engine = engine_p;
-
- if (api_version > SOURCEPAWN_ENGINE_API_VERSION || api_version < 2)
- {
- return SP_ERROR_PARAM;
- }
-
- return SP_ERROR_NONE;
+ return &g_engine1;
}
-EXPORTFUNC unsigned int GetExportCount()
+EXPORTFUNC ISourcePawnEngine2 *GetSourcePawnEngine2()
{
- return 1;
-}
-
-EXPORTFUNC SourcePawn::IVirtualMachine *GetExport(unsigned int exportnum)
-{
- /* Don't return anything if we're not initialized yet */
- if (!engine)
- {
- return NULL;
- }
-
- /* We only have one export - 0 */
- if (exportnum)
- {
- return NULL;
- }
-
- return &g_jit;
+ return &g_engine2;
}
#if defined __linux__
diff --git a/sourcepawn/jit/x86/dll_exports.h b/sourcepawn/jit/dll_exports.h
similarity index 100%
rename from sourcepawn/jit/x86/dll_exports.h
rename to sourcepawn/jit/dll_exports.h
diff --git a/sourcepawn/jit/engine2.cpp b/sourcepawn/jit/engine2.cpp
new file mode 100644
index 00000000..aa69bbc1
--- /dev/null
+++ b/sourcepawn/jit/engine2.cpp
@@ -0,0 +1,278 @@
+#include
+#include
+#include
+#include "engine2.h"
+#include "x86/jit_x86.h"
+#include "jit_version.h"
+#include "zlib/zlib.h"
+#include "BaseRuntime.h"
+#include "sp_vm_engine.h"
+
+using namespace SourcePawn;
+
+SourcePawnEngine2::SourcePawnEngine2()
+{
+ m_Profiler = NULL;
+}
+
+sp_plugin_t *_ReadPlugin(sp_file_hdr_t *hdr, uint8_t *base, sp_plugin_t *plugin, int *err)
+{
+ char *nameptr;
+ uint8_t sectnum = 0;
+ sp_file_section_t *secptr = (sp_file_section_t *)(base + sizeof(sp_file_hdr_t));
+
+ memset(plugin, 0, sizeof(sp_plugin_t));
+
+ plugin->base = base;
+
+ while (sectnum < hdr->sections)
+ {
+ nameptr = (char *)(base + hdr->stringtab + secptr->nameoffs);
+
+ if (!(plugin->pcode) && !strcmp(nameptr, ".code"))
+ {
+ sp_file_code_t *cod = (sp_file_code_t *)(base + secptr->dataoffs);
+ plugin->pcode = base + secptr->dataoffs + cod->code;
+ plugin->pcode_size = cod->codesize;
+ plugin->flags = cod->flags;
+ }
+ else if (!(plugin->data) && !strcmp(nameptr, ".data"))
+ {
+ sp_file_data_t *dat = (sp_file_data_t *)(base + secptr->dataoffs);
+ plugin->data = base + secptr->dataoffs + dat->data;
+ plugin->data_size = dat->datasize;
+ plugin->mem_size = dat->memsize;
+ plugin->memory = new uint8_t[plugin->mem_size];
+ memcpy(plugin->memory, plugin->data, plugin->data_size);
+ }
+ else if (!(plugin->info.publics) && !strcmp(nameptr, ".publics"))
+ {
+ plugin->info.publics_num = secptr->size / sizeof(sp_file_publics_t);
+ plugin->info.publics = (sp_file_publics_t *)(base + secptr->dataoffs);
+ }
+ else if (!(plugin->info.pubvars) && !strcmp(nameptr, ".pubvars"))
+ {
+ plugin->info.pubvars_num = secptr->size / sizeof(sp_file_pubvars_t);
+ plugin->info.pubvars = (sp_file_pubvars_t *)(base + secptr->dataoffs);
+ }
+ else if (!(plugin->info.natives) && !strcmp(nameptr, ".natives"))
+ {
+ plugin->info.natives_num = secptr->size / sizeof(sp_file_natives_t);
+ plugin->info.natives = (sp_file_natives_t *)(base + secptr->dataoffs);
+ }
+ else if (!(plugin->info.stringbase) && !strcmp(nameptr, ".names"))
+ {
+ plugin->info.stringbase = (const char *)(base + secptr->dataoffs);
+ }
+ else if (!(plugin->debug.files) && !strcmp(nameptr, ".dbg.files"))
+ {
+ plugin->debug.files = (sp_fdbg_file_t *)(base + secptr->dataoffs);
+ }
+ else if (!(plugin->debug.lines) && !strcmp(nameptr, ".dbg.lines"))
+ {
+ plugin->debug.lines = (sp_fdbg_line_t *)(base + secptr->dataoffs);
+ }
+ else if (!(plugin->debug.symbols) && !strcmp(nameptr, ".dbg.symbols"))
+ {
+ plugin->debug.symbols = (sp_fdbg_symbol_t *)(base + secptr->dataoffs);
+ }
+ else if (!(plugin->debug.lines_num) && !strcmp(nameptr, ".dbg.info"))
+ {
+ sp_fdbg_info_t *inf = (sp_fdbg_info_t *)(base + secptr->dataoffs);
+ plugin->debug.files_num = inf->num_files;
+ plugin->debug.lines_num = inf->num_lines;
+ plugin->debug.syms_num = inf->num_syms;
+ }
+ else if (!(plugin->debug.stringbase) && !strcmp(nameptr, ".dbg.strings"))
+ {
+ plugin->debug.stringbase = (const char *)(base + secptr->dataoffs);
+ }
+
+ secptr++;
+ sectnum++;
+ }
+
+ if (!(plugin->pcode) || !(plugin->data) || !(plugin->info.stringbase))
+ {
+ goto return_error;
+ }
+
+ if ((plugin->flags & SP_FLAG_DEBUG) && (!(plugin->debug.files) || !(plugin->debug.lines) || !(plugin->debug.symbols)))
+ {
+ goto return_error;
+ }
+
+ if (err)
+ {
+ *err = SP_ERROR_NONE;
+ }
+
+ return plugin;
+
+return_error:
+ if (err)
+ {
+ *err = SP_ERROR_FILE_FORMAT;
+ }
+
+ return NULL;
+}
+
+IPluginRuntime *SourcePawnEngine2::LoadPlugin(ICompilation *co, const char *file, int *err)
+{
+ sp_file_hdr_t hdr;
+ sp_plugin_t *plugin;
+ uint8_t *base;
+ int z_result;
+ int error;
+ BaseRuntime *pRuntime;
+
+ FILE *fp = fopen(file, "rb");
+
+ if (!fp)
+ {
+ error = SP_ERROR_NOT_FOUND;
+ goto return_error;
+ }
+
+ /* Rewind for safety */
+ fread(&hdr, sizeof(sp_file_hdr_t), 1, fp);
+
+ if (hdr.magic != SPFILE_MAGIC)
+ {
+ error = SP_ERROR_FILE_FORMAT;
+ goto return_error;
+ }
+
+ switch (hdr.compression)
+ {
+ case SPFILE_COMPRESSION_GZ:
+ {
+ uint32_t uncompsize = hdr.imagesize - hdr.dataoffs;
+ uint32_t compsize = hdr.disksize - hdr.dataoffs;
+ uint32_t sectsize = hdr.dataoffs - sizeof(sp_file_hdr_t);
+ uLongf destlen = uncompsize;
+
+ char *tempbuf = (char *)malloc(compsize);
+ void *uncompdata = malloc(uncompsize);
+ void *sectheader = malloc(sectsize);
+
+ fread(sectheader, sectsize, 1, fp);
+ fread(tempbuf, compsize, 1, fp);
+
+ z_result = uncompress((Bytef *)uncompdata, &destlen, (Bytef *)tempbuf, compsize);
+ free(tempbuf);
+ if (z_result != Z_OK)
+ {
+ free(sectheader);
+ free(uncompdata);
+ error = SP_ERROR_DECOMPRESSOR;
+ goto return_error;
+ }
+
+ base = (uint8_t *)malloc(hdr.imagesize);
+ memcpy(base, &hdr, sizeof(sp_file_hdr_t));
+ memcpy(base + sizeof(sp_file_hdr_t), sectheader, sectsize);
+ free(sectheader);
+ memcpy(base + hdr.dataoffs, uncompdata, uncompsize);
+ free(uncompdata);
+ break;
+ }
+ case SPFILE_COMPRESSION_NONE:
+ {
+ base = (uint8_t *)malloc(hdr.imagesize);
+ rewind(fp);
+ fread(base, hdr.imagesize, 1, fp);
+ break;
+ }
+ default:
+ {
+ error = SP_ERROR_DECOMPRESSOR;
+ goto return_error;
+ }
+ }
+
+ plugin = new sp_plugin_t;
+
+ memset(plugin, 0, sizeof(sp_plugin_t));
+
+ plugin->base_size = hdr.imagesize;
+ if (!_ReadPlugin(&hdr, base, plugin, err))
+ {
+ delete plugin;
+ free(base);
+ return NULL;
+ }
+
+ pRuntime = new BaseRuntime(plugin);
+
+ if (co == NULL)
+ {
+ co = g_Jit1.StartCompilation(pRuntime);
+ }
+
+
+ *err = pRuntime->ApplyCompilationOptions(co);
+ if (*err != SP_ERROR_NONE)
+ {
+ delete pRuntime;
+ return NULL;
+ }
+
+ return pRuntime;
+
+return_error:
+ *err = error;
+
+ return NULL;
+}
+
+SPVM_NATIVE_FUNC SourcePawnEngine2::CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData)
+{
+ return g_Jit1.CreateFakeNative(callback, pData);
+}
+
+void SourcePawnEngine2::DestroyFakeNative(SPVM_NATIVE_FUNC func)
+{
+ g_Jit1.DestroyFakeNative(func);
+}
+
+const char *SourcePawnEngine2::GetEngineName()
+{
+ return "SourcePawn 1.1, jit-x86";
+}
+
+const char *SourcePawnEngine2::GetVersionString()
+{
+ return SVN_FULL_VERSION;
+}
+
+IProfiler *SourcePawnEngine2::GetProfiler()
+{
+ return m_Profiler;
+}
+
+void SourcePawnEngine2::SetProfiler(IProfiler *profiler)
+{
+ m_Profiler = profiler;
+}
+
+IDebugListener *SourcePawnEngine2::SetDebugListener(IDebugListener *listener)
+{
+ return g_engine1.SetDebugListener(listener);
+}
+
+unsigned int SourcePawnEngine2::GetAPIVersion()
+{
+ return SOURCEPAWN_ENGINE2_API_VERSION;
+}
+
+ICompilation *SourcePawnEngine2::StartCompilation()
+{
+ return g_Jit1.StartCompilation();
+}
+
+const char *SourcePawnEngine2::GetErrorString(int err)
+{
+ return g_engine1.GetErrorString(err);
+}
diff --git a/sourcepawn/jit/engine2.h b/sourcepawn/jit/engine2.h
new file mode 100644
index 00000000..09de29d5
--- /dev/null
+++ b/sourcepawn/jit/engine2.h
@@ -0,0 +1,35 @@
+#ifndef _INCLUDE_SOURCEPAWN_ENGINE_2_H_
+#define _INCLUDE_SOURCEPAWN_ENGINE_2_H_
+
+#include
+
+namespace SourcePawn
+{
+ /**
+ * @brief Outlines the interface a Virtual Machine (JIT) must expose
+ */
+ class SourcePawnEngine2 : public ISourcePawnEngine2
+ {
+ public:
+ SourcePawnEngine2();
+ public:
+ unsigned int GetAPIVersion();
+ const char *GetEngineName();
+ const char *GetVersionString();
+ IPluginRuntime *LoadPlugin(ICompilation *co, const char *file, int *err);
+ SPVM_NATIVE_FUNC CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData);
+ void DestroyFakeNative(SPVM_NATIVE_FUNC func);
+ IDebugListener *SetDebugListener(IDebugListener *listener);
+ void SetProfiler(IProfiler *profiler);
+ ICompilation *StartCompilation();
+ const char *GetErrorString(int err);
+ public:
+ IProfiler *GetProfiler();
+ private:
+ IProfiler *m_Profiler;
+ };
+}
+
+extern SourcePawn::SourcePawnEngine2 g_engine2;
+
+#endif //_INCLUDE_SOURCEPAWN_ENGINE_2_H_
diff --git a/sourcepawn/jit/jit_shared.h b/sourcepawn/jit/jit_shared.h
new file mode 100644
index 00000000..11f4f573
--- /dev/null
+++ b/sourcepawn/jit/jit_shared.h
@@ -0,0 +1,95 @@
+#ifndef _INCLUDE_SOURCEPAWN_JIT_SHARED_H_
+#define _INCLUDE_SOURCEPAWN_JIT_SHARED_H_
+
+#include
+
+using namespace SourcePawn;
+
+/**
+* @brief Information about the core plugin tables. These may or may not be present!
+*/
+typedef struct sp_plugin_infotab_s
+{
+ const char *stringbase; /**< base of string table */
+ uint32_t publics_num; /**< number of publics */
+ sp_file_publics_t *publics; /**< public table */
+ uint32_t natives_num; /**< number of natives */
+ sp_file_natives_t *natives; /**< native table */
+ uint32_t pubvars_num; /**< number of pubvars */
+ sp_file_pubvars_t *pubvars; /**< pubvars table */
+} sp_plugin_infotab_t;
+
+/**
+* @brief Information about the plugin's debug tables. These are all present if one is present.
+*/
+typedef struct sp_plugin_debug_s
+{
+ const char *stringbase; /**< base of string table */
+ uint32_t files_num; /**< number of files */
+ sp_fdbg_file_t *files; /**< files table */
+ uint32_t lines_num; /**< number of lines */
+ sp_fdbg_line_t *lines; /**< lines table */
+ uint32_t syms_num; /**< number of symbols */
+ sp_fdbg_symbol_t *symbols; /**< symbol table */
+} sp_plugin_debug_t;
+
+class BaseContext;
+
+/**
+* Breaks into a debugger
+* Params:
+* [0] - plugin context
+* [1] - frm
+* [2] - cip
+*/
+typedef int (*SPVM_DEBUGBREAK)(BaseContext *, uint32_t, uint32_t);
+
+/**
+ * @brief The rebased memory format of a plugin. This differs from the on-disk structure
+ * to ensure that the format is properly read.
+ */
+namespace SourcePawn
+{
+ typedef struct sp_plugin_s
+ {
+ uint8_t *base; /**< Base of memory for this plugin. */
+ uint8_t *pcode; /**< P-Code of plugin */
+ uint32_t pcode_size; /**< Size of p-code */
+ uint8_t *data; /**< Data/memory layout */
+ uint32_t data_size; /**< Size of data */
+ uint32_t mem_size; /**< Required memory space */
+ uint16_t flags; /**< Code flags */
+ sp_plugin_infotab_t info; /**< Base info table */
+ sp_plugin_debug_t debug; /**< Debug info table */
+ size_t base_size; /**< Size of the entire plugin base */
+ void *codebase; /**< Base of generated code and memory */
+ SPVM_DEBUGBREAK dbreak; /**< Debug break function */
+ uint8_t *memory; /**< Data chunk */
+ sp_public_t *publics; /**< Public functions table */
+ sp_pubvar_t *pubvars; /**< Public variables table */
+ sp_native_t *natives; /**< Natives table */
+ sp_debug_file_t *files; /**< Files */
+ sp_debug_line_t *lines; /**< Lines */
+ sp_debug_symbol_t *symbols; /**< Symbols */
+ IProfiler *profiler; /**< Pointer to IProfiler */
+ uint32_t prof_flags; /**< Profiling flags */
+ uint32_t run_flags; /**< Runtime flags */
+ size_t jit_codesize; /**< JIT compiled codesize */
+ size_t jit_memsize; /**< JIT additional memory */
+ } sp_plugin_t;
+}
+
+typedef struct sp_context_s
+{
+ cell_t hp; /**< Heap pointer */
+ cell_t sp; /**< Stack pointer */
+ cell_t frm; /**< Frame pointer */
+ int32_t n_err; /**< Error code set by a native */
+ uint32_t n_idx; /**< Current native index being executed */
+ void * vm[8]; /**< VM-specific pointers */
+} sp_context_t;
+
+#define SPFLAG_PLUGIN_DEBUG (1<<0)
+#define SPFLAG_PLUGIN_PAUSED (1<<1)
+
+#endif //_INCLUDE_SOURCEPAWN_JIT_SHARED_H_
diff --git a/sourcepawn/jit/x86/jit_version.h b/sourcepawn/jit/jit_version.h
similarity index 100%
rename from sourcepawn/jit/x86/jit_version.h
rename to sourcepawn/jit/jit_version.h
diff --git a/sourcepawn/jit/x86/jit_version.tpl b/sourcepawn/jit/jit_version.tpl
similarity index 100%
rename from sourcepawn/jit/x86/jit_version.tpl
rename to sourcepawn/jit/jit_version.tpl
diff --git a/sourcepawn/jit/x86/msvc8/jit-x86.sln b/sourcepawn/jit/msvc8/jit-x86.sln
similarity index 100%
rename from sourcepawn/jit/x86/msvc8/jit-x86.sln
rename to sourcepawn/jit/msvc8/jit-x86.sln
diff --git a/sourcepawn/jit/x86/msvc8/jit-x86.vcproj b/sourcepawn/jit/msvc8/jit-x86.vcproj
similarity index 68%
rename from sourcepawn/jit/x86/msvc8/jit-x86.vcproj
rename to sourcepawn/jit/msvc8/jit-x86.vcproj
index 3e75a734..a1d74a10 100644
--- a/sourcepawn/jit/x86/msvc8/jit-x86.vcproj
+++ b/sourcepawn/jit/msvc8/jit-x86.vcproj
@@ -40,7 +40,7 @@
+
+
+
+
+
+
+
+
+
+
+
+
-
-
@@ -211,12 +231,20 @@
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
+
+
+
+
+
+
@@ -245,18 +277,6 @@
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
-
-
-
-
-
-
@@ -266,27 +286,75 @@
Name="SDK"
>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sourcepawn/jit/sp_vm_basecontext.cpp b/sourcepawn/jit/sp_vm_basecontext.cpp
new file mode 100644
index 00000000..5ac58d41
--- /dev/null
+++ b/sourcepawn/jit/sp_vm_basecontext.cpp
@@ -0,0 +1,810 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourcePawn
+ * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see .
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or .
+ *
+ * Version: $Id$
+ */
+
+#include
+#include
+#include
+#include
+#include "sp_vm_api.h"
+#include "sp_vm_basecontext.h"
+#include "sp_vm_engine.h"
+#include "x86/jit_x86.h"
+
+using namespace SourcePawn;
+
+#define CELLBOUNDMAX (INT_MAX/sizeof(cell_t))
+#define STACKMARGIN ((cell_t)(16*sizeof(cell_t)))
+
+BaseContext::BaseContext(BaseRuntime *pRuntime)
+{
+ m_pRuntime = pRuntime;
+ m_pPlugin = m_pRuntime->m_pPlugin;
+
+ m_InExec = false;
+ m_CustomMsg = false;
+
+ m_pNullVec = NULL;
+ m_pNullString = NULL;
+}
+
+BaseContext::~BaseContext()
+{
+}
+
+IVirtualMachine *BaseContext::GetVirtualMachine()
+{
+ return NULL;
+}
+
+sp_context_t *BaseContext::GetContext()
+{
+ return reinterpret_cast((IPluginContext * )this);
+}
+
+sp_context_t *BaseContext::GetCtx()
+{
+ return &m_ctx;
+}
+
+bool BaseContext::IsDebugging()
+{
+ return m_pRuntime->IsDebugging();
+}
+
+int BaseContext::SetDebugBreak(void *newpfn, void *oldpfn)
+{
+ return SP_ERROR_ABORTED;
+}
+
+IPluginDebugInfo *BaseContext::GetDebugInfo()
+{
+ return NULL;
+}
+
+int BaseContext::Execute(uint32_t code_addr, cell_t *result)
+{
+ return SP_ERROR_ABORTED;
+}
+
+void BaseContext::SetErrorMessage(const char *msg, va_list ap)
+{
+ m_CustomMsg = true;
+
+ vsnprintf(m_MsgCache, sizeof(m_MsgCache), msg, ap);
+}
+
+void BaseContext::_SetErrorMessage(const char *msg, ...)
+{
+ va_list ap;
+ va_start(ap, msg);
+ SetErrorMessage(msg, ap);
+ va_end(ap);
+}
+
+cell_t BaseContext::ThrowNativeErrorEx(int error, const char *msg, ...)
+{
+ if (!m_InExec)
+ {
+ return 0;
+ }
+
+ m_ctx.n_err = error;
+
+ if (msg)
+ {
+ va_list ap;
+ va_start(ap, msg);
+ SetErrorMessage(msg, ap);
+ va_end(ap);
+ }
+
+ return 0;
+}
+
+cell_t BaseContext::ThrowNativeError(const char *msg, ...)
+{
+ if (!m_InExec)
+ {
+ return 0;
+ }
+
+ m_ctx.n_err = SP_ERROR_NATIVE;
+
+ if (msg)
+ {
+ va_list ap;
+ va_start(ap, msg);
+ SetErrorMessage(msg, ap);
+ va_end(ap);
+ }
+
+ return 0;
+}
+
+int BaseContext::HeapAlloc(unsigned int cells, cell_t *local_addr, cell_t **phys_addr)
+{
+ cell_t *addr;
+ ucell_t realmem;
+
+#if 0
+ if (cells > CELLBOUNDMAX)
+ {
+ return SP_ERROR_ARAM;
+ }
+#else
+ assert(cells < CELLBOUNDMAX);
+#endif
+
+ realmem = cells * sizeof(cell_t);
+
+ /**
+ * Check if the space between the heap and stack is sufficient.
+ */
+ if ((cell_t)(m_ctx.sp - m_ctx.hp - realmem) < STACKMARGIN)
+ {
+ return SP_ERROR_HEAPLOW;
+ }
+
+ addr = (cell_t *)(m_pPlugin->memory + m_ctx.hp);
+ /* store size of allocation in cells */
+ *addr = (cell_t)cells;
+ addr++;
+ m_ctx.hp += sizeof(cell_t);
+
+ *local_addr = m_ctx.hp;
+
+ if (phys_addr)
+ {
+ *phys_addr = addr;
+ }
+
+ m_ctx.hp += realmem;
+
+ return SP_ERROR_NONE;
+}
+
+int BaseContext::HeapPop(cell_t local_addr)
+{
+ cell_t cellcount;
+ cell_t *addr;
+
+ /* check the bounds of this address */
+ local_addr -= sizeof(cell_t);
+ if (local_addr < (cell_t)m_pPlugin->data_size || local_addr >= m_ctx.sp)
+ {
+ return SP_ERROR_INVALID_ADDRESS;
+ }
+
+ addr = (cell_t *)(m_pPlugin->memory + local_addr);
+ cellcount = (*addr) * sizeof(cell_t);
+ /* check if this memory count looks valid */
+ if ((signed)(m_ctx.hp - cellcount - sizeof(cell_t)) != local_addr)
+ {
+ return SP_ERROR_INVALID_ADDRESS;
+ }
+
+ m_ctx.hp = local_addr;
+
+ return SP_ERROR_NONE;
+}
+
+
+int BaseContext::HeapRelease(cell_t local_addr)
+{
+ if (local_addr < (cell_t)m_pPlugin->data_size)
+ {
+ return SP_ERROR_INVALID_ADDRESS;
+ }
+
+ m_ctx.hp = local_addr - sizeof(cell_t);
+
+ return SP_ERROR_NONE;
+}
+
+int BaseContext::FindNativeByName(const char *name, uint32_t *index)
+{
+ return m_pRuntime->FindNativeByName(name, index);
+}
+
+int BaseContext::GetNativeByIndex(uint32_t index, sp_native_t **native)
+{
+ return m_pRuntime->GetNativeByIndex(index, native);
+}
+
+
+uint32_t BaseContext::GetNativesNum()
+{
+ return m_pRuntime->GetNativesNum();
+}
+
+int BaseContext::FindPublicByName(const char *name, uint32_t *index)
+{
+ return m_pRuntime->FindPublicByName(name, index);
+}
+
+int BaseContext::GetPublicByIndex(uint32_t index, sp_public_t **pblic)
+{
+ return m_pRuntime->GetPublicByIndex(index, pblic);
+}
+
+uint32_t BaseContext::GetPublicsNum()
+{
+ return m_pRuntime->GetPublicsNum();
+}
+
+int BaseContext::GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar)
+{
+ return m_pRuntime->GetPubvarByIndex(index, pubvar);
+}
+
+int BaseContext::FindPubvarByName(const char *name, uint32_t *index)
+{
+ return m_pRuntime->FindPubvarByName(name, index);
+}
+
+int BaseContext::GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr)
+{
+ return m_pRuntime->GetPubvarAddrs(index, local_addr, phys_addr);
+}
+
+uint32_t BaseContext::GetPubVarsNum()
+{
+ return m_pRuntime->GetPubVarsNum();
+}
+
+int BaseContext::BindNatives(const sp_nativeinfo_t *natives, unsigned int num, int overwrite)
+{
+ return SP_ERROR_ABORTED;
+}
+
+int BaseContext::BindNative(const sp_nativeinfo_t *native)
+{
+ return SP_ERROR_ABORTED;
+}
+
+int BaseContext::BindNativeToIndex(uint32_t index, SPVM_NATIVE_FUNC func)
+{
+ return SP_ERROR_ABORTED;
+}
+
+int BaseContext::BindNativeToAny(SPVM_NATIVE_FUNC native)
+{
+ return SP_ERROR_ABORTED;
+}
+
+int BaseContext::LocalToPhysAddr(cell_t local_addr, cell_t **phys_addr)
+{
+ if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp))
+ || (local_addr < 0) || ((ucell_t)local_addr >= m_pPlugin->mem_size))
+ {
+ return SP_ERROR_INVALID_ADDRESS;
+ }
+
+ if (phys_addr)
+ {
+ *phys_addr = (cell_t *)(m_pPlugin->memory + local_addr);
+ }
+
+ return SP_ERROR_NONE;
+}
+
+int BaseContext::PushCell(cell_t value)
+{
+ return SP_ERROR_ABORTED;
+}
+
+int BaseContext::PushCellsFromArray(cell_t array[], unsigned int numcells)
+{
+ return SP_ERROR_ABORTED;
+}
+
+int BaseContext::PushCellArray(cell_t *local_addr, cell_t **phys_addr, cell_t array[], unsigned int numcells)
+{
+ return SP_ERROR_ABORTED;
+}
+
+int BaseContext::LocalToString(cell_t local_addr, char **addr)
+{
+ if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp))
+ || (local_addr < 0) || ((ucell_t)local_addr >= m_pPlugin->mem_size))
+ {
+ return SP_ERROR_INVALID_ADDRESS;
+ }
+ *addr = (char *)(m_pPlugin->memory + local_addr);
+
+ return SP_ERROR_NONE;
+}
+
+int BaseContext::PushString(cell_t *local_addr, char **phys_addr, const char *string)
+{
+ return SP_ERROR_ABORTED;
+}
+
+int BaseContext::StringToLocal(cell_t local_addr, size_t bytes, const char *source)
+{
+ char *dest;
+ size_t len;
+
+ if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp))
+ || (local_addr < 0) || ((ucell_t)local_addr >= m_pPlugin->mem_size))
+ {
+ return SP_ERROR_INVALID_ADDRESS;
+ }
+
+ if (bytes == 0)
+ {
+ return SP_ERROR_NONE;
+ }
+
+ len = strlen(source);
+ dest = (char *)(m_pPlugin->memory + local_addr);
+
+ if (len >= bytes)
+ {
+ len = bytes - 1;
+ }
+
+ memmove(dest, source, len);
+ dest[len] = '\0';
+
+ return SP_ERROR_NONE;
+}
+
+inline int __CheckValidChar(char *c)
+{
+ int count;
+ int bytecount = 0;
+
+ for (count=1; (*c & 0xC0) == 0x80; count++)
+ {
+ c--;
+ }
+
+ switch (*c & 0xF0)
+ {
+ case 0xC0:
+ case 0xD0:
+ {
+ bytecount = 2;
+ break;
+ }
+ case 0xE0:
+ {
+ bytecount = 3;
+ break;
+ }
+ case 0xF0:
+ {
+ bytecount = 4;
+ break;
+ }
+ }
+
+ if (bytecount != count)
+ {
+ return count;
+ }
+
+ return 0;
+}
+
+int BaseContext::StringToLocalUTF8(cell_t local_addr, size_t maxbytes, const char *source, size_t *wrtnbytes)
+{
+ char *dest;
+ size_t len;
+ bool needtocheck = false;
+
+ if (((local_addr >= m_ctx.hp) && (local_addr < m_ctx.sp))
+ || (local_addr < 0)
+ || ((ucell_t)local_addr >= m_pPlugin->mem_size))
+ {
+ return SP_ERROR_INVALID_ADDRESS;
+ }
+
+ if (maxbytes == 0)
+ {
+ return SP_ERROR_NONE;
+ }
+
+ len = strlen(source);
+ dest = (char *)(m_pPlugin->memory + local_addr);
+
+ if ((size_t)len >= maxbytes)
+ {
+ len = maxbytes - 1;
+ needtocheck = true;
+ }
+
+ memmove(dest, source, len);
+ if ((dest[len-1] & 1<<7) && needtocheck)
+ {
+ len -= __CheckValidChar(dest+len-1);
+ }
+ dest[len] = '\0';
+
+ if (wrtnbytes)
+ {
+ *wrtnbytes = len;
+ }
+
+ return SP_ERROR_NONE;
+}
+
+IPluginFunction *BaseContext::GetFunctionById(funcid_t func_id)
+{
+ return m_pRuntime->GetFunctionById(func_id);
+}
+
+IPluginFunction *BaseContext::GetFunctionByName(const char *public_name)
+{
+ return m_pRuntime->GetFunctionByName(public_name);
+}
+
+int BaseContext::LocalToStringNULL(cell_t local_addr, char **addr)
+{
+ int err;
+ if ((err = LocalToString(local_addr, addr)) != SP_ERROR_NONE)
+ {
+ return err;
+ }
+
+ if ((cell_t *)*addr == m_pNullString)
+ {
+ *addr = NULL;
+ }
+
+ return SP_ERROR_NONE;
+}
+
+SourceMod::IdentityToken_t *BaseContext::GetIdentity()
+{
+ SourceMod::IdentityToken_t *tok;
+
+ if (GetKey(1, (void **)&tok))
+ {
+ return tok;
+ }
+
+ return NULL;
+}
+
+cell_t *BaseContext::GetNullRef(SP_NULL_TYPE type)
+{
+ if (type == SP_NULL_VECTOR)
+ {
+ return m_pNullVec;
+ }
+
+ return NULL;
+}
+
+bool BaseContext::IsInExec()
+{
+ return m_InExec;
+}
+
+int BaseContext::Execute2(IPluginFunction *function, const cell_t *params, unsigned int num_params, cell_t *result)
+{
+ int ir;
+ int serial;
+ cell_t *sp;
+ funcid_t fnid;
+ sp_public_t *pubfunc;
+ cell_t _ignore_result;
+
+ fnid = function->GetFunctionID();
+
+ if (fnid & 1)
+ {
+ unsigned int public_id;
+
+ public_id = fnid >> 1;
+
+ if (m_pRuntime->GetPublicByIndex(public_id, &pubfunc) != SP_ERROR_NONE)
+ {
+ return SP_ERROR_NOT_FOUND;
+ }
+ }
+ else
+ {
+ return SP_ERROR_INVALID_ADDRESS;
+ }
+
+ if (m_pRuntime->IsPaused())
+ {
+ return SP_ERROR_NOT_RUNNABLE;
+ }
+
+ if ((cell_t)(m_ctx.hp + 16*sizeof(cell_t)) > (cell_t)(m_ctx.sp - (sizeof(cell_t) * (num_params + 1))))
+ {
+ return SP_ERROR_STACKLOW;
+ }
+
+ if (result == NULL)
+ {
+ result = &_ignore_result;
+ }
+
+ /* We got this far. It's time to start profiling. */
+
+ if ((m_pPlugin->prof_flags & SP_PROF_CALLBACKS) == SP_PROF_CALLBACKS)
+ {
+ serial = m_pPlugin->profiler->OnCallbackBegin(this, pubfunc);
+ }
+
+ /* Save our previous state. */
+
+ bool save_exec;
+ uint32_t save_n_idx;
+ cell_t save_sp, save_hp;
+
+ save_sp = m_ctx.sp;
+ save_hp = m_ctx.hp;
+ save_exec = m_InExec;
+ save_n_idx = m_ctx.n_idx;
+
+ /* Push parameters */
+
+ m_ctx.sp -= sizeof(cell_t) * (num_params + 1);
+ sp = (cell_t *)(m_pPlugin->memory + m_ctx.sp);
+
+ sp[0] = num_params;
+ for (unsigned int i = 0; i < num_params; i++)
+ {
+ sp[i + 1] = params[i];
+ }
+
+ /* Clear internal state */
+ m_ctx.n_err = SP_ERROR_NONE;
+ m_ctx.n_idx = 0;
+ m_MsgCache[0] = '\0';
+ m_CustomMsg = false;
+ m_InExec = false;
+
+ /* Start the tracer */
+
+ g_engine1.PushTracer(this);
+
+ /* Execute the function */
+
+ ir = g_Jit1.ContextExecute(m_pPlugin, &m_ctx, pubfunc->code_offs, result);
+
+ /* Restore some states, stop tracing */
+
+ m_InExec = save_exec;
+
+ if (ir == SP_ERROR_NONE)
+ {
+ m_ctx.n_err = SP_ERROR_NONE;
+ if (m_ctx.sp != save_sp)
+ {
+ ir = SP_ERROR_STACKLEAK;
+ _SetErrorMessage("Stack leak detected: sp:%d should be %d!",
+ m_ctx.sp,
+ save_sp);
+ }
+ if (m_ctx.hp != save_hp)
+ {
+ ir = SP_ERROR_HEAPLEAK;
+ _SetErrorMessage("Heap leak detected: hp:%d should be %d!",
+ m_ctx.hp,
+ save_hp);
+ }
+ }
+
+ m_ctx.sp = save_sp;
+ m_ctx.hp = save_hp;
+
+ g_engine1.PopTracer(ir, m_CustomMsg ? m_MsgCache : NULL);
+
+ if ((m_pPlugin->prof_flags & SP_PROF_CALLBACKS) == SP_PROF_CALLBACKS)
+ {
+ m_pPlugin->profiler->OnCallbackEnd(serial);
+ }
+
+ m_ctx.n_idx = save_n_idx;
+ m_ctx.n_err = SP_ERROR_NONE;
+ m_MsgCache[0] = '\0';
+ m_CustomMsg = false;
+
+ return ir;
+}
+
+IPluginRuntime *BaseContext::GetRuntime()
+{
+ return m_pRuntime;
+}
+
+int BaseRuntime::ApplyCompilationOptions(ICompilation *co)
+{
+ int err;
+
+ /* The JIT does not destroy anything until it is guaranteed to succeed. */
+ if (!g_Jit1.Compile(co, this, &err))
+ {
+ return err;
+ }
+
+ RefreshFunctionCache();
+
+ m_pCtx->Refresh();
+
+ return SP_ERROR_NONE;
+}
+
+DebugInfo::DebugInfo(sp_plugin_t *plugin) : m_pPlugin(plugin)
+{
+}
+
+#define USHR(x) ((unsigned int)(x)>>1)
+
+int DebugInfo::LookupFile(ucell_t addr, const char **filename)
+{
+ int high, low, mid;
+
+ high = m_pPlugin->debug.files_num;
+ low = -1;
+
+ while (high - low > 1)
+ {
+ mid = USHR(low + high);
+ if (m_pPlugin->files[mid].addr <= addr)
+ {
+ low = mid;
+ } else {
+ high = mid;
+ }
+ }
+
+ if (low == -1)
+ {
+ return SP_ERROR_NOT_FOUND;
+ }
+
+ *filename = m_pPlugin->files[low].name;
+
+ return SP_ERROR_NONE;
+}
+
+int DebugInfo::LookupFunction(ucell_t addr, const char **name)
+{
+ uint32_t iter, max = m_pPlugin->debug.syms_num;
+
+ for (iter=0; itersymbols[iter].sym->ident == SP_SYM_FUNCTION)
+ && (m_pPlugin->symbols[iter].codestart <= addr)
+ && (m_pPlugin->symbols[iter].codeend > addr))
+ {
+ break;
+ }
+ }
+
+ if (iter >= max)
+ {
+ return SP_ERROR_NOT_FOUND;
+ }
+
+ *name = m_pPlugin->symbols[iter].name;
+
+ return SP_ERROR_NONE;
+}
+
+int DebugInfo::LookupLine(ucell_t addr, uint32_t *line)
+{
+ int high, low, mid;
+
+ high = m_pPlugin->debug.lines_num;
+ low = -1;
+
+ while (high - low > 1)
+ {
+ mid = USHR(low + high);
+ if (m_pPlugin->lines[mid].addr <= addr)
+ {
+ low = mid;
+ } else {
+ high = mid;
+ }
+ }
+
+ if (low == -1)
+ {
+ return SP_ERROR_NOT_FOUND;
+ }
+
+ /* Since the CIP occurs BEFORE the line, we have to add one */
+ *line = m_pPlugin->lines[low].line + 1;
+
+ return SP_ERROR_NONE;
+}
+
+#undef USHR
+
+int BaseContext::GetLastNativeError()
+{
+ return m_ctx.n_err;
+}
+
+cell_t *BaseContext::GetLocalParams()
+{
+ return (cell_t *)(m_pPlugin->memory + m_ctx.frm + (2 * sizeof(cell_t)));
+}
+
+void BaseContext::SetKey(int k, void *value)
+{
+ if (k < 1 || k > 4)
+ {
+ return;
+ }
+
+ m_keys[k - 1] = value;
+ m_keys_set[k - 1] = true;
+}
+
+bool BaseContext::GetKey(int k, void **value)
+{
+ if (k < 1 || k > 4 || m_keys_set[k - 1] == false)
+ {
+ return false;
+ }
+
+ *value = m_keys[k - 1];
+
+ return true;
+}
+
+void BaseContext::Refresh()
+{
+ /* Initialize the null references */
+ uint32_t index;
+ if (FindPubvarByName("NULL_VECTOR", &index) == SP_ERROR_NONE)
+ {
+ sp_pubvar_t *pubvar;
+ GetPubvarByIndex(index, &pubvar);
+ m_pNullVec = pubvar->offs;
+ }
+ else
+ {
+ m_pNullVec = NULL;
+ }
+
+ if (FindPubvarByName("NULL_STRING", &index) == SP_ERROR_NONE)
+ {
+ sp_pubvar_t *pubvar;
+ GetPubvarByIndex(index, &pubvar);
+ m_pNullString = pubvar->offs;
+ }
+ else
+ {
+ m_pNullString = NULL;
+ }
+}
diff --git a/sourcepawn/jit/sp_vm_basecontext.h b/sourcepawn/jit/sp_vm_basecontext.h
new file mode 100644
index 00000000..b92b33df
--- /dev/null
+++ b/sourcepawn/jit/sp_vm_basecontext.h
@@ -0,0 +1,114 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourcePawn
+ * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see .
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or .
+ *
+ * Version: $Id$
+ */
+
+#ifndef _INCLUDE_SOURCEPAWN_BASECONTEXT_H_
+#define _INCLUDE_SOURCEPAWN_BASECONTEXT_H_
+
+#include "sp_vm_api.h"
+#include "sp_vm_function.h"
+#include "BaseRuntime.h"
+#include "jit_shared.h"
+
+/**
+ * :TODO: Make functions allocate as a lump instead of individual allocations!
+ */
+
+class BaseContext : public IPluginContext
+{
+public:
+ BaseContext(BaseRuntime *pRuntime);
+ ~BaseContext();
+public: //IPluginContext
+ IVirtualMachine *GetVirtualMachine();
+ sp_context_t *GetContext();
+ sp_context_t *GetCtx();
+ bool IsDebugging();
+ int SetDebugBreak(void *newpfn, void *oldpfn);
+ IPluginDebugInfo *GetDebugInfo();
+ int HeapAlloc(unsigned int cells, cell_t *local_addr, cell_t **phys_addr);
+ int HeapPop(cell_t local_addr);
+ int HeapRelease(cell_t local_addr);
+ int FindNativeByName(const char *name, uint32_t *index);
+ int GetNativeByIndex(uint32_t index, sp_native_t **native);
+ uint32_t GetNativesNum();
+ int FindPublicByName(const char *name, uint32_t *index);
+ int GetPublicByIndex(uint32_t index, sp_public_t **publicptr);
+ uint32_t GetPublicsNum();
+ int GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar);
+ int FindPubvarByName(const char *name, uint32_t *index);
+ int GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr);
+ uint32_t GetPubVarsNum();
+ int LocalToPhysAddr(cell_t local_addr, cell_t **phys_addr);
+ int LocalToString(cell_t local_addr, char **addr);
+ int StringToLocal(cell_t local_addr, size_t chars, const char *source);
+ int StringToLocalUTF8(cell_t local_addr, size_t maxbytes, const char *source, size_t *wrtnbytes);
+ int PushCell(cell_t value);
+ int PushCellArray(cell_t *local_addr, cell_t **phys_addr, cell_t array[], unsigned int numcells);
+ int PushString(cell_t *local_addr, char **phys_addr, const char *string);
+ int PushCellsFromArray(cell_t array[], unsigned int numcells);
+ int BindNatives(const sp_nativeinfo_t *natives, unsigned int num, int overwrite);
+ int BindNative(const sp_nativeinfo_t *native);
+ int BindNativeToAny(SPVM_NATIVE_FUNC native);
+ int Execute(uint32_t code_addr, cell_t *result);
+ cell_t ThrowNativeErrorEx(int error, const char *msg, ...);
+ cell_t ThrowNativeError(const char *msg, ...);
+ IPluginFunction *GetFunctionByName(const char *public_name);
+ IPluginFunction *GetFunctionById(funcid_t func_id);
+ SourceMod::IdentityToken_t *GetIdentity();
+ cell_t *GetNullRef(SP_NULL_TYPE type);
+ int LocalToStringNULL(cell_t local_addr, char **addr);
+ int BindNativeToIndex(uint32_t index, SPVM_NATIVE_FUNC native);
+ int Execute2(IPluginFunction *function, const cell_t *params, unsigned int num_params, cell_t *result);
+ IPluginRuntime *GetRuntime();
+ int GetLastNativeError();
+ cell_t *GetLocalParams();
+ void SetKey(int k, void *value);
+ bool GetKey(int k, void **value);
+ void Refresh();
+public:
+ bool IsInExec();
+private:
+ void SetErrorMessage(const char *msg, va_list ap);
+ void _SetErrorMessage(const char *msg, ...);
+private:
+ sp_plugin_t *m_pPlugin;
+ cell_t *m_pNullVec;
+ cell_t *m_pNullString;
+ char m_MsgCache[1024];
+ bool m_CustomMsg;
+ bool m_InExec;
+ BaseRuntime *m_pRuntime;
+ sp_context_t m_ctx;
+ void *m_keys[4];
+ bool m_keys_set[4];
+};
+
+#endif //_INCLUDE_SOURCEPAWN_BASECONTEXT_H_
diff --git a/core/vm/sp_vm_engine.cpp b/sourcepawn/jit/sp_vm_engine.cpp
similarity index 55%
rename from core/vm/sp_vm_engine.cpp
rename to sourcepawn/jit/sp_vm_engine.cpp
index 6a28014b..944170b5 100644
--- a/core/vm/sp_vm_engine.cpp
+++ b/sourcepawn/jit/sp_vm_engine.cpp
@@ -48,6 +48,8 @@
#include "zlib/zlib.h"
#include "sp_vm_basecontext.h"
+SourcePawnEngine g_engine1;
+
#if defined WIN32
#define WIN32_LEAN_AND_MEAN
#include
@@ -92,7 +94,7 @@ static const char *g_ErrorMsgTable[] =
"Call was aborted",
};
-const char *GetSourcePawnErrorMessage(int error)
+const char *SourcePawnEngine::GetErrorString(int error)
{
if (error < 1 || error > ERROR_MESSAGE_MAX)
{
@@ -188,281 +190,31 @@ void SourcePawnEngine::BaseFree(void *memory)
free(memory);
}
-IPluginContext *SourcePawnEngine::CreateBaseContext(sp_context_t *ctx)
-{
- return new BaseContext(ctx);
-}
-
-void SourcePawnEngine::FreeBaseContext(IPluginContext *ctx)
-{
- delete ctx;
-}
-
-sp_plugin_t *_ReadPlugin(sp_file_hdr_t *hdr, uint8_t *base, sp_plugin_t *plugin, int *err)
-{
- char *nameptr;
- uint8_t sectnum = 0;
- sp_file_section_t *secptr = (sp_file_section_t *)(base + sizeof(sp_file_hdr_t));
-
- memset(plugin, 0, sizeof(sp_plugin_t));
-
- plugin->base = base;
-
- while (sectnum < hdr->sections)
- {
- nameptr = (char *)(base + hdr->stringtab + secptr->nameoffs);
-
- if (!(plugin->pcode) && !strcmp(nameptr, ".code"))
- {
- sp_file_code_t *cod = (sp_file_code_t *)(base + secptr->dataoffs);
- plugin->pcode = base + secptr->dataoffs + cod->code;
- plugin->pcode_size = cod->codesize;
- plugin->flags = cod->flags;
- }
- else if (!(plugin->data) && !strcmp(nameptr, ".data"))
- {
- sp_file_data_t *dat = (sp_file_data_t *)(base + secptr->dataoffs);
- plugin->data = base + secptr->dataoffs + dat->data;
- plugin->data_size = dat->datasize;
- plugin->memory = dat->memsize;
- }
- else if (!(plugin->info.publics) && !strcmp(nameptr, ".publics"))
- {
- plugin->info.publics_num = secptr->size / sizeof(sp_file_publics_t);
- plugin->info.publics = (sp_file_publics_t *)(base + secptr->dataoffs);
- }
- else if (!(plugin->info.pubvars) && !strcmp(nameptr, ".pubvars"))
- {
- plugin->info.pubvars_num = secptr->size / sizeof(sp_file_pubvars_t);
- plugin->info.pubvars = (sp_file_pubvars_t *)(base + secptr->dataoffs);
- }
- else if (!(plugin->info.natives) && !strcmp(nameptr, ".natives"))
- {
- plugin->info.natives_num = secptr->size / sizeof(sp_file_natives_t);
- plugin->info.natives = (sp_file_natives_t *)(base + secptr->dataoffs);
- }
- else if (!(plugin->info.stringbase) && !strcmp(nameptr, ".names"))
- {
- plugin->info.stringbase = (const char *)(base + secptr->dataoffs);
- }
- else if (!(plugin->debug.files) && !strcmp(nameptr, ".dbg.files"))
- {
- plugin->debug.files = (sp_fdbg_file_t *)(base + secptr->dataoffs);
- }
- else if (!(plugin->debug.lines) && !strcmp(nameptr, ".dbg.lines"))
- {
- plugin->debug.lines = (sp_fdbg_line_t *)(base + secptr->dataoffs);
- }
- else if (!(plugin->debug.symbols) && !strcmp(nameptr, ".dbg.symbols"))
- {
- plugin->debug.symbols = (sp_fdbg_symbol_t *)(base + secptr->dataoffs);
- }
- else if (!(plugin->debug.lines_num) && !strcmp(nameptr, ".dbg.info"))
- {
- sp_fdbg_info_t *inf = (sp_fdbg_info_t *)(base + secptr->dataoffs);
- plugin->debug.files_num = inf->num_files;
- plugin->debug.lines_num = inf->num_lines;
- plugin->debug.syms_num = inf->num_syms;
- }
- else if (!(plugin->debug.stringbase) && !strcmp(nameptr, ".dbg.strings"))
- {
- plugin->debug.stringbase = (const char *)(base + secptr->dataoffs);
- }
-
- secptr++;
- sectnum++;
- }
-
- if (!(plugin->pcode) || !(plugin->data) || !(plugin->info.stringbase))
- {
- goto return_error;
- }
-
- if ((plugin->flags & SP_FLAG_DEBUG) && (!(plugin->debug.files) || !(plugin->debug.lines) || !(plugin->debug.symbols)))
- {
- goto return_error;
- }
-
- if (err)
- {
- *err = SP_ERROR_NONE;
- }
-
- return plugin;
-
-return_error:
- if (err)
- {
- *err = SP_ERROR_FILE_FORMAT;
- }
-
- return NULL;
-}
-
sp_plugin_t *SourcePawnEngine::LoadFromFilePointer(FILE *fp, int *err)
{
- sp_file_hdr_t hdr;
- sp_plugin_t *plugin;
- uint8_t *base;
- int z_result;
- int error;
-
- if (!fp)
+ if (err != NULL)
{
- error = SP_ERROR_NOT_FOUND;
- goto return_error;
+ *err = SP_ERROR_ABORTED;
}
- /* Rewind for safety */
- rewind(fp);
- fread(&hdr, sizeof(sp_file_hdr_t), 1, fp);
-
- if (hdr.magic != SPFILE_MAGIC)
- {
- error = SP_ERROR_FILE_FORMAT;
- goto return_error;
- }
-
- switch (hdr.compression)
- {
- case SPFILE_COMPRESSION_GZ:
- {
- uint32_t uncompsize = hdr.imagesize - hdr.dataoffs;
- uint32_t compsize = hdr.disksize - hdr.dataoffs;
- uint32_t sectsize = hdr.dataoffs - sizeof(sp_file_hdr_t);
- uLongf destlen = uncompsize;
-
- char *tempbuf = (char *)malloc(compsize);
- void *uncompdata = malloc(uncompsize);
- void *sectheader = malloc(sectsize);
-
- fread(sectheader, sectsize, 1, fp);
- fread(tempbuf, compsize, 1, fp);
-
- z_result = uncompress((Bytef *)uncompdata, &destlen, (Bytef *)tempbuf, compsize);
- free(tempbuf);
- if (z_result != Z_OK)
- {
- free(sectheader);
- free(uncompdata);
- error = SP_ERROR_DECOMPRESSOR;
- goto return_error;
- }
-
- base = (uint8_t *)malloc(hdr.imagesize);
- memcpy(base, &hdr, sizeof(sp_file_hdr_t));
- memcpy(base + sizeof(sp_file_hdr_t), sectheader, sectsize);
- free(sectheader);
- memcpy(base + hdr.dataoffs, uncompdata, uncompsize);
- free(uncompdata);
- break;
- }
- case SPFILE_COMPRESSION_NONE:
- {
- base = (uint8_t *)malloc(hdr.imagesize);
- rewind(fp);
- fread(base, hdr.imagesize, 1, fp);
- break;
- }
- default:
- {
- error = SP_ERROR_DECOMPRESSOR;
- goto return_error;
- }
- }
-
- plugin = (sp_plugin_t *)malloc(sizeof(sp_plugin_t));
- if (!_ReadPlugin(&hdr, base, plugin, err))
- {
- free(plugin);
- free(base);
- return NULL;
- }
-
- plugin->allocflags = 0;
-
- return plugin;
-
-return_error:
- if (err)
- {
- *err = error;
- }
return NULL;
}
sp_plugin_t *SourcePawnEngine::LoadFromMemory(void *base, sp_plugin_t *plugin, int *err)
{
- sp_file_hdr_t hdr;
- uint8_t noptr = 0;
-
- memcpy(&hdr, base, sizeof(sp_file_hdr_t));
-
- if (!plugin)
+ if (err != NULL)
{
- plugin = (sp_plugin_t *)malloc(sizeof(sp_plugin_t));
- noptr = 1;
+ *err = SP_ERROR_ABORTED;
}
- if (!_ReadPlugin(&hdr, (uint8_t *)base, plugin, err))
- {
- if (noptr)
- {
- free(plugin);
- }
- return NULL;
- }
-
- if (!noptr)
- {
- plugin->allocflags |= SP_FA_SELF_EXTERNAL;
- }
- plugin->allocflags |= SP_FA_BASE_EXTERNAL;
-
- return plugin;
+ return NULL;
}
int SourcePawnEngine::FreeFromMemory(sp_plugin_t *plugin)
{
- if (!(plugin->allocflags & SP_FA_BASE_EXTERNAL))
- {
- free(plugin->base);
- plugin->base = NULL;
- }
- if (!(plugin->allocflags & SP_FA_SELF_EXTERNAL))
- {
- free(plugin);
- }
-
- return SP_ERROR_NONE;
+ return SP_ERROR_ABORTED;
}
-#if 0
-void SourcePawnEngine::ReleaseFunctionToPool(CFunction *func)
-{
- if (!func)
- {
- return;
- }
- func->Cancel();
- func->m_pNext = m_pFreeFuncs;
- m_pFreeFuncs = func;
-}
-
-CFunction *SourcePawnEngine::GetFunctionFromPool(funcid_t f, IPluginContext *plugin)
-{
- if (!m_pFreeFuncs)
- {
- return new CFunction(f, plugin);
- } else {
- CFunction *pFunc = m_pFreeFuncs;
- m_pFreeFuncs = m_pFreeFuncs->m_pNext;
- pFunc->Set(f, plugin);
- return pFunc;
- }
-}
-#endif
-
IDebugListener *SourcePawnEngine::SetDebugListener(IDebugListener *pListener)
{
IDebugListener *old = m_pDebugHook;
@@ -529,7 +281,7 @@ void SourcePawnEngine::FreeTracedCall(TracedCall *pCall)
}
}
-void SourcePawnEngine::PushTracer(sp_context_t *ctx)
+void SourcePawnEngine::PushTracer(BaseContext *ctx)
{
TracedCall *pCall = MakeTracedCall(true);
@@ -538,7 +290,7 @@ void SourcePawnEngine::PushTracer(sp_context_t *ctx)
pCall->frm = INVALID_CIP;
}
-void SourcePawnEngine::RunTracer(sp_context_t *ctx, uint32_t frame, uint32_t codeip)
+void SourcePawnEngine::RunTracer(BaseContext *ctx, uint32_t frame, uint32_t codeip)
{
assert(m_CallStack != NULL);
assert(m_CallStack->ctx == ctx);
@@ -577,13 +329,13 @@ void SourcePawnEngine::PopTracer(int error, const char *msg)
{
uint32_t native = INVALID_CIP;
- if (m_CallStack->ctx->n_err)
+ if (m_CallStack->ctx->GetCtx()->n_err)
{
- native = m_CallStack->ctx->n_idx;
+ native = m_CallStack->ctx->GetCtx()->n_idx;
}
CContextTrace trace(m_CallStack, error, msg, native);
- m_pDebugHook->OnContextExecuteError(m_CallStack->ctx->context, &trace);
+ m_pDebugHook->OnContextExecuteError(m_CallStack->ctx, &trace);
}
/* Now pop the error chain */
@@ -607,7 +359,7 @@ CContextTrace::CContextTrace(TracedCall *pStart, int error, const char *msg, uin
bool CContextTrace::DebugInfoAvailable()
{
- return ((m_pStart->ctx->flags & SP_FLAG_DEBUG) == SP_FLAG_DEBUG);
+ return m_pStart->ctx->IsDebugging();
}
const char *CContextTrace::GetCustomErrorString()
@@ -648,7 +400,7 @@ bool CContextTrace::GetTraceInfo(CallStackInfo *trace)
return false;
}
- IPluginContext *pContext = m_pIterator->ctx->context;
+ IPluginContext *pContext = m_pIterator->ctx;
IPluginDebugInfo *pInfo = pContext->GetDebugInfo();
if (!pInfo)
@@ -690,7 +442,7 @@ const char *CContextTrace::GetLastNative(uint32_t *index)
}
sp_native_t *native;
- if (m_pIterator->ctx->context->GetNativeByIndex(m_Native, &native) != SP_ERROR_NONE)
+ if (m_pIterator->ctx->GetNativeByIndex(m_Native, &native) != SP_ERROR_NONE)
{
return NULL;
}
diff --git a/core/vm/sp_vm_engine.h b/sourcepawn/jit/sp_vm_engine.h
similarity index 91%
rename from core/vm/sp_vm_engine.h
rename to sourcepawn/jit/sp_vm_engine.h
index c50f8267..08e5c79a 100644
--- a/core/vm/sp_vm_engine.h
+++ b/sourcepawn/jit/sp_vm_engine.h
@@ -35,11 +35,13 @@
#include "sp_vm_api.h"
#include "sp_vm_function.h"
+class BaseContext;
+
struct TracedCall
{
uint32_t cip;
uint32_t frm;
- sp_context_t *ctx;
+ BaseContext *ctx;
TracedCall *next;
unsigned int chain;
};
@@ -73,8 +75,6 @@ public: //ISourcePawnEngine
sp_plugin_t *LoadFromFilePointer(FILE *fp, int *err);
sp_plugin_t *LoadFromMemory(void *base, sp_plugin_t *plugin, int *err);
int FreeFromMemory(sp_plugin_t *plugin);
- IPluginContext *CreateBaseContext(sp_context_t *ctx);
- void FreeBaseContext(IPluginContext *ctx);
void *BaseAlloc(size_t size);
void BaseFree(void *memory);
void *ExecAlloc(size_t size);
@@ -86,13 +86,14 @@ public: //ISourcePawnEngine
void SetReadWrite(void *ptr);
void SetReadExecute(void *ptr);
void FreePageMemory(void *ptr);
+ const char *GetErrorString(int err);
public: //Debugger Stuff
/**
* @brief Pushes a context onto the top of the call tracer.
*
* @param ctx Plugin context.
*/
- void PushTracer(sp_context_t *ctx);
+ void PushTracer(BaseContext *ctx);
/**
* @brief Pops a plugin off the call tracer.
@@ -102,7 +103,7 @@ public: //Debugger Stuff
/**
* @brief Runs tracer from a debug break.
*/
- void RunTracer(sp_context_t *ctx, uint32_t frame, uint32_t codeip);
+ void RunTracer(BaseContext *ctx, uint32_t frame, uint32_t codeip);
public: //Plugin function stuff
CFunction *GetFunctionFromPool(funcid_t f, IPluginContext *plugin);
void ReleaseFunctionToPool(CFunction *func);
@@ -117,4 +118,6 @@ private:
//CFunction *m_pFreeFuncs;
};
+extern SourcePawnEngine g_engine1;
+
#endif //_INCLUDE_SOURCEPAWN_VM_ENGINE_H_
diff --git a/core/vm/sp_vm_function.cpp b/sourcepawn/jit/sp_vm_function.cpp
similarity index 74%
rename from core/vm/sp_vm_function.cpp
rename to sourcepawn/jit/sp_vm_function.cpp
index cfc080ab..6a52ea02 100644
--- a/core/vm/sp_vm_function.cpp
+++ b/sourcepawn/jit/sp_vm_function.cpp
@@ -32,76 +32,47 @@
#include
#include
#include "sp_vm_function.h"
-#include "sm_stringutil.h"
+#include "BaseRuntime.h"
/********************
* FUNCTION CALLING *
********************/
-void CFunction::Set(uint32_t code_addr, IPluginContext *plugin, funcid_t id, uint32_t pub_id)
+void CFunction::Set(uint32_t code_addr, BaseRuntime *runtime, funcid_t fnid, uint32_t pub_id)
{
m_codeaddr = code_addr;
- m_pContext = plugin;
+ m_pRuntime = runtime;
m_curparam = 0;
m_errorstate = SP_ERROR_NONE;
m_Invalid = false;
- m_pCtx = plugin ? plugin->GetContext() : NULL;
- m_FnId = id;
-
- m_pContext->GetPublicByIndex(pub_id, &m_pPublic);
+ m_FnId = fnid;
}
bool CFunction::IsRunnable()
{
- return ((m_pCtx->flags & SPFLAG_PLUGIN_PAUSED) != SPFLAG_PLUGIN_PAUSED);
+ return !m_pRuntime->IsPaused();
}
int CFunction::CallFunction(const cell_t *params, unsigned int num_params, cell_t *result)
{
- int ir, serial;
+ return CallFunction2(m_pRuntime->GetDefaultContext(), params, num_params, result);
+}
- if (!IsRunnable())
- {
- return SP_ERROR_NOT_RUNNABLE;
- }
-
- if ((m_pCtx->prof_flags & SP_PROF_CALLBACKS) == SP_PROF_CALLBACKS
- && m_pPublic != NULL)
- {
- serial = m_pCtx->profiler->OnCallbackBegin(m_pContext, m_pPublic);
- }
-
- while (num_params--)
- {
- m_pContext->PushCell(params[num_params]);
- }
-
- ir = m_pContext->Execute(m_codeaddr, result);
-
- if ((m_pCtx->prof_flags & SP_PROF_CALLBACKS) == SP_PROF_CALLBACKS
- && m_pPublic != NULL)
- {
- m_pCtx->profiler->OnCallbackEnd(serial);
- }
-
- return ir;
+int CFunction::CallFunction2(IPluginContext *pContext, const cell_t *params, unsigned int num_params, cell_t *result)
+{
+ return pContext->Execute2(this, params, num_params, result);
}
IPluginContext *CFunction::GetParentContext()
{
- return m_pContext;
+ return m_pRuntime->GetDefaultContext();
}
-CFunction::CFunction(uint32_t code_addr, IPluginContext *plugin, funcid_t id, uint32_t pub_id) :
- m_codeaddr(code_addr), m_pContext(plugin), m_curparam(0),
- m_errorstate(SP_ERROR_NONE), m_FnId(id)
+CFunction::CFunction(uint32_t code_addr, BaseRuntime *runtime, funcid_t id, uint32_t pub_id) :
+ m_codeaddr(code_addr), m_curparam(0), m_errorstate(SP_ERROR_NONE), m_FnId(id)
{
m_Invalid = false;
- if (plugin)
- {
- m_pCtx = plugin->GetContext();
- }
- m_pContext->GetPublicByIndex(pub_id, &m_pPublic);
+ m_pRuntime = runtime;
}
int CFunction::PushCell(cell_t cell)
@@ -198,6 +169,11 @@ void CFunction::Cancel()
}
int CFunction::Execute(cell_t *result)
+{
+ return Execute2(m_pRuntime->GetDefaultContext(), result);
+}
+
+int CFunction::Execute2(IPluginContext *ctx, cell_t *result)
{
int err = SP_ERROR_NONE;
@@ -236,9 +212,9 @@ int CFunction::Execute(cell_t *result)
if (!temp_info[i].str.is_sz)
{
/* Allocate a normal/generic array */
- if ((err=m_pContext->HeapAlloc(temp_info[i].size,
- &(temp_info[i].local_addr),
- &(temp_info[i].phys_addr)))
+ if ((err=ctx->HeapAlloc(temp_info[i].size,
+ &(temp_info[i].local_addr),
+ &(temp_info[i].phys_addr)))
!= SP_ERROR_NONE)
{
break;
@@ -254,9 +230,9 @@ int CFunction::Execute(cell_t *result)
size_t cells = (temp_info[i].size + sizeof(cell_t) - 1) / sizeof(cell_t);
/* Allocate the buffer */
- if ((err=m_pContext->HeapAlloc(cells,
- &(temp_info[i].local_addr),
- &(temp_info[i].phys_addr)))
+ if ((err=ctx->HeapAlloc(cells,
+ &(temp_info[i].local_addr),
+ &(temp_info[i].phys_addr)))
!= SP_ERROR_NONE)
{
break;
@@ -267,10 +243,10 @@ int CFunction::Execute(cell_t *result)
/* Cut off UTF-8 properly */
if (temp_info[i].str.sz_flags & SM_PARAM_STRING_UTF8)
{
- if ((err=m_pContext->StringToLocalUTF8(temp_info[i].local_addr,
- temp_info[i].size,
- (const char *)temp_info[i].orig_addr,
- NULL))
+ if ((err=ctx->StringToLocalUTF8(temp_info[i].local_addr,
+ temp_info[i].size,
+ (const char *)temp_info[i].orig_addr,
+ NULL))
!= SP_ERROR_NONE)
{
break;
@@ -284,9 +260,9 @@ int CFunction::Execute(cell_t *result)
/* Copy ASCII characters */
else
{
- if ((err=m_pContext->StringToLocal(temp_info[i].local_addr,
- temp_info[i].size,
- (const char *)temp_info[i].orig_addr))
+ if ((err=ctx->StringToLocal(temp_info[i].local_addr,
+ temp_info[i].size,
+ (const char *)temp_info[i].orig_addr))
!= SP_ERROR_NONE)
{
break;
@@ -307,7 +283,7 @@ int CFunction::Execute(cell_t *result)
/* Make the call if we can */
if (err == SP_ERROR_NONE)
{
- if ((err = CallFunction(temp_params, numparams, result)) != SP_ERROR_NONE)
+ if ((err = CallFunction2(ctx, temp_params, numparams, result)) != SP_ERROR_NONE)
{
docopies = false;
}
@@ -350,7 +326,7 @@ int CFunction::Execute(cell_t *result)
}
}
- if ((err=m_pContext->HeapPop(temp_info[i].local_addr)) != SP_ERROR_NONE)
+ if ((err=ctx->HeapPop(temp_info[i].local_addr)) != SP_ERROR_NONE)
{
return err;
}
@@ -364,3 +340,16 @@ funcid_t CFunction::GetFunctionID()
return m_FnId;
}
+int CFunction::SetError(int err)
+{
+ m_errorstate = err;
+
+ return err;
+}
+
+bool CFunction::IsInvalidated()
+{
+ return m_Invalid;
+}
+
+
diff --git a/core/vm/sp_vm_function.h b/sourcepawn/jit/sp_vm_function.h
similarity index 85%
rename from core/vm/sp_vm_function.h
rename to sourcepawn/jit/sp_vm_function.h
index 275143c9..c9f9c610 100644
--- a/core/vm/sp_vm_function.h
+++ b/sourcepawn/jit/sp_vm_function.h
@@ -32,7 +32,11 @@
#ifndef _INCLUDE_SOURCEMOD_BASEFUNCTION_H_
#define _INCLUDE_SOURCEMOD_BASEFUNCTION_H_
-#include "sm_globals.h"
+#include
+
+class BaseRuntime;
+
+using namespace SourcePawn;
struct ParamInfo
{
@@ -56,7 +60,7 @@ class CFunction : public IPluginFunction
friend class SourcePawnEngine;
public:
CFunction(uint32_t code_addr,
- IPluginContext *pContext,
+ BaseRuntime *pRuntime,
funcid_t fnid,
uint32_t pub_id);
public:
@@ -71,29 +75,23 @@ public:
virtual void Cancel();
virtual int CallFunction(const cell_t *params, unsigned int num_params, cell_t *result);
virtual IPluginContext *GetParentContext();
- inline bool IsInvalidated()
- {
- return m_Invalid;
- }
- inline void Invalidate()
- {
- m_Invalid = true;
- }
+ bool IsInvalidated();
+ void Invalidate();
bool IsRunnable();
funcid_t GetFunctionID();
+ int Execute2(IPluginContext *ctx, cell_t *result);
+ int CallFunction2(IPluginContext *ctx,
+ const cell_t *params,
+ unsigned int num_params,
+ cell_t *result);
public:
- void Set(uint32_t code_addr, IPluginContext *plugin, funcid_t fnid, uint32_t pub_id);
+ void Set(uint32_t code_addr, BaseRuntime *runtime, funcid_t fnid, uint32_t pub_id);
private:
int _PushString(const char *string, int sz_flags, int cp_flags, size_t len);
- inline int SetError(int err)
- {
- m_errorstate = err;
- return err;
- }
+ int SetError(int err);
private:
uint32_t m_codeaddr;
- IPluginContext *m_pContext;
- sp_context_t *m_pCtx;
+ BaseRuntime *m_pRuntime;
cell_t m_params[SP_MAX_EXEC_PARAMS];
ParamInfo m_info[SP_MAX_EXEC_PARAMS];
unsigned int m_curparam;
@@ -101,7 +99,6 @@ private:
CFunction *m_pNext;
bool m_Invalid;
funcid_t m_FnId;
- sp_public_t *m_pPublic;
};
#endif //_INCLUDE_SOURCEMOD_BASEFUNCTION_H_
diff --git a/sourcepawn/jit/x86/version.rc b/sourcepawn/jit/version.rc
similarity index 100%
rename from sourcepawn/jit/x86/version.rc
rename to sourcepawn/jit/version.rc
diff --git a/sourcepawn/jit/x86/jit_x86.cpp b/sourcepawn/jit/x86/jit_x86.cpp
index 8d68c91d..f8bb89ee 100644
--- a/sourcepawn/jit/x86/jit_x86.cpp
+++ b/sourcepawn/jit/x86/jit_x86.cpp
@@ -35,12 +35,24 @@
#include "jit_x86.h"
#include "opcode_helpers.h"
#include
-#include "jit_version.h"
+#include "../jit_version.h"
+#include "../sp_vm_engine.h"
+#include "../engine2.h"
+#include "../BaseRuntime.h"
+#include "../sp_vm_basecontext.h"
#if defined USE_UNGEN_OPCODES
#include "ungen_opcodes.h"
#endif
+JITX86 g_Jit1;
+ISourcePawnEngine *engine = &g_engine1;
+
+inline sp_plugin_t *GETPLUGIN(sp_context_t *ctx)
+{
+ return (sp_plugin_t *)(ctx->vm[JITVARS_PLUGIN]);
+}
+
inline void WriteOp_Move_Pri(JitWriter *jit)
{
//mov eax, edx
@@ -1318,12 +1330,12 @@ inline void WriteOp_Retn(JitWriter *jit)
void ProfCallGate_Begin(sp_context_t *ctx, const char *name)
{
- ctx->profiler->OnFunctionBegin(ctx->context, name);
+ ((IProfiler *)ctx->vm[JITVARS_PROFILER])->OnFunctionBegin((IPluginContext *)ctx->vm[JITVARS_BASECTX], name);
}
void ProfCallGate_End(sp_context_t *ctx)
{
- ctx->profiler->OnFunctionEnd();
+ ((IProfiler *)ctx->vm[JITVARS_PROFILER])->OnFunctionEnd();
}
const char *find_func_name(sp_plugin_t *plugin, uint32_t offs)
@@ -2264,8 +2276,11 @@ inline void WriteOp_FloatCompare(JitWriter *jit)
cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
{
sp_native_t *native;
+ sp_plugin_t *plugin;
+
+ plugin = (sp_plugin_t *)ctx->vm[JITVARS_PLUGIN];
- native = &ctx->natives[native_idx];
+ native = &plugin->natives[native_idx];
ctx->n_idx = native_idx;
@@ -2276,15 +2291,18 @@ cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
return 0;
}
- return native->pfn(ctx->context, params);
+ return native->pfn(GET_CONTEXT(ctx), params);
}
cell_t NativeCallback_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
{
cell_t val;
sp_native_t *native;
+ sp_plugin_t *plugin;
- native = &ctx->natives[native_idx];
+ plugin = (sp_plugin_t *)ctx->vm[JITVARS_PLUGIN];
+
+ native = &plugin->natives[native_idx];
ctx->n_idx = native_idx;
@@ -2295,9 +2313,9 @@ cell_t NativeCallback_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *par
return 0;
}
- ctx->profiler->OnNativeBegin(ctx->context, native);
- val = native->pfn(ctx->context, params);
- ctx->profiler->OnNativeEnd();
+ plugin->profiler->OnNativeBegin(GET_CONTEXT(ctx), native);
+ val = native->pfn(GET_CONTEXT(ctx), params);
+ plugin->profiler->OnNativeEnd();
return val;
}
@@ -2307,9 +2325,11 @@ cell_t NativeCallback_Debug(sp_context_t *ctx, ucell_t native_idx, cell_t *param
cell_t save_sp = ctx->sp;
cell_t save_hp = ctx->hp;
+ sp_plugin_t *pl = GETPLUGIN(ctx);
+
ctx->n_idx = native_idx;
- if (ctx->hp < ctx->heap_base)
+ if (ctx->hp < (cell_t)pl->data_size)
{
ctx->n_err = SP_ERROR_HEAPMIN;
return 0;
@@ -2321,7 +2341,7 @@ cell_t NativeCallback_Debug(sp_context_t *ctx, ucell_t native_idx, cell_t *param
return 0;
}
- if ((uint32_t)ctx->sp >= ctx->mem_size)
+ if ((uint32_t)ctx->sp >= pl->mem_size)
{
ctx->n_err = SP_ERROR_STACKMIN;
return 0;
@@ -2353,9 +2373,11 @@ cell_t NativeCallback_Debug_Profile(sp_context_t *ctx, ucell_t native_idx, cell_
cell_t save_sp = ctx->sp;
cell_t save_hp = ctx->hp;
+ sp_plugin_t *pl = GETPLUGIN(ctx);
+
ctx->n_idx = native_idx;
- if (ctx->hp < ctx->heap_base)
+ if (ctx->hp < (cell_t)pl->data_size)
{
ctx->n_err = SP_ERROR_HEAPMIN;
return 0;
@@ -2367,7 +2389,7 @@ cell_t NativeCallback_Debug_Profile(sp_context_t *ctx, ucell_t native_idx, cell_
return 0;
}
- if ((uint32_t)ctx->sp >= ctx->mem_size)
+ if ((uint32_t)ctx->sp >= pl->mem_size)
{
ctx->n_err = SP_ERROR_STACKMIN;
return 0;
@@ -2396,10 +2418,7 @@ cell_t NativeCallback_Debug_Profile(sp_context_t *ctx, ucell_t native_idx, cell_
static cell_t InvalidNative(IPluginContext *pCtx, const cell_t *params)
{
- sp_context_t *ctx = pCtx->GetContext();
- ctx->n_err = SP_ERROR_INVALID_NATIVE;
-
- return 0;
+ return pCtx->ThrowNativeErrorEx(SP_ERROR_INVALID_NATIVE, "Invalid native");
}
jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative)
@@ -2457,11 +2476,27 @@ void WriteErrorRoutines(CompData *data, JitWriter *jit)
Write_GetError(jit);
}
-sp_context_t *JITX86::CompileToContext(ICompilation *co, int *err)
+bool JITX86::Compile(ICompilation *co, BaseRuntime *prt, int *err)
{
CompData *data = (CompData *)co;
sp_plugin_t *plugin = data->plugin;
+ if (data->plugin == NULL)
+ {
+ if (data->debug && !(prt->m_pPlugin->flags & SP_FLAG_DEBUG))
+ {
+ if (err != NULL)
+ {
+ *err = SP_ERROR_NOTDEBUGGING;
+ }
+ co->Abort();
+ return false;
+ }
+
+ data->SetRuntime(prt);
+ plugin = data->plugin;
+ }
+
/* The first phase is to browse */
uint8_t *code = plugin->pcode;
uint8_t *end_cip = plugin->pcode + plugin->pcode_size;
@@ -2584,8 +2619,8 @@ jit_rewind:
if (data->error_set != SP_ERROR_NONE)
{
*err = data->error_set;
- AbortCompilation(co);
- return NULL;
+ co->Abort();
+ return false;
}
}
/* Write these last because error jumps should be unpredicted, and thus forward */
@@ -2627,23 +2662,29 @@ jit_rewind:
* FOURTH PASS - Context Setup
*************/
- sp_context_t *ctx = new sp_context_t;
- memset(ctx, 0, sizeof(sp_context_t));
-
/* setup basics */
- ctx->codebase = writer.outbase;
- ctx->plugin = plugin;
- ctx->vmbase = this;
- ctx->flags = (data->debug ? SPFLAG_PLUGIN_DEBUG : 0);
+ sp_context_t *ctx = data->runtime->GetBaseContext()->GetCtx();
+
+ /* Clear out any old cruft */
+ if (plugin->codebase != NULL)
+ {
+ FreePluginVars(data->runtime->m_pPlugin);
+ FreeContextVars(ctx);
+ }
+
+ plugin->codebase = writer.outbase;
+ plugin->jit_codesize = codemem;
+ plugin->jit_memsize = 0;
/* setup memory */
- ctx->memory = new uint8_t[plugin->memory];
- memcpy(ctx->memory, plugin->data, plugin->data_size);
- ctx->mem_size = plugin->memory;
- ctx->heap_base = plugin->data_size;
- ctx->hp = ctx->heap_base;
- ctx->sp = ctx->mem_size - sizeof(cell_t);
- ctx->prof_flags = data->profile;
+
+ ctx->hp = plugin->data_size;
+ ctx->sp = plugin->mem_size - sizeof(cell_t);
+ ctx->frm = ctx->sp;
+ ctx->n_err = SP_ERROR_NONE;
+ ctx->n_idx = SP_ERROR_NONE;
+ plugin->prof_flags = data->profile;
+ plugin->flags = data->debug ? SPFLAG_PLUGIN_DEBUG : 0;
const char *strbase = plugin->info.stringbase;
uint32_t max, iter;
@@ -2651,39 +2692,42 @@ jit_rewind:
/* relocate public info */
if ((max = plugin->info.publics_num))
{
- ctx->publics = new sp_public_t[max];
+ plugin->publics = new sp_public_t[max];
+ plugin->jit_memsize += sizeof(sp_public_t) * max;
for (iter=0; iterpublics[iter].name = strbase + plugin->info.publics[iter].name;
- ctx->publics[iter].code_offs = RelocLookup(jit, plugin->info.publics[iter].address, false);
+ plugin->publics[iter].name = strbase + plugin->info.publics[iter].name;
+ plugin->publics[iter].code_offs = RelocLookup(jit, plugin->info.publics[iter].address, false);
/* Encode the ID as a straight code offset */
- ctx->publics[iter].funcid = (ctx->publics[iter].code_offs << 1);
+ plugin->publics[iter].funcid = (plugin->publics[iter].code_offs << 1);
}
}
/* relocate pubvar info */
if ((max = plugin->info.pubvars_num))
{
- uint8_t *dat = ctx->memory;
- ctx->pubvars = new sp_pubvar_t[max];
+ uint8_t *dat = plugin->memory;
+ plugin->pubvars = new sp_pubvar_t[max];
+ plugin->jit_memsize += sizeof(sp_pubvar_t) * max;
for (iter=0; iterpubvars[iter].name = strbase + plugin->info.pubvars[iter].name;
- ctx->pubvars[iter].offs = (cell_t *)(dat + plugin->info.pubvars[iter].address);
+ plugin->pubvars[iter].name = strbase + plugin->info.pubvars[iter].name;
+ plugin->pubvars[iter].offs = (cell_t *)(dat + plugin->info.pubvars[iter].address);
}
}
/* relocate native info */
if ((max = plugin->info.natives_num))
{
- ctx->natives = new sp_native_t[max];
+ plugin->natives = new sp_native_t[max];
+ plugin->jit_memsize += sizeof(sp_native_t) * max;
for (iter=0; iternatives[iter].name = strbase + plugin->info.natives[iter].name;
- ctx->natives[iter].pfn = &InvalidNative;
- ctx->natives[iter].status = SP_NATIVE_UNBOUND;
- ctx->natives[iter].flags = 0;
- ctx->natives[iter].user = NULL;
+ plugin->natives[iter].name = strbase + plugin->info.natives[iter].name;
+ plugin->natives[iter].pfn = &InvalidNative;
+ plugin->natives[iter].status = SP_NATIVE_UNBOUND;
+ plugin->natives[iter].flags = 0;
+ plugin->natives[iter].user = NULL;
}
}
@@ -2696,20 +2740,22 @@ jit_rewind:
/* relocate files */
max = plugin->debug.files_num;
- ctx->files = new sp_debug_file_t[max];
+ plugin->files = new sp_debug_file_t[max];
+ plugin->jit_memsize += sizeof(sp_debug_file_t) * max;
for (iter=0; iterfiles[iter].addr = RelocLookup(jit, plugin->debug.files[iter].addr, false);
- ctx->files[iter].name = strbase + plugin->debug.files[iter].name;
+ plugin->files[iter].addr = RelocLookup(jit, plugin->debug.files[iter].addr, false);
+ plugin->files[iter].name = strbase + plugin->debug.files[iter].name;
}
/* relocate lines */
max = plugin->debug.lines_num;
- ctx->lines = new sp_debug_line_t[max];
+ plugin->lines = new sp_debug_line_t[max];
+ plugin->jit_memsize += sizeof(sp_debug_line_t) * max;
for (iter=0; iterlines[iter].addr = RelocLookup(jit, plugin->debug.lines[iter].addr, false);
- ctx->lines[iter].line = plugin->debug.lines[iter].line;
+ plugin->lines[iter].addr = RelocLookup(jit, plugin->debug.lines[iter].addr, false);
+ plugin->lines[iter].line = plugin->debug.lines[iter].line;
}
/* relocate arrays */
@@ -2718,7 +2764,8 @@ jit_rewind:
uint8_t *cursor = (uint8_t *)(plugin->debug.symbols);
max = plugin->debug.syms_num;
- ctx->symbols = new sp_debug_symbol_t[max];
+ plugin->symbols = new sp_debug_symbol_t[max];
+ plugin->jit_memsize += sizeof(sp_debug_symbol_t) * max;
for (iter=0; itercodestart > data->codesize)
{
- ctx->symbols[iter].codestart = 0;
+ plugin->symbols[iter].codestart = 0;
} else {
- ctx->symbols[iter].codestart = RelocLookup(jit, sym->codestart, false);
+ plugin->symbols[iter].codestart = RelocLookup(jit, sym->codestart, false);
}
if (sym->codeend > data->codesize)
{
- ctx->symbols[iter].codeend = data->codesize;
+ plugin->symbols[iter].codeend = data->codesize;
} else {
- ctx->symbols[iter].codeend = RelocLookup(jit, sym->codeend, false);
+ plugin->symbols[iter].codeend = RelocLookup(jit, sym->codeend, false);
}
- ctx->symbols[iter].name = strbase + sym->name;
- ctx->symbols[iter].sym = sym;
+ plugin->symbols[iter].name = strbase + sym->name;
+ plugin->symbols[iter].sym = sym;
if (sym->dimcount > 0)
{
cursor += sizeof(sp_fdbg_symbol_t);
arr = (sp_fdbg_arraydim_t *)cursor;
- ctx->symbols[iter].dims = arr;
+ plugin->symbols[iter].dims = arr;
cursor += sizeof(sp_fdbg_arraydim_t) * sym->dimcount;
continue;
}
- ctx->symbols[iter].dims = NULL;
+ plugin->symbols[iter].dims = NULL;
cursor += sizeof(sp_fdbg_symbol_t);
}
}
tracker_t *trk = new tracker_t;
ctx->vm[JITVARS_TRACKER] = trk;
+ ctx->vm[JITVARS_BASECTX] = data->runtime->GetDefaultContext();
+ ctx->vm[JITVARS_PROFILER] = g_engine2.GetProfiler();
+ ctx->vm[JITVARS_PLUGIN] = data->runtime->m_pPlugin;
trk->pBase = (ucell_t *)malloc(1024);
trk->pCur = trk->pBase;
trk->size = 1024 / sizeof(cell_t);
- functracker_t *fnc = new functracker_t;
- ctx->vm[JITVARS_FUNCINFO] = fnc;
- ctx->vm[JITVARS_REBASE] = data->rebase;
- fnc->code_size = codemem;
- fnc->num_functions = data->func_idx;
+ plugin->jit_memsize += trk->size;
/* clean up relocation+compilation memory */
- data->rebase = NULL;
- AbortCompilation(co);
+ co->Abort();
*err = SP_ERROR_NONE;
- return ctx;
+ return true;
}
SPVM_NATIVE_FUNC JITX86::CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData)
@@ -2851,126 +2896,149 @@ void JITX86::DestroyFakeNative(SPVM_NATIVE_FUNC func)
engine->FreePageMemory((void *)func);
}
-const char *JITX86::GetVMName()
-{
- return "JIT (x86)";
-}
-
-int JITX86::ContextExecute(sp_context_t *ctx, uint32_t code_idx, cell_t *result)
+int JITX86::ContextExecute(sp_plugin_t *pl, sp_context_t *ctx, uint32_t code_idx, cell_t *result)
{
typedef int (*CONTEXT_EXECUTE)(sp_context_t *, uint32_t, cell_t *);
- CONTEXT_EXECUTE fn = (CONTEXT_EXECUTE)ctx->codebase;
+ CONTEXT_EXECUTE fn = (CONTEXT_EXECUTE)pl->codebase;
return fn(ctx, code_idx, result);
}
-void JITX86::FreeContext(sp_context_t *ctx)
-{
- engine->FreePageMemory(ctx->codebase);
- delete [] ctx->memory;
- delete [] ctx->files;
- delete [] ctx->lines;
- delete [] ctx->natives;
- delete [] ctx->publics;
- delete [] ctx->pubvars;
- delete [] ctx->symbols;
- engine->BaseFree(ctx->vm[JITVARS_REBASE]);
- free(((tracker_t *)(ctx->vm[JITVARS_TRACKER]))->pBase);
- delete (tracker_t *)ctx->vm[JITVARS_TRACKER];
- delete (functracker_t *)ctx->vm[JITVARS_FUNCINFO];
- delete ctx;
-}
-
-ICompilation *JITX86::StartCompilation(sp_plugin_t *plugin)
+ICompilation *JITX86::StartCompilation()
{
CompData *data = new CompData;
+
+ data->jit_float_table = NULL;
+
+ return data;
+}
+
+void CompData::SetRuntime(BaseRuntime *runtime)
+{
+ plugin = runtime->m_pPlugin;
+
uint32_t max_natives = plugin->info.natives_num;
const char *strbase = plugin->info.stringbase;
- data->plugin = plugin;
- data->inline_level = JIT_INLINE_ERRORCHECKS|JIT_INLINE_NATIVES;
- data->error_set = SP_ERROR_NONE;
+ this->runtime = runtime;
- data->jit_float_table = new floattbl_t[max_natives];
+ inline_level = JIT_INLINE_ERRORCHECKS|JIT_INLINE_NATIVES;
+ error_set = SP_ERROR_NONE;
+
+ jit_float_table = new floattbl_t[max_natives];
for (uint32_t i=0; iinfo.natives[i].name;
if (!strcmp(name, "FloatAbs"))
{
- data->jit_float_table[i].found = true;
- data->jit_float_table[i].index = OP_FABS;
+ jit_float_table[i].found = true;
+ jit_float_table[i].index = OP_FABS;
} else if (!strcmp(name, "FloatAdd")) {
- data->jit_float_table[i].found = true;
- data->jit_float_table[i].index = OP_FLOATADD;
+ jit_float_table[i].found = true;
+ jit_float_table[i].index = OP_FLOATADD;
} else if (!strcmp(name, "FloatSub")) {
- data->jit_float_table[i].found = true;
- data->jit_float_table[i].index = OP_FLOATSUB;
+ jit_float_table[i].found = true;
+ jit_float_table[i].index = OP_FLOATSUB;
} else if (!strcmp(name, "FloatMul")) {
- data->jit_float_table[i].found = true;
- data->jit_float_table[i].index = OP_FLOATMUL;
+ jit_float_table[i].found = true;
+ jit_float_table[i].index = OP_FLOATMUL;
} else if (!strcmp(name, "FloatDiv")) {
- data->jit_float_table[i].found = true;
- data->jit_float_table[i].index = OP_FLOATDIV;
+ jit_float_table[i].found = true;
+ jit_float_table[i].index = OP_FLOATDIV;
} else if (!strcmp(name, "float")) {
- data->jit_float_table[i].found = true;
- data->jit_float_table[i].index = OP_FLOAT;
+ jit_float_table[i].found = true;
+ jit_float_table[i].index = OP_FLOAT;
} else if (!strcmp(name, "FloatCompare")) {
- data->jit_float_table[i].found = true;
- data->jit_float_table[i].index = OP_FLOATCMP;
+ jit_float_table[i].found = true;
+ jit_float_table[i].index = OP_FLOATCMP;
} else if (!strcmp(name, "RoundToZero")) {
- data->jit_float_table[i].found = true;
- data->jit_float_table[i].index = OP_RND_TO_ZERO;
+ jit_float_table[i].found = true;
+ jit_float_table[i].index = OP_RND_TO_ZERO;
} else if (!strcmp(name, "RoundToCeil")) {
- data->jit_float_table[i].found = true;
- data->jit_float_table[i].index = OP_RND_TO_CEIL;
+ jit_float_table[i].found = true;
+ jit_float_table[i].index = OP_RND_TO_CEIL;
} else if (!strcmp(name, "RoundToFloor")) {
- data->jit_float_table[i].found = true;
- data->jit_float_table[i].index = OP_RND_TO_FLOOR;
+ jit_float_table[i].found = true;
+ jit_float_table[i].index = OP_RND_TO_FLOOR;
} else if (!strcmp(name, "RoundToNearest")) {
- data->jit_float_table[i].found = true;
- data->jit_float_table[i].index = OP_RND_TO_NEAREST;
+ jit_float_table[i].found = true;
+ jit_float_table[i].index = OP_RND_TO_NEAREST;
}
}
+}
+
+ICompilation *JITX86::StartCompilation(BaseRuntime *runtime)
+{
+ CompData *data = new CompData;
+
+ data->SetRuntime(runtime);
return data;
}
-void JITX86::AbortCompilation(ICompilation *co)
+void CompData::Abort()
{
- if (((CompData *)co)->rebase)
+ if (rebase)
{
- engine->BaseFree(((CompData *)co)->rebase);
+ engine->BaseFree(rebase);
}
- delete [] ((CompData *)co)->jit_float_table;
- delete (CompData *)co;
+ delete [] jit_float_table;
+ delete this;
}
-bool JITX86::SetCompilationOption(ICompilation *co, const char *key, const char *val)
+void JITX86::FreeContextVars(sp_context_t *ctx)
{
- CompData *data = (CompData *)co;
+ free(((tracker_t *)(ctx->vm[JITVARS_TRACKER]))->pBase);
+ delete (tracker_t *)ctx->vm[JITVARS_TRACKER];
+}
+void JITX86::FreePluginVars(sp_plugin_t *pl)
+{
+ delete [] pl->files;
+ delete [] pl->lines;
+ delete [] pl->natives;
+ delete [] pl->publics;
+ delete [] pl->pubvars;
+ delete [] pl->symbols;
+
+ if (pl->codebase != NULL)
+ {
+ g_engine1.FreePageMemory(pl->codebase);
+ pl->codebase = NULL;
+ }
+
+ pl->files = NULL;
+ pl->lines = NULL;
+ pl->natives = NULL;
+ pl->publics = NULL;
+ pl->pubvars = NULL;
+ pl->symbols = NULL;
+}
+
+bool CompData::SetOption(const char *key, const char *val)
+{
if (strcmp(key, SP_JITCONF_DEBUG) == 0)
{
if ((atoi(val) == 1) || !strcmp(val, "yes"))
{
- data->debug = true;
+ debug = true;
} else {
- data->debug = false;
+ debug = false;
}
- if (data->debug && !(data->plugin->flags & SP_FLAG_DEBUG))
+ if (debug && plugin && !(plugin->flags & SP_FLAG_DEBUG))
{
- data->debug = false;
+ debug = false;
return false;
}
return true;
}
else if (strcmp(key, SP_JITCONF_PROFILE) == 0)
{
- data->profile = atoi(val);
+ profile = atoi(val);
/** Callbacks must be profiled to profile functions! */
- if ((data->profile & SP_PROF_FUNCTIONS) == SP_PROF_FUNCTIONS)
+ if ((profile & SP_PROF_FUNCTIONS) == SP_PROF_FUNCTIONS)
{
- data->profile |= SP_PROF_CALLBACKS;
+ profile |= SP_PROF_CALLBACKS;
}
return true;
@@ -2979,83 +3047,3 @@ bool JITX86::SetCompilationOption(ICompilation *co, const char *key, const char
return false;
}
-unsigned int JITX86::GetAPIVersion()
-{
- return SOURCEPAWN_VM_API_VERSION;
-}
-
-bool JITX86::FunctionPLookup(const sp_context_t *ctx, uint32_t code_addr, unsigned int *result)
-{
- uint8_t *rebase = (uint8_t *)ctx->vm[JITVARS_REBASE];
-
- /* Is this within the pcode bounds? */
- if (code_addr >= ctx->plugin->pcode_size - sizeof(uint32_t))
- {
- return false;
- }
-
- /* Relocate this */
- code_addr = *(jitoffs_t *)(rebase + code_addr);
-
- /* Check if this is in the relocation bounds */
- functracker_t *fnc = (functracker_t *)ctx->vm[JITVARS_FUNCINFO];
- if (code_addr >= fnc->code_size)
- {
- return false;
- }
-
- /* Get the function info and sanity check */
- funcinfo_t *f = (funcinfo_t *)((char *)ctx->codebase + code_addr - sizeof(funcinfo_t));
- if (f->magic != JIT_FUNCMAGIC || f->index >= fnc->num_functions)
- {
- return false;
- }
-
- if (result)
- {
- *result = f->index;
- }
-
- return true;
-}
-
-bool JITX86::FunctionLookup(const sp_context_t *ctx, uint32_t code_addr, unsigned int *result)
-{
- /* Check if this is in the relocation bounds */
- functracker_t *fnc = (functracker_t *)ctx->vm[JITVARS_FUNCINFO];
- if (code_addr >= fnc->code_size)
- {
- return false;
- }
-
- /* Get the function info and sanity check */
- funcinfo_t *f = (funcinfo_t *)((char *)ctx->codebase + code_addr - sizeof(funcinfo_t));
- if (f->magic != JIT_FUNCMAGIC || f->index >= fnc->num_functions)
- {
- return false;
- }
-
- if (result)
- {
- *result = f->index;
- }
-
- return true;
-}
-
-unsigned int JITX86::FunctionCount(const sp_context_t *ctx)
-{
- functracker_t *fnc = (functracker_t *)ctx->vm[JITVARS_FUNCINFO];
-
- return fnc->num_functions;
-}
-
-const char *JITX86::GetVersionString()
-{
- return SVN_FULL_VERSION;
-}
-
-const char *JITX86::GetCPUOptimizations()
-{
- return "Generic i686";
-}
diff --git a/sourcepawn/jit/x86/jit_x86.h b/sourcepawn/jit/x86/jit_x86.h
index 9e093831..7b8bdf31 100644
--- a/sourcepawn/jit/x86/jit_x86.h
+++ b/sourcepawn/jit/x86/jit_x86.h
@@ -35,6 +35,8 @@
#include
#include
#include
+#include "../jit_shared.h"
+#include "../BaseRuntime.h"
using namespace SourcePawn;
@@ -44,11 +46,14 @@ using namespace SourcePawn;
#define JIT_FUNCMAGIC 0x214D4148 //magic function offset
#define JITVARS_TRACKER 0 //important: don't change this to avoid trouble
-#define JITVARS_FUNCINFO 1 //important: don't change this aWOAWOGJQG I LIKE HAM
-#define JITVARS_REBASE 2 //important: hi, i'm bail
+#define JITVARS_BASECTX 1 //important: don't change this aWOAWOGJQG I LIKE HAM
+#define JITVARS_PROFILER 2 //profiler
+#define JITVARS_PLUGIN 3 //sp_plugin_t
#define sDIMEN_MAX 5 //this must mirror what the compiler has.
+#define GET_CONTEXT(c) ((IPluginContext *)c->vm[JITVARS_BASECTX])
+
typedef struct tracker_s
{
size_t size;
@@ -87,7 +92,11 @@ public:
error_set(SP_ERROR_NONE), func_idx(0)
{
};
+ bool SetOption(const char *key, const char *val);
+ void SetRuntime(BaseRuntime *runtime);
+ void Abort();
public:
+ BaseRuntime *runtime; /* runtime handle */
sp_plugin_t *plugin; /* plugin handle */
bool debug; /* whether to compile debug mode */
int profile; /* profiling flags */
@@ -116,22 +125,15 @@ public:
uint32_t codesize; /* total codesize */
};
-class JITX86 : public IVirtualMachine
+class JITX86
{
public:
- const char *GetVMName();
- ICompilation *StartCompilation(sp_plugin_t *plugin);
- bool SetCompilationOption(ICompilation *co, const char *key, const char *val);
- sp_context_t *CompileToContext(ICompilation *co, int *err);
- void AbortCompilation(ICompilation *co);
- void FreeContext(sp_context_t *ctx);
- int ContextExecute(sp_context_t *ctx, uint32_t code_idx, cell_t *result);
- unsigned int GetAPIVersion();
- bool FunctionLookup(const sp_context_t *ctx, uint32_t code_addr, unsigned int *result);
- bool FunctionPLookup(const sp_context_t *ctx, uint32_t code_addr, unsigned int *result);
- unsigned int FunctionCount(const sp_context_t *ctx);
- const char *GetVersionString();
- const char *GetCPUOptimizations();
+ ICompilation *StartCompilation(BaseRuntime *runtime);
+ ICompilation *StartCompilation();
+ bool Compile(ICompilation *co, BaseRuntime *runtime, int *err);
+ void FreePluginVars(sp_plugin_t *pl);
+ void FreeContextVars(sp_context_t *ctx);
+ int ContextExecute(sp_plugin_t *pl, sp_context_t *ctx, uint32_t code_idx, cell_t *result);
SPVM_NATIVE_FUNC CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData);
void DestroyFakeNative(SPVM_NATIVE_FUNC func);
};
@@ -157,6 +159,6 @@ jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative=false);
#define AMX_INFO_CONTEXT 12 //physical
#define AMX_INFO_STACKTOP 16 //relocated
-extern ISourcePawnEngine *engine;
+extern JITX86 g_Jit1;
#endif //_INCLUDE_SOURCEPAWN_JIT_X86_H_
diff --git a/sourcepawn/jit/x86/opcode_helpers.cpp b/sourcepawn/jit/x86/opcode_helpers.cpp
index 8ec41cb6..2b12036c 100644
--- a/sourcepawn/jit/x86/opcode_helpers.cpp
+++ b/sourcepawn/jit/x86/opcode_helpers.cpp
@@ -40,6 +40,7 @@
jitoffs_t Write_Execute_Function(JitWriter *jit)
{
+ CompData *co = (CompData *)jit->data;
/**
* The variables we're passed in:
* sp_context_t *ctx, uint32_t code_idx, cell_t *result
@@ -76,14 +77,14 @@ jitoffs_t Write_Execute_Function(JitWriter *jit)
//mov [esi+12], eax - store context into info pointer
//mov ecx, [eax+] - get heap pointer
//mov [esi+4], ecx - store heap into info pointer
- //mov ebp, [eax+] - get data pointer
+ //mov ebp, - get data pointer
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, REG_EBP, 16);
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_EAX, AMX_INFO_RETVAL);
IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, REG_EBP, 8);
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_EAX, AMX_INFO_CONTEXT);
IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, REG_EAX, offsetof(sp_context_t, hp));
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_ECX, AMX_INFO_HEAP);
- IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_DAT, REG_EAX, offsetof(sp_context_t, memory));
+ IA32_Mov_Reg_Imm32(jit, AMX_REG_DAT, jit_int32_t(co->plugin->memory));
/* Frame setup */
//mov edi, [eax+] - get stack pointer
@@ -97,15 +98,23 @@ jitoffs_t Write_Execute_Function(JitWriter *jit)
//mov ecx, [eax+] - copy memsize to temp var
//add ecx, ebp - relocate
//mov [esi+x], ecx - store relocated
- IA32_Mov_Reg_Rm_Disp8(jit, REG_ECX, REG_EAX, offsetof(sp_context_t, mem_size));
+ IA32_Mov_Reg_Imm32(jit, REG_ECX, co->plugin->mem_size);
IA32_Add_Reg_Rm(jit, AMX_REG_TMP, AMX_REG_DAT, MOD_REG);
IA32_Mov_Rm_Reg_Disp8(jit, AMX_REG_INFO, REG_ECX, AMX_INFO_STACKTOP);
/* Remaining needed vars */
//mov ecx, [esp+(4*(NUM_INFO_PARAMS+3))+12] - get code index (normally esp+12, but we have another array on the stack)
- //add ecx, [eax+] - add code base to index
+ //push eax
+ //mov eax,
+ //mov eax, [eax]
+ //add ecx, eax
+ //pop eax
IA32_Mov_Reg_Esp_Disp8(jit, REG_ECX, 12+(4*(NUM_INFO_PARAMS+3)));
- IA32_Add_Reg_Rm_Disp8(jit, REG_ECX, REG_EAX, offsetof(sp_context_t, codebase));
+ IA32_Push_Reg(jit, REG_EAX);
+ IA32_Mov_Reg_Imm32(jit, REG_EAX, jit_int32_t(&co->plugin->codebase));
+ IA32_Mov_Reg_Rm(jit, REG_EAX, REG_EAX, MOD_MEM_REG);
+ IA32_Add_Reg_Rm(jit, REG_ECX, REG_EAX, MOD_REG);
+ IA32_Pop_Reg(jit, REG_EAX);
/* by now, everything is set up, so we can call into the plugin */
//call ecx
@@ -161,36 +170,30 @@ void Write_BreakDebug(JitWriter *jit)
//push edi
//mov edi, ecx
//mov ecx, [esi+ctx]
- //cmp [ecx+dbreak], 0
- //jnz :nocall
IA32_Push_Reg(jit, REG_EDI);
IA32_Mov_Reg_Rm(jit, REG_EDI, REG_ECX, MOD_REG);
IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_INFO, AMX_INFO_CONTEXT);
- IA32_Cmp_Rm_Disp8_Imm8(jit, AMX_REG_TMP, offsetof(sp_context_t, dbreak), 0);
- jitoffs_t jmp = IA32_Jump_Cond_Imm8(jit, CC_Z, 0);
//:TODO: align the stack to 16bytes like in sysreq.x
/* NOTE, Hack! PUSHAD pushes EDI last which still has the CIP */
//pushad
//push [esi+frm]
- //push ctx
- //mov ecx, [ecx+dbreak]
+ //push [ctx+basectx]
+ //mov ecx,
//call ecx
//add esp, 8
//popad
IA32_Pushad(jit);
IA32_Push_Rm_Disp8(jit, AMX_REG_INFO, AMX_INFO_FRAME); //:TODO: move to regs and push? and dont disp for 0
- IA32_Push_Reg(jit, AMX_REG_TMP);
- IA32_Mov_Reg_Rm_Disp8(jit, AMX_REG_TMP, AMX_REG_TMP, offsetof(sp_context_t, dbreak));
+ IA32_Push_Rm_Disp8(jit, AMX_REG_TMP, offsetof(sp_context_t, vm[JITVARS_BASECTX]));
+ IA32_Mov_Reg_Imm32(jit, AMX_REG_TMP, jit_int32_t(((CompData *)jit->data)->plugin->dbreak));
IA32_Call_Reg(jit, AMX_REG_TMP);
IA32_Add_Rm_Imm8(jit, REG_ESP, 4*2, MOD_REG);
IA32_Popad(jit);
- //:nocall
//pop edi
//ret
IA32_Pop_Reg(jit, REG_EDI);
- IA32_Send_Jump8_Here(jit, jmp);
IA32_Return(jit);
}
@@ -314,7 +317,7 @@ void Write_Check_VerifyAddr(JitWriter *jit, jit_uint8_t reg)
/* Part 1: Check if we're in the memory bounds */
//cmp ,
//jae :error
- IA32_Cmp_Rm_Imm32(jit, MOD_REG, reg, ((CompData *)jit->data)->plugin->memory);
+ IA32_Cmp_Rm_Imm32(jit, MOD_REG, reg, ((CompData *)jit->data)->plugin->mem_size);
IA32_Jump_Cond_Imm32_Abs(jit, CC_AE, ((CompData *)jit->data)->jit_error_memaccess);
/* Part 2: Check if we're in the invalid region between HP and SP */
diff --git a/core/zlib/adler32.c b/sourcepawn/jit/zlib/adler32.c
similarity index 100%
rename from core/zlib/adler32.c
rename to sourcepawn/jit/zlib/adler32.c
diff --git a/core/zlib/compress.c b/sourcepawn/jit/zlib/compress.c
similarity index 100%
rename from core/zlib/compress.c
rename to sourcepawn/jit/zlib/compress.c
diff --git a/core/zlib/crc32.c b/sourcepawn/jit/zlib/crc32.c
similarity index 100%
rename from core/zlib/crc32.c
rename to sourcepawn/jit/zlib/crc32.c
diff --git a/core/zlib/crc32.h b/sourcepawn/jit/zlib/crc32.h
similarity index 100%
rename from core/zlib/crc32.h
rename to sourcepawn/jit/zlib/crc32.h
diff --git a/core/zlib/deflate.c b/sourcepawn/jit/zlib/deflate.c
similarity index 100%
rename from core/zlib/deflate.c
rename to sourcepawn/jit/zlib/deflate.c
diff --git a/core/zlib/deflate.h b/sourcepawn/jit/zlib/deflate.h
similarity index 100%
rename from core/zlib/deflate.h
rename to sourcepawn/jit/zlib/deflate.h
diff --git a/core/zlib/gzio.c b/sourcepawn/jit/zlib/gzio.c
similarity index 100%
rename from core/zlib/gzio.c
rename to sourcepawn/jit/zlib/gzio.c
diff --git a/core/zlib/infback.c b/sourcepawn/jit/zlib/infback.c
similarity index 100%
rename from core/zlib/infback.c
rename to sourcepawn/jit/zlib/infback.c
diff --git a/core/zlib/inffast.c b/sourcepawn/jit/zlib/inffast.c
similarity index 100%
rename from core/zlib/inffast.c
rename to sourcepawn/jit/zlib/inffast.c
diff --git a/core/zlib/inffast.h b/sourcepawn/jit/zlib/inffast.h
similarity index 100%
rename from core/zlib/inffast.h
rename to sourcepawn/jit/zlib/inffast.h
diff --git a/core/zlib/inffixed.h b/sourcepawn/jit/zlib/inffixed.h
similarity index 100%
rename from core/zlib/inffixed.h
rename to sourcepawn/jit/zlib/inffixed.h
diff --git a/core/zlib/inflate.c b/sourcepawn/jit/zlib/inflate.c
similarity index 100%
rename from core/zlib/inflate.c
rename to sourcepawn/jit/zlib/inflate.c
diff --git a/core/zlib/inflate.h b/sourcepawn/jit/zlib/inflate.h
similarity index 100%
rename from core/zlib/inflate.h
rename to sourcepawn/jit/zlib/inflate.h
diff --git a/core/zlib/inftrees.c b/sourcepawn/jit/zlib/inftrees.c
similarity index 100%
rename from core/zlib/inftrees.c
rename to sourcepawn/jit/zlib/inftrees.c
diff --git a/core/zlib/inftrees.h b/sourcepawn/jit/zlib/inftrees.h
similarity index 100%
rename from core/zlib/inftrees.h
rename to sourcepawn/jit/zlib/inftrees.h
diff --git a/core/zlib/trees.c b/sourcepawn/jit/zlib/trees.c
similarity index 100%
rename from core/zlib/trees.c
rename to sourcepawn/jit/zlib/trees.c
diff --git a/core/zlib/trees.h b/sourcepawn/jit/zlib/trees.h
similarity index 100%
rename from core/zlib/trees.h
rename to sourcepawn/jit/zlib/trees.h
diff --git a/core/zlib/uncompr.c b/sourcepawn/jit/zlib/uncompr.c
similarity index 100%
rename from core/zlib/uncompr.c
rename to sourcepawn/jit/zlib/uncompr.c
diff --git a/core/zlib/zconf.h b/sourcepawn/jit/zlib/zconf.h
similarity index 100%
rename from core/zlib/zconf.h
rename to sourcepawn/jit/zlib/zconf.h
diff --git a/core/zlib/zlib.h b/sourcepawn/jit/zlib/zlib.h
similarity index 100%
rename from core/zlib/zlib.h
rename to sourcepawn/jit/zlib/zlib.h
diff --git a/core/zlib/zutil.c b/sourcepawn/jit/zlib/zutil.c
similarity index 100%
rename from core/zlib/zutil.c
rename to sourcepawn/jit/zlib/zutil.c
diff --git a/core/zlib/zutil.h b/sourcepawn/jit/zlib/zutil.h
similarity index 100%
rename from core/zlib/zutil.h
rename to sourcepawn/jit/zlib/zutil.h