diff --git a/sourcepawn/compiler/sc1.c b/sourcepawn/compiler/sc1.c
index 7d621142..0f678fa1 100644
--- a/sourcepawn/compiler/sc1.c
+++ b/sourcepawn/compiler/sc1.c
@@ -505,6 +505,8 @@ cleanup:
   delete_pathtable();
   delete_sourcefiletable();
   delete_dbgstringtable();
+  funcenums_free();
+  pstructs_free();
   #if !defined NO_DEFINE
     delete_substtable();
   #endif
diff --git a/sourcepawn/include/sp_vm_api.h b/sourcepawn/include/sp_vm_api.h
index 1859324d..61cbecfc 100644
--- a/sourcepawn/include/sp_vm_api.h
+++ b/sourcepawn/include/sp_vm_api.h
@@ -4,6 +4,8 @@
 #include <stdio.h>
 #include "sp_vm_types.h"
 
+#define SOURCEPAWN_VM_API_VERSION		1
+
 namespace SourcePawn
 {
 	class IVirtualMachine;
@@ -393,12 +395,17 @@ namespace SourcePawn
 	{
 	public:
 		/**
-		 * Returns the string name of a VM implementation.
+		 * @brief Returns the current API version.
+		 */
+		virtual unsigned int GetAPIVersion() =0;
+
+		/**
+		 * @brief Returns the string name of a VM implementation.
 		 */
 		virtual const char *GetVMName() =0;
 
 		/**
-		 * Begins a new compilation
+		 * @brief Begins a new compilation
 		 * 
 		 * @param plugin	Pointer to a plugin structure.
 		 * @return			New compilation pointer.
@@ -406,7 +413,7 @@ namespace SourcePawn
 		virtual ICompilation *StartCompilation(sp_plugin_t *plugin) =0;
 
 		/**
-		 * Sets a compilation option.
+		 * @brief Sets a compilation option.
 		 *
 		 * @param co		Pointer to a compilation.
 		 * @param key		Option key name.
@@ -416,7 +423,7 @@ namespace SourcePawn
 		virtual bool SetCompilationOption(ICompilation *co, const char *key, const char *val) =0;
 
 		/**
-		 * Finalizes a compilation into a new sp_context_t.
+		 * @brief Finalizes a compilation into a new sp_context_t.
 		 * Note: This will free the ICompilation pointer.
 		 *
 		 * @param co		Compilation pointer.
@@ -426,28 +433,46 @@ namespace SourcePawn
 		virtual sp_context_t *CompileToContext(ICompilation *co, int *err) =0;
 
 		/**
-		 * Aborts a compilation and frees the ICompilation pointer.
+		 * @brief Aborts a compilation and frees the ICompilation pointer.
 		 *
 		 * @param co		Compilation pointer.
 		 */
 		virtual void AbortCompilation(ICompilation *co) =0;
 
 		/**
-		 * Frees any internal variable usage on a context.
+		 * @brief Frees any internal variable usage on a context.
 		 *
 		 * @param ctx		Context structure pointer.
 		 */
 		virtual void FreeContext(sp_context_t *ctx) =0;
 
 		/**
-		 * Calls the "execute" function on a context.
+		 * @brief Calls the "execute" function on a context.
 		 *
 		 * @param ctx		Executes a function in a context.
-		 * @param code_idx	Index into the code section.
-		 * @param result	Pointer to store result in.
+		 * @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_idx, cell_t *result) =0;
+		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;
 	};
 };
 
diff --git a/sourcepawn/include/sp_vm_types.h b/sourcepawn/include/sp_vm_types.h
index 2c7bea84..91117b13 100644
--- a/sourcepawn/include/sp_vm_types.h
+++ b/sourcepawn/include/sp_vm_types.h
@@ -104,7 +104,7 @@ namespace SourcePawn
 
 struct sp_context_s;
 
-typedef cell_t (*SPVM_NATIVE_FUNC)(struct sp_context_s *, cell_t *);
+typedef cell_t (*SPVM_NATIVE_FUNC)(struct sp_context_s *, const cell_t *);
 
 /**********************************************
  *** The following structures are bound to the VM/JIT.
diff --git a/sourcepawn/jit/x86/jit_x86.cpp b/sourcepawn/jit/x86/jit_x86.cpp
index 1dfe2d97..aedd936a 100644
--- a/sourcepawn/jit/x86/jit_x86.cpp
+++ b/sourcepawn/jit/x86/jit_x86.cpp
@@ -233,6 +233,7 @@ inline void WriteOp_Proc(JitWriter *jit)
 	 * Just in case, we guard this memory with INT3 to break into the debugger.
 	 */
 	jitoffs_t cur_offs = jit->get_outputpos();
+	CompData *co = (CompData *)jit->data;
 	if (cur_offs % 4)
 	{
 		cur_offs = 4 - (cur_offs % 4);
@@ -240,11 +241,25 @@ inline void WriteOp_Proc(JitWriter *jit)
 		{
 			jit->write_ubyte(IA32_INT3);
 		}
-		/* add this amt to the offset we relocated */
+	}
+
+	/* Write the info struct about this function */
+	jit->write_uint32(JIT_FUNCMAGIC);
+	jit->write_uint32(co->func_idx);
+
+	/* Now we have to backpatch our reloction offset! */
+	{
 		jitoffs_t offs = jit->get_inputpos() - sizeof(cell_t);
 		jitcode_t rebase = ((CompData *)jit->data)->rebase;
 		*(jitoffs_t *)((unsigned char  *)rebase + offs) = jit->get_outputpos();
 	}
+
+	/* Lastly, if we're writing, keep track of the function count */
+	if (jit->outbase)
+	{
+		co->func_idx++;
+	}
+
 	//push old frame on stack:
 	//mov ecx, [esi+frm]
 	//mov [edi-4], ecx
@@ -1756,7 +1771,7 @@ cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
 	return native->pfn(ctx, params);
 }
 
-cell_t InvalidNative(sp_context_t *ctx, cell_t *params)
+cell_t InvalidNative(sp_context_t *ctx, const cell_t *params)
 {
 	ctx->err = SP_ERROR_INVALID_NATIVE;
 
@@ -1877,6 +1892,7 @@ sp_context_t *JITX86::CompileToContext(ICompilation *co, int *err)
 	JitWriter writer;
 	JitWriter *jit = &writer;
 	cell_t *endptr = (cell_t *)(end_cip);
+	uint32_t codemem = 0;
 
 	/* Initial code is written "blank,"
 	 * so we can check the exact memory usage.
@@ -1957,8 +1973,8 @@ jit_rewind:
 		WriteErrorRoutines(data, jit);
 
 		/* the total codesize is now known! */
-		uint32_t mem = writer.get_outputpos();
-		writer.outbase = (jitcode_t)engine->ExecAlloc(mem);
+		codemem = writer.get_outputpos();
+		writer.outbase = (jitcode_t)engine->ExecAlloc(codemem);
 		writer.outptr = writer.outbase;
 		/* go back for third pass */
 		goto jit_rewind;
@@ -2100,6 +2116,11 @@ jit_rewind:
 	trk->pCur = trk->pBase;
 	trk->size = 1024 / sizeof(cell_t);
 
+	functracker_t *fnc = new functracker_t;
+	ctx->vm[JITVARS_FUNCINFO] = fnc;
+	fnc->code_size = codemem;
+	fnc->num_functions = data->func_idx;
+
 	/* clean up relocation+compilation memory */
 	AbortCompilation(co);
 
@@ -2172,3 +2193,38 @@ bool JITX86::SetCompilationOption(ICompilation *co, const char *key, const char
 
 	return false;
 }
+
+unsigned int JITX86::GetAPIVersion()
+{
+	return SOURCEPAWN_VM_API_VERSION;
+}
+
+bool JITX86::FunctionLookup(const sp_context_t *ctx, uint32_t code_addr, unsigned int *result)
+{
+	functracker_t *fnc = (functracker_t *)ctx->vm[JITVARS_FUNCINFO];
+
+	if (code_addr >= fnc->code_size)
+	{
+		return false;
+	}
+
+	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;
+}
diff --git a/sourcepawn/jit/x86/jit_x86.h b/sourcepawn/jit/x86/jit_x86.h
index f4f40f4c..5f8eae60 100644
--- a/sourcepawn/jit/x86/jit_x86.h
+++ b/sourcepawn/jit/x86/jit_x86.h
@@ -9,9 +9,11 @@ using namespace SourcePawn;
 
 #define JIT_INLINE_ERRORCHECKS		(1<<0)
 #define JIT_INLINE_NATIVES			(1<<1)
-#define STACK_MARGIN				64		//8 parameters of safety, I guess
+#define STACK_MARGIN				64			//8 parameters of safety, I guess
+#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
 
 typedef struct tracker_s
 {
@@ -20,12 +22,24 @@ typedef struct tracker_s
 	ucell_t *pCur;
 } tracker_t;
 
+typedef struct funcinfo_s
+{
+	unsigned int magic;
+	unsigned int index;
+} funcinfo_t;
+
+typedef struct functracker_s
+{
+	unsigned int num_functions;
+	unsigned int code_size;
+} functracker_t;
+
 class CompData : public ICompilation
 {
 public:
 	CompData() : plugin(NULL), 
 		debug(false), inline_level(0), rebase(NULL),
-		error_set(SP_ERROR_NONE)
+		error_set(SP_ERROR_NONE), func_idx(0)
 	{
 	};
 public:
@@ -49,6 +63,7 @@ public:
 	jitoffs_t jit_extern_error;		/* returning generic error */
 	jitoffs_t jit_sysreq_c;			/* old version! */
 	uint32_t codesize;				/* total codesize */
+	unsigned int func_idx;			/* current function index */
 	int inline_level;				/* inline optimization level */
 	int error_set;					/* error code to halt process */
 	bool debug;						/* whether to compile debug mode */
@@ -64,6 +79,9 @@ public:
 	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);
+	unsigned int FunctionCount(const sp_context_t *ctx);
 };
 
 cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params);