Back to home page

Enduro/X

 
 

    


0001 /*

0002     see copyright notice in pscript.h

0003 */
0004 #include "pspcheader.h"
0005 #include "psvm.h"
0006 #include "psstring.h"
0007 #include "psarray.h"
0008 #include "pstable.h"
0009 #include "psuserdata.h"
0010 #include "psfuncproto.h"
0011 #include "psclass.h"
0012 #include "psclosure.h"
0013 
0014 
0015 const PSChar *IdType2Name(PSObjectType type)
0016 {
0017     switch(_RAW_TYPE(type))
0018     {
0019     case _RT_NULL:return _SC("null");
0020     case _RT_INTEGER:return _SC("integer");
0021     case _RT_FLOAT:return _SC("float");
0022     case _RT_BOOL:return _SC("bool");
0023     case _RT_STRING:return _SC("string");
0024     case _RT_TABLE:return _SC("table");
0025     case _RT_ARRAY:return _SC("array");
0026     case _RT_GENERATOR:return _SC("generator");
0027     case _RT_CLOSURE:
0028     case _RT_NATIVECLOSURE:
0029         return _SC("function");
0030     case _RT_USERDATA:
0031     case _RT_USERPOINTER:
0032         return _SC("userdata");
0033     case _RT_THREAD: return _SC("thread");
0034     case _RT_FUNCPROTO: return _SC("function");
0035     case _RT_CLASS: return _SC("class");
0036     case _RT_INSTANCE: return _SC("instance");
0037     case _RT_WEAKREF: return _SC("weakref");
0038     case _RT_OUTER: return _SC("outer");
0039     default:
0040         return NULL;
0041     }
0042 }
0043 
0044 const PSChar *GetTypeName(const PSObjectPtr &obj1)
0045 {
0046     return IdType2Name(type(obj1));
0047 }
0048 
0049 PSString *PSString::Create(PSSharedState *ss,const PSChar *s,PSInteger len)
0050 {
0051     PSString *str=ADD_STRING(ss,s,len);
0052     return str;
0053 }
0054 
0055 void PSString::Release()
0056 {
0057     REMOVE_STRING(_sharedstate,this);
0058 }
0059 
0060 PSInteger PSString::Next(const PSObjectPtr &refpos, PSObjectPtr &outkey, PSObjectPtr &outval)
0061 {
0062     PSInteger idx = (PSInteger)TranslateIndex(refpos);
0063     while(idx < _len){
0064         outkey = (PSInteger)idx;
0065         outval = (PSInteger)((PSUnsignedInteger)_val[idx]);
0066         //return idx for the next iteration

0067         return ++idx;
0068     }
0069     //nothing to iterate anymore

0070     return -1;
0071 }
0072 
0073 PSUnsignedInteger TranslateIndex(const PSObjectPtr &idx)
0074 {
0075     switch(type(idx)){
0076         case OT_NULL:
0077             return 0;
0078         case OT_INTEGER:
0079             return (PSUnsignedInteger)_integer(idx);
0080         default: assert(0); break;
0081     }
0082     return 0;
0083 }
0084 
0085 PSWeakRef *PSRefCounted::GetWeakRef(PSObjectType type)
0086 {
0087     if(!_weakref) {
0088         ps_new(_weakref,PSWeakRef);
0089 #if defined(PSUSEDOUBLE) && !defined(_PS64)
0090         _weakref->_obj._unVal.raw = 0; //clean the whole union on 32 bits with double

0091 #endif
0092         _weakref->_obj._type = type;
0093         _weakref->_obj._unVal.pRefCounted = this;
0094     }
0095     return _weakref;
0096 }
0097 
0098 PSRefCounted::~PSRefCounted()
0099 {
0100     if(_weakref) {
0101         _weakref->_obj._type = OT_NULL;
0102         _weakref->_obj._unVal.pRefCounted = NULL;
0103     }
0104 }
0105 
0106 void PSWeakRef::Release() {
0107     if(ISREFCOUNTED(_obj._type)) {
0108         _obj._unVal.pRefCounted->_weakref = NULL;
0109     }
0110     ps_delete(this,PSWeakRef);
0111 }
0112 
0113 bool PSDelegable::GetMetaMethod(PSVM *v,PSMetaMethod mm,PSObjectPtr &res) {
0114     if(_delegate) {
0115         return _delegate->Get((*_ss(v)->_metamethods)[mm],res);
0116     }
0117     return false;
0118 }
0119 
0120 bool PSDelegable::SetDelegate(PSTable *mt)
0121 {
0122     PSTable *temp = mt;
0123     if(temp == this) return false;
0124     while (temp) {
0125         if (temp->_delegate == this) return false; //cycle detected

0126         temp = temp->_delegate;
0127     }
0128     if (mt) __ObjAddRef(mt);
0129     __ObjRelease(_delegate);
0130     _delegate = mt;
0131     return true;
0132 }
0133 
0134 bool PSGenerator::Yield(PSVM *v,PSInteger target)
0135 {
0136     if(_state==eSuspended) { v->Raise_Error(_SC("internal vm error, yielding dead generator"));  return false;}
0137     if(_state==eDead) { v->Raise_Error(_SC("internal vm error, yielding a dead generator")); return false; }
0138     PSInteger size = v->_top-v->_stackbase;
0139 
0140     _stack.resize(size);
0141     PSObject _this = v->_stack[v->_stackbase];
0142     _stack._vals[0] = ISREFCOUNTED(type(_this)) ? PSObjectPtr(_refcounted(_this)->GetWeakRef(type(_this))) : _this;
0143     for(PSInteger n =1; n<target; n++) {
0144         _stack._vals[n] = v->_stack[v->_stackbase+n];
0145     }
0146     for(PSInteger j =0; j < size; j++)
0147     {
0148         v->_stack[v->_stackbase+j].Null();
0149     }
0150 
0151     _ci = *v->ci;
0152     _ci._generator=NULL;
0153     for(PSInteger i=0;i<_ci._etraps;i++) {
0154         _etraps.push_back(v->_etraps.top());
0155         v->_etraps.pop_back();
0156         // store relative stack base and size in case of resume to other _top

0157         PSExceptionTrap &et = _etraps.back();
0158         et._stackbase -= v->_stackbase;
0159         et._stacksize -= v->_stackbase;
0160     }
0161     _state=eSuspended;
0162     return true;
0163 }
0164 
0165 bool PSGenerator::Resume(PSVM *v,PSObjectPtr &dest)
0166 {
0167     if(_state==eDead){ v->Raise_Error(_SC("resuming dead generator")); return false; }
0168     if(_state==eRunning){ v->Raise_Error(_SC("resuming active generator")); return false; }
0169     PSInteger size = _stack.size();
0170     PSInteger target = &dest - &(v->_stack._vals[v->_stackbase]);
0171     assert(target>=0 && target<=255);
0172     PSInteger newbase = v->_top;
0173     if(!v->EnterFrame(v->_top, v->_top + size, false))
0174         return false;
0175     v->ci->_generator   = this;
0176     v->ci->_target      = (PSInt32)target;
0177     v->ci->_closure     = _ci._closure;
0178     v->ci->_ip          = _ci._ip;
0179     v->ci->_literals    = _ci._literals;
0180     v->ci->_ncalls      = _ci._ncalls;
0181     v->ci->_etraps      = _ci._etraps;
0182     v->ci->_root        = _ci._root;
0183 
0184 
0185     for(PSInteger i=0;i<_ci._etraps;i++) {
0186         v->_etraps.push_back(_etraps.top());
0187         _etraps.pop_back();
0188         PSExceptionTrap &et = v->_etraps.back();
0189         // restore absolute stack base and size

0190         et._stackbase += newbase;
0191         et._stacksize += newbase;
0192     }
0193     PSObject _this = _stack._vals[0];
0194     v->_stack[v->_stackbase] = type(_this) == OT_WEAKREF ? _weakref(_this)->_obj : _this;
0195 
0196     for(PSInteger n = 1; n<size; n++) {
0197         v->_stack[v->_stackbase+n] = _stack._vals[n];
0198         _stack._vals[n].Null();
0199     }
0200 
0201     _state=eRunning;
0202     if (v->_debughook)
0203         v->CallDebugHook(_SC('c'));
0204 
0205     return true;
0206 }
0207 
0208 void PSArray::Extend(const PSArray *a){
0209     PSInteger xlen;
0210     if((xlen=a->Size()))
0211         for(PSInteger i=0;i<xlen;i++)
0212             Append(a->_values[i]);
0213 }
0214 
0215 const PSChar* PSFunctionProto::GetLocal(PSVM *vm,PSUnsignedInteger stackbase,PSUnsignedInteger nseq,PSUnsignedInteger nop)
0216 {
0217     PSUnsignedInteger nvars=_nlocalvarinfos;
0218     const PSChar *res=NULL;
0219     if(nvars>=nseq){
0220         for(PSUnsignedInteger i=0;i<nvars;i++){
0221             if(_localvarinfos[i]._start_op<=nop && _localvarinfos[i]._end_op>=nop)
0222             {
0223                 if(nseq==0){
0224                     vm->Push(vm->_stack[stackbase+_localvarinfos[i]._pos]);
0225                     res=_stringval(_localvarinfos[i]._name);
0226                     break;
0227                 }
0228                 nseq--;
0229             }
0230         }
0231     }
0232     return res;
0233 }
0234 
0235 
0236 PSInteger PSFunctionProto::GetLine(PSInstruction *curr)
0237 {
0238     PSInteger op = (PSInteger)(curr-_instructions);
0239     PSInteger line=_lineinfos[0]._line;
0240     PSInteger low = 0;
0241     PSInteger high = _nlineinfos - 1;
0242     PSInteger mid = 0;
0243     while(low <= high)
0244     {
0245         mid = low + ((high - low) >> 1);
0246         PSInteger curop = _lineinfos[mid]._op;
0247         if(curop > op)
0248         {
0249             high = mid - 1;
0250         }
0251         else if(curop < op) {
0252             if(mid < (_nlineinfos - 1)
0253                 && _lineinfos[mid + 1]._op >= op) {
0254                 break;
0255             }
0256             low = mid + 1;
0257         }
0258         else { //equal

0259             break;
0260         }
0261     }
0262 
0263     while(mid > 0 && _lineinfos[mid]._op >= op) mid--;
0264 
0265     line = _lineinfos[mid]._line;
0266 
0267     return line;
0268 }
0269 
0270 PSClosure::~PSClosure()
0271 {
0272     __ObjRelease(_root);
0273     __ObjRelease(_env);
0274     __ObjRelease(_base);
0275     REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
0276 }
0277 
0278 #define _CHECK_IO(exp)  { if(!exp)return false; }
0279 bool SafeWrite(HPSCRIPTVM v,PSWRITEFUNC write,PSUserPointer up,PSUserPointer dest,PSInteger size)
0280 {
0281     if(write(up,dest,size) != size) {
0282         v->Raise_Error(_SC("io error (write function failure)"));
0283         return false;
0284     }
0285     return true;
0286 }
0287 
0288 bool SafeRead(HPSCRIPTVM v,PSWRITEFUNC read,PSUserPointer up,PSUserPointer dest,PSInteger size)
0289 {
0290     if(size && read(up,dest,size) != size) {
0291         v->Raise_Error(_SC("io error, read function failure, the origin stream could be corrupted/trucated"));
0292         return false;
0293     }
0294     return true;
0295 }
0296 
0297 bool WriteTag(HPSCRIPTVM v,PSWRITEFUNC write,PSUserPointer up,PSUnsignedInteger32 tag)
0298 {
0299     return SafeWrite(v,write,up,&tag,sizeof(tag));
0300 }
0301 
0302 bool CheckTag(HPSCRIPTVM v,PSWRITEFUNC read,PSUserPointer up,PSUnsignedInteger32 tag)
0303 {
0304     PSUnsignedInteger32 t;
0305     _CHECK_IO(SafeRead(v,read,up,&t,sizeof(t)));
0306     if(t != tag){
0307         v->Raise_Error(_SC("invalid or corrupted closure stream"));
0308         return false;
0309     }
0310     return true;
0311 }
0312 
0313 bool WriteObject(HPSCRIPTVM v,PSUserPointer up,PSWRITEFUNC write,PSObjectPtr &o)
0314 {
0315     PSUnsignedInteger32 _type = (PSUnsignedInteger32)type(o);
0316     _CHECK_IO(SafeWrite(v,write,up,&_type,sizeof(_type)));
0317     switch(type(o)){
0318     case OT_STRING:
0319         _CHECK_IO(SafeWrite(v,write,up,&_string(o)->_len,sizeof(PSInteger)));
0320         _CHECK_IO(SafeWrite(v,write,up,_stringval(o),ps_rsl(_string(o)->_len)));
0321         break;
0322     case OT_BOOL:
0323     case OT_INTEGER:
0324         _CHECK_IO(SafeWrite(v,write,up,&_integer(o),sizeof(PSInteger)));break;
0325     case OT_FLOAT:
0326         _CHECK_IO(SafeWrite(v,write,up,&_float(o),sizeof(PSFloat)));break;
0327     case OT_NULL:
0328         break;
0329     default:
0330         v->Raise_Error(_SC("cannot serialize a %s"),GetTypeName(o));
0331         return false;
0332     }
0333     return true;
0334 }
0335 
0336 bool ReadObject(HPSCRIPTVM v,PSUserPointer up,PSREADFUNC read,PSObjectPtr &o)
0337 {
0338     PSUnsignedInteger32 _type;
0339     _CHECK_IO(SafeRead(v,read,up,&_type,sizeof(_type)));
0340     PSObjectType t = (PSObjectType)_type;
0341     switch(t){
0342     case OT_STRING:{
0343         PSInteger len;
0344         _CHECK_IO(SafeRead(v,read,up,&len,sizeof(PSInteger)));
0345         _CHECK_IO(SafeRead(v,read,up,_ss(v)->GetScratchPad(ps_rsl(len)),ps_rsl(len)));
0346         o=PSString::Create(_ss(v),_ss(v)->GetScratchPad(-1),len);
0347                    }
0348         break;
0349     case OT_INTEGER:{
0350         PSInteger i;
0351         _CHECK_IO(SafeRead(v,read,up,&i,sizeof(PSInteger))); o = i; break;
0352                     }
0353     case OT_BOOL:{
0354         PSInteger i;
0355         _CHECK_IO(SafeRead(v,read,up,&i,sizeof(PSInteger))); o._type = OT_BOOL; o._unVal.nInteger = i; break;
0356                     }
0357     case OT_FLOAT:{
0358         PSFloat f;
0359         _CHECK_IO(SafeRead(v,read,up,&f,sizeof(PSFloat))); o = f; break;
0360                   }
0361     case OT_NULL:
0362         o.Null();
0363         break;
0364     default:
0365         v->Raise_Error(_SC("cannot serialize a %s"),IdType2Name(t));
0366         return false;
0367     }
0368     return true;
0369 }
0370 
0371 bool PSClosure::Save(PSVM *v,PSUserPointer up,PSWRITEFUNC write)
0372 {
0373     _CHECK_IO(WriteTag(v,write,up,PS_CLOSURESTREAM_HEAD));
0374     _CHECK_IO(WriteTag(v,write,up,sizeof(PSChar)));
0375     _CHECK_IO(WriteTag(v,write,up,sizeof(PSInteger)));
0376     _CHECK_IO(WriteTag(v,write,up,sizeof(PSFloat)));
0377     _CHECK_IO(_function->Save(v,up,write));
0378     _CHECK_IO(WriteTag(v,write,up,PS_CLOSURESTREAM_TAIL));
0379     return true;
0380 }
0381 
0382 bool PSClosure::Load(PSVM *v,PSUserPointer up,PSREADFUNC read,PSObjectPtr &ret)
0383 {
0384     _CHECK_IO(CheckTag(v,read,up,PS_CLOSURESTREAM_HEAD));
0385     _CHECK_IO(CheckTag(v,read,up,sizeof(PSChar)));
0386     _CHECK_IO(CheckTag(v,read,up,sizeof(PSInteger)));
0387     _CHECK_IO(CheckTag(v,read,up,sizeof(PSFloat)));
0388     PSObjectPtr func;
0389     _CHECK_IO(PSFunctionProto::Load(v,up,read,func));
0390     _CHECK_IO(CheckTag(v,read,up,PS_CLOSURESTREAM_TAIL));
0391     ret = PSClosure::Create(_ss(v),_funcproto(func),_table(v->_roottable)->GetWeakRef(OT_TABLE));
0392     //FIXME: load an root for this closure

0393     return true;
0394 }
0395 
0396 PSFunctionProto::PSFunctionProto(PSSharedState *ss)
0397 {
0398     _stacksize=0;
0399     _bgenerator=false;
0400     INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);
0401 }
0402 
0403 PSFunctionProto::~PSFunctionProto()
0404 {
0405     REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
0406 }
0407 
0408 bool PSFunctionProto::Save(PSVM *v,PSUserPointer up,PSWRITEFUNC write)
0409 {
0410     PSInteger i,nliterals = _nliterals,nparameters = _nparameters;
0411     PSInteger noutervalues = _noutervalues,nlocalvarinfos = _nlocalvarinfos;
0412     PSInteger nlineinfos=_nlineinfos,ninstructions = _ninstructions,nfunctions=_nfunctions;
0413     PSInteger ndefaultparams = _ndefaultparams;
0414     _CHECK_IO(WriteTag(v,write,up,PS_CLOSURESTREAM_PART));
0415     _CHECK_IO(WriteObject(v,up,write,_sourcename));
0416     _CHECK_IO(WriteObject(v,up,write,_name));
0417     _CHECK_IO(WriteTag(v,write,up,PS_CLOSURESTREAM_PART));
0418     _CHECK_IO(SafeWrite(v,write,up,&nliterals,sizeof(nliterals)));
0419     _CHECK_IO(SafeWrite(v,write,up,&nparameters,sizeof(nparameters)));
0420     _CHECK_IO(SafeWrite(v,write,up,&noutervalues,sizeof(noutervalues)));
0421     _CHECK_IO(SafeWrite(v,write,up,&nlocalvarinfos,sizeof(nlocalvarinfos)));
0422     _CHECK_IO(SafeWrite(v,write,up,&nlineinfos,sizeof(nlineinfos)));
0423     _CHECK_IO(SafeWrite(v,write,up,&ndefaultparams,sizeof(ndefaultparams)));
0424     _CHECK_IO(SafeWrite(v,write,up,&ninstructions,sizeof(ninstructions)));
0425     _CHECK_IO(SafeWrite(v,write,up,&nfunctions,sizeof(nfunctions)));
0426     _CHECK_IO(WriteTag(v,write,up,PS_CLOSURESTREAM_PART));
0427     for(i=0;i<nliterals;i++){
0428         _CHECK_IO(WriteObject(v,up,write,_literals[i]));
0429     }
0430 
0431     _CHECK_IO(WriteTag(v,write,up,PS_CLOSURESTREAM_PART));
0432     for(i=0;i<nparameters;i++){
0433         _CHECK_IO(WriteObject(v,up,write,_parameters[i]));
0434     }
0435 
0436     _CHECK_IO(WriteTag(v,write,up,PS_CLOSURESTREAM_PART));
0437     for(i=0;i<noutervalues;i++){
0438         _CHECK_IO(SafeWrite(v,write,up,&_outervalues[i]._type,sizeof(PSUnsignedInteger)));
0439         _CHECK_IO(WriteObject(v,up,write,_outervalues[i]._src));
0440         _CHECK_IO(WriteObject(v,up,write,_outervalues[i]._name));
0441     }
0442 
0443     _CHECK_IO(WriteTag(v,write,up,PS_CLOSURESTREAM_PART));
0444     for(i=0;i<nlocalvarinfos;i++){
0445         PSLocalVarInfo &lvi=_localvarinfos[i];
0446         _CHECK_IO(WriteObject(v,up,write,lvi._name));
0447         _CHECK_IO(SafeWrite(v,write,up,&lvi._pos,sizeof(PSUnsignedInteger)));
0448         _CHECK_IO(SafeWrite(v,write,up,&lvi._start_op,sizeof(PSUnsignedInteger)));
0449         _CHECK_IO(SafeWrite(v,write,up,&lvi._end_op,sizeof(PSUnsignedInteger)));
0450     }
0451 
0452     _CHECK_IO(WriteTag(v,write,up,PS_CLOSURESTREAM_PART));
0453     _CHECK_IO(SafeWrite(v,write,up,_lineinfos,sizeof(PSLineInfo)*nlineinfos));
0454 
0455     _CHECK_IO(WriteTag(v,write,up,PS_CLOSURESTREAM_PART));
0456     _CHECK_IO(SafeWrite(v,write,up,_defaultparams,sizeof(PSInteger)*ndefaultparams));
0457 
0458     _CHECK_IO(WriteTag(v,write,up,PS_CLOSURESTREAM_PART));
0459     _CHECK_IO(SafeWrite(v,write,up,_instructions,sizeof(PSInstruction)*ninstructions));
0460 
0461     _CHECK_IO(WriteTag(v,write,up,PS_CLOSURESTREAM_PART));
0462     for(i=0;i<nfunctions;i++){
0463         _CHECK_IO(_funcproto(_functions[i])->Save(v,up,write));
0464     }
0465     _CHECK_IO(SafeWrite(v,write,up,&_stacksize,sizeof(_stacksize)));
0466     _CHECK_IO(SafeWrite(v,write,up,&_bgenerator,sizeof(_bgenerator)));
0467     _CHECK_IO(SafeWrite(v,write,up,&_varparams,sizeof(_varparams)));
0468     return true;
0469 }
0470 
0471 bool PSFunctionProto::Load(PSVM *v,PSUserPointer up,PSREADFUNC read,PSObjectPtr &ret)
0472 {
0473     PSInteger i, nliterals,nparameters;
0474     PSInteger noutervalues ,nlocalvarinfos ;
0475     PSInteger nlineinfos,ninstructions ,nfunctions,ndefaultparams ;
0476     PSObjectPtr sourcename, name;
0477     PSObjectPtr o;
0478     _CHECK_IO(CheckTag(v,read,up,PS_CLOSURESTREAM_PART));
0479     _CHECK_IO(ReadObject(v, up, read, sourcename));
0480     _CHECK_IO(ReadObject(v, up, read, name));
0481 
0482     _CHECK_IO(CheckTag(v,read,up,PS_CLOSURESTREAM_PART));
0483     _CHECK_IO(SafeRead(v,read,up, &nliterals, sizeof(nliterals)));
0484     _CHECK_IO(SafeRead(v,read,up, &nparameters, sizeof(nparameters)));
0485     _CHECK_IO(SafeRead(v,read,up, &noutervalues, sizeof(noutervalues)));
0486     _CHECK_IO(SafeRead(v,read,up, &nlocalvarinfos, sizeof(nlocalvarinfos)));
0487     _CHECK_IO(SafeRead(v,read,up, &nlineinfos, sizeof(nlineinfos)));
0488     _CHECK_IO(SafeRead(v,read,up, &ndefaultparams, sizeof(ndefaultparams)));
0489     _CHECK_IO(SafeRead(v,read,up, &ninstructions, sizeof(ninstructions)));
0490     _CHECK_IO(SafeRead(v,read,up, &nfunctions, sizeof(nfunctions)));
0491 
0492 
0493     PSFunctionProto *f = PSFunctionProto::Create(_opt_ss(v),ninstructions,nliterals,nparameters,
0494             nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams);
0495     PSObjectPtr proto = f; //gets a ref in case of failure

0496     f->_sourcename = sourcename;
0497     f->_name = name;
0498 
0499     _CHECK_IO(CheckTag(v,read,up,PS_CLOSURESTREAM_PART));
0500 
0501     for(i = 0;i < nliterals; i++){
0502         _CHECK_IO(ReadObject(v, up, read, o));
0503         f->_literals[i] = o;
0504     }
0505     _CHECK_IO(CheckTag(v,read,up,PS_CLOSURESTREAM_PART));
0506 
0507     for(i = 0; i < nparameters; i++){
0508         _CHECK_IO(ReadObject(v, up, read, o));
0509         f->_parameters[i] = o;
0510     }
0511     _CHECK_IO(CheckTag(v,read,up,PS_CLOSURESTREAM_PART));
0512 
0513     for(i = 0; i < noutervalues; i++){
0514         PSUnsignedInteger type;
0515         PSObjectPtr name;
0516         _CHECK_IO(SafeRead(v,read,up, &type, sizeof(PSUnsignedInteger)));
0517         _CHECK_IO(ReadObject(v, up, read, o));
0518         _CHECK_IO(ReadObject(v, up, read, name));
0519         f->_outervalues[i] = PSOuterVar(name,o, (PSOuterType)type);
0520     }
0521     _CHECK_IO(CheckTag(v,read,up,PS_CLOSURESTREAM_PART));
0522 
0523     for(i = 0; i < nlocalvarinfos; i++){
0524         PSLocalVarInfo lvi;
0525         _CHECK_IO(ReadObject(v, up, read, lvi._name));
0526         _CHECK_IO(SafeRead(v,read,up, &lvi._pos, sizeof(PSUnsignedInteger)));
0527         _CHECK_IO(SafeRead(v,read,up, &lvi._start_op, sizeof(PSUnsignedInteger)));
0528         _CHECK_IO(SafeRead(v,read,up, &lvi._end_op, sizeof(PSUnsignedInteger)));
0529         f->_localvarinfos[i] = lvi;
0530     }
0531     _CHECK_IO(CheckTag(v,read,up,PS_CLOSURESTREAM_PART));
0532     _CHECK_IO(SafeRead(v,read,up, f->_lineinfos, sizeof(PSLineInfo)*nlineinfos));
0533 
0534     _CHECK_IO(CheckTag(v,read,up,PS_CLOSURESTREAM_PART));
0535     _CHECK_IO(SafeRead(v,read,up, f->_defaultparams, sizeof(PSInteger)*ndefaultparams));
0536 
0537     _CHECK_IO(CheckTag(v,read,up,PS_CLOSURESTREAM_PART));
0538     _CHECK_IO(SafeRead(v,read,up, f->_instructions, sizeof(PSInstruction)*ninstructions));
0539 
0540     _CHECK_IO(CheckTag(v,read,up,PS_CLOSURESTREAM_PART));
0541     for(i = 0; i < nfunctions; i++){
0542         _CHECK_IO(_funcproto(o)->Load(v, up, read, o));
0543         f->_functions[i] = o;
0544     }
0545     _CHECK_IO(SafeRead(v,read,up, &f->_stacksize, sizeof(f->_stacksize)));
0546     _CHECK_IO(SafeRead(v,read,up, &f->_bgenerator, sizeof(f->_bgenerator)));
0547     _CHECK_IO(SafeRead(v,read,up, &f->_varparams, sizeof(f->_varparams)));
0548 
0549     ret = f;
0550     return true;
0551 }
0552 
0553 #ifndef NO_GARBAGE_COLLECTOR
0554 
0555 #define START_MARK()    if(!(_uiRef&MARK_FLAG)){ \
0556         _uiRef|=MARK_FLAG;
0557 
0558 #define END_MARK() RemoveFromChain(&_sharedstate->_gc_chain, this); \
0559         AddToChain(chain, this); }
0560 
0561 void PSVM::Mark(PSCollectable **chain)
0562 {
0563     START_MARK()
0564         PSSharedState::MarkObject(_lasterror,chain);
0565         PSSharedState::MarkObject(_errorhandler,chain);
0566         PSSharedState::MarkObject(_debughook_closure,chain);
0567         PSSharedState::MarkObject(_roottable, chain);
0568         PSSharedState::MarkObject(temp_reg, chain);
0569         for(PSUnsignedInteger i = 0; i < _stack.size(); i++) PSSharedState::MarkObject(_stack[i], chain);
0570         for(PSInteger k = 0; k < _callsstacksize; k++) PSSharedState::MarkObject(_callsstack[k]._closure, chain);
0571     END_MARK()
0572 }
0573 
0574 void PSArray::Mark(PSCollectable **chain)
0575 {
0576     START_MARK()
0577         PSInteger len = _values.size();
0578         for(PSInteger i = 0;i < len; i++) PSSharedState::MarkObject(_values[i], chain);
0579     END_MARK()
0580 }
0581 void PSTable::Mark(PSCollectable **chain)
0582 {
0583     START_MARK()
0584         if(_delegate) _delegate->Mark(chain);
0585         PSInteger len = _numofnodes;
0586         for(PSInteger i = 0; i < len; i++){
0587             PSSharedState::MarkObject(_nodes[i].key, chain);
0588             PSSharedState::MarkObject(_nodes[i].val, chain);
0589         }
0590     END_MARK()
0591 }
0592 
0593 void PSClass::Mark(PSCollectable **chain)
0594 {
0595     START_MARK()
0596         _members->Mark(chain);
0597         if(_base) _base->Mark(chain);
0598         PSSharedState::MarkObject(_attributes, chain);
0599         for(PSUnsignedInteger i =0; i< _defaultvalues.size(); i++) {
0600             PSSharedState::MarkObject(_defaultvalues[i].val, chain);
0601             PSSharedState::MarkObject(_defaultvalues[i].attrs, chain);
0602         }
0603         for(PSUnsignedInteger j =0; j< _methods.size(); j++) {
0604             PSSharedState::MarkObject(_methods[j].val, chain);
0605             PSSharedState::MarkObject(_methods[j].attrs, chain);
0606         }
0607         for(PSUnsignedInteger k =0; k< MT_LAST; k++) {
0608             PSSharedState::MarkObject(_metamethods[k], chain);
0609         }
0610     END_MARK()
0611 }
0612 
0613 void PSInstance::Mark(PSCollectable **chain)
0614 {
0615     START_MARK()
0616         _class->Mark(chain);
0617         PSUnsignedInteger nvalues = _class->_defaultvalues.size();
0618         for(PSUnsignedInteger i =0; i< nvalues; i++) {
0619             PSSharedState::MarkObject(_values[i], chain);
0620         }
0621     END_MARK()
0622 }
0623 
0624 void PSGenerator::Mark(PSCollectable **chain)
0625 {
0626     START_MARK()
0627         for(PSUnsignedInteger i = 0; i < _stack.size(); i++) PSSharedState::MarkObject(_stack[i], chain);
0628         PSSharedState::MarkObject(_closure, chain);
0629     END_MARK()
0630 }
0631 
0632 void PSFunctionProto::Mark(PSCollectable **chain)
0633 {
0634     START_MARK()
0635         for(PSInteger i = 0; i < _nliterals; i++) PSSharedState::MarkObject(_literals[i], chain);
0636         for(PSInteger k = 0; k < _nfunctions; k++) PSSharedState::MarkObject(_functions[k], chain);
0637     END_MARK()
0638 }
0639 
0640 void PSClosure::Mark(PSCollectable **chain)
0641 {
0642     START_MARK()
0643         if(_base) _base->Mark(chain);
0644         PSFunctionProto *fp = _function;
0645         fp->Mark(chain);
0646         for(PSInteger i = 0; i < fp->_noutervalues; i++) PSSharedState::MarkObject(_outervalues[i], chain);
0647         for(PSInteger k = 0; k < fp->_ndefaultparams; k++) PSSharedState::MarkObject(_defaultparams[k], chain);
0648     END_MARK()
0649 }
0650 
0651 void PSNativeClosure::Mark(PSCollectable **chain)
0652 {
0653     START_MARK()
0654         for(PSUnsignedInteger i = 0; i < _noutervalues; i++) PSSharedState::MarkObject(_outervalues[i], chain);
0655     END_MARK()
0656 }
0657 
0658 void PSOuter::Mark(PSCollectable **chain)
0659 {
0660     START_MARK()
0661     /* If the valptr points to a closed value, that value is alive */
0662     if(_valptr == &_value) {
0663       PSSharedState::MarkObject(_value, chain);
0664     }
0665     END_MARK()
0666 }
0667 
0668 void PSUserData::Mark(PSCollectable **chain){
0669     START_MARK()
0670         if(_delegate) _delegate->Mark(chain);
0671     END_MARK()
0672 }
0673 
0674 void PSCollectable::UnMark() { _uiRef&=~MARK_FLAG; }
0675 
0676 #endif
0677