case _RT_CLASS: return _SC("class");\r
case _RT_INSTANCE: return _SC("instance");\r
case _RT_WEAKREF: return _SC("weakref");\r
+ case _RT_OUTER: return _SC("outer");\r
default:\r
return NULL;\r
}\r
SQString *SQString::Create(SQSharedState *ss,const SQChar *s,SQInteger len)\r
{\r
SQString *str=ADD_STRING(ss,s,len);\r
- str->_sharedstate=ss;\r
return str;\r
}\r
\r
SQInteger idx = (SQInteger)TranslateIndex(refpos);\r
while(idx < _len){\r
outkey = (SQInteger)idx;\r
- outval = SQInteger(_val[idx]);\r
+ outval = (SQInteger)((SQUnsignedInteger)_val[idx]);\r
//return idx for the next iteration\r
return ++idx;\r
}\r
return true;\r
}\r
\r
-bool SQGenerator::Yield(SQVM *v)\r
+bool SQGenerator::Yield(SQVM *v,SQInteger target)\r
{\r
if(_state==eSuspended) { v->Raise_Error(_SC("internal vm error, yielding dead generator")); return false;}\r
if(_state==eDead) { v->Raise_Error(_SC("internal vm error, yielding a dead generator")); return false; }\r
SQInteger size = v->_top-v->_stackbase;\r
- _ci=*v->ci;\r
+ \r
_stack.resize(size);\r
- for(SQInteger n =0; n<size; n++) {\r
+ SQObject _this = v->_stack[v->_stackbase];\r
+ _stack._vals[0] = ISREFCOUNTED(type(_this)) ? SQObjectPtr(_refcounted(_this)->GetWeakRef(type(_this))) : _this;\r
+ for(SQInteger n =1; n<target; n++) {\r
_stack._vals[n] = v->_stack[v->_stackbase+n];\r
- v->_stack[v->_stackbase+n] = _null_;\r
}\r
- SQInteger nvargs = v->ci->_vargs.size;\r
- SQInteger vargsbase = v->ci->_vargs.base;\r
- for(SQInteger j = nvargs - 1; j >= 0; j--) {\r
- _vargsstack.push_back(v->_vargsstack[vargsbase+j]);\r
+ for(SQInteger j =0; j < size; j++)\r
+ {\r
+ v->_stack[v->_stackbase+j].Null();\r
}\r
+\r
+ _ci = *v->ci;\r
_ci._generator=NULL;\r
for(SQInteger i=0;i<_ci._etraps;i++) {\r
_etraps.push_back(v->_etraps.top());\r
return true;\r
}\r
\r
-bool SQGenerator::Resume(SQVM *v,SQInteger target)\r
+bool SQGenerator::Resume(SQVM *v,SQObjectPtr &dest)\r
{\r
- SQInteger size=_stack.size();\r
if(_state==eDead){ v->Raise_Error(_SC("resuming dead generator")); return false; }\r
if(_state==eRunning){ v->Raise_Error(_SC("resuming active generator")); return false; }\r
- SQInteger prevtop=v->_top-v->_stackbase;\r
- PUSH_CALLINFO(v,_ci);\r
- SQInteger oldstackbase=v->_stackbase;\r
- v->_stackbase = v->_top;\r
- v->ci->_target = (SQInt32)target;\r
- v->ci->_generator = this;\r
- v->ci->_vargs.size = (unsigned short)_vargsstack.size();\r
- \r
+ SQInteger size = _stack.size();\r
+ SQInteger target = &dest - &(v->_stack._vals[v->_stackbase]);\r
+ assert(target>=0 && target<=255);\r
+ if(!v->EnterFrame(v->_top, v->_top + size, false)) \r
+ return false;\r
+ v->ci->_generator = this;\r
+ v->ci->_target = (SQInt32)target;\r
+ v->ci->_closure = _ci._closure;\r
+ v->ci->_ip = _ci._ip;\r
+ v->ci->_literals = _ci._literals;\r
+ v->ci->_ncalls = _ci._ncalls;\r
+ v->ci->_etraps = _ci._etraps;\r
+ v->ci->_root = _ci._root;\r
+\r
+\r
for(SQInteger i=0;i<_ci._etraps;i++) {\r
v->_etraps.push_back(_etraps.top());\r
_etraps.pop_back();\r
}\r
- for(SQInteger n =0; n<size; n++) {\r
+ SQObject _this = _stack._vals[0];\r
+ v->_stack[v->_stackbase] = type(_this) == OT_WEAKREF ? _weakref(_this)->_obj : _this;\r
+\r
+ for(SQInteger n = 1; n<size; n++) {\r
v->_stack[v->_stackbase+n] = _stack._vals[n];\r
- _stack._vals[0] = _null_;\r
+ _stack._vals[n].Null();\r
}\r
- while(_vargsstack.size()) {\r
- v->_vargsstack.push_back(_vargsstack.back());\r
- _vargsstack.pop_back();\r
- }\r
- v->ci->_vargs.base = (unsigned short)(v->_vargsstack.size() - v->ci->_vargs.size);\r
- v->_top=v->_stackbase+size;\r
- v->ci->_prevtop = (SQInt32)prevtop;\r
- v->ci->_prevstkbase = (SQInt32)(v->_stackbase - oldstackbase);\r
+\r
_state=eRunning;\r
- if (type(v->_debughook) != OT_NULL && _rawval(v->_debughook) != _rawval(v->ci->_closure))\r
+ if (v->_debughook)\r
v->CallDebugHook(_SC('c'));\r
\r
return true;\r
return res;\r
}\r
\r
+\r
SQInteger SQFunctionProto::GetLine(SQInstruction *curr)\r
{\r
SQInteger op = (SQInteger)(curr-_instructions);\r
SQInteger line=_lineinfos[0]._line;\r
- for(SQInteger i=1;i<_nlineinfos;i++){\r
- if(_lineinfos[i]._op>=op)\r
- return line;\r
- line=_lineinfos[i]._line;\r
+ SQInteger low = 0;\r
+ SQInteger high = _nlineinfos - 1;\r
+ SQInteger mid = 0;\r
+ while(low <= high)\r
+ {\r
+ mid = low + ((high - low) >> 1);\r
+ SQInteger curop = _lineinfos[mid]._op;\r
+ if(curop > op)\r
+ {\r
+ high = mid - 1;\r
+ }\r
+ else if(curop < op) {\r
+ if(mid < (_nlineinfos - 1) \r
+ && _lineinfos[mid + 1]._op >= op) {\r
+ break;\r
+ }\r
+ low = mid + 1;\r
+ }\r
+ else { //equal\r
+ break;\r
+ }\r
}\r
+\r
+ line = _lineinfos[mid]._line;\r
return line;\r
}\r
\r
+SQClosure::~SQClosure()\r
+{\r
+ __ObjRelease(_env);\r
+ __ObjRelease(_base);\r
+ REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);\r
+}\r
+\r
#define _CHECK_IO(exp) { if(!exp)return false; }\r
bool SafeWrite(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUserPointer dest,SQInteger size)\r
{\r
return true;\r
}\r
\r
-bool WriteTag(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQInteger tag)\r
+bool WriteTag(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUnsignedInteger32 tag)\r
{\r
return SafeWrite(v,write,up,&tag,sizeof(tag));\r
}\r
\r
-bool CheckTag(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQInteger tag)\r
+bool CheckTag(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQUnsignedInteger32 tag)\r
{\r
- SQInteger t;\r
+ SQUnsignedInteger32 t;\r
_CHECK_IO(SafeRead(v,read,up,&t,sizeof(t)));\r
if(t != tag){\r
v->Raise_Error(_SC("invalid or corrupted closure stream"));\r
\r
bool WriteObject(HSQUIRRELVM v,SQUserPointer up,SQWRITEFUNC write,SQObjectPtr &o)\r
{\r
- _CHECK_IO(SafeWrite(v,write,up,&type(o),sizeof(SQObjectType)));\r
+ SQUnsignedInteger32 _type = (SQUnsignedInteger32)type(o);\r
+ _CHECK_IO(SafeWrite(v,write,up,&_type,sizeof(_type)));\r
switch(type(o)){\r
case OT_STRING:\r
_CHECK_IO(SafeWrite(v,write,up,&_string(o)->_len,sizeof(SQInteger)));\r
_CHECK_IO(SafeWrite(v,write,up,_stringval(o),rsl(_string(o)->_len)));\r
break;\r
+ case OT_BOOL:\r
case OT_INTEGER:\r
_CHECK_IO(SafeWrite(v,write,up,&_integer(o),sizeof(SQInteger)));break;\r
case OT_FLOAT:\r
\r
bool ReadObject(HSQUIRRELVM v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &o)\r
{\r
- SQObjectType t;\r
- _CHECK_IO(SafeRead(v,read,up,&t,sizeof(SQObjectType)));\r
+ SQUnsignedInteger32 _type;\r
+ _CHECK_IO(SafeRead(v,read,up,&_type,sizeof(_type)));\r
+ SQObjectType t = (SQObjectType)_type;\r
switch(t){\r
case OT_STRING:{\r
SQInteger len;\r
SQInteger i;\r
_CHECK_IO(SafeRead(v,read,up,&i,sizeof(SQInteger))); o = i; break;\r
}\r
+ case OT_BOOL:{\r
+ SQInteger i;\r
+ _CHECK_IO(SafeRead(v,read,up,&i,sizeof(SQInteger))); o._type = OT_BOOL; o._unVal.nInteger = i; break;\r
+ }\r
case OT_FLOAT:{\r
SQFloat f;\r
_CHECK_IO(SafeRead(v,read,up,&f,sizeof(SQFloat))); o = f; break;\r
}\r
case OT_NULL:\r
- o=_null_;\r
+ o.Null();\r
break;\r
default:\r
v->Raise_Error(_SC("cannot serialize a %s"),IdType2Name(t));\r
{\r
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_HEAD));\r
_CHECK_IO(WriteTag(v,write,up,sizeof(SQChar)));\r
- _CHECK_IO(_funcproto(_function)->Save(v,up,write));\r
+ _CHECK_IO(WriteTag(v,write,up,sizeof(SQInteger)));\r
+ _CHECK_IO(WriteTag(v,write,up,sizeof(SQFloat)));\r
+ _CHECK_IO(_function->Save(v,up,write));\r
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_TAIL));\r
return true;\r
}\r
{\r
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_HEAD));\r
_CHECK_IO(CheckTag(v,read,up,sizeof(SQChar)));\r
+ _CHECK_IO(CheckTag(v,read,up,sizeof(SQInteger)));\r
+ _CHECK_IO(CheckTag(v,read,up,sizeof(SQFloat)));\r
SQObjectPtr func;\r
_CHECK_IO(SQFunctionProto::Load(v,up,read,func));\r
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_TAIL));\r
return true;\r
}\r
\r
+SQFunctionProto::SQFunctionProto(SQSharedState *ss)\r
+{\r
+ _stacksize=0;\r
+ _bgenerator=false;\r
+ INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);\r
+}\r
+\r
+SQFunctionProto::~SQFunctionProto()\r
+{\r
+ REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);\r
+}\r
+\r
bool SQFunctionProto::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write)\r
{\r
SQInteger i,nliterals = _nliterals,nparameters = _nparameters;\r
_CHECK_IO(SafeRead(v,read,up, &nfunctions, sizeof(nfunctions)));\r
\r
\r
- SQFunctionProto *f = SQFunctionProto::Create(ninstructions,nliterals,nparameters,\r
+ SQFunctionProto *f = SQFunctionProto::Create(_opt_ss(v),ninstructions,nliterals,nparameters,\r
nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams);\r
SQObjectPtr proto = f; //gets a ref in case of failure\r
f->_sourcename = sourcename;\r
START_MARK()\r
SQSharedState::MarkObject(_lasterror,chain);\r
SQSharedState::MarkObject(_errorhandler,chain);\r
- SQSharedState::MarkObject(_debughook,chain);\r
+ SQSharedState::MarkObject(_debughook_closure,chain);\r
SQSharedState::MarkObject(_roottable, chain);\r
SQSharedState::MarkObject(temp_reg, chain);\r
for(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain);\r
- for(SQUnsignedInteger j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain);\r
for(SQInteger k = 0; k < _callsstacksize; k++) SQSharedState::MarkObject(_callsstack[k]._closure, chain);\r
END_MARK()\r
}\r
SQSharedState::MarkObject(_methods[j].val, chain);\r
SQSharedState::MarkObject(_methods[j].attrs, chain);\r
}\r
- for(SQUnsignedInteger k =0; k< _metamethods.size(); k++) {\r
+ for(SQUnsignedInteger k =0; k< MT_LAST; k++) {\r
SQSharedState::MarkObject(_metamethods[k], chain);\r
}\r
END_MARK()\r
{\r
START_MARK()\r
for(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain);\r
- for(SQUnsignedInteger j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain);\r
SQSharedState::MarkObject(_closure, chain);\r
END_MARK()\r
}\r
\r
+void SQFunctionProto::Mark(SQCollectable **chain)\r
+{\r
+ START_MARK()\r
+ for(SQInteger i = 0; i < _nliterals; i++) SQSharedState::MarkObject(_literals[i], chain);\r
+ for(SQInteger k = 0; k < _nfunctions; k++) SQSharedState::MarkObject(_functions[k], chain);\r
+ END_MARK()\r
+}\r
+\r
void SQClosure::Mark(SQCollectable **chain)\r
{\r
START_MARK()\r
- for(SQUnsignedInteger i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain);\r
- for(SQUnsignedInteger i = 0; i < _defaultparams.size(); i++) SQSharedState::MarkObject(_defaultparams[i], chain);\r
+ if(_base) _base->Mark(chain);\r
+ SQFunctionProto *fp = _function;\r
+ fp->Mark(chain);\r
+ for(SQInteger i = 0; i < fp->_noutervalues; i++) SQSharedState::MarkObject(_outervalues[i], chain);\r
+ for(SQInteger k = 0; k < fp->_ndefaultparams; k++) SQSharedState::MarkObject(_defaultparams[k], chain);\r
END_MARK()\r
}\r
\r
void SQNativeClosure::Mark(SQCollectable **chain)\r
{\r
START_MARK()\r
- for(SQUnsignedInteger i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain);\r
+ for(SQUnsignedInteger i = 0; i < _noutervalues; i++) SQSharedState::MarkObject(_outervalues[i], chain);\r
+ END_MARK()\r
+}\r
+\r
+void SQOuter::Mark(SQCollectable **chain)\r
+{\r
+ START_MARK()\r
+ /* If the valptr points to a closed value, that value is alive */\r
+ if(_valptr == &_value) {\r
+ SQSharedState::MarkObject(_value, chain);\r
+ }\r
END_MARK()\r
}\r
\r