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:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário