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