summaryrefslogtreecommitdiff
path: root/src/3rdparty/squirrel/squirrel/sqvm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/squirrel/squirrel/sqvm.cpp')
-rw-r--r--src/3rdparty/squirrel/squirrel/sqvm.cpp49
1 files changed, 38 insertions, 11 deletions
diff --git a/src/3rdparty/squirrel/squirrel/sqvm.cpp b/src/3rdparty/squirrel/squirrel/sqvm.cpp
index 10edc5970..c2ca7e19c 100644
--- a/src/3rdparty/squirrel/squirrel/sqvm.cpp
+++ b/src/3rdparty/squirrel/squirrel/sqvm.cpp
@@ -17,6 +17,21 @@
#define TOP() (_stack._vals[_top-1])
+#define CLEARSTACK(_last_top) { if((_last_top) >= _top) ClearStack(_last_top); }
+void SQVM::ClearStack(SQInteger last_top)
+{
+ SQObjectType tOldType;
+ SQObjectValue unOldVal;
+ while (last_top >= _top) {
+ SQObjectPtr &o = _stack._vals[last_top--];
+ tOldType = o._type;
+ unOldVal = o._unVal;
+ o._type = OT_NULL;
+ o._unVal.pUserPointer = NULL;
+ __Release(tOldType,unOldVal);
+ }
+}
+
bool SQVM::BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2)
{
SQInteger res;
@@ -50,7 +65,9 @@ bool SQVM::ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,
res = i1 / i2;
break;
case '*': res = i1 * i2; break;
- case '%': res = i1 % i2; break;
+ case '%': if(i2 == 0) { Raise_Error(_SC("modulo by zero")); return false; }
+ res = i1 % i2;
+ break;
default: res = 0xDEADBEEF;
}
trg = res;
@@ -288,12 +305,10 @@ void SQVM::TypeOf(const SQObjectPtr &obj1,SQObjectPtr &dest)
bool SQVM::Init(SQVM *friendvm, SQInteger stacksize)
{
_stack.resize(stacksize);
- //_callsstack.reserve(4);
_alloccallsstacksize = 4;
_callstackdata.resize(_alloccallsstacksize);
_callsstacksize = 0;
_callsstack = &_callstackdata[0];
- //_callsstack = (CallInfo*)sq_malloc(_alloccallsstacksize*sizeof(CallInfo));
_stackbase = 0;
_top = 0;
if(!friendvm)
@@ -672,20 +687,34 @@ bool SQVM::Execute(SQObjectPtr &closure, SQInteger target, SQInteger nargs, SQIn
bool ct_tailcall;
switch(et) {
- case ET_CALL:
- if(!StartCall(_closure(closure), _top - nargs, nargs, stackbase, false)) {
+ case ET_CALL: {
+ SQInteger last_top = _top;
+ temp_reg = closure;
+ if(!StartCall(_closure(temp_reg), _top - nargs, nargs, stackbase, false)) {
//call the handler if there are no calls in the stack, if not relies on the previous node
if(ci == NULL) CallErrorHandler(_lasterror);
return false;
}
+ if (_funcproto(_closure(temp_reg)->_function)->_bgenerator) {
+ //SQFunctionProto *f = _funcproto(_closure(temp_reg)->_function);
+ SQGenerator *gen = SQGenerator::Create(_ss(this), _closure(temp_reg));
+ _GUARD(gen->Yield(this));
+ Return(1, ci->_target, temp_reg);
+ outres = gen;
+ CLEARSTACK(last_top);
+ return true;
+ }
ci->_root = SQTrue;
+ }
break;
case ET_RESUME_GENERATOR: _generator(closure)->Resume(this, target); ci->_root = SQTrue; traps += ci->_etraps; break;
case ET_RESUME_VM:
+ case ET_RESUME_THROW_VM:
traps = _suspended_traps;
ci->_root = _suspended_root;
ci->_vargs = _suspend_varargs;
_suspended = SQFalse;
+ if(et == ET_RESUME_THROW_VM) { SQ_THROW(); }
break;
case ET_RESUME_OPENTTD:
traps = _suspended_traps;
@@ -716,7 +745,7 @@ exception_restore:
case _OP_DLOAD: TARGET = ci->_literals[arg1]; STK(arg2) = ci->_literals[arg3];continue;
case _OP_TAILCALL:
temp_reg = STK(arg1);
- if (type(temp_reg) == OT_CLOSURE){
+ if (type(temp_reg) == OT_CLOSURE && !_funcproto(_closure(temp_reg)->_function)->_bgenerator){
ct_tailcall = true;
if(ci->_vargs.size) PopVarArgs(ci->_vargs);
for (SQInteger i = 0; i < arg3; i++) STK(i) = STK(arg2 + i);
@@ -741,7 +770,7 @@ common_call:
_GUARD(gen->Yield(this));
Return(1, ct_target, clo);
STK(ct_target) = gen;
- while (last_top >= _top) _stack._vals[last_top--].Null();
+ CLEARSTACK(last_top);
continue;
}
}
@@ -1022,7 +1051,7 @@ exception_trap:
_stackbase = et._stackbase;
_stack._vals[_stackbase+et._extarget] = currerror;
_etraps.pop_back(); traps--; ci->_etraps--;
- while(last_top >= _top) _stack._vals[last_top--].Null();
+ CLEARSTACK(last_top);
goto exception_restore;
}
//if is a native closure
@@ -1050,7 +1079,7 @@ exception_trap:
if( (ci && type(ci->_closure) != OT_CLOSURE) || exitafterthisone) break;
} while(_callsstacksize);
- while(last_top >= _top) _stack._vals[last_top--].Null();
+ CLEARSTACK(last_top);
}
_lasterror = currerror;
return false;
@@ -1062,8 +1091,6 @@ bool SQVM::CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr
{
inst = theclass->CreateInstance();
if(!theclass->Get(_ss(this)->_constructoridx,constructor)) {
- //if(!Call(constr,nargs,stackbase,constr,false))
- // return false;
constructor = _null_;
}
return true;