ソースを参照

Fixes from squirrel 3.0.6 and an attempt to use computed gotos on the vm, right now it does not add any performance enhancements.

mingodad 11 年 前
コミット
ae743d1eaa
3 ファイル変更211 行追加97 行削除
  1. 24 8
      SquiLu/squirrel/sqcompiler.cpp
  2. 5 0
      SquiLu/squirrel/sqobject.cpp
  3. 182 89
      SquiLu/squirrel/sqvm.cpp

+ 24 - 8
SquiLu/squirrel/sqcompiler.cpp

@@ -26,6 +26,8 @@ struct SQExpState {
   bool       donot_get;   /* signal not to deref the next value */
 };
 
+#define MAX_COMPILER_ERROR_LEN 256
+
 struct SQScope {
 	SQInteger outers;
 	SQInteger stacksize;
@@ -85,7 +87,7 @@ public:
 		_scope.outers = 0;
 		_scope.stacksize = 0;
 		_scope.nested = 0;
-		compilererror = NULL;
+		_compilererror = NULL;
 		_globals = SQTable::Create(_ss(_vm),0);
 	}
 	~SQCompiler(){
@@ -104,7 +106,7 @@ public:
 		va_start(vl, s);
 		scvsnprintf(error_buf, sizeof(error_buf), s, vl);
 		va_end(vl);
-		compilererror = error_buf;
+		_compilererror = error_buf;
 		longjmp(_errorjmp,1);
 	}
 
@@ -328,10 +330,10 @@ public:
 		}
 		else {
 			if(_raiseerror && _ss(_vm)->_compilererrorhandler) {
-				_ss(_vm)->_compilererrorhandler(_vm, compilererror, type(_sourcename) == OT_STRING?_stringval(_sourcename):_SC("unknown"),
+				_ss(_vm)->_compilererrorhandler(_vm, _compilererror, type(_sourcename) == OT_STRING?_stringval(_sourcename):_SC("unknown"),
 					_lex._currentline, _lex._currentcolumn);
 			}
-			_vm->_lasterror = SQString::Create(_ss(_vm), compilererror, -1);
+			_vm->_lasterror = SQString::Create(_ss(_vm), _compilererror, -1);
 			return false;
 		}
 		return true;
@@ -1522,8 +1524,17 @@ if(color == "yellow"){
 			//condition
 			Lex(); ExpressionScalar() /*Expression()*/; Expect(_SC(':'));
 			SQInteger trg = _fs->PopTarget();
-			_fs->AddInstruction(_OP_EQ, trg, trg, expr);
-			_fs->AddInstruction(_OP_JZ, trg, 0);
+			SQInteger eqtarget = trg;
+			bool local = _fs->IsLocal(trg);
+			if(local) {
+				eqtarget = _fs->PushTarget(); //we need to allocate a extra reg
+			}
+			_fs->AddInstruction(_OP_EQ, eqtarget, trg, expr);
+			_fs->AddInstruction(_OP_JZ, eqtarget, 0);
+			if(local) {
+				_fs->PopTarget();
+			}
+
 			//end condition
 			if(skipcondjmp != -1) {
 				_fs->SetIntructionParam(skipcondjmp, 1, (_fs->GetCurrentPos() - skipcondjmp));
@@ -1610,6 +1621,11 @@ if(color == "yellow"){
 			case TK_STRING_LITERAL:
 				val = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1);
 				break;
+			case TK_TRUE:
+			case TK_FALSE:
+				val._type = OT_BOOL;
+				val._unVal.nInteger = _token == TK_TRUE ? 1 : 0;
+				break;
 			case '-':
 				Lex();
 				switch(_token)
@@ -1923,12 +1939,12 @@ private:
 	SQInteger _debugop;
 	SQExpState   _es;
 	SQScope _scope;
-	SQChar *compilererror;
+	SQChar *_compilererror;
 	jmp_buf _errorjmp;
 	SQVM *_vm;
 	SQObjectPtrVec _scope_consts;
 	SQObjectPtr _globals;
-	SQChar error_buf[256];
+	SQChar error_buf[MAX_COMPILER_ERROR_LEN];
 };
 
 bool Compile(SQVM *vm,SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, SQObjectPtr &out,

+ 5 - 0
SquiLu/squirrel/sqobject.cpp

@@ -367,6 +367,7 @@ bool WriteObject(HSQUIRRELVM v,SQUserPointer up,SQWRITEFUNC write,SQObjectPtr &o
 		_CHECK_IO(SafeWrite(v,write,up,&_string(o)->_len,sizeof(SQInteger)));
 		_CHECK_IO(SafeWrite(v,write,up,_stringval(o),rsl(_string(o)->_len)));
 		break;
+	case OT_BOOL:
 	case OT_INTEGER:
 		_CHECK_IO(SafeWrite(v,write,up,&_integer(o),sizeof(SQInteger)));break;
 	case OT_FLOAT:
@@ -397,6 +398,10 @@ bool ReadObject(HSQUIRRELVM v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &o)
 		SQInteger i;
 		_CHECK_IO(SafeRead(v,read,up,&i,sizeof(SQInteger))); o = i; break;
 					}
+	case OT_BOOL:{
+		SQInteger i;
+		_CHECK_IO(SafeRead(v,read,up,&i,sizeof(SQInteger))); o._type = OT_BOOL; o._unVal.nInteger = i; break;
+					}
 	case OT_FLOAT:{
 		SQFloat f;
 		_CHECK_IO(SafeRead(v,read,up,&f,sizeof(SQFloat))); o = f; break;

+ 182 - 89
SquiLu/squirrel/sqvm.cpp

@@ -707,7 +707,28 @@ bool SQVM::IsFalse(SQObjectPtr &o)
 		return true;
 	}
 	return false;
-}
+}
+
+#if defined(__GNUC__) && defined(USE_COMPUTED_GOTOS)
+    //it doesn't generate faster code, even slower
+    //on lua it has a small noticeable improvement
+    //needs -fno-gcse or even -fno-crossjumping
+    #define COMPUTED_GOTO 1
+    #pragma GCC push_options
+    //#pragma GCC optimize ("no-gcse")
+    //#pragma GCC optimize ("no-crossjumping")
+#endif
+
+#ifdef COMPUTED_GOTO
+	#define OPCODE_TARGET(op) DO_OP_##op:
+	#define CALL_OPCODE(op) \
+		if ((op < sizeof(opcodes) / sizeof(opcodes[0])) && opcodes[op]) \
+			goto *opcodes[op];
+	#define OPCODE_PTR(op) [_OP_##op] = &&DO_OP_##op
+#else
+	#define OPCODE_TARGET(op) case _OP_##op:
+	#define CALL_OPCODE(op) switch (op)
+#endif
 
 bool SQVM::Execute(SQObjectPtr &closure, SQInteger nargs, SQInteger stackbase,SQObjectPtr &outres, SQBool raiseerror,ExecutionType et)
 {
@@ -716,6 +737,73 @@ bool SQVM::Execute(SQObjectPtr &closure, SQInteger nargs, SQInteger stackbase,SQ
 	AutoDec ad(&_nnativecalls);
 	SQInteger traps = 0;
 	CallInfo *prevci = ci;
+#ifdef COMPUTED_GOTO
+  static const void *opcodes[] = {
+	OPCODE_PTR(LINE),
+	OPCODE_PTR(LOAD),
+	OPCODE_PTR(LOADINT),
+	OPCODE_PTR(LOADFLOAT),
+	OPCODE_PTR(DLOAD),
+	OPCODE_PTR(TAILCALL),
+	OPCODE_PTR(CALL),
+	OPCODE_PTR(PREPCALL),
+	OPCODE_PTR(PREPCALLK),
+	OPCODE_PTR(GETK),
+	OPCODE_PTR(MOVE),
+	OPCODE_PTR(NEWSLOT),
+	OPCODE_PTR(DELETE),
+	OPCODE_PTR(SET),
+	OPCODE_PTR(GET),
+	OPCODE_PTR(EQ),
+	OPCODE_PTR(NE),
+	OPCODE_PTR(ADD),
+	OPCODE_PTR(SUB),
+	OPCODE_PTR(MUL),
+	OPCODE_PTR(DIV),
+	OPCODE_PTR(MOD),
+	OPCODE_PTR(BITW),
+	OPCODE_PTR(RETURN),
+	OPCODE_PTR(LOADNULLS),
+	OPCODE_PTR(LOADROOT),
+	OPCODE_PTR(LOADBOOL),
+	OPCODE_PTR(DMOVE),
+	OPCODE_PTR(JMP),
+	OPCODE_PTR(JCMP),
+	OPCODE_PTR(JZ),
+	OPCODE_PTR(SETOUTER),
+	OPCODE_PTR(GETOUTER),
+	OPCODE_PTR(NEWOBJ),
+	OPCODE_PTR(APPENDARRAY),
+	OPCODE_PTR(COMPARITH),
+	OPCODE_PTR(INC),
+	OPCODE_PTR(INCL),
+	OPCODE_PTR(PINC),
+	OPCODE_PTR(PINCL),
+	OPCODE_PTR(CMP),
+	OPCODE_PTR(EXISTS),
+	OPCODE_PTR(INSTANCEOF),
+	OPCODE_PTR(AND),
+	OPCODE_PTR(OR),
+	OPCODE_PTR(NEG),
+	OPCODE_PTR(NOT),
+	OPCODE_PTR(BWNOT),
+	OPCODE_PTR(CLOSURE),
+	OPCODE_PTR(YIELD),
+	OPCODE_PTR(RESUME),
+	OPCODE_PTR(FOREACH),
+	OPCODE_PTR(POSTFOREACH),
+	OPCODE_PTR(CLONE),
+	OPCODE_PTR(TYPEOF),
+	OPCODE_PTR(PUSHTRAP),
+	OPCODE_PTR(POPTRAP),
+	OPCODE_PTR(THROW),
+	OPCODE_PTR(NEWSLOTA),
+	OPCODE_PTR(GETBASE),
+	OPCODE_PTR(CLOSE),
+	OPCODE_PTR(EQI),
+	OPCODE_PTR(NEI),
+};
+#endif
 
 	switch(et) {
 		case ET_CALL: {
@@ -796,19 +884,19 @@ exception_restore:
 			OpProfile &opp = _op_profile[_i_.op];
 			++opp.count;
 #endif
-			switch(_i_.op)
+			CALL_OPCODE(_i_.op)
 			{
-			case _OP_LINE: if (_debughook) CallDebugHook(_SC('l'),arg1); continue;
-			case _OP_LOAD: TARGET = ci->_literals[arg1]; continue;
-			case _OP_LOADINT:
+			OPCODE_TARGET(LINE) { if (_debughook) CallDebugHook(_SC('l'),arg1); continue;}
+			OPCODE_TARGET(LOAD) { TARGET = ci->_literals[arg1]; continue;}
+			OPCODE_TARGET(LOADINT) {
 #ifndef _SQ64
-				TARGET = (SQInteger)arg1; continue;
+				TARGET = (SQInteger)arg1; continue;}
 #else
-				TARGET = (SQInteger)((SQUnsignedInteger32)arg1); continue;
+				TARGET = (SQInteger)((SQUnsignedInteger32)arg1); continue;}
 #endif
-			case _OP_LOADFLOAT: TARGET = *((SQFloat *)&arg1); continue;
-			case _OP_DLOAD: TARGET = ci->_literals[arg1]; STK(arg2) = ci->_literals[arg3];continue;
-			case _OP_TAILCALL:{
+			OPCODE_TARGET(LOADFLOAT) { TARGET = *((SQFloat *)&arg1); continue;}
+			OPCODE_TARGET(DLOAD) { TARGET = ci->_literals[arg1]; STK(arg2) = ci->_literals[arg3];continue;}
+			OPCODE_TARGET(TAILCALL) {
 				SQObjectPtr &t = STK(arg1);
 				if (type(t) == OT_CLOSURE
 					&& (!_closure(t)->_function->_bgenerator)){
@@ -819,7 +907,7 @@ exception_restore:
 					continue;
 				}
 							  }
-			case _OP_CALL: {
+			OPCODE_TARGET(CALL) {
 					SQObjectPtr clo = STK(arg1);
 					switch (type(clo)) {
 					case OT_CLOSURE:
@@ -890,8 +978,8 @@ exception_restore:
 					}
 				}
 				  continue;
-			case _OP_PREPCALL:
-			case _OP_PREPCALLK:	{
+			OPCODE_TARGET(PREPCALL)
+			OPCODE_TARGET(PREPCALLK) {
 					SQObjectPtr &key = _i_.op == _OP_PREPCALLK?(ci->_literals)[arg1]:STK(arg1);
 					SQObjectPtr &o = STK(arg2);
 					if (!Get(o, key, temp_reg,false,arg2)) {
@@ -901,7 +989,7 @@ exception_restore:
 					_Swap(TARGET,temp_reg);//TARGET = temp_reg;
 				}
 				continue;
-			case _OP_GETK:
+			OPCODE_TARGET(GETK) {
 #ifndef NO_EXCEPTION_KEY_NOT_FOUND
 				if (!Get(STK(arg2), ci->_literals[arg1], temp_reg, false,arg2)) { SQ_THROW();}
 #else
@@ -909,40 +997,40 @@ exception_restore:
 				if(!Get(STK(arg2), ci->_literals[arg1], temp_reg, false,arg2)) temp_reg.Null();
 #endif
 				_Swap(TARGET,temp_reg);//TARGET = temp_reg;
-				continue;
-			case _OP_MOVE: TARGET = STK(arg1); continue;
-			case _OP_NEWSLOT:
+				continue;}
+			OPCODE_TARGET(MOVE) { TARGET = STK(arg1); continue;}
+			OPCODE_TARGET(NEWSLOT) {
 				_GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3),false));
 				if(arg0 != 0xFF) TARGET = STK(arg3);
-				continue;
-			case _OP_DELETE: _GUARD(DeleteSlot(STK(arg1), STK(arg2), TARGET)); continue;
-			case _OP_SET:
+				continue;}
+			OPCODE_TARGET(DELETE) { _GUARD(DeleteSlot(STK(arg1), STK(arg2), TARGET)); continue;}
+			OPCODE_TARGET(SET) {
 				if (!Set(STK(arg1), STK(arg2), STK(arg3),arg1)) { SQ_THROW(); }
 				if (arg0 != 0xFF) TARGET = STK(arg3);
-				continue;
-			case _OP_GET:
+				continue;}
+			OPCODE_TARGET(GET) {
 				if (!Get(STK(arg1), STK(arg2), temp_reg, false,arg1)) { SQ_THROW(); }
 				_Swap(TARGET,temp_reg);//TARGET = temp_reg;
-				continue;
-			case _OP_EQ:
+				continue;}
+			OPCODE_TARGET(EQ) {
 				TARGET = IsEqual(STK(arg2),COND_LITERAL)?true:false;
-				continue;
-			case _OP_EQI:
+				continue;}
+			OPCODE_TARGET(EQI) {
 				TARGET = IsEqualIdentity(STK(arg2),COND_LITERAL)?true:false;
-				continue;
-			case _OP_NE:
+				continue;}
+			OPCODE_TARGET(NE) {
 				TARGET = (!IsEqual(STK(arg2),COND_LITERAL))?true:false;
-				continue;
-			case _OP_NEI:
+				continue;}
+			OPCODE_TARGET(NEI) {
 				TARGET = (!IsEqualIdentity(STK(arg2),COND_LITERAL))?true:false;
-				continue;
-			case _OP_ADD: _ARITH_(+,TARGET,STK(arg2),STK(arg1)); continue;
-			case _OP_SUB: _ARITH_(-,TARGET,STK(arg2),STK(arg1)); continue;
-			case _OP_MUL: _ARITH_(*,TARGET,STK(arg2),STK(arg1)); continue;
-			case _OP_DIV: _ARITH_NOZERO(/,TARGET,STK(arg2),STK(arg1),_SC("division by zero")); continue;
-			case _OP_MOD: ARITH_OP('%',TARGET,STK(arg2),STK(arg1)); continue;
-			case _OP_BITW:	_GUARD(BW_OP( arg3,TARGET,STK(arg2),STK(arg1))); continue;
-			case _OP_RETURN:
+				continue;}
+			OPCODE_TARGET(ADD) { _ARITH_(+,TARGET,STK(arg2),STK(arg1)); continue;}
+			OPCODE_TARGET(SUB) { _ARITH_(-,TARGET,STK(arg2),STK(arg1)); continue;}
+			OPCODE_TARGET(MUL) { _ARITH_(*,TARGET,STK(arg2),STK(arg1)); continue;}
+			OPCODE_TARGET(DIV) { _ARITH_NOZERO(/,TARGET,STK(arg2),STK(arg1),_SC("division by zero")); continue;}
+			OPCODE_TARGET(MOD) { ARITH_OP('%',TARGET,STK(arg2),STK(arg1)); continue;}
+			OPCODE_TARGET(BITW) {	_GUARD(BW_OP( arg3,TARGET,STK(arg2),STK(arg1))); continue;}
+			OPCODE_TARGET(RETURN) {
 				if((ci)->_generator) {
 					(ci)->_generator->Kill();
 				}
@@ -952,25 +1040,25 @@ exception_restore:
 					_Swap(outres,temp_reg);
 					return true;
 				}
-				continue;
-			case _OP_LOADNULLS:{ for(SQInt32 n=0; n < arg1; n++) STK(arg0+n).Null(); }continue;
-			case _OP_LOADROOT:	TARGET = _roottable; continue;
-			case _OP_LOADBOOL: TARGET = arg1?true:false; continue;
-			case _OP_DMOVE: STK(arg0) = STK(arg1); STK(arg2) = STK(arg3); continue;
-			case _OP_JMP: ci->_ip += (sarg1); continue;
-			//case _OP_JNZ: if(!IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue;
-			case _OP_JCMP:
+				continue;}
+			OPCODE_TARGET(LOADNULLS) { for(SQInt32 n=0; n < arg1; n++) STK(arg0+n).Null(); }continue;
+			OPCODE_TARGET(LOADROOT) {	TARGET = _roottable; continue;}
+			OPCODE_TARGET(LOADBOOL) { TARGET = arg1?true:false; continue;}
+			OPCODE_TARGET(DMOVE) { STK(arg0) = STK(arg1); STK(arg2) = STK(arg3); continue;}
+			OPCODE_TARGET(JMP) { ci->_ip += (sarg1); continue;}
+			//OPCODE_TARGET(JNZ) { if(!IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue;
+			OPCODE_TARGET(JCMP) {
 				_GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg0),temp_reg));
 				if(IsFalse(temp_reg)) ci->_ip+=(sarg1);
-				continue;
-			case _OP_JZ: if(IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue;
-			case _OP_GETOUTER: {
+				continue;}
+			OPCODE_TARGET(JZ) { if(IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue;}
+			OPCODE_TARGET(GETOUTER) {
 				SQClosure *cur_cls = _closure(ci->_closure);
 				SQOuter *otr = _outer(cur_cls->_outervalues[arg1]);
 				TARGET = *(otr->_valptr);
 				}
 			continue;
-			case _OP_SETOUTER: {
+			OPCODE_TARGET(SETOUTER) {
 				SQClosure *cur_cls = _closure(ci->_closure);
 				SQOuter   *otr = _outer(cur_cls->_outervalues[arg1]);
 				*(otr->_valptr) = STK(arg2);
@@ -979,14 +1067,14 @@ exception_restore:
 				}
 				}
 			continue;
-			case _OP_NEWOBJ:
+			OPCODE_TARGET(NEWOBJ) {
 				switch(arg3) {
 					case NOT_TABLE: TARGET = SQTable::Create(_ss(this), arg1); continue;
 					case NOT_ARRAY: TARGET = SQArray::Create(_ss(this), 0); _array(TARGET)->Reserve(arg1); continue;
 					case NOT_CLASS: _GUARD(CLASS_OP(TARGET,arg1,arg2)); continue;
 					default: assert(0); continue;
-				}
-			case _OP_APPENDARRAY:
+				}}
+			OPCODE_TARGET(APPENDARRAY) {
 				{
 					SQObject val;
 					val._unVal.raw = 0;
@@ -1015,14 +1103,14 @@ exception_restore:
 
 				}
 				_array(STK(arg0))->Append(val);	continue;
-				}
-			case _OP_COMPARITH: {
+				}}
+			OPCODE_TARGET(COMPARITH) {
 				SQInteger selfidx = (((SQUnsignedInteger)arg1&0xFFFF0000)>>16);
 				_GUARD(DerefInc(arg3, TARGET, STK(selfidx), STK(arg2), STK(arg1&0x0000FFFF), false, selfidx));
 								}
 				continue;
-			case _OP_INC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, false, arg1));} continue;
-			case _OP_INCL: {
+			OPCODE_TARGET(INC) {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, false, arg1));} continue;
+			OPCODE_TARGET(INCL) {
 				SQObjectPtr &a = STK(arg1);
 				if(type(a) == OT_INTEGER) {
 					a._unVal.nInteger = _integer(a) + sarg3;
@@ -1032,8 +1120,8 @@ exception_restore:
 					_ARITH_(+,a,a,o);
 				}
 						   } continue;
-			case _OP_PINC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, true, arg1));} continue;
-			case _OP_PINCL:	{
+			OPCODE_TARGET(PINC) {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, true, arg1));} continue;
+			OPCODE_TARGET(PINCL) {
 				SQObjectPtr &a = STK(arg1);
 				if(type(a) == OT_INTEGER) {
 					TARGET = a;
@@ -1044,42 +1132,42 @@ exception_restore:
 				}
 
 						} continue;
-			case _OP_CMP:	_GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg1),TARGET))	continue;
-			case _OP_EXISTS: TARGET = Get(STK(arg1), STK(arg2), temp_reg, true,DONT_FALL_BACK)?true:false;continue;
-			case _OP_INSTANCEOF:
+			OPCODE_TARGET(CMP) {	_GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg1),TARGET))	continue;}
+			OPCODE_TARGET(EXISTS) { TARGET = Get(STK(arg1), STK(arg2), temp_reg, true,DONT_FALL_BACK)?true:false;continue;}
+			OPCODE_TARGET(INSTANCEOF) {
 				if(type(STK(arg1)) != OT_CLASS)
 				{Raise_Error(_SC("cannot apply instanceof between a %s and a %s"),GetTypeName(STK(arg1)),GetTypeName(STK(arg2))); SQ_THROW();}
 				TARGET = (type(STK(arg2)) == OT_INSTANCE) ? (_instance(STK(arg2))->InstanceOf(_class(STK(arg1)))?true:false) : false;
-				continue;
-			case _OP_AND:
+				continue;}
+			OPCODE_TARGET(AND) {
 				if(IsFalse(STK(arg2))) {
 					TARGET = STK(arg2);
 					ci->_ip += (sarg1);
 				}
-				continue;
-			case _OP_OR:
+				continue;}
+			OPCODE_TARGET(OR) {
 				if(!IsFalse(STK(arg2))) {
 					TARGET = STK(arg2);
 					ci->_ip += (sarg1);
 				}
-				continue;
-			case _OP_NEG: _GUARD(NEG_OP(TARGET,STK(arg1))); continue;
-			case _OP_NOT: TARGET = IsFalse(STK(arg1)); continue;
-			case _OP_BWNOT:
+				continue;}
+			OPCODE_TARGET(NEG) { _GUARD(NEG_OP(TARGET,STK(arg1))); continue;}
+			OPCODE_TARGET(NOT) { TARGET = IsFalse(STK(arg1)); continue;}
+			OPCODE_TARGET(BWNOT) {
 				if(type(STK(arg1)) == OT_INTEGER) {
 					SQInteger t = _integer(STK(arg1));
 					TARGET = SQInteger(~t);
 					continue;
 				}
 				Raise_Error(_SC("attempt to perform a bitwise op on a %s"), GetTypeName(STK(arg1)));
-				SQ_THROW();
-			case _OP_CLOSURE: {
+				SQ_THROW();}
+			OPCODE_TARGET(CLOSURE) {
 				SQClosure *c = ci->_closure._unVal.pClosure;
 				SQFunctionProto *fp = c->_function;
 				if(!CLOSURE_OP(TARGET,fp->_functions[arg1]._unVal.pFunctionProto)) { SQ_THROW(); }
 				continue;
 			}
-			case _OP_YIELD:{
+			OPCODE_TARGET(YIELD) {
 				if(ci->_generator) {
 					if(sarg1 != MAX_FUNC_STACKSIZE) temp_reg = STK(arg1);
 					_GUARD(ci->_generator->Yield(this,arg2));
@@ -1095,40 +1183,40 @@ exception_restore:
 
 				}
 				continue;
-			case _OP_RESUME:
+			OPCODE_TARGET(RESUME) {
 				if(type(STK(arg1)) != OT_GENERATOR){ Raise_Error(_SC("trying to resume a '%s',only genenerator can be resumed"), GetTypeName(STK(arg1))); SQ_THROW();}
 				_GUARD(_generator(STK(arg1))->Resume(this, TARGET));
 				traps += ci->_etraps;
-                continue;
-			case _OP_FOREACH:{ int tojump;
+                continue;}
+			OPCODE_TARGET(FOREACH) { int tojump;
 				_GUARD(FOREACH_OP(STK(arg0),STK(arg2),STK(arg2+1),STK(arg2+2),arg2,sarg1,tojump));
 				ci->_ip += tojump; }
 				continue;
-			case _OP_POSTFOREACH:
+			OPCODE_TARGET(POSTFOREACH) {
 				assert(type(STK(arg0)) == OT_GENERATOR);
 				if(_generator(STK(arg0))->_state == SQGenerator::eDead)
 					ci->_ip += (sarg1 - 1);
-				continue;
-			case _OP_CLONE: _GUARD(Clone(STK(arg1), TARGET)); continue;
-			case _OP_TYPEOF: _GUARD(TypeOf(STK(arg1), TARGET)) continue;
-			case _OP_PUSHTRAP:{
+				continue;}
+			OPCODE_TARGET(CLONE) { _GUARD(Clone(STK(arg1), TARGET)); continue;}
+			OPCODE_TARGET(TYPEOF) { _GUARD(TypeOf(STK(arg1), TARGET)) continue;}
+			OPCODE_TARGET(PUSHTRAP) {
 				SQInstruction *_iv = _closure(ci->_closure)->_function->_instructions;
 				_etraps.push_back(SQExceptionTrap(_top,_stackbase, &_iv[(ci->_ip-_iv)+arg1], arg0)); traps++;
 				ci->_etraps++;
 							  }
 				continue;
-			case _OP_POPTRAP: {
+			OPCODE_TARGET(POPTRAP) {
 				for(SQInteger i = 0; i < arg0; i++) {
 					_etraps.pop_back(); traps--;
 					ci->_etraps--;
 				}
 							  }
 				continue;
-			case _OP_THROW:	Raise_Error(TARGET); SQ_THROW(); continue;
-			case _OP_NEWSLOTA:
+			OPCODE_TARGET(THROW) {	Raise_Error(TARGET); SQ_THROW(); continue;}
+			OPCODE_TARGET(NEWSLOTA) {
 				_GUARD(NewSlotA(STK(arg1),STK(arg2),STK(arg3),(arg0&NEW_SLOT_ATTRIBUTES_FLAG) ? STK(arg2-1) : SQObjectPtr(),(arg0&NEW_SLOT_STATIC_FLAG)?true:false,false));
-				continue;
-			case _OP_GETBASE:{
+				continue;}
+			OPCODE_TARGET(GETBASE) {
 				SQClosure *clo = _closure(ci->_closure);
 				if(clo->_base) {
 					TARGET = clo->_base;
@@ -1138,12 +1226,17 @@ exception_restore:
 				}
 				continue;
 			}
-			case _OP_CLOSE:
+			OPCODE_TARGET(CLOSE) {
 				if(_openouters) CloseOuters(&(STK(arg1)));
-				continue;
+				continue;}
 			}
 		}
-	}
+	}
+
+#if defined(__GNUC__) && defined(USE_COMPUTED_GOTOS)
+    #pragma GCC pop_options
+#endif
+
 #endif
 
 exception_trap: