Просмотр исходного кода

Add an experimental "scratchstr" to preallocate a SQString and avoid double allocation and copy

mingodad 5 лет назад
Родитель
Сommit
50037b6597

+ 3 - 0
SquiLu/include/sqapi.h

@@ -105,6 +105,9 @@ SQUIRREL_API_FUNC(SQRESULT, gettypetag, (HSQUIRRELVM v,SQInteger idx,SQUserPoint
 SQUIRREL_API_FUNC(void, setreleasehook, (HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook))
 SQUIRREL_API_FUNC(SQRELEASEHOOK, getreleasehook, (HSQUIRRELVM v,SQInteger idx))
 SQUIRREL_API_FUNC(SQChar*, getscratchpad, (HSQUIRRELVM v,SQInteger minsize))
+SQUIRREL_API_FUNC(SQChar*, getscratchstr, (HSQUIRRELVM v,SQInteger size))
+SQUIRREL_API_FUNC(void, pushscratchstr, (HSQUIRRELVM v))
+SQUIRREL_API_FUNC(SQBool, delscratchstr, (HSQUIRRELVM v,SQChar*))
 SQUIRREL_API_FUNC(SQRESULT, getfunctioninfo, (HSQUIRRELVM v,SQInteger level,SQFunctionInfo *fi))
 SQUIRREL_API_FUNC(SQRESULT, getclosureinfo, (HSQUIRRELVM v,SQInteger idx,SQInteger *nparams,SQInteger *nfreevars))
 SQUIRREL_API_FUNC(SQRESULT, getclosurename, (HSQUIRRELVM v,SQInteger idx))

+ 9 - 4
SquiLu/sqstdlib/sqstdio.cpp

@@ -632,11 +632,16 @@ SQInteger _g_io_readfile(HSQUIRRELVM v)
         SQInteger size,res;
         SQChar *data;
         size = fs.Len();
-        data = sq_getscratchpad(v,size);
+        data = sq_getscratchstr(v,size);
         res = fs.Read(data,size);
-        if(res <= 0)
-            return sq_throwerror(v,_SC("no data left to read"));
-        sq_pushstring(v,data,res);
+        if(res != size)
+        {
+            sq_delscratchstr(v, data);
+            if(res <= 0)
+                return sq_throwerror(v,_SC("no data left to read"));
+            return sq_throwerror(v,_SC("could not read whole file"));
+        }
+        sq_pushscratchstr(v);
         return 1;
     }
 	return sq_throwerror(v,_SC("could not open file %s"), filename);

+ 18 - 0
SquiLu/squirrel/sqapi.cpp

@@ -1751,6 +1751,24 @@ SQChar *sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize)
 	return _ss(v)->GetScratchPad(minsize);
 }
 
+SQChar *sq_getscratchstr(HSQUIRRELVM v,SQInteger size)
+{
+	return _ss(v)->GetScratchStr(size);
+}
+
+SQBool sq_delscratchstr(HSQUIRRELVM v, SQChar *s)
+{
+	return _ss(v)->DelScratchStr(s);
+}
+
+void sq_pushscratchstr(HSQUIRRELVM v)
+{
+    SQString *s = _ss(v)->AddScratchStr();
+	if(s)
+		v->Push(SQObjectPtr(s));
+	else v->PushNull();
+}
+
 SQRESULT sq_resurrectunreachable(HSQUIRRELVM v)
 {
 #ifndef NO_GARBAGE_COLLECTOR

+ 33 - 0
SquiLu/squirrel/sqstate.cpp

@@ -105,6 +105,7 @@ static SQTable *CreateDefaultDelegate(SQSharedState *ss,const SQRegFunction *fun
 
 void SQSharedState::Init()
 {
+	_scratchstr=NULL;
 	_scratchpad=NULL;
 	_scratchpadsize=0;
 #ifndef NO_GARBAGE_COLLECTOR
@@ -249,6 +250,7 @@ SQSharedState::~SQSharedState()
 	sq_delete(_types,SQObjectPtrVec);
 	sq_delete(_systemstrings,SQObjectPtrVec);
 	sq_delete(_metamethods,SQObjectPtrVec);
+	if(_scratchstr) DelScratchStr(_scratchstr->_val);
 	sq_delete(_stringtable,SQStringTable);
 	if(_scratchpad)SQ_FREE(_scratchpad,_scratchpadsize);
 }
@@ -464,6 +466,32 @@ SQChar* SQSharedState::GetScratchPad(SQInteger size)
 	return _scratchpad;
 }
 
+SQChar* SQSharedState::GetScratchStr(SQInteger size)
+{
+    if(_scratchstr) return NULL; //only one at a time
+    _scratchstr = _stringtable->NewStrBuf(size);
+	return _scratchstr->_val;
+}
+
+SQString* SQSharedState::AddScratchStr()
+{
+    if(!_scratchstr) return NULL;
+    SQString *str = _stringtable->Add(_scratchstr);
+    _scratchstr = NULL;
+	return str;
+}
+
+SQBool SQSharedState::DelScratchStr(SQChar *s)
+{
+    if(_scratchstr && _scratchstr->_val == s)
+    {
+        _stringtable->DeleteStrBuf(_scratchstr);
+        _scratchstr = NULL;
+        return SQTrue;
+    }
+    return SQFalse;
+}
+
 RefTable::RefTable()
 {
 	AllocNodes(4);
@@ -715,6 +743,11 @@ SQString *SQStringTable::NewStrBuf(SQInteger len)
 	return t;
 }
 
+void SQStringTable::DeleteStrBuf(SQString *sb)
+{
+    SQ_FREE(sb,SQSTRING_CALCULATED_SIZE(rsl(sb->_len)));
+}
+
 void SQStringTable::Resize(SQInteger size)
 {
 	SQInteger oldsize=_numofslots;

+ 5 - 0
SquiLu/squirrel/sqstate.h

@@ -16,6 +16,7 @@ struct SQStringTable
 	SQString *Add(const SQChar *,SQInteger len);
 	SQString *Add(SQString *strBuf);
 	SQString *NewStrBuf(SQInteger len);
+	void DeleteStrBuf(SQString *);
 	void Remove(SQString *);
 private:
     SQString *Contains(const SQChar *news, SQInteger &len, SQHash &newhash, SQHash &h);
@@ -75,6 +76,9 @@ struct SQSharedState
 	void Init();
 public:
 	SQChar* GetScratchPad(SQInteger size);
+	SQChar* GetScratchStr(SQInteger size);
+	SQString* AddScratchStr();
+	SQBool DelScratchStr(SQChar *s);
 	SQInteger GetMetaMethodIdxByName(const SQObjectPtr &name);
 #ifndef NO_GARBAGE_COLLECTOR
 	SQInteger CollectGarbage(SQVM *vm);
@@ -135,6 +139,7 @@ public:
 	SQRELEASEHOOK _releasehook;
 private:
 	SQChar *_scratchpad;
+	SQString *_scratchstr;
 	SQInteger _scratchpadsize;
 #ifdef SQ_WITH_DELAYED_RELEASE_HOOKS
 	bool _already_in_CallDelayedReleaseHooks;

+ 1 - 0
SquiLu/squirrel/sqstring.h

@@ -21,6 +21,7 @@ struct SQString : public SQRefCounted
 	~SQString(){}
 public:
 	static SQString *Create(SQSharedState *ss, const SQChar *, SQInteger len = -1 );
+	static SQString *Create(SQSharedState *ss, SQString * );
 	SQInteger Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);
 	void Release();
 	SQSharedState *_sharedstate;