4 #include "sqpcheader.h" 7 #include "sqfuncproto.h" 12 #include "squserdata.h" 18 SQObjectPtr
_one_((SQInteger)1);
21 SQSharedState::SQSharedState()
23 _compilererrorhandler =
NULL;
26 _notifyallexceptions =
false;
29 #define newsysstring(s) { \ 30 _systemstrings->push_back(SQString::Create(this,s)); \ 33 #define newmetamethod(s) { \ 34 _metamethods->push_back(SQString::Create(this,s)); \ 35 _table(_metamethodsmap)->NewSlot(_metamethods->back(),(SQInteger)(_metamethods->size()-1)); \ 43 while(typemask[i] != 0) {
46 case 'o': mask |= _RT_NULL;
break;
47 case 'i': mask |= _RT_INTEGER;
break;
48 case 'f': mask |= _RT_FLOAT;
break;
49 case 'n': mask |= (_RT_FLOAT | _RT_INTEGER);
break;
50 case 's': mask |= _RT_STRING;
break;
51 case 't': mask |= _RT_TABLE;
break;
52 case 'a': mask |= _RT_ARRAY;
break;
53 case 'u': mask |= _RT_USERDATA;
break;
54 case 'c': mask |= (_RT_CLOSURE | _RT_NATIVECLOSURE);
break;
55 case 'b': mask |= _RT_BOOL;
break;
56 case 'g': mask |= _RT_GENERATOR;
break;
57 case 'p': mask |= _RT_USERPOINTER;
break;
58 case 'v': mask |= _RT_THREAD;
break;
59 case 'x': mask |= _RT_INSTANCE;
break;
60 case 'y': mask |= _RT_CLASS;
break;
61 case 'r': mask |= _RT_WEAKREF;
break;
62 case '.': mask = -1; res.push_back(mask); i++; mask = 0;
continue;
63 case ' ': i++;
continue;
68 if(typemask[i] ==
'|') {
84 SQTable *t=SQTable::Create(ss,0);
85 while(funcz[i].name!=0){
86 SQNativeClosure *nc = SQNativeClosure::Create(ss,funcz[i].f);
87 nc->_nparamscheck = funcz[i].nparamscheck;
88 nc->_name = SQString::Create(ss,funcz[i].name);
89 if(funcz[i].typemask && !
CompileTypemask(nc->_typecheck,funcz[i].typemask))
91 t->NewSlot(SQString::Create(ss,funcz[i].name),nc);
97 void SQSharedState::Init()
101 #ifndef NO_GARBAGE_COLLECTOR 104 sq_new(_stringtable,SQStringTable);
105 sq_new(_metamethods,SQObjectPtrVec);
106 sq_new(_systemstrings,SQObjectPtrVec);
107 sq_new(_types,SQObjectPtrVec);
108 _metamethodsmap = SQTable::Create(
this,MT_LAST-1);
146 _constructoridx = SQString::Create(
this,_SC(
"constructor"));
147 _registry = SQTable::Create(
this,0);
148 _consts = SQTable::Create(
this,0);
162 SQSharedState::~SQSharedState()
165 _table(_registry)->Finalize();
166 _table(_consts)->Finalize();
167 _table(_metamethodsmap)->Finalize();
171 while(!_systemstrings->empty()) {
172 _systemstrings->back()=
_null_;
173 _systemstrings->pop_back();
175 _thread(_root_vm)->Finalize();
177 _table_default_delegate =
_null_;
178 _array_default_delegate =
_null_;
179 _string_default_delegate =
_null_;
180 _number_default_delegate =
_null_;
181 _closure_default_delegate =
_null_;
182 _generator_default_delegate =
_null_;
183 _thread_default_delegate =
_null_;
184 _class_default_delegate =
_null_;
185 _instance_default_delegate =
_null_;
186 _weakref_default_delegate =
_null_;
187 _refs_table.Finalize();
188 #ifndef NO_GARBAGE_COLLECTOR 189 SQCollectable *t = _gc_chain;
190 SQCollectable *nx =
NULL;
202 assert(_gc_chain==
NULL);
205 _gc_chain->Release();
209 sq_delete(_types,SQObjectPtrVec);
210 sq_delete(_systemstrings,SQObjectPtrVec);
211 sq_delete(_metamethods,SQObjectPtrVec);
212 sq_delete(_stringtable,SQStringTable);
213 if(_scratchpad)SQ_FREE(_scratchpad,_scratchpadsize);
217 SQInteger SQSharedState::GetMetaMethodIdxByName(
const SQObjectPtr &name)
219 if(type(name) != OT_STRING)
222 if(_table(_metamethodsmap)->Get(name,ret)) {
223 return _integer(ret);
228 #ifndef NO_GARBAGE_COLLECTOR 230 void SQSharedState::MarkObject(SQObjectPtr &o,SQCollectable **chain)
233 case OT_TABLE:_table(o)->Mark(chain);
break;
234 case OT_ARRAY:_array(o)->Mark(chain);
break;
235 case OT_USERDATA:_userdata(o)->Mark(chain);
break;
236 case OT_CLOSURE:_closure(o)->Mark(chain);
break;
237 case OT_NATIVECLOSURE:_nativeclosure(o)->Mark(chain);
break;
238 case OT_GENERATOR:_generator(o)->Mark(chain);
break;
239 case OT_THREAD:_thread(o)->Mark(chain);
break;
240 case OT_CLASS:_class(o)->Mark(chain);
break;
241 case OT_INSTANCE:_instance(o)->Mark(chain);
break;
248 SQInteger SQSharedState::CollectGarbage(SQVM * )
251 SQCollectable *tchain=
NULL;
252 SQVM *vms = _thread(_root_vm);
255 SQInteger x = _table(_thread(_root_vm)->_roottable)->CountUsed();
256 _refs_table.Mark(&tchain);
257 MarkObject(_registry,&tchain);
258 MarkObject(_consts,&tchain);
259 MarkObject(_metamethodsmap,&tchain);
260 MarkObject(_table_default_delegate,&tchain);
261 MarkObject(_array_default_delegate,&tchain);
262 MarkObject(_string_default_delegate,&tchain);
263 MarkObject(_number_default_delegate,&tchain);
264 MarkObject(_generator_default_delegate,&tchain);
265 MarkObject(_thread_default_delegate,&tchain);
266 MarkObject(_closure_default_delegate,&tchain);
267 MarkObject(_class_default_delegate,&tchain);
268 MarkObject(_instance_default_delegate,&tchain);
269 MarkObject(_weakref_default_delegate,&tchain);
271 SQCollectable *t = _gc_chain;
272 SQCollectable *nx =
NULL;
292 SQInteger z = _table(_thread(_root_vm)->_roottable)->CountUsed();
298 #ifndef NO_GARBAGE_COLLECTOR 299 void SQCollectable::AddToChain(SQCollectable **chain,SQCollectable *c)
303 if(*chain) (*chain)->_prev = c;
307 void SQCollectable::RemoveFromChain(SQCollectable **chain,SQCollectable *c)
309 if(c->_prev) c->_prev->_next = c->_next;
310 else *chain = c->_next;
312 c->_next->_prev = c->_prev;
318 SQChar* SQSharedState::GetScratchPad(SQInteger size)
322 if(_scratchpadsize < size) {
323 newsize = size + (size>>1);
324 _scratchpad = (
SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize);
325 _scratchpadsize = newsize;
327 }
else if(_scratchpadsize >= (size<<5)) {
328 newsize = _scratchpadsize >> 1;
329 _scratchpad = (
SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize);
330 _scratchpadsize = newsize;
341 void RefTable::Finalize()
343 RefNode *nodes = _nodes;
344 for(SQUnsignedInteger n = 0; n < _numofslots; n++) {
350 RefTable::~RefTable()
352 SQ_FREE(_buckets,(_numofslots *
sizeof(RefNode *)) + (_numofslots *
sizeof(RefNode)));
355 #ifndef NO_GARBAGE_COLLECTOR 356 void RefTable::Mark(SQCollectable **chain)
358 RefNode *nodes = (RefNode *)_nodes;
359 for(SQUnsignedInteger n = 0; n < _numofslots; n++) {
360 if(type(nodes->obj) != OT_NULL) {
361 SQSharedState::MarkObject(nodes->obj,chain);
368 void RefTable::AddRef(SQObject &obj)
372 RefNode *
ref = Get(obj,mainpos,&prev,
true);
376 SQBool RefTable::Release(SQObject &obj)
380 RefNode *
ref = Get(obj,mainpos,&prev,
false);
382 if(--ref->refs == 0) {
383 SQObjectPtr o = ref->obj;
385 prev->next = ref->next;
388 _buckets[mainpos] = ref->next;
390 ref->next = _freelist;
404 void RefTable::Resize(SQUnsignedInteger size)
406 RefNode **oldbucks = _buckets;
408 SQUnsignedInteger oldnumofslots = _numofslots;
411 SQUnsignedInteger nfound = 0;
412 for(SQUnsignedInteger n = 0; n < oldnumofslots; n++) {
413 if(type(t->obj) != OT_NULL) {
415 assert(t->refs != 0);
416 RefNode *nn =
Add(::HashObj(t->obj)&(_numofslots-1),t->obj);
423 assert(nfound == oldnumofslots);
424 SQ_FREE(oldbucks,(oldnumofslots *
sizeof(RefNode *)) + (oldnumofslots *
sizeof(RefNode)));
427 RefTable::RefNode *
RefTable::Add(SQHash mainpos,SQObject &obj)
429 RefNode *t = _buckets[mainpos];
430 RefNode *newnode = _freelist;
432 _buckets[mainpos] = newnode;
433 _freelist = _freelist->next;
435 assert(newnode->refs == 0);
440 RefTable::RefNode *RefTable::Get(SQObject &obj,SQHash &mainpos,RefNode **prev,
bool add)
443 mainpos = ::HashObj(obj)&(_numofslots-1);
445 for (ref = _buckets[mainpos];
ref; ) {
446 if(_rawval(ref->obj) == _rawval(obj) && type(ref->obj) == type(obj))
451 if(ref ==
NULL && add) {
452 if(_numofslots == _slotused) {
453 assert(_freelist == 0);
454 Resize(_numofslots*2);
455 mainpos = ::HashObj(obj)&(_numofslots-1);
457 ref =
Add(mainpos,obj);
462 void RefTable::AllocNodes(SQUnsignedInteger size)
466 bucks = (RefNode **)SQ_MALLOC((size *
sizeof(RefNode *)) + (size *
sizeof(RefNode)));
467 nodes = (RefNode *)&bucks[size];
468 RefNode *temp = nodes;
470 for(n = 0; n < size - 1; n++) {
473 new (&temp->obj) SQObjectPtr;
479 new (&temp->obj) SQObjectPtr;
495 SQStringTable::SQStringTable()
501 SQStringTable::~SQStringTable()
503 SQ_FREE(_strings,
sizeof(SQString*)*_numofslots);
507 void SQStringTable::AllocNodes(SQInteger size)
510 _strings = (SQString**)SQ_MALLOC(
sizeof(SQString*)*_numofslots);
511 memset(_strings,0,
sizeof(SQString*)*_numofslots);
517 len = (SQInteger)scstrlen(news);
518 SQHash h = ::_hashstr(news,len)&(_numofslots-1);
520 for (s = _strings[h]; s; s = s->_next){
521 if(s->_len == len && (!memcmp(news,s->_val,rsl(len))))
525 SQString *t=(SQString *)SQ_MALLOC(rsl(len)+
sizeof(SQString));
527 memcpy(t->_val,news,rsl(len));
528 t->_val[len] = _SC(
'\0');
530 t->_hash = ::_hashstr(news,len);
531 t->_next = _strings[h];
534 if (_slotused > _numofslots)
535 Resize(_numofslots*2);
539 void SQStringTable::Resize(SQInteger size)
541 SQInteger oldsize=_numofslots;
542 SQString **oldtable=_strings;
544 for (SQInteger i=0; i<oldsize; i++){
545 SQString *p = oldtable[i];
547 SQString *next = p->_next;
548 SQHash h = p->_hash&(_numofslots-1);
549 p->_next = _strings[h];
554 SQ_FREE(oldtable,oldsize*
sizeof(SQString*));
557 void SQStringTable::Remove(SQString *bs)
561 SQHash h = bs->_hash&(_numofslots - 1);
563 for (s = _strings[h]; s; ){
566 prev->_next = s->_next;
568 _strings[h] = s->_next;
570 SQInteger slen = s->_len;
572 SQ_FREE(s,
sizeof(SQString) + rsl(slen));
DLLIMPORT bool Add(const wxString &name, const wxString &mask)
Add a new extension filter.
SQObjectPtr _false_(false)
SQObjectPtr _one_((SQInteger) 1)
bool CompileTypemask(SQIntVec &res, const SQChar *typemask)
const wxString ref(_T("&"))
SQObjectPtr _minusone_((SQInteger) -1)
SQTable * CreateDefaultDelegate(SQSharedState *ss, SQRegFunction *funcz)