diff options
Diffstat (limited to 'src/3rdparty/squirrel/squirrel/sqvm.cpp')
-rw-r--r-- | src/3rdparty/squirrel/squirrel/sqvm.cpp | 49 |
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; |