Răsfoiți Sursa

faster string cat

Alberto Demichelis 1 an în urmă
părinte
comite
95569768ed
5 a modificat fișierele cu 71 adăugiri și 5 ștergeri
  1. 6 0
      squirrel/sqobject.cpp
  2. 35 0
      squirrel/sqstate.cpp
  3. 1 0
      squirrel/sqstate.h
  4. 21 0
      squirrel/sqstring.h
  5. 8 5
      squirrel/sqvm.cpp

+ 6 - 0
squirrel/sqobject.cpp

@@ -52,6 +52,12 @@ SQString *SQString::Create(SQSharedState *ss,const SQChar *s,SQInteger len)
     return str;
 }
 
+SQString* SQString::Concat(SQSharedState* ss, const SQChar* a, SQInteger alen, const SQChar* b, SQInteger blen)
+{
+    SQString* str = ss->_stringtable->Concat(a, alen, b, blen);
+    return str;
+}
+
 void SQString::Release()
 {
     REMOVE_STRING(_sharedstate,this);

+ 35 - 0
squirrel/sqstate.cpp

@@ -577,6 +577,41 @@ void SQStringTable::AllocNodes(SQInteger size)
     memset(_strings,0,sizeof(SQString*)*_numofslots);
 }
 
+SQString* SQStringTable::Concat(const SQChar* a, SQInteger alen, const SQChar* b, SQInteger blen)
+{
+    SQHash newhash = ::_hashstr2(a, alen, b, blen);
+    SQHash h = newhash & (_numofslots - 1);
+    SQString* s;
+    SQInteger len = alen + blen;
+    for (s = _strings[h]; s; s = s->_next) {
+        if (s->_len == len) {
+            if ((!memcmp(a, s->_val, sq_rsl(alen)))
+                && (!memcmp(b, &s->_val[alen], sq_rsl(blen)))) {
+                return s; //found
+            }
+        }
+    }
+    //
+    SQString* t = (SQString*)SQ_MALLOC(sq_rsl(len) + sizeof(SQString));
+    new (t) SQString;
+    t->_sharedstate = _sharedstate;
+    memcpy(t->_val, a, sq_rsl(alen));
+    memcpy(&t->_val[alen], b, sq_rsl(blen));
+    t->_val[len] = _SC('\0');
+    t->_len = len;
+    t->_hash = newhash;
+    t->_next = _strings[h];
+    _strings[h] = t;
+    _slotused++;
+#ifdef _DEBUG
+    SQHash old_newhash = ::_hashstr(t->_val, t->_len);
+    assert(old_newhash == newhash);
+#endif
+    if (_slotused > _numofslots)  /* too crowded? */
+        Resize(_numofslots * 2);
+    return t;
+}
+
 SQString *SQStringTable::Add(const SQChar *news,SQInteger len)
 {
     if(len<0)

+ 1 - 0
squirrel/sqstate.h

@@ -14,6 +14,7 @@ struct SQStringTable
     SQStringTable(SQSharedState*ss);
     ~SQStringTable();
     SQString *Add(const SQChar *,SQInteger len);
+    SQString* Concat(const SQChar* a, SQInteger alen, const SQChar* b, SQInteger blen);
     void Remove(SQString *);
 private:
     void Resize(SQInteger size);

+ 21 - 0
squirrel/sqstring.h

@@ -12,12 +12,33 @@ inline SQHash _hashstr (const SQChar *s, size_t l)
 	return h;
 }
 
+inline SQHash _hashstr2(const SQChar* as, size_t al, const SQChar* bs, size_t bl)
+{
+    size_t l = al + bl;
+    SQHash h = (SQHash)l;  /* seed */
+    SQInteger step = (SQInteger)((l >> 5) + 1);  /* if string is too long, don't hash all its chars */
+    SQInteger l1 = (SQInteger)l;
+    for (; l1 >= step; l1 -= step) {
+        SQInteger idx = l1 - 1 - al;
+        if (idx < 0) {
+            break;
+        }
+        h = h ^ ((h << 5) + (h >> 2) + ((unsigned short)bs[idx]));
+    }
+    for (; l1 >= step; l1 -= step) {
+        SQInteger idx = l1 - 1;
+        h = h ^ ((h << 5) + (h >> 2) + ((unsigned short)as[idx]));
+    }
+    return h;
+}
+
 struct SQString : public SQRefCounted
 {
     SQString(){}
     ~SQString(){}
 public:
     static SQString *Create(SQSharedState *ss, const SQChar *, SQInteger len = -1 );
+    static SQString* Concat(SQSharedState* ss, const SQChar* a, SQInteger alen, const SQChar* b, SQInteger blen);
     SQInteger Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);
     void Release();
     SQSharedState *_sharedstate;

+ 8 - 5
squirrel/sqvm.cpp

@@ -322,17 +322,20 @@ bool SQVM::ToString(const SQObjectPtr &o,SQObjectPtr &res)
     return true;
 }
 
-
 bool SQVM::StringCat(const SQObjectPtr &str,const SQObjectPtr &obj,SQObjectPtr &dest)
 {
     SQObjectPtr a, b;
     if(!ToString(str, a)) return false;
     if(!ToString(obj, b)) return false;
     SQInteger l = _string(a)->_len , ol = _string(b)->_len;
-    SQChar *s = _sp(sq_rsl(l + ol + 1));
+#ifdef SQ_NO_FAST_STRINGCAT
+    SQChar* s = _sp(sq_rsl(l + ol + 1));
     memcpy(s, _stringval(a), sq_rsl(l));
     memcpy(s + l, _stringval(b), sq_rsl(ol));
     dest = SQString::Create(_ss(this), _spval, l + ol);
+#else
+    dest = SQString::Concat(_ss(this),_stringval(a),l,_stringval(b),ol);
+#endif
     return true;
 }
 
@@ -1779,11 +1782,11 @@ void SQVM::dumpstack(SQInteger stackbase,bool dumpall)
     for(SQInteger i=0;i<size;i++){
         SQObjectPtr &obj=_stack[i];
         if(stackbase==i)scprintf(_SC(">"));else scprintf(_SC(" "));
-        scprintf(_SC("[" _PRINT_INT_FMT "]:"),n);
+        scprintf(_SC("[") _PRINT_INT_FMT _SC("]:"),n);
         switch(sq_type(obj)){
         case OT_FLOAT:          scprintf(_SC("FLOAT %.3f"),_float(obj));break;
-        case OT_INTEGER:        scprintf(_SC("INTEGER " _PRINT_INT_FMT),_integer(obj));break;
-        case OT_BOOL:           scprintf(_SC("BOOL %s"),_integer(obj)?"true":"false");break;
+        case OT_INTEGER:        scprintf(_SC("INTEGER ") _PRINT_INT_FMT,_integer(obj));break;
+        case OT_BOOL:           scprintf(_SC("BOOL %s"),_integer(obj)?_SC("true"):_SC("false"));break;
         case OT_STRING:         scprintf(_SC("STRING %s"),_stringval(obj));break;
         case OT_NULL:           scprintf(_SC("NULL"));  break;
         case OT_TABLE:          scprintf(_SC("TABLE %p[%p]"),_table(obj),_table(obj)->_delegate);break;