Update SQUIRREL to 2.2.5
[supertux.git] / external / squirrel / squirrel / sqobject.cpp
1 /*\r
2         see copyright notice in squirrel.h\r
3 */\r
4 #include "sqpcheader.h"\r
5 #include "sqvm.h"\r
6 #include "sqstring.h"\r
7 #include "sqarray.h"\r
8 #include "sqtable.h"\r
9 #include "squserdata.h"\r
10 #include "sqfuncproto.h"\r
11 #include "sqclass.h"\r
12 #include "sqclosure.h"\r
13 \r
14 \r
15 const SQChar *IdType2Name(SQObjectType type)\r
16 {\r
17         switch(_RAW_TYPE(type))\r
18         {\r
19         case _RT_NULL:return _SC("null");\r
20         case _RT_INTEGER:return _SC("integer");\r
21         case _RT_FLOAT:return _SC("float");\r
22         case _RT_BOOL:return _SC("bool");\r
23         case _RT_STRING:return _SC("string");\r
24         case _RT_TABLE:return _SC("table");\r
25         case _RT_ARRAY:return _SC("array");\r
26         case _RT_GENERATOR:return _SC("generator");\r
27         case _RT_CLOSURE:\r
28         case _RT_NATIVECLOSURE:\r
29                 return _SC("function");\r
30         case _RT_USERDATA:\r
31         case _RT_USERPOINTER:\r
32                 return _SC("userdata");\r
33         case _RT_THREAD: return _SC("thread");\r
34         case _RT_FUNCPROTO: return _SC("function");\r
35         case _RT_CLASS: return _SC("class");\r
36         case _RT_INSTANCE: return _SC("instance");\r
37         case _RT_WEAKREF: return _SC("weakref");\r
38         default:\r
39                 return NULL;\r
40         }\r
41 }\r
42 \r
43 const SQChar *GetTypeName(const SQObjectPtr &obj1)\r
44 {\r
45         return IdType2Name(type(obj1)); \r
46 }\r
47 \r
48 SQString *SQString::Create(SQSharedState *ss,const SQChar *s,SQInteger len)\r
49 {\r
50         SQString *str=ADD_STRING(ss,s,len);\r
51         str->_sharedstate=ss;\r
52         return str;\r
53 }\r
54 \r
55 void SQString::Release()\r
56 {\r
57         REMOVE_STRING(_sharedstate,this);\r
58 }\r
59 \r
60 SQInteger SQString::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)\r
61 {\r
62         SQInteger idx = (SQInteger)TranslateIndex(refpos);\r
63         while(idx < _len){\r
64                 outkey = (SQInteger)idx;\r
65                 outval = SQInteger(_val[idx]);\r
66                 //return idx for the next iteration\r
67                 return ++idx;\r
68         }\r
69         //nothing to iterate anymore\r
70         return -1;\r
71 }\r
72 \r
73 SQUnsignedInteger TranslateIndex(const SQObjectPtr &idx)\r
74 {\r
75         switch(type(idx)){\r
76                 case OT_NULL:\r
77                         return 0;\r
78                 case OT_INTEGER:\r
79                         return (SQUnsignedInteger)_integer(idx);\r
80                 default: assert(0); break;\r
81         }\r
82         return 0;\r
83 }\r
84 \r
85 SQWeakRef *SQRefCounted::GetWeakRef(SQObjectType type)\r
86 {\r
87         if(!_weakref) {\r
88                 sq_new(_weakref,SQWeakRef);\r
89                 _weakref->_obj._type = type;\r
90                 _weakref->_obj._unVal.pRefCounted = this;\r
91         }\r
92         return _weakref;\r
93 }\r
94 \r
95 SQRefCounted::~SQRefCounted()\r
96 {\r
97         if(_weakref) {\r
98                 _weakref->_obj._type = OT_NULL;\r
99                 _weakref->_obj._unVal.pRefCounted = NULL;\r
100         }\r
101 }\r
102 \r
103 void SQWeakRef::Release() { \r
104         if(ISREFCOUNTED(_obj._type)) { \r
105                 _obj._unVal.pRefCounted->_weakref = NULL;\r
106         } \r
107         sq_delete(this,SQWeakRef);\r
108 }\r
109 \r
110 bool SQDelegable::GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res) {\r
111         if(_delegate) {\r
112                 return _delegate->Get((*_ss(v)->_metamethods)[mm],res);\r
113         }\r
114         return false;\r
115 }\r
116 \r
117 bool SQDelegable::SetDelegate(SQTable *mt)\r
118 {\r
119         SQTable *temp = mt;\r
120         if(temp == this) return false;\r
121         while (temp) {\r
122                 if (temp->_delegate == this) return false; //cycle detected\r
123                 temp = temp->_delegate;\r
124         }\r
125         if (mt) __ObjAddRef(mt);\r
126         __ObjRelease(_delegate);\r
127         _delegate = mt;\r
128         return true;\r
129 }\r
130 \r
131 bool SQGenerator::Yield(SQVM *v)\r
132 {\r
133         if(_state==eSuspended) { v->Raise_Error(_SC("internal vm error, yielding dead generator"));  return false;}\r
134         if(_state==eDead) { v->Raise_Error(_SC("internal vm error, yielding a dead generator")); return false; }\r
135         SQInteger size = v->_top-v->_stackbase;\r
136         _ci=*v->ci;\r
137         _stack.resize(size);\r
138         for(SQInteger n =0; n<size; n++) {\r
139                 _stack._vals[n] = v->_stack[v->_stackbase+n];\r
140                 v->_stack[v->_stackbase+n] = _null_;\r
141         }\r
142         SQInteger nvargs = v->ci->_vargs.size;\r
143         SQInteger vargsbase = v->ci->_vargs.base;\r
144         for(SQInteger j = nvargs - 1; j >= 0; j--) {\r
145                 _vargsstack.push_back(v->_vargsstack[vargsbase+j]);\r
146         }\r
147         _ci._generator=NULL;\r
148         for(SQInteger i=0;i<_ci._etraps;i++) {\r
149                 _etraps.push_back(v->_etraps.top());\r
150                 v->_etraps.pop_back();\r
151         }\r
152         _state=eSuspended;\r
153         return true;\r
154 }\r
155 \r
156 bool SQGenerator::Resume(SQVM *v,SQInteger target)\r
157 {\r
158         SQInteger size=_stack.size();\r
159         if(_state==eDead){ v->Raise_Error(_SC("resuming dead generator")); return false; }\r
160         if(_state==eRunning){ v->Raise_Error(_SC("resuming active generator")); return false; }\r
161         SQInteger prevtop=v->_top-v->_stackbase;\r
162         PUSH_CALLINFO(v,_ci);\r
163         SQInteger oldstackbase=v->_stackbase;\r
164         v->_stackbase = v->_top;\r
165         v->ci->_target = (SQInt32)target;\r
166         v->ci->_generator = this;\r
167         v->ci->_vargs.size = (unsigned short)_vargsstack.size();\r
168         \r
169         for(SQInteger i=0;i<_ci._etraps;i++) {\r
170                 v->_etraps.push_back(_etraps.top());\r
171                 _etraps.pop_back();\r
172         }\r
173         for(SQInteger n =0; n<size; n++) {\r
174                 v->_stack[v->_stackbase+n] = _stack._vals[n];\r
175                 _stack._vals[0] = _null_;\r
176         }\r
177         while(_vargsstack.size()) {\r
178                 v->_vargsstack.push_back(_vargsstack.back());\r
179                 _vargsstack.pop_back();\r
180         }\r
181         v->ci->_vargs.base = (unsigned short)(v->_vargsstack.size() - v->ci->_vargs.size);\r
182         v->_top=v->_stackbase+size;\r
183         v->ci->_prevtop = (SQInt32)prevtop;\r
184         v->ci->_prevstkbase = (SQInt32)(v->_stackbase - oldstackbase);\r
185         _state=eRunning;\r
186         if (type(v->_debughook) != OT_NULL && _rawval(v->_debughook) != _rawval(v->ci->_closure))\r
187                 v->CallDebugHook(_SC('c'));\r
188 \r
189         return true;\r
190 }\r
191 \r
192 void SQArray::Extend(const SQArray *a){\r
193         SQInteger xlen;\r
194         if((xlen=a->Size()))\r
195                 for(SQInteger i=0;i<xlen;i++)\r
196                         Append(a->_values[i]);\r
197 }\r
198 \r
199 const SQChar* SQFunctionProto::GetLocal(SQVM *vm,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop)\r
200 {\r
201         SQUnsignedInteger nvars=_nlocalvarinfos;\r
202         const SQChar *res=NULL; \r
203         if(nvars>=nseq){\r
204                 for(SQUnsignedInteger i=0;i<nvars;i++){\r
205                         if(_localvarinfos[i]._start_op<=nop && _localvarinfos[i]._end_op>=nop)\r
206                         {\r
207                                 if(nseq==0){\r
208                                         vm->Push(vm->_stack[stackbase+_localvarinfos[i]._pos]);\r
209                                         res=_stringval(_localvarinfos[i]._name);\r
210                                         break;\r
211                                 }\r
212                                 nseq--;\r
213                         }\r
214                 }\r
215         }\r
216         return res;\r
217 }\r
218 \r
219 SQInteger SQFunctionProto::GetLine(SQInstruction *curr)\r
220 {\r
221         SQInteger op = (SQInteger)(curr-_instructions);\r
222         SQInteger line=_lineinfos[0]._line;\r
223         for(SQInteger i=1;i<_nlineinfos;i++){\r
224                 if(_lineinfos[i]._op>=op)\r
225                         return line;\r
226                 line=_lineinfos[i]._line;\r
227         }\r
228         return line;\r
229 }\r
230 \r
231 #define _CHECK_IO(exp)  { if(!exp)return false; }\r
232 bool SafeWrite(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUserPointer dest,SQInteger size)\r
233 {\r
234         if(write(up,dest,size) != size) {\r
235                 v->Raise_Error(_SC("io error (write function failure)"));\r
236                 return false;\r
237         }\r
238         return true;\r
239 }\r
240 \r
241 bool SafeRead(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQUserPointer dest,SQInteger size)\r
242 {\r
243         if(size && read(up,dest,size) != size) {\r
244                 v->Raise_Error(_SC("io error, read function failure, the origin stream could be corrupted/trucated"));\r
245                 return false;\r
246         }\r
247         return true;\r
248 }\r
249 \r
250 bool WriteTag(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQInteger tag)\r
251 {\r
252         return SafeWrite(v,write,up,&tag,sizeof(tag));\r
253 }\r
254 \r
255 bool CheckTag(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQInteger tag)\r
256 {\r
257         SQInteger t;\r
258         _CHECK_IO(SafeRead(v,read,up,&t,sizeof(t)));\r
259         if(t != tag){\r
260                 v->Raise_Error(_SC("invalid or corrupted closure stream"));\r
261                 return false;\r
262         }\r
263         return true;\r
264 }\r
265 \r
266 bool WriteObject(HSQUIRRELVM v,SQUserPointer up,SQWRITEFUNC write,SQObjectPtr &o)\r
267 {\r
268         _CHECK_IO(SafeWrite(v,write,up,&type(o),sizeof(SQObjectType)));\r
269         switch(type(o)){\r
270         case OT_STRING:\r
271                 _CHECK_IO(SafeWrite(v,write,up,&_string(o)->_len,sizeof(SQInteger)));\r
272                 _CHECK_IO(SafeWrite(v,write,up,_stringval(o),rsl(_string(o)->_len)));\r
273                 break;\r
274         case OT_INTEGER:\r
275                 _CHECK_IO(SafeWrite(v,write,up,&_integer(o),sizeof(SQInteger)));break;\r
276         case OT_FLOAT:\r
277                 _CHECK_IO(SafeWrite(v,write,up,&_float(o),sizeof(SQFloat)));break;\r
278         case OT_NULL:\r
279                 break;\r
280         default:\r
281                 v->Raise_Error(_SC("cannot serialize a %s"),GetTypeName(o));\r
282                 return false;\r
283         }\r
284         return true;\r
285 }\r
286 \r
287 bool ReadObject(HSQUIRRELVM v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &o)\r
288 {\r
289         SQObjectType t;\r
290         _CHECK_IO(SafeRead(v,read,up,&t,sizeof(SQObjectType)));\r
291         switch(t){\r
292         case OT_STRING:{\r
293                 SQInteger len;\r
294                 _CHECK_IO(SafeRead(v,read,up,&len,sizeof(SQInteger)));\r
295                 _CHECK_IO(SafeRead(v,read,up,_ss(v)->GetScratchPad(rsl(len)),rsl(len)));\r
296                 o=SQString::Create(_ss(v),_ss(v)->GetScratchPad(-1),len);\r
297                                    }\r
298                 break;\r
299         case OT_INTEGER:{\r
300                 SQInteger i;\r
301                 _CHECK_IO(SafeRead(v,read,up,&i,sizeof(SQInteger))); o = i; break;\r
302                                         }\r
303         case OT_FLOAT:{\r
304                 SQFloat f;\r
305                 _CHECK_IO(SafeRead(v,read,up,&f,sizeof(SQFloat))); o = f; break;\r
306                                   }\r
307         case OT_NULL:\r
308                 o=_null_;\r
309                 break;\r
310         default:\r
311                 v->Raise_Error(_SC("cannot serialize a %s"),IdType2Name(t));\r
312                 return false;\r
313         }\r
314         return true;\r
315 }\r
316 \r
317 bool SQClosure::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write)\r
318 {\r
319         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_HEAD));\r
320         _CHECK_IO(WriteTag(v,write,up,sizeof(SQChar)));\r
321         _CHECK_IO(_funcproto(_function)->Save(v,up,write));\r
322         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_TAIL));\r
323         return true;\r
324 }\r
325 \r
326 bool SQClosure::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret)\r
327 {\r
328         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_HEAD));\r
329         _CHECK_IO(CheckTag(v,read,up,sizeof(SQChar)));\r
330         SQObjectPtr func;\r
331         _CHECK_IO(SQFunctionProto::Load(v,up,read,func));\r
332         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_TAIL));\r
333         ret = SQClosure::Create(_ss(v),_funcproto(func));\r
334         return true;\r
335 }\r
336 \r
337 bool SQFunctionProto::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write)\r
338 {\r
339         SQInteger i,nliterals = _nliterals,nparameters = _nparameters;\r
340         SQInteger noutervalues = _noutervalues,nlocalvarinfos = _nlocalvarinfos;\r
341         SQInteger nlineinfos=_nlineinfos,ninstructions = _ninstructions,nfunctions=_nfunctions;\r
342         SQInteger ndefaultparams = _ndefaultparams;\r
343         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
344         _CHECK_IO(WriteObject(v,up,write,_sourcename));\r
345         _CHECK_IO(WriteObject(v,up,write,_name));\r
346         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
347         _CHECK_IO(SafeWrite(v,write,up,&nliterals,sizeof(nliterals)));\r
348         _CHECK_IO(SafeWrite(v,write,up,&nparameters,sizeof(nparameters)));\r
349         _CHECK_IO(SafeWrite(v,write,up,&noutervalues,sizeof(noutervalues)));\r
350         _CHECK_IO(SafeWrite(v,write,up,&nlocalvarinfos,sizeof(nlocalvarinfos)));\r
351         _CHECK_IO(SafeWrite(v,write,up,&nlineinfos,sizeof(nlineinfos)));\r
352         _CHECK_IO(SafeWrite(v,write,up,&ndefaultparams,sizeof(ndefaultparams)));\r
353         _CHECK_IO(SafeWrite(v,write,up,&ninstructions,sizeof(ninstructions)));\r
354         _CHECK_IO(SafeWrite(v,write,up,&nfunctions,sizeof(nfunctions)));\r
355         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
356         for(i=0;i<nliterals;i++){\r
357                 _CHECK_IO(WriteObject(v,up,write,_literals[i]));\r
358         }\r
359 \r
360         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
361         for(i=0;i<nparameters;i++){\r
362                 _CHECK_IO(WriteObject(v,up,write,_parameters[i]));\r
363         }\r
364 \r
365         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
366         for(i=0;i<noutervalues;i++){\r
367                 _CHECK_IO(SafeWrite(v,write,up,&_outervalues[i]._type,sizeof(SQUnsignedInteger)));\r
368                 _CHECK_IO(WriteObject(v,up,write,_outervalues[i]._src));\r
369                 _CHECK_IO(WriteObject(v,up,write,_outervalues[i]._name));\r
370         }\r
371 \r
372         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
373         for(i=0;i<nlocalvarinfos;i++){\r
374                 SQLocalVarInfo &lvi=_localvarinfos[i];\r
375                 _CHECK_IO(WriteObject(v,up,write,lvi._name));\r
376                 _CHECK_IO(SafeWrite(v,write,up,&lvi._pos,sizeof(SQUnsignedInteger)));\r
377                 _CHECK_IO(SafeWrite(v,write,up,&lvi._start_op,sizeof(SQUnsignedInteger)));\r
378                 _CHECK_IO(SafeWrite(v,write,up,&lvi._end_op,sizeof(SQUnsignedInteger)));\r
379         }\r
380 \r
381         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
382         _CHECK_IO(SafeWrite(v,write,up,_lineinfos,sizeof(SQLineInfo)*nlineinfos));\r
383 \r
384         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
385         _CHECK_IO(SafeWrite(v,write,up,_defaultparams,sizeof(SQInteger)*ndefaultparams));\r
386 \r
387         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
388         _CHECK_IO(SafeWrite(v,write,up,_instructions,sizeof(SQInstruction)*ninstructions));\r
389 \r
390         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
391         for(i=0;i<nfunctions;i++){\r
392                 _CHECK_IO(_funcproto(_functions[i])->Save(v,up,write));\r
393         }\r
394         _CHECK_IO(SafeWrite(v,write,up,&_stacksize,sizeof(_stacksize)));\r
395         _CHECK_IO(SafeWrite(v,write,up,&_bgenerator,sizeof(_bgenerator)));\r
396         _CHECK_IO(SafeWrite(v,write,up,&_varparams,sizeof(_varparams)));\r
397         return true;\r
398 }\r
399 \r
400 bool SQFunctionProto::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret)\r
401 {\r
402         SQInteger i, nliterals,nparameters;\r
403         SQInteger noutervalues ,nlocalvarinfos ;\r
404         SQInteger nlineinfos,ninstructions ,nfunctions,ndefaultparams ;\r
405         SQObjectPtr sourcename, name;\r
406         SQObjectPtr o;\r
407         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
408         _CHECK_IO(ReadObject(v, up, read, sourcename));\r
409         _CHECK_IO(ReadObject(v, up, read, name));\r
410         \r
411         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
412         _CHECK_IO(SafeRead(v,read,up, &nliterals, sizeof(nliterals)));\r
413         _CHECK_IO(SafeRead(v,read,up, &nparameters, sizeof(nparameters)));\r
414         _CHECK_IO(SafeRead(v,read,up, &noutervalues, sizeof(noutervalues)));\r
415         _CHECK_IO(SafeRead(v,read,up, &nlocalvarinfos, sizeof(nlocalvarinfos)));\r
416         _CHECK_IO(SafeRead(v,read,up, &nlineinfos, sizeof(nlineinfos)));\r
417         _CHECK_IO(SafeRead(v,read,up, &ndefaultparams, sizeof(ndefaultparams)));\r
418         _CHECK_IO(SafeRead(v,read,up, &ninstructions, sizeof(ninstructions)));\r
419         _CHECK_IO(SafeRead(v,read,up, &nfunctions, sizeof(nfunctions)));\r
420         \r
421 \r
422         SQFunctionProto *f = SQFunctionProto::Create(ninstructions,nliterals,nparameters,\r
423                         nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams);\r
424         SQObjectPtr proto = f; //gets a ref in case of failure\r
425         f->_sourcename = sourcename;\r
426         f->_name = name;\r
427 \r
428         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
429 \r
430         for(i = 0;i < nliterals; i++){\r
431                 _CHECK_IO(ReadObject(v, up, read, o));\r
432                 f->_literals[i] = o;\r
433         }\r
434         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
435 \r
436         for(i = 0; i < nparameters; i++){\r
437                 _CHECK_IO(ReadObject(v, up, read, o));\r
438                 f->_parameters[i] = o;\r
439         }\r
440         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
441 \r
442         for(i = 0; i < noutervalues; i++){\r
443                 SQUnsignedInteger type;\r
444                 SQObjectPtr name;\r
445                 _CHECK_IO(SafeRead(v,read,up, &type, sizeof(SQUnsignedInteger)));\r
446                 _CHECK_IO(ReadObject(v, up, read, o));\r
447                 _CHECK_IO(ReadObject(v, up, read, name));\r
448                 f->_outervalues[i] = SQOuterVar(name,o, (SQOuterType)type);\r
449         }\r
450         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
451 \r
452         for(i = 0; i < nlocalvarinfos; i++){\r
453                 SQLocalVarInfo lvi;\r
454                 _CHECK_IO(ReadObject(v, up, read, lvi._name));\r
455                 _CHECK_IO(SafeRead(v,read,up, &lvi._pos, sizeof(SQUnsignedInteger)));\r
456                 _CHECK_IO(SafeRead(v,read,up, &lvi._start_op, sizeof(SQUnsignedInteger)));\r
457                 _CHECK_IO(SafeRead(v,read,up, &lvi._end_op, sizeof(SQUnsignedInteger)));\r
458                 f->_localvarinfos[i] = lvi;\r
459         }\r
460         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
461         _CHECK_IO(SafeRead(v,read,up, f->_lineinfos, sizeof(SQLineInfo)*nlineinfos));\r
462 \r
463         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
464         _CHECK_IO(SafeRead(v,read,up, f->_defaultparams, sizeof(SQInteger)*ndefaultparams));\r
465 \r
466         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
467         _CHECK_IO(SafeRead(v,read,up, f->_instructions, sizeof(SQInstruction)*ninstructions));\r
468 \r
469         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
470         for(i = 0; i < nfunctions; i++){\r
471                 _CHECK_IO(_funcproto(o)->Load(v, up, read, o));\r
472                 f->_functions[i] = o;\r
473         }\r
474         _CHECK_IO(SafeRead(v,read,up, &f->_stacksize, sizeof(f->_stacksize)));\r
475         _CHECK_IO(SafeRead(v,read,up, &f->_bgenerator, sizeof(f->_bgenerator)));\r
476         _CHECK_IO(SafeRead(v,read,up, &f->_varparams, sizeof(f->_varparams)));\r
477         \r
478         ret = f;\r
479         return true;\r
480 }\r
481 \r
482 #ifndef NO_GARBAGE_COLLECTOR\r
483 \r
484 #define START_MARK()    if(!(_uiRef&MARK_FLAG)){ \\r
485                 _uiRef|=MARK_FLAG;\r
486 \r
487 #define END_MARK() RemoveFromChain(&_sharedstate->_gc_chain, this); \\r
488                 AddToChain(chain, this); }\r
489 \r
490 void SQVM::Mark(SQCollectable **chain)\r
491 {\r
492         START_MARK()\r
493                 SQSharedState::MarkObject(_lasterror,chain);\r
494                 SQSharedState::MarkObject(_errorhandler,chain);\r
495                 SQSharedState::MarkObject(_debughook,chain);\r
496                 SQSharedState::MarkObject(_roottable, chain);\r
497                 SQSharedState::MarkObject(temp_reg, chain);\r
498                 for(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain);\r
499                 for(SQUnsignedInteger j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain);\r
500                 for(SQInteger k = 0; k < _callsstacksize; k++) SQSharedState::MarkObject(_callsstack[k]._closure, chain);\r
501         END_MARK()\r
502 }\r
503 \r
504 void SQArray::Mark(SQCollectable **chain)\r
505 {\r
506         START_MARK()\r
507                 SQInteger len = _values.size();\r
508                 for(SQInteger i = 0;i < len; i++) SQSharedState::MarkObject(_values[i], chain);\r
509         END_MARK()\r
510 }\r
511 void SQTable::Mark(SQCollectable **chain)\r
512 {\r
513         START_MARK()\r
514                 if(_delegate) _delegate->Mark(chain);\r
515                 SQInteger len = _numofnodes;\r
516                 for(SQInteger i = 0; i < len; i++){\r
517                         SQSharedState::MarkObject(_nodes[i].key, chain);\r
518                         SQSharedState::MarkObject(_nodes[i].val, chain);\r
519                 }\r
520         END_MARK()\r
521 }\r
522 \r
523 void SQClass::Mark(SQCollectable **chain)\r
524 {\r
525         START_MARK()\r
526                 _members->Mark(chain);\r
527                 if(_base) _base->Mark(chain);\r
528                 SQSharedState::MarkObject(_attributes, chain);\r
529                 for(SQUnsignedInteger i =0; i< _defaultvalues.size(); i++) {\r
530                         SQSharedState::MarkObject(_defaultvalues[i].val, chain);\r
531                         SQSharedState::MarkObject(_defaultvalues[i].attrs, chain);\r
532                 }\r
533                 for(SQUnsignedInteger j =0; j< _methods.size(); j++) {\r
534                         SQSharedState::MarkObject(_methods[j].val, chain);\r
535                         SQSharedState::MarkObject(_methods[j].attrs, chain);\r
536                 }\r
537                 for(SQUnsignedInteger k =0; k< _metamethods.size(); k++) {\r
538                         SQSharedState::MarkObject(_metamethods[k], chain);\r
539                 }\r
540         END_MARK()\r
541 }\r
542 \r
543 void SQInstance::Mark(SQCollectable **chain)\r
544 {\r
545         START_MARK()\r
546                 _class->Mark(chain);\r
547                 SQUnsignedInteger nvalues = _class->_defaultvalues.size();\r
548                 for(SQUnsignedInteger i =0; i< nvalues; i++) {\r
549                         SQSharedState::MarkObject(_values[i], chain);\r
550                 }\r
551         END_MARK()\r
552 }\r
553 \r
554 void SQGenerator::Mark(SQCollectable **chain)\r
555 {\r
556         START_MARK()\r
557                 for(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain);\r
558                 for(SQUnsignedInteger j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain);\r
559                 SQSharedState::MarkObject(_closure, chain);\r
560         END_MARK()\r
561 }\r
562 \r
563 void SQClosure::Mark(SQCollectable **chain)\r
564 {\r
565         START_MARK()\r
566                 for(SQUnsignedInteger i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain);\r
567                 for(SQUnsignedInteger i = 0; i < _defaultparams.size(); i++) SQSharedState::MarkObject(_defaultparams[i], chain);\r
568         END_MARK()\r
569 }\r
570 \r
571 void SQNativeClosure::Mark(SQCollectable **chain)\r
572 {\r
573         START_MARK()\r
574                 for(SQUnsignedInteger i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain);\r
575         END_MARK()\r
576 }\r
577 \r
578 void SQUserData::Mark(SQCollectable **chain){\r
579         START_MARK()\r
580                 if(_delegate) _delegate->Mark(chain);\r
581         END_MARK()\r
582 }\r
583 \r
584 void SQCollectable::UnMark() { _uiRef&=~MARK_FLAG; }\r
585 \r
586 #endif\r
587 \r