Browse Source

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 12 years ago
parent
commit
ae743d1eaa
3 changed files with 211 additions and 97 deletions
  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: