Optimize string offset setting

I was looking at this code while working on a vector
translator diff and noticed that we're doing some unnecessary
refcounting.
Esse commit está contido em:
bsimmers
2013-05-13 17:49:49 -07:00
commit de Sara Golemon
commit 72d0e84e1b
3 arquivos alterados com 69 adições e 12 exclusões
+52 -1
Ver Arquivo
@@ -85,6 +85,34 @@ void tvCastToInt64InPlace(TypedValue* tv, int base /* = 10 */) {
tv->m_type = KindOfInt64;
}
int64_t tvCastToInt64(TypedValue* tv, int base /* = 10 */) {
if (tv->m_type == KindOfRef) {
tv = tv->m_data.pref->tv();
}
switch (tv->m_type) {
case KindOfUninit:
case KindOfNull:
return 0;
case KindOfBoolean:
assert(tv->m_data.num == 0LL || tv->m_data.num == 1LL);
// Fall through
case KindOfInt64:
return tv->m_data.num;
case KindOfDouble:
return toInt64(tv->m_data.dbl);
case KindOfStaticString:
case KindOfString:
return tv->m_data.pstr->toInt64(base);
case KindOfArray:
return tv->m_data.parr->empty() ? 0 : 1;
case KindOfObject:
return tv->m_data.pobj->o_toInt64();
default:
not_reached();
}
}
void tvCastToDoubleInPlace(TypedValue* tv) {
if (tv->m_type == KindOfRef) {
tvUnbox(tv);
@@ -133,13 +161,36 @@ void tvCastToStringInPlace(TypedValue* tv) {
tvAsVariant(tv) = tv->m_data.pobj->t___tostring();
return;
}
default: assert(false); s = buildStringData(""); break;
default: not_reached();
}
tv->m_data.pstr = s;
tv->m_type = KindOfString;
tv->m_data.pstr->incRefCount();
}
StringData* tvCastToString(TypedValue* tv) {
if (tv->m_type == KindOfRef) {
tv = tv->m_data.pref->tv();
}
StringData* s;
switch (tv->m_type) {
case KindOfUninit:
case KindOfNull: s = buildStringData(""); break;
case KindOfBoolean: s = buildStringData(tv->m_data.num ? "1" : ""); break;
case KindOfInt64: s = buildStringData(tv->m_data.num); break;
case KindOfDouble: s = buildStringData(tv->m_data.dbl); break;
case KindOfStaticString:
case KindOfString: s = tv->m_data.pstr; break;
case KindOfArray: return StringData::GetStaticString("Array");
case KindOfObject: return tv->m_data.pobj->t___tostring().detach();
default: not_reached();
}
s->incRefCount();
return s;
}
void tvCastToArrayInPlace(TypedValue* tv) {
if (tv->m_type == KindOfRef) {
tvUnbox(tv);
+2
Ver Arquivo
@@ -447,8 +447,10 @@ inline bool tvIsString(const TypedValue* tv) {
void tvCastToBooleanInPlace(TypedValue* tv);
void tvCastToInt64InPlace(TypedValue* tv, int base = 10);
int64_t tvCastToInt64(TypedValue* tv, int base = 10);
void tvCastToDoubleInPlace(TypedValue* tv);
void tvCastToStringInPlace(TypedValue* tv);
StringData* tvCastToString(TypedValue* tv);
void tvCastToArrayInPlace(TypedValue* tv);
void tvCastToObjectInPlace(TypedValue* tv);
+15 -11
Ver Arquivo
@@ -650,11 +650,10 @@ inline void SetElem(TypedValue* base, TypedValue* key, Cell* value) {
} else {
// Convert key to string offset.
int64_t x;
{
TypedValue tv;
tvDup(key, &tv);
tvCastToInt64InPlace(&tv);
x = tv.m_data.num;
if (LIKELY(key->m_type == KindOfInt64)) {
x = key->m_data.num;
} else {
x = tvCastToInt64(key);
}
if (x < 0 || x >= StringData::MaxSize) {
// Andrei: can't use PRId64 here because of order of inclusion
@@ -673,16 +672,21 @@ inline void SetElem(TypedValue* base, TypedValue* key, Cell* value) {
// Extract the first character of (string)value.
char y[2];
{
TypedValue tv;
tvDup(value, &tv);
tvCastToStringInPlace(&tv);
if (tv.m_data.pstr->size() > 0) {
y[0] = tv.m_data.pstr->data()[0];
StringData* valStr;
if (LIKELY(IS_STRING_TYPE(value->m_type))) {
valStr = value->m_data.pstr;
valStr->incRefCount();
} else {
valStr = tvCastToString(value);
}
if (valStr->size() > 0) {
y[0] = valStr->data()[0];
y[1] = '\0';
} else {
y[0] = '\0';
}
tvRefcountedDecRef(&tv);
decRefStr(valStr);
}
// Create and save the result.
if (x >= 0 && x < baseLen && base->m_data.pstr->getCount() <= 1) {