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