SQObjectPtr _null_;
SQObjectPtr _true_(true);
SQObjectPtr _false_(false);
-SQObjectPtr _one_(1);
-SQObjectPtr _minusone_(-1);
+SQObjectPtr _one_((SQInteger)1);
+SQObjectPtr _minusone_((SQInteger)-1);
SQSharedState::SQSharedState()
{
_compilererrorhandler = NULL;
_printfunc = NULL;
_debuginfo = false;
+ _notifyallexceptions = false;
}
#define newsysstring(s) { \
bool CompileTypemask(SQIntVec &res,const SQChar *typemask)
{
- int i = 0;
-
- int mask = 0;
+ SQInteger i = 0;
+
+ SQInteger mask = 0;
while(typemask[i] != 0) {
-
+
switch(typemask[i]){
case 'o': mask |= _RT_NULL; break;
case 'i': mask |= _RT_INTEGER; break;
case 'v': mask |= _RT_THREAD; break;
case 'x': mask |= _RT_INSTANCE; break;
case 'y': mask |= _RT_CLASS; break;
+ case 'r': mask |= _RT_WEAKREF; break;
case '.': mask = -1; res.push_back(mask); i++; mask = 0; continue;
case ' ': i++; continue; //ignores spaces
default:
return false;
}
i++;
- if(typemask[i] == '|') {
- i++;
+ if(typemask[i] == '|') {
+ i++;
if(typemask[i] == 0)
return false;
- continue;
+ continue;
}
res.push_back(mask);
mask = 0;
-
+
}
return true;
}
SQTable *CreateDefaultDelegate(SQSharedState *ss,SQRegFunction *funcz)
{
- int i=0;
+ SQInteger i=0;
SQTable *t=SQTable::Create(ss,0);
while(funcz[i].name!=0){
SQNativeClosure *nc = SQNativeClosure::Create(ss,funcz[i].f);
}
void SQSharedState::Init()
-{
+{
_scratchpad=NULL;
_scratchpadsize=0;
#ifndef NO_GARBAGE_COLLECTOR
newmetamethod(MM_CLONED);
newmetamethod(MM_NEWSLOT);
newmetamethod(MM_DELSLOT);
+ newmetamethod(MM_TOSTRING);
+ newmetamethod(MM_NEWMEMBER);
+ newmetamethod(MM_INHERITED);
_constructoridx = SQString::Create(this,_SC("constructor"));
- _refs_table = SQTable::Create(this,0);
_registry = SQTable::Create(this,0);
_table_default_delegate=CreateDefaultDelegate(this,_table_default_delegate_funcz);
_array_default_delegate=CreateDefaultDelegate(this,_array_default_delegate_funcz);
_thread_default_delegate=CreateDefaultDelegate(this,_thread_default_delegate_funcz);
_class_default_delegate=CreateDefaultDelegate(this,_class_default_delegate_funcz);
_instance_default_delegate=CreateDefaultDelegate(this,_instance_default_delegate_funcz);
+ _weakref_default_delegate=CreateDefaultDelegate(this,_weakref_default_delegate_funcz);
}
SQSharedState::~SQSharedState()
{
_constructoridx = _null_;
- _table(_refs_table)->Finalize();
+ _refs_table.Finalize();
_table(_registry)->Finalize();
_table(_metamethodsmap)->Finalize();
- _refs_table = _null_;
+// _refs_table = _null_;
_registry = _null_;
_metamethodsmap = _null_;
while(!_systemstrings->empty()){
_thread_default_delegate=_null_;
_class_default_delegate=_null_;
_instance_default_delegate=_null_;
-
+ _weakref_default_delegate=_null_;
+
#ifndef NO_GARBAGE_COLLECTOR
-
-
+
+
SQCollectable *t=_gc_chain;
SQCollectable *nx=NULL;
while(t){
case OT_THREAD:_thread(o)->Mark(chain);break;
case OT_CLASS:_class(o)->Mark(chain);break;
case OT_INSTANCE:_instance(o)->Mark(chain);break;
+ default: break; //shutup compiler
}
}
-int SQSharedState::CollectGarbage(SQVM *vm)
+SQInteger SQSharedState::CollectGarbage(SQVM *vm)
{
- int n=0;
+ SQInteger n=0;
SQCollectable *tchain=NULL;
SQVM *vms=_thread(_root_vm);
-
+
vms->Mark(&tchain);
- int x = _table(_thread(_root_vm)->_roottable)->CountUsed();
- MarkObject(_refs_table,&tchain);
+ SQInteger x = _table(_thread(_root_vm)->_roottable)->CountUsed();
+ _refs_table.Mark(&tchain);
MarkObject(_registry,&tchain);
MarkObject(_metamethodsmap,&tchain);
MarkObject(_table_default_delegate,&tchain);
MarkObject(_closure_default_delegate,&tchain);
MarkObject(_class_default_delegate,&tchain);
MarkObject(_instance_default_delegate,&tchain);
-
+ MarkObject(_weakref_default_delegate,&tchain);
+
SQCollectable *t=_gc_chain;
SQCollectable *nx=NULL;
while(t){
t=t->_next;
}
_gc_chain=tchain;
- int z = _table(_thread(_root_vm)->_roottable)->CountUsed();
+ SQInteger z = _table(_thread(_root_vm)->_roottable)->CountUsed();
assert(z == x);
return n;
}
}
#endif
-SQChar* SQSharedState::GetScratchPad(int size)
+SQChar* SQSharedState::GetScratchPad(SQInteger size)
{
- int newsize;
+ SQInteger newsize;
if(size>0){
if(_scratchpadsize<size){
newsize=size+(size>>1);
return _scratchpad;
}
+RefTable::RefTable()
+{
+ AllocNodes(4);
+}
+
+void RefTable::Finalize()
+{
+ RefNode *nodes = (RefNode *)&_buckets[_numofslots];
+ for(SQUnsignedInteger n = 0; n < _numofslots; n++) {
+ nodes->obj = _null_;
+ nodes++;
+ }
+}
+
+RefTable::~RefTable()
+{
+ SQ_FREE(_buckets,_buffersize);
+}
+#ifndef NO_GARBAGE_COLLECTOR
+void RefTable::Mark(SQCollectable **chain)
+{
+ RefNode *nodes = (RefNode *)&_buckets[_numofslots];
+ for(SQUnsignedInteger n = 0; n < _numofslots; n++) {
+ if(type(nodes->obj) != OT_NULL) {
+ SQSharedState::MarkObject(nodes->obj,chain);
+ }
+ nodes++;
+ }
+}
+#endif
+void RefTable::AddRef(SQObject &obj)
+{
+ SQHash mainpos;
+ RefNode *prev;
+ RefNode *ref = Get(obj,mainpos,&prev,true);
+ ref->refs++;
+}
+
+SQBool RefTable::Release(SQObject &obj)
+{
+ SQHash mainpos;
+ RefNode *prev;
+ RefNode *ref = Get(obj,mainpos,&prev,false);
+ if(ref) {
+ if(--ref->refs == 0) {
+ ref->obj = _null_;
+ if(prev) {
+ prev->next = ref->next;
+ }
+ else {
+ _buckets[mainpos] = ref->next;
+ }
+ ref->next = _freelist;
+ _freelist = ref;
+ _slotused--;
+ //<<FIXME>>test for shrink?
+ return SQTrue;
+ }
+ }
+ return SQFalse;
+}
+
+void RefTable::Resize(SQUnsignedInteger size)
+{
+ RefNode **oldbuffer = _buckets;
+ RefNode *oldnodes = (RefNode *)&_buckets[_numofslots];
+ SQUnsignedInteger oldnumofslots = _numofslots;
+ SQUnsignedInteger oldbuffersize = _buffersize;
+ AllocNodes(size);
+ //rehash
+ for(SQUnsignedInteger n = 0; n < oldnumofslots; n++) {
+ if(type(oldnodes->obj) != OT_NULL) {
+ //add back;
+ assert(oldnodes->refs != 0);
+ RefNode *nn = Add(::HashObj(oldnodes->obj)&(_numofslots-1),oldnodes->obj);
+ nn->refs = oldnodes->refs;
+ oldnodes->obj = _null_;
+ }
+ oldnodes++;
+ }
+ SQ_FREE(oldbuffer,oldbuffersize);
+}
+
+RefTable::RefNode *RefTable::Add(SQHash mainpos,SQObject &obj)
+{
+ RefNode *t = _buckets[mainpos];
+ RefNode *newnode = _freelist;
+ newnode->obj = obj;
+ _buckets[mainpos] = newnode;
+ _freelist = _freelist->next;
+ newnode->next = t;
+ assert(newnode->refs == 0);
+ _slotused++;
+ return newnode;
+}
+
+RefTable::RefNode *RefTable::Get(SQObject &obj,SQHash &mainpos,RefNode **prev,bool add)
+{
+ RefNode *ref;
+ mainpos = ::HashObj(obj)&(_numofslots-1);
+ *prev = NULL;
+ for (ref = _buckets[mainpos]; ref; ) {
+ if(_rawval(ref->obj) == _rawval(obj) && type(ref->obj) == type(obj))
+ break;
+ *prev = ref;
+ ref = ref->next;
+ }
+ if(ref == NULL && add) {
+ if(_numofslots == _slotused) {
+ Resize(_numofslots*2);
+ }
+ ref = Add(mainpos,obj);
+ }
+ return ref;
+}
+
+void RefTable::AllocNodes(SQUnsignedInteger size)
+{
+ RefNode **bucks;
+ RefNode *firstnode;
+ _buffersize = size * sizeof(RefNode *) + size * sizeof(RefNode);
+ bucks = (RefNode **)SQ_MALLOC(_buffersize);
+ firstnode = (RefNode *)&bucks[size];
+ RefNode *temp = firstnode;
+ SQUnsignedInteger n;
+ for(n = 0; n < size - 1; n++) {
+ bucks[n] = NULL;
+ temp->refs = 0;
+ new (&temp->obj) SQObjectPtr;
+ temp->next = temp+1;
+ temp++;
+ }
+ bucks[n] = NULL;
+ temp->refs = 0;
+ new (&temp->obj) SQObjectPtr;
+ temp->next = NULL;
+ _freelist = firstnode;
+ _buckets = bucks;
+ _slotused = 0;
+ _numofslots = size;
+}
//////////////////////////////////////////////////////////////////////////
//StringTable
/*
* http://www.lua.org/source/4.0.1/src_lstring.c.html
*/
-int SQString::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)
-{
- int idx = (int)TranslateIndex(refpos);
- while(idx < _len){
- outkey = (SQInteger)idx;
- outval = SQInteger(_val[idx]);
- //return idx for the next iteration
- return ++idx;
- }
- //nothing to iterate anymore
- return -1;
-}
-
StringTable::StringTable()
{
AllocNodes(4);
_strings=NULL;
}
-void StringTable::AllocNodes(int size)
+void StringTable::AllocNodes(SQInteger size)
{
_numofslots=size;
//_slotused=0;
memset(_strings,0,sizeof(SQString*)*_numofslots);
}
-SQString *StringTable::Add(const SQChar *news,int len)
+SQString *StringTable::Add(const SQChar *news,SQInteger len)
{
if(len<0)
- len=scstrlen(news);
- unsigned int h=::_hashstr(news,len)&(_numofslots-1);
+ len = (SQInteger)scstrlen(news);
+ SQHash h = ::_hashstr(news,len)&(_numofslots-1);
SQString *s;
for (s = _strings[h]; s; s = s->_next){
if(s->_len == len && (!memcmp(news,s->_val,rsl(len))))
SQString *t=(SQString *)SQ_MALLOC(rsl(len)+sizeof(SQString));
new (t) SQString;
memcpy(t->_val,news,rsl(len));
- t->_val[len]=_SC('\0');
- t->_len=len;
- t->_hash=::_hashstr(news,len);
- t->_next=_strings[h];
- t->_uiRef=0;
- _strings[h]=t;
+ t->_val[len] = _SC('\0');
+ t->_len = len;
+ t->_hash = ::_hashstr(news,len);
+ t->_next = _strings[h];
+ _strings[h] = t;
_slotused++;
if (_slotused > _numofslots) /* too crowded? */
Resize(_numofslots*2);
return t;
}
-void StringTable::Resize(int size)
+void StringTable::Resize(SQInteger size)
{
- int oldsize=_numofslots;
+ SQInteger oldsize=_numofslots;
SQString **oldtable=_strings;
AllocNodes(size);
- for (int i=0; i<oldsize; i++){
+ for (SQInteger i=0; i<oldsize; i++){
SQString *p = oldtable[i];
while(p){
SQString *next = p->_next;
- unsigned int h=p->_hash&(_numofslots-1);
- p->_next=_strings[h];
+ SQHash h = p->_hash&(_numofslots-1);
+ p->_next = _strings[h];
_strings[h] = p;
- p=next;
+ p = next;
}
}
SQ_FREE(oldtable,oldsize*sizeof(SQString*));
{
SQString *s;
SQString *prev=NULL;
- unsigned int h=bs->_hash&(_numofslots-1);
-
+ SQHash h = bs->_hash&(_numofslots - 1);
+
for (s = _strings[h]; s; ){
if(s == bs){
if(prev)
else
_strings[h] = s->_next;
_slotused--;
- int slen=s->_len;
+ SQInteger slen = s->_len;
s->~SQString();
- SQ_FREE(s,sizeof(SQString)+rsl(slen));
+ SQ_FREE(s,sizeof(SQString) + rsl(slen));
return;
}
prev = s;