diff options
author | cedeel@gmail.com <cedeel@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6> | 2012-06-14 15:06:06 +0200 |
---|---|---|
committer | cedeel@gmail.com <cedeel@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6> | 2012-06-14 15:06:06 +0200 |
commit | 92c59963f82f81aa3202657e7fdbb2592924ede3 (patch) | |
tree | b7eb2474528a4998fa102e3ec9119b908cee08b4 /squirrel_3_0_1_stable/squirrel/sqstate.cpp | |
parent | Added HOOK_WEATHER_CHANGE. (diff) | |
download | cuberite-92c59963f82f81aa3202657e7fdbb2592924ede3.tar cuberite-92c59963f82f81aa3202657e7fdbb2592924ede3.tar.gz cuberite-92c59963f82f81aa3202657e7fdbb2592924ede3.tar.bz2 cuberite-92c59963f82f81aa3202657e7fdbb2592924ede3.tar.lz cuberite-92c59963f82f81aa3202657e7fdbb2592924ede3.tar.xz cuberite-92c59963f82f81aa3202657e7fdbb2592924ede3.tar.zst cuberite-92c59963f82f81aa3202657e7fdbb2592924ede3.zip |
Diffstat (limited to 'squirrel_3_0_1_stable/squirrel/sqstate.cpp')
-rw-r--r-- | squirrel_3_0_1_stable/squirrel/sqstate.cpp | 1296 |
1 files changed, 648 insertions, 648 deletions
diff --git a/squirrel_3_0_1_stable/squirrel/sqstate.cpp b/squirrel_3_0_1_stable/squirrel/sqstate.cpp index 0bee40661..8e77900f3 100644 --- a/squirrel_3_0_1_stable/squirrel/sqstate.cpp +++ b/squirrel_3_0_1_stable/squirrel/sqstate.cpp @@ -1,648 +1,648 @@ -/*
- see copyright notice in squirrel.h
-*/
-#include "sqpcheader.h"
-#include "sqopcodes.h"
-#include "sqvm.h"
-#include "sqfuncproto.h"
-#include "sqclosure.h"
-#include "sqstring.h"
-#include "sqtable.h"
-#include "sqarray.h"
-#include "squserdata.h"
-#include "sqclass.h"
-
-//SQObjectPtr _null_;
-//SQObjectPtr _true_(true);
-//SQObjectPtr _false_(false);
-//SQObjectPtr _one_((SQInteger)1);
-//SQObjectPtr _minusone_((SQInteger)-1);
-
-SQSharedState::SQSharedState()
-{
- _compilererrorhandler = NULL;
- _printfunc = NULL;
- _errorfunc = NULL;
- _debuginfo = false;
- _notifyallexceptions = false;
-}
-
-#define newsysstring(s) { \
- _systemstrings->push_back(SQString::Create(this,s)); \
- }
-
-#define newmetamethod(s) { \
- _metamethods->push_back(SQString::Create(this,s)); \
- _table(_metamethodsmap)->NewSlot(_metamethods->back(),(SQInteger)(_metamethods->size()-1)); \
- }
-
-bool CompileTypemask(SQIntVec &res,const SQChar *typemask)
-{
- 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 'f': mask |= _RT_FLOAT; break;
- case 'n': mask |= (_RT_FLOAT | _RT_INTEGER); break;
- case 's': mask |= _RT_STRING; break;
- case 't': mask |= _RT_TABLE; break;
- case 'a': mask |= _RT_ARRAY; break;
- case 'u': mask |= _RT_USERDATA; break;
- case 'c': mask |= (_RT_CLOSURE | _RT_NATIVECLOSURE); break;
- case 'b': mask |= _RT_BOOL; break;
- case 'g': mask |= _RT_GENERATOR; break;
- case 'p': mask |= _RT_USERPOINTER; 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] == 0)
- return false;
- continue;
- }
- res.push_back(mask);
- mask = 0;
-
- }
- return true;
-}
-
-SQTable *CreateDefaultDelegate(SQSharedState *ss,SQRegFunction *funcz)
-{
- SQInteger i=0;
- SQTable *t=SQTable::Create(ss,0);
- while(funcz[i].name!=0){
- SQNativeClosure *nc = SQNativeClosure::Create(ss,funcz[i].f,0);
- nc->_nparamscheck = funcz[i].nparamscheck;
- nc->_name = SQString::Create(ss,funcz[i].name);
- if(funcz[i].typemask && !CompileTypemask(nc->_typecheck,funcz[i].typemask))
- return NULL;
- t->NewSlot(SQString::Create(ss,funcz[i].name),nc);
- i++;
- }
- return t;
-}
-
-void SQSharedState::Init()
-{
- _scratchpad=NULL;
- _scratchpadsize=0;
-#ifndef NO_GARBAGE_COLLECTOR
- _gc_chain=NULL;
-#endif
- _stringtable = (SQStringTable*)SQ_MALLOC(sizeof(SQStringTable));
- new (_stringtable) SQStringTable(this);
- sq_new(_metamethods,SQObjectPtrVec);
- sq_new(_systemstrings,SQObjectPtrVec);
- sq_new(_types,SQObjectPtrVec);
- _metamethodsmap = SQTable::Create(this,MT_LAST-1);
- //adding type strings to avoid memory trashing
- //types names
- newsysstring(_SC("null"));
- newsysstring(_SC("table"));
- newsysstring(_SC("array"));
- newsysstring(_SC("closure"));
- newsysstring(_SC("string"));
- newsysstring(_SC("userdata"));
- newsysstring(_SC("integer"));
- newsysstring(_SC("float"));
- newsysstring(_SC("userpointer"));
- newsysstring(_SC("function"));
- newsysstring(_SC("generator"));
- newsysstring(_SC("thread"));
- newsysstring(_SC("class"));
- newsysstring(_SC("instance"));
- newsysstring(_SC("bool"));
- //meta methods
- newmetamethod(MM_ADD);
- newmetamethod(MM_SUB);
- newmetamethod(MM_MUL);
- newmetamethod(MM_DIV);
- newmetamethod(MM_UNM);
- newmetamethod(MM_MODULO);
- newmetamethod(MM_SET);
- newmetamethod(MM_GET);
- newmetamethod(MM_TYPEOF);
- newmetamethod(MM_NEXTI);
- newmetamethod(MM_CMP);
- newmetamethod(MM_CALL);
- newmetamethod(MM_CLONED);
- newmetamethod(MM_NEWSLOT);
- newmetamethod(MM_DELSLOT);
- newmetamethod(MM_TOSTRING);
- newmetamethod(MM_NEWMEMBER);
- newmetamethod(MM_INHERITED);
-
- _constructoridx = SQString::Create(this,_SC("constructor"));
- _registry = SQTable::Create(this,0);
- _consts = SQTable::Create(this,0);
- _table_default_delegate = CreateDefaultDelegate(this,_table_default_delegate_funcz);
- _array_default_delegate = CreateDefaultDelegate(this,_array_default_delegate_funcz);
- _string_default_delegate = CreateDefaultDelegate(this,_string_default_delegate_funcz);
- _number_default_delegate = CreateDefaultDelegate(this,_number_default_delegate_funcz);
- _closure_default_delegate = CreateDefaultDelegate(this,_closure_default_delegate_funcz);
- _generator_default_delegate = CreateDefaultDelegate(this,_generator_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(_registry)->Finalize();
- _table(_consts)->Finalize();
- _table(_metamethodsmap)->Finalize();
- _registry.Null();
- _consts.Null();
- _metamethodsmap.Null();
- while(!_systemstrings->empty()) {
- _systemstrings->back().Null();
- _systemstrings->pop_back();
- }
- _thread(_root_vm)->Finalize();
- _root_vm.Null();
- _table_default_delegate.Null();
- _array_default_delegate.Null();
- _string_default_delegate.Null();
- _number_default_delegate.Null();
- _closure_default_delegate.Null();
- _generator_default_delegate.Null();
- _thread_default_delegate.Null();
- _class_default_delegate.Null();
- _instance_default_delegate.Null();
- _weakref_default_delegate.Null();
- _refs_table.Finalize();
-#ifndef NO_GARBAGE_COLLECTOR
- SQCollectable *t = _gc_chain;
- SQCollectable *nx = NULL;
- while(t) {
- t->_uiRef++;
- t->Finalize();
- nx = t->_next;
- if(--t->_uiRef == 0)
- t->Release();
- t=nx;
- }
- assert(_gc_chain==NULL); //just to proove a theory
- while(_gc_chain){
- _gc_chain->_uiRef++;
- _gc_chain->Release();
- }
-#endif
-
- sq_delete(_types,SQObjectPtrVec);
- sq_delete(_systemstrings,SQObjectPtrVec);
- sq_delete(_metamethods,SQObjectPtrVec);
- sq_delete(_stringtable,SQStringTable);
- if(_scratchpad)SQ_FREE(_scratchpad,_scratchpadsize);
-}
-
-
-SQInteger SQSharedState::GetMetaMethodIdxByName(const SQObjectPtr &name)
-{
- if(type(name) != OT_STRING)
- return -1;
- SQObjectPtr ret;
- if(_table(_metamethodsmap)->Get(name,ret)) {
- return _integer(ret);
- }
- return -1;
-}
-
-#ifndef NO_GARBAGE_COLLECTOR
-
-void SQSharedState::MarkObject(SQObjectPtr &o,SQCollectable **chain)
-{
- switch(type(o)){
- case OT_TABLE:_table(o)->Mark(chain);break;
- case OT_ARRAY:_array(o)->Mark(chain);break;
- case OT_USERDATA:_userdata(o)->Mark(chain);break;
- case OT_CLOSURE:_closure(o)->Mark(chain);break;
- case OT_NATIVECLOSURE:_nativeclosure(o)->Mark(chain);break;
- case OT_GENERATOR:_generator(o)->Mark(chain);break;
- case OT_THREAD:_thread(o)->Mark(chain);break;
- case OT_CLASS:_class(o)->Mark(chain);break;
- case OT_INSTANCE:_instance(o)->Mark(chain);break;
- case OT_OUTER:_outer(o)->Mark(chain);break;
- case OT_FUNCPROTO:_funcproto(o)->Mark(chain);break;
- default: break; //shutup compiler
- }
-}
-
-
-void SQSharedState::RunMark(SQVM *vm,SQCollectable **tchain)
-{
- SQVM *vms = _thread(_root_vm);
-
- vms->Mark(tchain);
-
- _refs_table.Mark(tchain);
- MarkObject(_registry,tchain);
- MarkObject(_consts,tchain);
- MarkObject(_metamethodsmap,tchain);
- MarkObject(_table_default_delegate,tchain);
- MarkObject(_array_default_delegate,tchain);
- MarkObject(_string_default_delegate,tchain);
- MarkObject(_number_default_delegate,tchain);
- MarkObject(_generator_default_delegate,tchain);
- MarkObject(_thread_default_delegate,tchain);
- MarkObject(_closure_default_delegate,tchain);
- MarkObject(_class_default_delegate,tchain);
- MarkObject(_instance_default_delegate,tchain);
- MarkObject(_weakref_default_delegate,tchain);
-
-}
-
-SQInteger SQSharedState::ResurrectUnreachable(SQVM *vm)
-{
- SQInteger n=0;
- SQCollectable *tchain=NULL;
-
- RunMark(vm,&tchain);
-
- SQCollectable *resurrected = _gc_chain;
- SQCollectable *t = resurrected;
- //SQCollectable *nx = NULL;
-
- _gc_chain = tchain;
-
- SQArray *ret = NULL;
- if(resurrected) {
- ret = SQArray::Create(this,0);
- SQCollectable *rlast = NULL;
- while(t) {
- rlast = t;
- SQObjectType type = t->GetType();
- if(type != OT_FUNCPROTO && type != OT_OUTER) {
- SQObject sqo;
- sqo._type = type;
- sqo._unVal.pRefCounted = t;
- ret->Append(sqo);
- }
- t = t->_next;
- n++;
- }
-
- assert(rlast->_next == NULL);
- rlast->_next = _gc_chain;
- if(_gc_chain)
- {
- _gc_chain->_prev = rlast;
- }
- _gc_chain = resurrected;
- }
-
- t = _gc_chain;
- while(t) {
- t->UnMark();
- t = t->_next;
- }
-
- if(ret) {
- SQObjectPtr temp = ret;
- vm->Push(temp);
- }
- else {
- vm->PushNull();
- }
- return n;
-}
-
-SQInteger SQSharedState::CollectGarbage(SQVM *vm)
-{
- SQInteger n=0;
- SQCollectable *tchain=NULL;
-
- RunMark(vm,&tchain);
-
- SQCollectable *t = _gc_chain;
- SQCollectable *nx = NULL;
- while(t) {
- t->_uiRef++;
- t->Finalize();
- nx = t->_next;
- if(--t->_uiRef == 0)
- t->Release();
- t = nx;
- n++;
- }
-
- t = tchain;
- while(t) {
- t->UnMark();
- t = t->_next;
- }
- _gc_chain = tchain;
-
- return n;
-}
-#endif
-
-#ifndef NO_GARBAGE_COLLECTOR
-void SQCollectable::AddToChain(SQCollectable **chain,SQCollectable *c)
-{
- c->_prev = NULL;
- c->_next = *chain;
- if(*chain) (*chain)->_prev = c;
- *chain = c;
-}
-
-void SQCollectable::RemoveFromChain(SQCollectable **chain,SQCollectable *c)
-{
- if(c->_prev) c->_prev->_next = c->_next;
- else *chain = c->_next;
- if(c->_next)
- c->_next->_prev = c->_prev;
- c->_next = NULL;
- c->_prev = NULL;
-}
-#endif
-
-SQChar* SQSharedState::GetScratchPad(SQInteger size)
-{
- SQInteger newsize;
- if(size>0) {
- if(_scratchpadsize < size) {
- newsize = size + (size>>1);
- _scratchpad = (SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize);
- _scratchpadsize = newsize;
-
- }else if(_scratchpadsize >= (size<<5)) {
- newsize = _scratchpadsize >> 1;
- _scratchpad = (SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize);
- _scratchpadsize = newsize;
- }
- }
- return _scratchpad;
-}
-
-RefTable::RefTable()
-{
- AllocNodes(4);
-}
-
-void RefTable::Finalize()
-{
- RefNode *nodes = _nodes;
- for(SQUnsignedInteger n = 0; n < _numofslots; n++) {
- nodes->obj.Null();
- nodes++;
- }
-}
-
-RefTable::~RefTable()
-{
- SQ_FREE(_buckets,(_numofslots * sizeof(RefNode *)) + (_numofslots * sizeof(RefNode)));
-}
-
-#ifndef NO_GARBAGE_COLLECTOR
-void RefTable::Mark(SQCollectable **chain)
-{
- RefNode *nodes = (RefNode *)_nodes;
- 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++;
-}
-
-SQUnsignedInteger RefTable::GetRefCount(SQObject &obj)
-{
- SQHash mainpos;
- RefNode *prev;
- RefNode *ref = Get(obj,mainpos,&prev,true);
- return ref->refs;
-}
-
-
-SQBool RefTable::Release(SQObject &obj)
-{
- SQHash mainpos;
- RefNode *prev;
- RefNode *ref = Get(obj,mainpos,&prev,false);
- if(ref) {
- if(--ref->refs == 0) {
- SQObjectPtr o = ref->obj;
- if(prev) {
- prev->next = ref->next;
- }
- else {
- _buckets[mainpos] = ref->next;
- }
- ref->next = _freelist;
- _freelist = ref;
- _slotused--;
- ref->obj.Null();
- //<<FIXME>>test for shrink?
- return SQTrue;
- }
- }
- else {
- assert(0);
- }
- return SQFalse;
-}
-
-void RefTable::Resize(SQUnsignedInteger size)
-{
- RefNode **oldbucks = _buckets;
- RefNode *t = _nodes;
- SQUnsignedInteger oldnumofslots = _numofslots;
- AllocNodes(size);
- //rehash
- SQUnsignedInteger nfound = 0;
- for(SQUnsignedInteger n = 0; n < oldnumofslots; n++) {
- if(type(t->obj) != OT_NULL) {
- //add back;
- assert(t->refs != 0);
- RefNode *nn = Add(::HashObj(t->obj)&(_numofslots-1),t->obj);
- nn->refs = t->refs;
- t->obj.Null();
- nfound++;
- }
- t++;
- }
- assert(nfound == oldnumofslots);
- SQ_FREE(oldbucks,(oldnumofslots * sizeof(RefNode *)) + (oldnumofslots * sizeof(RefNode)));
-}
-
-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) {
- assert(_freelist == 0);
- Resize(_numofslots*2);
- mainpos = ::HashObj(obj)&(_numofslots-1);
- }
- ref = Add(mainpos,obj);
- }
- return ref;
-}
-
-void RefTable::AllocNodes(SQUnsignedInteger size)
-{
- RefNode **bucks;
- RefNode *nodes;
- bucks = (RefNode **)SQ_MALLOC((size * sizeof(RefNode *)) + (size * sizeof(RefNode)));
- nodes = (RefNode *)&bucks[size];
- RefNode *temp = nodes;
- 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 = nodes;
- _nodes = nodes;
- _buckets = bucks;
- _slotused = 0;
- _numofslots = size;
-}
-//////////////////////////////////////////////////////////////////////////
-//SQStringTable
-/*
-* The following code is based on Lua 4.0 (Copyright 1994-2002 Tecgraf, PUC-Rio.)
-* http://www.lua.org/copyright.html#4
-* http://www.lua.org/source/4.0.1/src_lstring.c.html
-*/
-
-SQStringTable::SQStringTable(SQSharedState *ss)
-{
- _sharedstate = ss;
- AllocNodes(4);
- _slotused = 0;
-}
-
-SQStringTable::~SQStringTable()
-{
- SQ_FREE(_strings,sizeof(SQString*)*_numofslots);
- _strings = NULL;
-}
-
-void SQStringTable::AllocNodes(SQInteger size)
-{
- _numofslots = size;
- _strings = (SQString**)SQ_MALLOC(sizeof(SQString*)*_numofslots);
- memset(_strings,0,sizeof(SQString*)*_numofslots);
-}
-
-SQString *SQStringTable::Add(const SQChar *news,SQInteger len)
-{
- if(len<0)
- 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))))
- return s; //found
- }
-
- SQString *t=(SQString *)SQ_MALLOC(rsl(len)+sizeof(SQString));
- new (t) SQString;
- t->_sharedstate = _sharedstate;
- memcpy(t->_val,news,rsl(len));
- 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 SQStringTable::Resize(SQInteger size)
-{
- SQInteger oldsize=_numofslots;
- SQString **oldtable=_strings;
- AllocNodes(size);
- for (SQInteger i=0; i<oldsize; i++){
- SQString *p = oldtable[i];
- while(p){
- SQString *next = p->_next;
- SQHash h = p->_hash&(_numofslots-1);
- p->_next = _strings[h];
- _strings[h] = p;
- p = next;
- }
- }
- SQ_FREE(oldtable,oldsize*sizeof(SQString*));
-}
-
-void SQStringTable::Remove(SQString *bs)
-{
- SQString *s;
- SQString *prev=NULL;
- SQHash h = bs->_hash&(_numofslots - 1);
-
- for (s = _strings[h]; s; ){
- if(s == bs){
- if(prev)
- prev->_next = s->_next;
- else
- _strings[h] = s->_next;
- _slotused--;
- SQInteger slen = s->_len;
- s->~SQString();
- SQ_FREE(s,sizeof(SQString) + rsl(slen));
- return;
- }
- prev = s;
- s = s->_next;
- }
- assert(0);//if this fail something is wrong
-}
+/* + see copyright notice in squirrel.h +*/ +#include "sqpcheader.h" +#include "sqopcodes.h" +#include "sqvm.h" +#include "sqfuncproto.h" +#include "sqclosure.h" +#include "sqstring.h" +#include "sqtable.h" +#include "sqarray.h" +#include "squserdata.h" +#include "sqclass.h" + +//SQObjectPtr _null_; +//SQObjectPtr _true_(true); +//SQObjectPtr _false_(false); +//SQObjectPtr _one_((SQInteger)1); +//SQObjectPtr _minusone_((SQInteger)-1); + +SQSharedState::SQSharedState() +{ + _compilererrorhandler = NULL; + _printfunc = NULL; + _errorfunc = NULL; + _debuginfo = false; + _notifyallexceptions = false; +} + +#define newsysstring(s) { \ + _systemstrings->push_back(SQString::Create(this,s)); \ + } + +#define newmetamethod(s) { \ + _metamethods->push_back(SQString::Create(this,s)); \ + _table(_metamethodsmap)->NewSlot(_metamethods->back(),(SQInteger)(_metamethods->size()-1)); \ + } + +bool CompileTypemask(SQIntVec &res,const SQChar *typemask) +{ + 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 'f': mask |= _RT_FLOAT; break; + case 'n': mask |= (_RT_FLOAT | _RT_INTEGER); break; + case 's': mask |= _RT_STRING; break; + case 't': mask |= _RT_TABLE; break; + case 'a': mask |= _RT_ARRAY; break; + case 'u': mask |= _RT_USERDATA; break; + case 'c': mask |= (_RT_CLOSURE | _RT_NATIVECLOSURE); break; + case 'b': mask |= _RT_BOOL; break; + case 'g': mask |= _RT_GENERATOR; break; + case 'p': mask |= _RT_USERPOINTER; 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] == 0) + return false; + continue; + } + res.push_back(mask); + mask = 0; + + } + return true; +} + +SQTable *CreateDefaultDelegate(SQSharedState *ss,SQRegFunction *funcz) +{ + SQInteger i=0; + SQTable *t=SQTable::Create(ss,0); + while(funcz[i].name!=0){ + SQNativeClosure *nc = SQNativeClosure::Create(ss,funcz[i].f,0); + nc->_nparamscheck = funcz[i].nparamscheck; + nc->_name = SQString::Create(ss,funcz[i].name); + if(funcz[i].typemask && !CompileTypemask(nc->_typecheck,funcz[i].typemask)) + return NULL; + t->NewSlot(SQString::Create(ss,funcz[i].name),nc); + i++; + } + return t; +} + +void SQSharedState::Init() +{ + _scratchpad=NULL; + _scratchpadsize=0; +#ifndef NO_GARBAGE_COLLECTOR + _gc_chain=NULL; +#endif + _stringtable = (SQStringTable*)SQ_MALLOC(sizeof(SQStringTable)); + new (_stringtable) SQStringTable(this); + sq_new(_metamethods,SQObjectPtrVec); + sq_new(_systemstrings,SQObjectPtrVec); + sq_new(_types,SQObjectPtrVec); + _metamethodsmap = SQTable::Create(this,MT_LAST-1); + //adding type strings to avoid memory trashing + //types names + newsysstring(_SC("null")); + newsysstring(_SC("table")); + newsysstring(_SC("array")); + newsysstring(_SC("closure")); + newsysstring(_SC("string")); + newsysstring(_SC("userdata")); + newsysstring(_SC("integer")); + newsysstring(_SC("float")); + newsysstring(_SC("userpointer")); + newsysstring(_SC("function")); + newsysstring(_SC("generator")); + newsysstring(_SC("thread")); + newsysstring(_SC("class")); + newsysstring(_SC("instance")); + newsysstring(_SC("bool")); + //meta methods + newmetamethod(MM_ADD); + newmetamethod(MM_SUB); + newmetamethod(MM_MUL); + newmetamethod(MM_DIV); + newmetamethod(MM_UNM); + newmetamethod(MM_MODULO); + newmetamethod(MM_SET); + newmetamethod(MM_GET); + newmetamethod(MM_TYPEOF); + newmetamethod(MM_NEXTI); + newmetamethod(MM_CMP); + newmetamethod(MM_CALL); + newmetamethod(MM_CLONED); + newmetamethod(MM_NEWSLOT); + newmetamethod(MM_DELSLOT); + newmetamethod(MM_TOSTRING); + newmetamethod(MM_NEWMEMBER); + newmetamethod(MM_INHERITED); + + _constructoridx = SQString::Create(this,_SC("constructor")); + _registry = SQTable::Create(this,0); + _consts = SQTable::Create(this,0); + _table_default_delegate = CreateDefaultDelegate(this,_table_default_delegate_funcz); + _array_default_delegate = CreateDefaultDelegate(this,_array_default_delegate_funcz); + _string_default_delegate = CreateDefaultDelegate(this,_string_default_delegate_funcz); + _number_default_delegate = CreateDefaultDelegate(this,_number_default_delegate_funcz); + _closure_default_delegate = CreateDefaultDelegate(this,_closure_default_delegate_funcz); + _generator_default_delegate = CreateDefaultDelegate(this,_generator_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(_registry)->Finalize(); + _table(_consts)->Finalize(); + _table(_metamethodsmap)->Finalize(); + _registry.Null(); + _consts.Null(); + _metamethodsmap.Null(); + while(!_systemstrings->empty()) { + _systemstrings->back().Null(); + _systemstrings->pop_back(); + } + _thread(_root_vm)->Finalize(); + _root_vm.Null(); + _table_default_delegate.Null(); + _array_default_delegate.Null(); + _string_default_delegate.Null(); + _number_default_delegate.Null(); + _closure_default_delegate.Null(); + _generator_default_delegate.Null(); + _thread_default_delegate.Null(); + _class_default_delegate.Null(); + _instance_default_delegate.Null(); + _weakref_default_delegate.Null(); + _refs_table.Finalize(); +#ifndef NO_GARBAGE_COLLECTOR + SQCollectable *t = _gc_chain; + SQCollectable *nx = NULL; + while(t) { + t->_uiRef++; + t->Finalize(); + nx = t->_next; + if(--t->_uiRef == 0) + t->Release(); + t=nx; + } + assert(_gc_chain==NULL); //just to proove a theory + while(_gc_chain){ + _gc_chain->_uiRef++; + _gc_chain->Release(); + } +#endif + + sq_delete(_types,SQObjectPtrVec); + sq_delete(_systemstrings,SQObjectPtrVec); + sq_delete(_metamethods,SQObjectPtrVec); + sq_delete(_stringtable,SQStringTable); + if(_scratchpad)SQ_FREE(_scratchpad,_scratchpadsize); +} + + +SQInteger SQSharedState::GetMetaMethodIdxByName(const SQObjectPtr &name) +{ + if(type(name) != OT_STRING) + return -1; + SQObjectPtr ret; + if(_table(_metamethodsmap)->Get(name,ret)) { + return _integer(ret); + } + return -1; +} + +#ifndef NO_GARBAGE_COLLECTOR + +void SQSharedState::MarkObject(SQObjectPtr &o,SQCollectable **chain) +{ + switch(type(o)){ + case OT_TABLE:_table(o)->Mark(chain);break; + case OT_ARRAY:_array(o)->Mark(chain);break; + case OT_USERDATA:_userdata(o)->Mark(chain);break; + case OT_CLOSURE:_closure(o)->Mark(chain);break; + case OT_NATIVECLOSURE:_nativeclosure(o)->Mark(chain);break; + case OT_GENERATOR:_generator(o)->Mark(chain);break; + case OT_THREAD:_thread(o)->Mark(chain);break; + case OT_CLASS:_class(o)->Mark(chain);break; + case OT_INSTANCE:_instance(o)->Mark(chain);break; + case OT_OUTER:_outer(o)->Mark(chain);break; + case OT_FUNCPROTO:_funcproto(o)->Mark(chain);break; + default: break; //shutup compiler + } +} + + +void SQSharedState::RunMark(SQVM *vm,SQCollectable **tchain) +{ + SQVM *vms = _thread(_root_vm); + + vms->Mark(tchain); + + _refs_table.Mark(tchain); + MarkObject(_registry,tchain); + MarkObject(_consts,tchain); + MarkObject(_metamethodsmap,tchain); + MarkObject(_table_default_delegate,tchain); + MarkObject(_array_default_delegate,tchain); + MarkObject(_string_default_delegate,tchain); + MarkObject(_number_default_delegate,tchain); + MarkObject(_generator_default_delegate,tchain); + MarkObject(_thread_default_delegate,tchain); + MarkObject(_closure_default_delegate,tchain); + MarkObject(_class_default_delegate,tchain); + MarkObject(_instance_default_delegate,tchain); + MarkObject(_weakref_default_delegate,tchain); + +} + +SQInteger SQSharedState::ResurrectUnreachable(SQVM *vm) +{ + SQInteger n=0; + SQCollectable *tchain=NULL; + + RunMark(vm,&tchain); + + SQCollectable *resurrected = _gc_chain; + SQCollectable *t = resurrected; + //SQCollectable *nx = NULL; + + _gc_chain = tchain; + + SQArray *ret = NULL; + if(resurrected) { + ret = SQArray::Create(this,0); + SQCollectable *rlast = NULL; + while(t) { + rlast = t; + SQObjectType type = t->GetType(); + if(type != OT_FUNCPROTO && type != OT_OUTER) { + SQObject sqo; + sqo._type = type; + sqo._unVal.pRefCounted = t; + ret->Append(sqo); + } + t = t->_next; + n++; + } + + assert(rlast->_next == NULL); + rlast->_next = _gc_chain; + if(_gc_chain) + { + _gc_chain->_prev = rlast; + } + _gc_chain = resurrected; + } + + t = _gc_chain; + while(t) { + t->UnMark(); + t = t->_next; + } + + if(ret) { + SQObjectPtr temp = ret; + vm->Push(temp); + } + else { + vm->PushNull(); + } + return n; +} + +SQInteger SQSharedState::CollectGarbage(SQVM *vm) +{ + SQInteger n=0; + SQCollectable *tchain=NULL; + + RunMark(vm,&tchain); + + SQCollectable *t = _gc_chain; + SQCollectable *nx = NULL; + while(t) { + t->_uiRef++; + t->Finalize(); + nx = t->_next; + if(--t->_uiRef == 0) + t->Release(); + t = nx; + n++; + } + + t = tchain; + while(t) { + t->UnMark(); + t = t->_next; + } + _gc_chain = tchain; + + return n; +} +#endif + +#ifndef NO_GARBAGE_COLLECTOR +void SQCollectable::AddToChain(SQCollectable **chain,SQCollectable *c) +{ + c->_prev = NULL; + c->_next = *chain; + if(*chain) (*chain)->_prev = c; + *chain = c; +} + +void SQCollectable::RemoveFromChain(SQCollectable **chain,SQCollectable *c) +{ + if(c->_prev) c->_prev->_next = c->_next; + else *chain = c->_next; + if(c->_next) + c->_next->_prev = c->_prev; + c->_next = NULL; + c->_prev = NULL; +} +#endif + +SQChar* SQSharedState::GetScratchPad(SQInteger size) +{ + SQInteger newsize; + if(size>0) { + if(_scratchpadsize < size) { + newsize = size + (size>>1); + _scratchpad = (SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize); + _scratchpadsize = newsize; + + }else if(_scratchpadsize >= (size<<5)) { + newsize = _scratchpadsize >> 1; + _scratchpad = (SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize); + _scratchpadsize = newsize; + } + } + return _scratchpad; +} + +RefTable::RefTable() +{ + AllocNodes(4); +} + +void RefTable::Finalize() +{ + RefNode *nodes = _nodes; + for(SQUnsignedInteger n = 0; n < _numofslots; n++) { + nodes->obj.Null(); + nodes++; + } +} + +RefTable::~RefTable() +{ + SQ_FREE(_buckets,(_numofslots * sizeof(RefNode *)) + (_numofslots * sizeof(RefNode))); +} + +#ifndef NO_GARBAGE_COLLECTOR +void RefTable::Mark(SQCollectable **chain) +{ + RefNode *nodes = (RefNode *)_nodes; + 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++; +} + +SQUnsignedInteger RefTable::GetRefCount(SQObject &obj) +{ + SQHash mainpos; + RefNode *prev; + RefNode *ref = Get(obj,mainpos,&prev,true); + return ref->refs; +} + + +SQBool RefTable::Release(SQObject &obj) +{ + SQHash mainpos; + RefNode *prev; + RefNode *ref = Get(obj,mainpos,&prev,false); + if(ref) { + if(--ref->refs == 0) { + SQObjectPtr o = ref->obj; + if(prev) { + prev->next = ref->next; + } + else { + _buckets[mainpos] = ref->next; + } + ref->next = _freelist; + _freelist = ref; + _slotused--; + ref->obj.Null(); + //<<FIXME>>test for shrink? + return SQTrue; + } + } + else { + assert(0); + } + return SQFalse; +} + +void RefTable::Resize(SQUnsignedInteger size) +{ + RefNode **oldbucks = _buckets; + RefNode *t = _nodes; + SQUnsignedInteger oldnumofslots = _numofslots; + AllocNodes(size); + //rehash + SQUnsignedInteger nfound = 0; + for(SQUnsignedInteger n = 0; n < oldnumofslots; n++) { + if(type(t->obj) != OT_NULL) { + //add back; + assert(t->refs != 0); + RefNode *nn = Add(::HashObj(t->obj)&(_numofslots-1),t->obj); + nn->refs = t->refs; + t->obj.Null(); + nfound++; + } + t++; + } + assert(nfound == oldnumofslots); + SQ_FREE(oldbucks,(oldnumofslots * sizeof(RefNode *)) + (oldnumofslots * sizeof(RefNode))); +} + +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) { + assert(_freelist == 0); + Resize(_numofslots*2); + mainpos = ::HashObj(obj)&(_numofslots-1); + } + ref = Add(mainpos,obj); + } + return ref; +} + +void RefTable::AllocNodes(SQUnsignedInteger size) +{ + RefNode **bucks; + RefNode *nodes; + bucks = (RefNode **)SQ_MALLOC((size * sizeof(RefNode *)) + (size * sizeof(RefNode))); + nodes = (RefNode *)&bucks[size]; + RefNode *temp = nodes; + 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 = nodes; + _nodes = nodes; + _buckets = bucks; + _slotused = 0; + _numofslots = size; +} +////////////////////////////////////////////////////////////////////////// +//SQStringTable +/* +* The following code is based on Lua 4.0 (Copyright 1994-2002 Tecgraf, PUC-Rio.) +* http://www.lua.org/copyright.html#4 +* http://www.lua.org/source/4.0.1/src_lstring.c.html +*/ + +SQStringTable::SQStringTable(SQSharedState *ss) +{ + _sharedstate = ss; + AllocNodes(4); + _slotused = 0; +} + +SQStringTable::~SQStringTable() +{ + SQ_FREE(_strings,sizeof(SQString*)*_numofslots); + _strings = NULL; +} + +void SQStringTable::AllocNodes(SQInteger size) +{ + _numofslots = size; + _strings = (SQString**)SQ_MALLOC(sizeof(SQString*)*_numofslots); + memset(_strings,0,sizeof(SQString*)*_numofslots); +} + +SQString *SQStringTable::Add(const SQChar *news,SQInteger len) +{ + if(len<0) + 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)))) + return s; //found + } + + SQString *t=(SQString *)SQ_MALLOC(rsl(len)+sizeof(SQString)); + new (t) SQString; + t->_sharedstate = _sharedstate; + memcpy(t->_val,news,rsl(len)); + 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 SQStringTable::Resize(SQInteger size) +{ + SQInteger oldsize=_numofslots; + SQString **oldtable=_strings; + AllocNodes(size); + for (SQInteger i=0; i<oldsize; i++){ + SQString *p = oldtable[i]; + while(p){ + SQString *next = p->_next; + SQHash h = p->_hash&(_numofslots-1); + p->_next = _strings[h]; + _strings[h] = p; + p = next; + } + } + SQ_FREE(oldtable,oldsize*sizeof(SQString*)); +} + +void SQStringTable::Remove(SQString *bs) +{ + SQString *s; + SQString *prev=NULL; + SQHash h = bs->_hash&(_numofslots - 1); + + for (s = _strings[h]; s; ){ + if(s == bs){ + if(prev) + prev->_next = s->_next; + else + _strings[h] = s->_next; + _slotused--; + SQInteger slen = s->_len; + s->~SQString(); + SQ_FREE(s,sizeof(SQString) + rsl(slen)); + return; + } + prev = s; + s = s->_next; + } + assert(0);//if this fail something is wrong +} |