7875fe1acd
1) JIT compilation/optimization now occurs per-function, and only when functions are first used. We're now officially a whole-method JIT rather than an AOT compiler (albiet, still a simple JIT). This has two implications: Functions are now much better abstracted internally, and loading a plugin is now much less expensive. If a function contains calls to other functions, THOSE functions are only compiled when they're invoked as well. 2) I've removed debug mode. We always show full backtraces now, as there was a very cheap way to implement this which really cleaned up everything. This is great for a number of reasons -- there's less code, the JIT is better designed, we don't need to relocate debug tables, and best of all we no longer have to tell users to enable debug mode at their own expense. --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%402459
780 lines
12 KiB
C++
780 lines
12 KiB
C++
/**
|
|
* vim: set ts=4 :
|
|
* =============================================================================
|
|
* SourceMod
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
*
|
|
* 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 <http://www.sourcemod.net/license.php>.
|
|
*
|
|
* Version: $Id$
|
|
*/
|
|
|
|
case OP_MOVE_PRI:
|
|
{
|
|
WriteOp_Move_Pri(jit);
|
|
break;
|
|
}
|
|
case OP_MOVE_ALT:
|
|
{
|
|
WriteOp_Move_Alt(jit);
|
|
break;
|
|
}
|
|
case OP_XCHG:
|
|
{
|
|
WriteOp_Xchg(jit);
|
|
break;
|
|
}
|
|
case OP_PUSH:
|
|
{
|
|
WriteOp_Push(jit);
|
|
break;
|
|
}
|
|
case OP_PUSH_S:
|
|
{
|
|
WriteOp_Push_S(jit);
|
|
break;
|
|
}
|
|
case OP_PUSH2_C:
|
|
{
|
|
WriteOp_Push2_C(jit);
|
|
break;
|
|
}
|
|
case OP_PUSH3_C:
|
|
{
|
|
WriteOp_Push3_C(jit);
|
|
break;
|
|
}
|
|
case OP_PUSH4_C:
|
|
{
|
|
WriteOp_Push4_C(jit);
|
|
break;
|
|
}
|
|
case OP_PUSH5_C:
|
|
{
|
|
WriteOp_Push5_C(jit);
|
|
break;
|
|
}
|
|
case OP_PUSH2_ADR:
|
|
{
|
|
WriteOp_Push2_Adr(jit);
|
|
break;
|
|
}
|
|
case OP_PUSH3_ADR:
|
|
{
|
|
WriteOp_Push3_Adr(jit);
|
|
break;
|
|
}
|
|
case OP_PUSH4_ADR:
|
|
{
|
|
WriteOp_Push4_Adr(jit);
|
|
break;
|
|
}
|
|
case OP_PUSH5_ADR:
|
|
{
|
|
WriteOp_Push5_Adr(jit);
|
|
break;
|
|
}
|
|
case OP_PUSH2_S:
|
|
{
|
|
WriteOp_Push2_S(jit);
|
|
break;
|
|
}
|
|
case OP_PUSH3_S:
|
|
{
|
|
WriteOp_Push3_S(jit);
|
|
break;
|
|
}
|
|
case OP_PUSH4_S:
|
|
{
|
|
WriteOp_Push4_S(jit);
|
|
break;
|
|
}
|
|
case OP_PUSH5_S:
|
|
{
|
|
WriteOp_Push5_S(jit);
|
|
break;
|
|
}
|
|
case OP_PUSH5:
|
|
{
|
|
WriteOp_Push5(jit);
|
|
break;
|
|
}
|
|
case OP_PUSH4:
|
|
{
|
|
WriteOp_Push4(jit);
|
|
break;
|
|
}
|
|
case OP_PUSH3:
|
|
{
|
|
WriteOp_Push3(jit);
|
|
break;
|
|
}
|
|
case OP_PUSH2:
|
|
{
|
|
WriteOp_Push2(jit);
|
|
break;
|
|
}
|
|
case OP_ZERO_PRI:
|
|
{
|
|
WriteOp_Zero_Pri(jit);
|
|
break;
|
|
}
|
|
case OP_ZERO_ALT:
|
|
{
|
|
WriteOp_Zero_Alt(jit);
|
|
break;
|
|
}
|
|
case OP_PROC:
|
|
{
|
|
WriteOp_Proc(jit);
|
|
break;
|
|
}
|
|
case OP_SHL:
|
|
{
|
|
WriteOp_Shl(jit);
|
|
break;
|
|
}
|
|
case OP_SHR:
|
|
{
|
|
WriteOp_Shr(jit);
|
|
break;
|
|
}
|
|
case OP_SSHR:
|
|
{
|
|
WriteOp_Sshr(jit);
|
|
break;
|
|
}
|
|
case OP_SHL_C_PRI:
|
|
{
|
|
WriteOp_Shl_C_Pri(jit);
|
|
break;
|
|
}
|
|
case OP_SHL_C_ALT:
|
|
{
|
|
WriteOp_Shl_C_Alt(jit);
|
|
break;
|
|
}
|
|
case OP_SHR_C_PRI:
|
|
{
|
|
WriteOp_Shr_C_Pri(jit);
|
|
break;
|
|
}
|
|
case OP_SHR_C_ALT:
|
|
{
|
|
WriteOp_Shr_C_Alt(jit);
|
|
break;
|
|
}
|
|
case OP_SMUL:
|
|
{
|
|
WriteOp_SMul(jit);
|
|
break;
|
|
}
|
|
case OP_ADD:
|
|
{
|
|
WriteOp_Add(jit);
|
|
break;
|
|
}
|
|
case OP_SUB:
|
|
{
|
|
WriteOp_Sub(jit);
|
|
break;
|
|
}
|
|
case OP_SUB_ALT:
|
|
{
|
|
WriteOp_Sub_Alt(jit);
|
|
break;
|
|
}
|
|
case OP_NOP:
|
|
{
|
|
/* do nothing */
|
|
break;
|
|
}
|
|
case OP_NOT:
|
|
{
|
|
WriteOp_Not(jit);
|
|
break;
|
|
}
|
|
case OP_NEG:
|
|
{
|
|
WriteOp_Neg(jit);
|
|
break;
|
|
}
|
|
case OP_XOR:
|
|
{
|
|
WriteOp_Xor(jit);
|
|
break;
|
|
}
|
|
case OP_OR:
|
|
{
|
|
WriteOp_Or(jit);
|
|
break;
|
|
}
|
|
case OP_AND:
|
|
{
|
|
WriteOp_And(jit);
|
|
break;
|
|
}
|
|
case OP_INVERT:
|
|
{
|
|
WriteOp_Invert(jit);
|
|
break;
|
|
}
|
|
case OP_ADD_C:
|
|
{
|
|
WriteOp_Add_C(jit);
|
|
break;
|
|
}
|
|
case OP_SMUL_C:
|
|
{
|
|
WriteOp_SMul_C(jit);
|
|
break;
|
|
}
|
|
case OP_SIGN_PRI:
|
|
{
|
|
WriteOp_Sign_Pri(jit);
|
|
break;
|
|
}
|
|
case OP_SIGN_ALT:
|
|
{
|
|
WriteOp_Sign_Alt(jit);
|
|
break;
|
|
}
|
|
case OP_EQ:
|
|
{
|
|
WriteOp_Eq(jit);
|
|
break;
|
|
}
|
|
case OP_NEQ:
|
|
{
|
|
WriteOp_Neq(jit);
|
|
break;
|
|
}
|
|
case OP_SLESS:
|
|
{
|
|
WriteOp_Sless(jit);
|
|
break;
|
|
}
|
|
case OP_SLEQ:
|
|
{
|
|
WriteOp_Sleq(jit);
|
|
break;
|
|
}
|
|
case OP_SGRTR:
|
|
{
|
|
WriteOp_Sgrtr(jit);
|
|
break;
|
|
}
|
|
case OP_SGEQ:
|
|
{
|
|
WriteOp_Sgeq(jit);
|
|
break;
|
|
}
|
|
case OP_EQ_C_PRI:
|
|
{
|
|
WriteOp_Eq_C_Pri(jit);
|
|
break;
|
|
}
|
|
case OP_EQ_C_ALT:
|
|
{
|
|
WriteOp_Eq_C_Alt(jit);
|
|
break;
|
|
}
|
|
case OP_INC_PRI:
|
|
{
|
|
WriteOp_Inc_Pri(jit);
|
|
break;
|
|
}
|
|
case OP_INC_ALT:
|
|
{
|
|
WriteOp_Inc_Alt(jit);
|
|
break;
|
|
}
|
|
case OP_INC:
|
|
{
|
|
WriteOp_Inc(jit);
|
|
break;
|
|
}
|
|
case OP_INC_S:
|
|
{
|
|
WriteOp_Inc_S(jit);
|
|
break;
|
|
}
|
|
case OP_INC_I:
|
|
{
|
|
WriteOp_Inc_I(jit);
|
|
break;
|
|
}
|
|
case OP_DEC_PRI:
|
|
{
|
|
WriteOp_Dec_Pri(jit);
|
|
break;
|
|
}
|
|
case OP_DEC_ALT:
|
|
{
|
|
WriteOp_Dec_Alt(jit);
|
|
break;
|
|
}
|
|
case OP_DEC:
|
|
{
|
|
WriteOp_Dec(jit);
|
|
break;
|
|
}
|
|
case OP_DEC_S:
|
|
{
|
|
WriteOp_Dec_S(jit);
|
|
break;
|
|
}
|
|
case OP_DEC_I:
|
|
{
|
|
WriteOp_Dec_I(jit);
|
|
break;
|
|
}
|
|
case OP_LOAD_PRI:
|
|
{
|
|
WriteOp_Load_Pri(jit);
|
|
break;
|
|
}
|
|
case OP_LOAD_ALT:
|
|
{
|
|
WriteOp_Load_Alt(jit);
|
|
break;
|
|
}
|
|
case OP_LOAD_S_PRI:
|
|
{
|
|
WriteOp_Load_S_Pri(jit);
|
|
break;
|
|
}
|
|
case OP_LOAD_S_ALT:
|
|
{
|
|
WriteOp_Load_S_Alt(jit);
|
|
break;
|
|
}
|
|
case OP_LREF_PRI:
|
|
{
|
|
WriteOp_Lref_Pri(jit);
|
|
break;
|
|
}
|
|
case OP_LREF_ALT:
|
|
{
|
|
WriteOp_Lref_Alt(jit);
|
|
break;
|
|
}
|
|
case OP_LREF_S_PRI:
|
|
{
|
|
WriteOp_Lref_S_Pri(jit);
|
|
break;
|
|
}
|
|
case OP_LREF_S_ALT:
|
|
{
|
|
WriteOp_Lref_S_Alt(jit);
|
|
break;
|
|
}
|
|
case OP_CONST_PRI:
|
|
{
|
|
WriteOp_Const_Pri(jit);
|
|
break;
|
|
}
|
|
case OP_CONST_ALT:
|
|
{
|
|
WriteOp_Const_Alt(jit);
|
|
break;
|
|
}
|
|
case OP_ADDR_PRI:
|
|
{
|
|
WriteOp_Addr_Pri(jit);
|
|
break;
|
|
}
|
|
case OP_ADDR_ALT:
|
|
{
|
|
WriteOp_Addr_Alt(jit);
|
|
break;
|
|
}
|
|
case OP_STOR_PRI:
|
|
{
|
|
WriteOp_Stor_Pri(jit);
|
|
break;
|
|
}
|
|
case OP_STOR_ALT:
|
|
{
|
|
WriteOp_Stor_Alt(jit);
|
|
break;
|
|
}
|
|
case OP_STOR_S_PRI:
|
|
{
|
|
WriteOp_Stor_S_Pri(jit);
|
|
break;
|
|
}
|
|
case OP_STOR_S_ALT:
|
|
{
|
|
WriteOp_Stor_S_Alt(jit);
|
|
break;
|
|
}
|
|
case OP_IDXADDR:
|
|
{
|
|
WriteOp_Idxaddr(jit);
|
|
break;
|
|
}
|
|
case OP_SREF_PRI:
|
|
{
|
|
WriteOp_Sref_Pri(jit);
|
|
break;
|
|
}
|
|
case OP_SREF_ALT:
|
|
{
|
|
WriteOp_Sref_Alt(jit);
|
|
break;
|
|
}
|
|
case OP_SREF_S_PRI:
|
|
{
|
|
WriteOp_Sref_S_Pri(jit);
|
|
break;
|
|
}
|
|
case OP_SREF_S_ALT:
|
|
{
|
|
WriteOp_Sref_S_Alt(jit);
|
|
break;
|
|
}
|
|
case OP_POP_PRI:
|
|
{
|
|
WriteOp_Pop_Pri(jit);
|
|
break;
|
|
}
|
|
case OP_POP_ALT:
|
|
{
|
|
WriteOp_Pop_Alt(jit);
|
|
break;
|
|
}
|
|
case OP_SWAP_PRI:
|
|
{
|
|
WriteOp_Swap_Pri(jit);
|
|
break;
|
|
}
|
|
case OP_SWAP_ALT:
|
|
{
|
|
WriteOp_Swap_Alt(jit);
|
|
break;
|
|
}
|
|
case OP_PUSH_ADR:
|
|
{
|
|
WriteOp_PushAddr(jit);
|
|
break;
|
|
}
|
|
case OP_MOVS:
|
|
{
|
|
WriteOp_Movs(jit);
|
|
break;
|
|
}
|
|
case OP_FILL:
|
|
{
|
|
WriteOp_Fill(jit);
|
|
break;
|
|
}
|
|
case OP_PUSH_C:
|
|
{
|
|
WriteOp_Push_C(jit);
|
|
break;
|
|
}
|
|
case OP_ZERO:
|
|
{
|
|
WriteOp_Zero(jit);
|
|
break;
|
|
}
|
|
case OP_ZERO_S:
|
|
{
|
|
WriteOp_Zero_S(jit);
|
|
break;
|
|
}
|
|
case OP_PUSH_PRI:
|
|
{
|
|
WriteOp_Push_Pri(jit);
|
|
break;
|
|
}
|
|
case OP_PUSH_ALT:
|
|
{
|
|
WriteOp_Push_Alt(jit);
|
|
break;
|
|
}
|
|
case OP_LOAD_BOTH:
|
|
{
|
|
WriteOp_Load_Both(jit);
|
|
break;
|
|
}
|
|
case OP_LOAD_S_BOTH:
|
|
{
|
|
WriteOp_Load_S_Both(jit);
|
|
break;
|
|
}
|
|
case OP_CONST:
|
|
{
|
|
WriteOp_Const(jit);
|
|
break;
|
|
}
|
|
case OP_CONST_S:
|
|
{
|
|
WriteOp_Const_S(jit);
|
|
break;
|
|
}
|
|
case OP_LOAD_I:
|
|
{
|
|
WriteOp_Load_I(jit);
|
|
break;
|
|
}
|
|
case OP_LODB_I:
|
|
{
|
|
WriteOp_Lodb_I(jit);
|
|
break;
|
|
}
|
|
case OP_STOR_I:
|
|
{
|
|
WriteOp_Stor_I(jit);
|
|
break;
|
|
}
|
|
case OP_STRB_I:
|
|
{
|
|
WriteOp_Strb_I(jit);
|
|
break;
|
|
}
|
|
case OP_LIDX:
|
|
{
|
|
WriteOp_Lidx(jit);
|
|
break;
|
|
}
|
|
case OP_LIDX_B:
|
|
{
|
|
WriteOp_Lidx_B(jit);
|
|
break;
|
|
}
|
|
case OP_IDXADDR_B:
|
|
{
|
|
WriteOp_Idxaddr_B(jit);
|
|
break;
|
|
}
|
|
case OP_STACK:
|
|
{
|
|
WriteOp_Stack(jit);
|
|
break;
|
|
}
|
|
case OP_HEAP:
|
|
{
|
|
WriteOp_Heap(jit);
|
|
break;
|
|
}
|
|
case OP_SDIV:
|
|
{
|
|
WriteOp_SDiv(jit);
|
|
break;
|
|
}
|
|
case OP_SDIV_ALT:
|
|
{
|
|
WriteOp_SDiv_Alt(jit);
|
|
break;
|
|
}
|
|
case OP_RETN:
|
|
{
|
|
WriteOp_Retn(jit);
|
|
break;
|
|
}
|
|
case OP_BOUNDS:
|
|
{
|
|
WriteOp_Bounds(jit);
|
|
break;
|
|
}
|
|
case OP_HALT:
|
|
{
|
|
WriteOp_Halt(jit);
|
|
break;
|
|
}
|
|
case OP_BREAK:
|
|
{
|
|
WriteOp_Break(jit);
|
|
break;
|
|
}
|
|
case OP_JUMP:
|
|
{
|
|
WriteOp_Jump(jit);
|
|
break;
|
|
}
|
|
case OP_JZER:
|
|
{
|
|
WriteOp_Jzer(jit);
|
|
break;
|
|
}
|
|
case OP_JNZ:
|
|
{
|
|
WriteOp_Jnz(jit);
|
|
break;
|
|
}
|
|
case OP_JEQ:
|
|
{
|
|
WriteOp_Jeq(jit);
|
|
break;
|
|
}
|
|
case OP_JNEQ:
|
|
{
|
|
WriteOp_Jneq(jit);
|
|
break;
|
|
}
|
|
case OP_JSLESS:
|
|
{
|
|
WriteOp_Jsless(jit);
|
|
break;
|
|
}
|
|
case OP_JSGRTR:
|
|
{
|
|
WriteOp_JsGrtr(jit);
|
|
break;
|
|
}
|
|
case OP_JSGEQ:
|
|
{
|
|
WriteOp_JsGeq(jit);
|
|
break;
|
|
}
|
|
case OP_JSLEQ:
|
|
{
|
|
WriteOp_Jsleq(jit);
|
|
break;
|
|
}
|
|
case OP_SWITCH:
|
|
{
|
|
WriteOp_Switch(jit);
|
|
break;
|
|
}
|
|
case OP_CASETBL:
|
|
{
|
|
WriteOp_Casetbl(jit);
|
|
break;
|
|
}
|
|
case OP_CALL:
|
|
{
|
|
WriteOp_Call(jit);
|
|
break;
|
|
}
|
|
case OP_SYSREQ_C:
|
|
{
|
|
WriteOp_Sysreq_C(jit);
|
|
break;
|
|
}
|
|
case OP_SYSREQ_N:
|
|
{
|
|
WriteOp_Sysreq_N(jit);
|
|
break;
|
|
}
|
|
case OP_TRACKER_PUSH_C:
|
|
{
|
|
WriteOp_Tracker_Push_C(jit);
|
|
break;
|
|
}
|
|
case OP_TRACKER_POP_SETHEAP:
|
|
{
|
|
WriteOp_Tracker_Pop_SetHeap(jit);
|
|
break;
|
|
}
|
|
case OP_GENARRAY:
|
|
{
|
|
WriteOp_GenArray(jit, false);
|
|
break;
|
|
}
|
|
case OP_GENARRAY_Z:
|
|
{
|
|
WriteOp_GenArray(jit, true);
|
|
break;
|
|
}
|
|
case OP_STRADJUST_PRI:
|
|
{
|
|
WriteOp_Stradjust_Pri(jit);
|
|
break;
|
|
}
|
|
case OP_FABS:
|
|
{
|
|
WriteOp_FloatAbs(jit);
|
|
break;
|
|
}
|
|
case OP_FLOAT:
|
|
{
|
|
WriteOp_Float(jit);
|
|
break;
|
|
}
|
|
case OP_FLOATADD:
|
|
{
|
|
WriteOp_FloatAdd(jit);
|
|
break;
|
|
}
|
|
case OP_FLOATSUB:
|
|
{
|
|
WriteOp_FloatSub(jit);
|
|
break;
|
|
}
|
|
case OP_FLOATMUL:
|
|
{
|
|
WriteOp_FloatMul(jit);
|
|
break;
|
|
}
|
|
case OP_FLOATDIV:
|
|
{
|
|
WriteOp_FloatDiv(jit);
|
|
break;
|
|
}
|
|
case OP_RND_TO_NEAREST:
|
|
{
|
|
WriteOp_RountToNearest(jit);
|
|
break;
|
|
}
|
|
case OP_RND_TO_FLOOR:
|
|
{
|
|
WriteOp_RoundToFloor(jit);
|
|
break;
|
|
}
|
|
case OP_RND_TO_ZERO:
|
|
{
|
|
WriteOp_RoundToZero(jit);
|
|
break;
|
|
}
|
|
case OP_RND_TO_CEIL:
|
|
{
|
|
WriteOp_RoundToCeil(jit);
|
|
break;
|
|
}
|
|
case OP_FLOATCMP:
|
|
{
|
|
WriteOp_FloatCompare(jit);
|
|
break;
|
|
}
|
|
case OP_STACKADJUST:
|
|
{
|
|
WriteOp_StackAdjust(jit);
|
|
break;
|
|
}
|
|
case OP_ENDPROC:
|
|
{
|
|
WriteOp_EndProc(jit);
|
|
break;
|
|
}
|
|
#if defined USE_UNGEN_OPCODES
|
|
#include "ungen_opcode_switch.inc"
|
|
#endif
|
|
default:
|
|
{
|
|
data->error_set = SP_ERROR_INVALID_INSTRUCTION;
|
|
break;
|
|
}
|