squirrel update
[supertux.git] / src / 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 SQString *SQString::Create(SQSharedState *ss,const SQChar *s,SQInteger len)\r
15 {\r
16         SQString *str=ADD_STRING(ss,s,len);\r
17         str->_sharedstate=ss;\r
18         return str;\r
19 }\r
20 \r
21 void SQString::Release()\r
22 {\r
23         REMOVE_STRING(_sharedstate,this);\r
24 }\r
25 \r
26 SQUnsignedInteger TranslateIndex(const SQObjectPtr &idx)\r
27 {\r
28         switch(type(idx)){\r
29                 case OT_NULL:\r
30                         return 0;\r
31                 case OT_INTEGER:\r
32                         return (SQUnsignedInteger)_integer(idx);\r
33         }\r
34         assert(0);\r
35         return 0;\r
36 }\r
37 \r
38 SQWeakRef *SQRefCounted::GetWeakRef(SQObjectType type)\r
39 {\r
40         if(!_weakref) {\r
41                 sq_new(_weakref,SQWeakRef);\r
42                 _weakref->_obj._type = type;\r
43                 _weakref->_obj._unVal.pRefCounted = this;\r
44         }\r
45         return _weakref;\r
46 }\r
47 \r
48 SQRefCounted::~SQRefCounted()\r
49 {\r
50         if(_weakref) {\r
51                 _weakref->_obj._type = OT_NULL;\r
52                 _weakref->_obj._unVal.pRefCounted = NULL;\r
53         }\r
54 }\r
55 \r
56 void SQWeakRef::Release() { \r
57         if(ISREFCOUNTED(_obj._type)) { \r
58                 _obj._unVal.pRefCounted->_weakref = NULL;\r
59         } \r
60         sq_delete(this,SQWeakRef);\r
61 }\r
62 \r
63 bool SQDelegable::GetMetaMethod(SQMetaMethod mm,SQObjectPtr &res) {\r
64         if(_delegate) {\r
65                 return _delegate->Get((*_ss(this)->_metamethods)[mm],res);\r
66         }\r
67         return false;\r
68 }\r
69 \r
70 bool SQDelegable::SetDelegate(SQTable *mt)\r
71 {\r
72         SQTable *temp = mt;\r
73         while (temp) {\r
74                 if (temp->_delegate == this) return false; //cycle detected\r
75                 temp = temp->_delegate;\r
76         }\r
77         if (mt) __ObjAddRef(mt);\r
78         __ObjRelease(_delegate);\r
79         _delegate = mt;\r
80         return true;\r
81 }\r
82 \r
83 bool SQGenerator::Yield(SQVM *v)\r
84 {\r
85         if(_state==eSuspended) { v->Raise_Error(_SC("internal vm error, yielding dead generator"));  return false;}\r
86         if(_state==eDead) { v->Raise_Error(_SC("internal vm error, yielding a dead generator")); return false; }\r
87         SQInteger size = v->_top-v->_stackbase;\r
88         _ci=*v->ci;\r
89         _stack.resize(size);\r
90         for(SQInteger n =0; n<size; n++) {\r
91                 _stack._vals[n] = v->_stack[v->_stackbase+n];\r
92                 v->_stack[v->_stackbase+n] = _null_;\r
93         }\r
94         SQInteger nvargs = v->ci->_vargs.size;\r
95         SQInteger vargsbase = v->ci->_vargs.base;\r
96         for(SQInteger j = nvargs - 1; j >= 0; j--) {\r
97                 _vargsstack.push_back(v->_vargsstack[vargsbase+j]);\r
98         }\r
99         _ci._generator=_null_;\r
100         for(SQInteger i=0;i<_ci._etraps;i++) {\r
101                 _etraps.push_back(v->_etraps.top());\r
102                 v->_etraps.pop_back();\r
103         }\r
104         _state=eSuspended;\r
105         return true;\r
106 }\r
107 \r
108 bool SQGenerator::Resume(SQVM *v,SQInteger target)\r
109 {\r
110         SQInteger size=_stack.size();\r
111         if(_state==eDead){ v->Raise_Error(_SC("resuming dead generator")); return false; }\r
112         if(_state==eRunning){ v->Raise_Error(_SC("resuming active generator")); return false; }\r
113         SQInteger prevtop=v->_top-v->_stackbase;\r
114         PUSH_CALLINFO(v,_ci);\r
115         SQInteger oldstackbase=v->_stackbase;\r
116         v->_stackbase=v->_top;\r
117         v->ci->_target=target;\r
118         v->ci->_generator=SQObjectPtr(this);\r
119         v->ci->_vargs.size = _vargsstack.size();\r
120         \r
121         for(SQInteger i=0;i<_ci._etraps;i++) {\r
122                 v->_etraps.push_back(_etraps.top());\r
123                 _etraps.pop_back();\r
124         }\r
125         for(SQInteger n =0; n<size; n++) {\r
126                 v->_stack[v->_stackbase+n] = _stack._vals[n];\r
127                 _stack._vals[0] = _null_;\r
128         }\r
129         while(_vargsstack.size()) {\r
130                 v->_vargsstack.push_back(_vargsstack.back());\r
131                 _vargsstack.pop_back();\r
132         }\r
133         v->ci->_vargs.base = v->_vargsstack.size() - v->ci->_vargs.size;\r
134         v->_top=v->_stackbase+size;\r
135         v->ci->_prevtop=prevtop;\r
136         v->ci->_prevstkbase=v->_stackbase-oldstackbase;\r
137         _state=eRunning;\r
138         return true;\r
139 }\r
140 \r
141 void SQArray::Extend(const SQArray *a){\r
142         SQInteger xlen;\r
143         if((xlen=a->Size()))\r
144                 for(SQInteger i=0;i<xlen;i++)\r
145                         Append(a->_values[i]);\r
146 }\r
147 \r
148 const SQChar* SQFunctionProto::GetLocal(SQVM *vm,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop)\r
149 {\r
150         SQUnsignedInteger nvars=_localvarinfos.size();\r
151         const SQChar *res=NULL; \r
152         if(nvars>=nseq){\r
153                 for(SQUnsignedInteger i=0;i<nvars;i++){\r
154                         if(_localvarinfos[i]._start_op<=nop && _localvarinfos[i]._end_op>=nop)\r
155                         {\r
156                                 if(nseq==0){\r
157                                         vm->Push(vm->_stack[stackbase+_localvarinfos[i]._pos]);\r
158                                         res=_stringval(_localvarinfos[i]._name);\r
159                                         break;\r
160                                 }\r
161                                 nseq--;\r
162                         }\r
163                 }\r
164         }\r
165         return res;\r
166 }\r
167 \r
168 SQInteger SQFunctionProto::GetLine(SQInstruction *curr)\r
169 {\r
170         SQInteger op=(curr-_instructions._vals);\r
171         SQInteger line=_lineinfos[0]._line;\r
172         for(SQUnsignedInteger i=1;i<_lineinfos.size();i++){\r
173                 if(_lineinfos[i]._op>=op)\r
174                         return line;\r
175                 line=_lineinfos[i]._line;\r
176         }\r
177         return line;\r
178 }\r
179 \r
180 //#define _ERROR_TRAP() error_trap:\r
181 #define _CHECK_IO(exp)  { if(!exp)return false; }\r
182 bool SafeWrite(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUserPointer dest,SQInteger size)\r
183 {\r
184         if(write(up,dest,size) != size) {\r
185                 v->Raise_Error(_SC("io error (write function failure)"));\r
186                 return false;\r
187         }\r
188         return true;\r
189 }\r
190 \r
191 bool SafeRead(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQUserPointer dest,SQInteger size)\r
192 {\r
193         if(size && read(up,dest,size) != size) {\r
194                 v->Raise_Error(_SC("io error, read function failure, the origin stream could be corrupted/trucated"));\r
195                 return false;\r
196         }\r
197         return true;\r
198 }\r
199 \r
200 bool WriteTag(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQInteger tag)\r
201 {\r
202         return SafeWrite(v,write,up,&tag,sizeof(tag));\r
203 }\r
204 \r
205 bool CheckTag(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQInteger tag)\r
206 {\r
207         SQInteger t;\r
208         _CHECK_IO(SafeRead(v,read,up,&t,sizeof(t)));\r
209         if(t != tag){\r
210                 v->Raise_Error(_SC("invalid or corrupted closure stream"));\r
211                 return false;\r
212         }\r
213         return true;\r
214 }\r
215 \r
216 bool WriteObject(HSQUIRRELVM v,SQUserPointer up,SQWRITEFUNC write,SQObjectPtr &o)\r
217 {\r
218         _CHECK_IO(SafeWrite(v,write,up,&type(o),sizeof(SQObjectType)));\r
219         switch(type(o)){\r
220         case OT_STRING:\r
221                 _CHECK_IO(SafeWrite(v,write,up,&_string(o)->_len,sizeof(SQInteger)));\r
222                 _CHECK_IO(SafeWrite(v,write,up,_stringval(o),rsl(_string(o)->_len)));\r
223                 break;\r
224         case OT_INTEGER:\r
225                 _CHECK_IO(SafeWrite(v,write,up,&_integer(o),sizeof(SQInteger)));break;\r
226         case OT_FLOAT:\r
227                 _CHECK_IO(SafeWrite(v,write,up,&_float(o),sizeof(SQFloat)));break;\r
228         case OT_NULL:\r
229                 break;\r
230         default:\r
231                 v->Raise_Error(_SC("cannot serialize a %s"),GetTypeName(o));\r
232                 return false;\r
233         }\r
234         return true;\r
235 }\r
236 \r
237 bool ReadObject(HSQUIRRELVM v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &o)\r
238 {\r
239         SQObjectType t;\r
240         _CHECK_IO(SafeRead(v,read,up,&t,sizeof(SQObjectType)));\r
241         switch(t){\r
242         case OT_STRING:{\r
243                 SQInteger len;\r
244                 _CHECK_IO(SafeRead(v,read,up,&len,sizeof(SQInteger)));\r
245                 _CHECK_IO(SafeRead(v,read,up,_ss(v)->GetScratchPad(rsl(len)),rsl(len)));\r
246                 o=SQString::Create(_ss(v),_ss(v)->GetScratchPad(-1),len);\r
247                                    }\r
248                 break;\r
249         case OT_INTEGER:{\r
250                 SQInteger i;\r
251                 _CHECK_IO(SafeRead(v,read,up,&i,sizeof(SQInteger))); o = i; break;\r
252                                         }\r
253         case OT_FLOAT:{\r
254                 SQFloat f;\r
255                 _CHECK_IO(SafeRead(v,read,up,&f,sizeof(SQFloat))); o = f; break;\r
256                                   }\r
257         case OT_NULL:\r
258                 o=_null_;\r
259                 break;\r
260         default:\r
261                 v->Raise_Error(_SC("cannot serialize a %s"),IdType2Name(t));\r
262                 return false;\r
263         }\r
264         return true;\r
265 }\r
266 \r
267 bool SQClosure::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write)\r
268 {\r
269         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_HEAD));\r
270         _CHECK_IO(WriteTag(v,write,up,sizeof(SQChar)));\r
271         _CHECK_IO(_funcproto(_function)->Save(v,up,write));\r
272         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_TAIL));\r
273         return true;\r
274 }\r
275 \r
276 bool SQClosure::Load(SQVM *v,SQUserPointer up,SQREADFUNC read)\r
277 {\r
278         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_HEAD));\r
279         _CHECK_IO(CheckTag(v,read,up,sizeof(SQChar)));\r
280         _CHECK_IO(_funcproto(_function)->Load(v,up,read));\r
281         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_TAIL));\r
282         return true;\r
283 }\r
284 \r
285 bool SQFunctionProto::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write)\r
286 {\r
287         SQInteger i,nsize=_literals.size();\r
288         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
289         _CHECK_IO(WriteObject(v,up,write,_sourcename));\r
290         _CHECK_IO(WriteObject(v,up,write,_name));\r
291         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
292         _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));\r
293         for(i=0;i<nsize;i++){\r
294                 _CHECK_IO(WriteObject(v,up,write,_literals[i]));\r
295         }\r
296         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
297         nsize=_parameters.size();\r
298         _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));\r
299         for(i=0;i<nsize;i++){\r
300                 _CHECK_IO(WriteObject(v,up,write,_parameters[i]));\r
301         }\r
302         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
303         nsize=_outervalues.size();\r
304         _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));\r
305         for(i=0;i<nsize;i++){\r
306                 _CHECK_IO(SafeWrite(v,write,up,&_outervalues[i]._type,sizeof(SQUnsignedInteger)));\r
307                 _CHECK_IO(WriteObject(v,up,write,_outervalues[i]._src));\r
308                 _CHECK_IO(WriteObject(v,up,write,_outervalues[i]._name));\r
309         }\r
310         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
311         nsize=_localvarinfos.size();\r
312         _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));\r
313         for(i=0;i<nsize;i++){\r
314                 SQLocalVarInfo &lvi=_localvarinfos[i];\r
315                 _CHECK_IO(WriteObject(v,up,write,lvi._name));\r
316                 _CHECK_IO(SafeWrite(v,write,up,&lvi._pos,sizeof(SQUnsignedInteger)));\r
317                 _CHECK_IO(SafeWrite(v,write,up,&lvi._start_op,sizeof(SQUnsignedInteger)));\r
318                 _CHECK_IO(SafeWrite(v,write,up,&lvi._end_op,sizeof(SQUnsignedInteger)));\r
319         }\r
320         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
321         nsize=_lineinfos.size();\r
322         _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));\r
323         _CHECK_IO(SafeWrite(v,write,up,&_lineinfos[0],sizeof(SQLineInfo)*nsize));\r
324         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
325         nsize=_instructions.size();\r
326         _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));\r
327         _CHECK_IO(SafeWrite(v,write,up,&_instructions[0],sizeof(SQInstruction)*nsize));\r
328         _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
329         nsize=_functions.size();\r
330         _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));\r
331         for(i=0;i<nsize;i++){\r
332                 _CHECK_IO(_funcproto(_functions[i])->Save(v,up,write));\r
333         }\r
334         _CHECK_IO(SafeWrite(v,write,up,&_stacksize,sizeof(_stacksize)));\r
335         _CHECK_IO(SafeWrite(v,write,up,&_bgenerator,sizeof(_bgenerator)));\r
336         _CHECK_IO(SafeWrite(v,write,up,&_varparams,sizeof(_varparams)));\r
337         return true;\r
338 }\r
339 \r
340 bool SQFunctionProto::Load(SQVM *v,SQUserPointer up,SQREADFUNC read)\r
341 {\r
342         SQInteger i, nsize = _literals.size();\r
343         SQObjectPtr o;\r
344         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
345         _CHECK_IO(ReadObject(v, up, read, _sourcename));\r
346         _CHECK_IO(ReadObject(v, up, read, _name));\r
347         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
348         _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize)));\r
349         for(i = 0;i < nsize; i++){\r
350                 _CHECK_IO(ReadObject(v, up, read, o));\r
351                 _literals.push_back(o);\r
352         }\r
353         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
354         _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize)));\r
355         for(i = 0; i < nsize; i++){\r
356                 _CHECK_IO(ReadObject(v, up, read, o));\r
357                 _parameters.push_back(o);\r
358         }\r
359         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
360         _CHECK_IO(SafeRead(v,read,up,&nsize,sizeof(nsize)));\r
361         for(i = 0; i < nsize; i++){\r
362                 SQUnsignedInteger type;\r
363                 SQObjectPtr name;\r
364                 _CHECK_IO(SafeRead(v,read,up, &type, sizeof(SQUnsignedInteger)));\r
365                 _CHECK_IO(ReadObject(v, up, read, o));\r
366                 _CHECK_IO(ReadObject(v, up, read, name));\r
367                 _outervalues.push_back(SQOuterVar(name,o, (SQOuterType)type));\r
368         }\r
369         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
370         _CHECK_IO(SafeRead(v,read,up,&nsize, sizeof(nsize)));\r
371         for(i = 0; i < nsize; i++){\r
372                 SQLocalVarInfo lvi;\r
373                 _CHECK_IO(ReadObject(v, up, read, lvi._name));\r
374                 _CHECK_IO(SafeRead(v,read,up, &lvi._pos, sizeof(SQUnsignedInteger)));\r
375                 _CHECK_IO(SafeRead(v,read,up, &lvi._start_op, sizeof(SQUnsignedInteger)));\r
376                 _CHECK_IO(SafeRead(v,read,up, &lvi._end_op, sizeof(SQUnsignedInteger)));\r
377                 _localvarinfos.push_back(lvi);\r
378         }\r
379         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
380         _CHECK_IO(SafeRead(v,read,up, &nsize,sizeof(nsize)));\r
381         _lineinfos.resize(nsize);\r
382         _CHECK_IO(SafeRead(v,read,up, &_lineinfos[0], sizeof(SQLineInfo)*nsize));\r
383         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
384         _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize)));\r
385         _instructions.resize(nsize);\r
386         _CHECK_IO(SafeRead(v,read,up, &_instructions[0], sizeof(SQInstruction)*nsize));\r
387         _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
388         _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize)));\r
389         for(i = 0; i < nsize; i++){\r
390                 o = SQFunctionProto::Create();\r
391                 _CHECK_IO(_funcproto(o)->Load(v, up, read));\r
392                 _functions.push_back(o);\r
393         }\r
394         _CHECK_IO(SafeRead(v,read,up, &_stacksize, sizeof(_stacksize)));\r
395         _CHECK_IO(SafeRead(v,read,up, &_bgenerator, sizeof(_bgenerator)));\r
396         _CHECK_IO(SafeRead(v,read,up, &_varparams, sizeof(_varparams)));\r
397         return true;\r
398 }\r
399 \r
400 #ifndef NO_GARBAGE_COLLECTOR\r
401 \r
402 #define START_MARK()    if(!(_uiRef&MARK_FLAG)){ \\r
403                 _uiRef|=MARK_FLAG;\r
404 \r
405 #define END_MARK() RemoveFromChain(&_sharedstate->_gc_chain, this); \\r
406                 AddToChain(chain, this); }\r
407 \r
408 void SQVM::Mark(SQCollectable **chain)\r
409 {\r
410         START_MARK()\r
411                 SQSharedState::MarkObject(_lasterror,chain);\r
412                 SQSharedState::MarkObject(_errorhandler,chain);\r
413                 SQSharedState::MarkObject(_debughook,chain);\r
414                 SQSharedState::MarkObject(_roottable, chain);\r
415                 SQSharedState::MarkObject(temp_reg, chain);\r
416                 for(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain);\r
417                 for(SQUnsignedInteger j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain);\r
418         END_MARK()\r
419 }\r
420 \r
421 void SQArray::Mark(SQCollectable **chain)\r
422 {\r
423         START_MARK()\r
424                 SQInteger len = _values.size();\r
425                 for(SQInteger i = 0;i < len; i++) SQSharedState::MarkObject(_values[i], chain);\r
426         END_MARK()\r
427 }\r
428 void SQTable::Mark(SQCollectable **chain)\r
429 {\r
430         START_MARK()\r
431                 if(_delegate) _delegate->Mark(chain);\r
432                 SQInteger len = _numofnodes;\r
433                 for(SQInteger i = 0; i < len; i++){\r
434                         SQSharedState::MarkObject(_nodes[i].key, chain);\r
435                         SQSharedState::MarkObject(_nodes[i].val, chain);\r
436                 }\r
437         END_MARK()\r
438 }\r
439 \r
440 void SQClass::Mark(SQCollectable **chain)\r
441 {\r
442         START_MARK()\r
443                 _members->Mark(chain);\r
444                 if(_base) _base->Mark(chain);\r
445                 SQSharedState::MarkObject(_attributes, chain);\r
446                 for(SQUnsignedInteger i =0; i< _defaultvalues.size(); i++) {\r
447                         SQSharedState::MarkObject(_defaultvalues[i].val, chain);\r
448                         SQSharedState::MarkObject(_defaultvalues[i].attrs, chain);\r
449                 }\r
450                 for(SQUnsignedInteger j =0; j< _methods.size(); j++) {\r
451                         SQSharedState::MarkObject(_methods[j].val, chain);\r
452                         SQSharedState::MarkObject(_methods[j].attrs, chain);\r
453                 }\r
454                 for(SQUnsignedInteger k =0; k< _metamethods.size(); k++) {\r
455                         SQSharedState::MarkObject(_metamethods[k], chain);\r
456                 }\r
457         END_MARK()\r
458 }\r
459 \r
460 void SQInstance::Mark(SQCollectable **chain)\r
461 {\r
462         START_MARK()\r
463                 _class->Mark(chain);\r
464                 for(SQUnsignedInteger i =0; i< _nvalues; i++) {\r
465                         SQSharedState::MarkObject(_values[i], chain);\r
466                 }\r
467         END_MARK()\r
468 }\r
469 \r
470 void SQGenerator::Mark(SQCollectable **chain)\r
471 {\r
472         START_MARK()\r
473                 for(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain);\r
474                 for(SQUnsignedInteger j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain);\r
475                 SQSharedState::MarkObject(_closure, chain);\r
476         END_MARK()\r
477 }\r
478 \r
479 void SQClosure::Mark(SQCollectable **chain)\r
480 {\r
481         START_MARK()\r
482                 for(SQUnsignedInteger i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain);\r
483         END_MARK()\r
484 }\r
485 \r
486 void SQNativeClosure::Mark(SQCollectable **chain)\r
487 {\r
488         START_MARK()\r
489                 for(SQUnsignedInteger i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain);\r
490         END_MARK()\r
491 }\r
492 \r
493 void SQUserData::Mark(SQCollectable **chain){\r
494         START_MARK()\r
495                 if(_delegate) _delegate->Mark(chain);\r
496         END_MARK()\r
497 }\r
498 \r
499 void SQCollectable::UnMark() { _uiRef&=~MARK_FLAG; }\r
500 \r
501 #endif\r
502 \r