Remove ArrayData::nvSet() wrappers and several dead Array helpers.
nvSet() only casts the value from TypedValue* to const Variant&; do it at callsites. Inlined array_setm_ik1_v0() and array_setm_s0k1_v0() into their only remaining callsites in translator-runtime.cpp.
Esse commit está contido em:
@@ -1643,221 +1643,6 @@ CVarRef HphpArray::endRef() {
|
||||
return tvAsCVarRef(&e->data);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// VM runtime support functions.
|
||||
|
||||
// Helpers for array_setm.
|
||||
ArrayData* nvCheckedSet(ArrayData* a, StringData* key, TypedValue* value,
|
||||
bool copy) {
|
||||
int64_t i;
|
||||
return UNLIKELY(key->isStrictlyInteger(i)) ? a->nvSet(i, value, copy) :
|
||||
a->nvSet(key, value, copy);
|
||||
}
|
||||
|
||||
ArrayData* nvCheckedSet(ArrayData* a, int64_t key, TypedValue* value,
|
||||
bool copy) {
|
||||
return a->nvSet(key, value, copy);
|
||||
}
|
||||
|
||||
void setmDecRef(int64_t i) { /* nop */ }
|
||||
void setmDecRef(StringData* sd) { decRefStr(sd); }
|
||||
|
||||
template<typename Key, bool DecRefValue, bool CheckInt, bool DecRefKey>
|
||||
static inline
|
||||
ArrayData*
|
||||
array_setm(RefData* ref, ArrayData* ad, Key key, TypedValue* value) {
|
||||
ArrayData* retval;
|
||||
bool copy = ad->getCount() > 1;
|
||||
// nvSet will decRef any old value that may have been overwritten
|
||||
// if appropriate
|
||||
retval = CheckInt ? nvCheckedSet(ad, key, value, copy) :
|
||||
ad->nvSet(key, value, copy);
|
||||
if (DecRefKey) setmDecRef(key);
|
||||
|
||||
// TODO Task #1970153: It would be great if there were nvSet()
|
||||
// methods that didn't bump up the refcount so that we didn't
|
||||
// have to decrement it here
|
||||
if (DecRefValue) tvRefcountedDecRef(value);
|
||||
if (!ref) return arrayRefShuffle<false>(ad, retval, nullptr);
|
||||
arrayRefShuffle<true>(ad, retval, ref->tv());
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unary integer keys.
|
||||
* array_setm_ik1_v --
|
||||
* Polymorphic value.
|
||||
*
|
||||
* array_setm_ik1_v0 --
|
||||
* Don't count the array's reference to the polymorphic value.
|
||||
*/
|
||||
ArrayData* array_setm_ik1_v(RefData* ref, ArrayData* ad, int64_t key,
|
||||
TypedValue* value) {
|
||||
return array_setm<int64_t, false, false, false>(ref, ad, key, value);
|
||||
}
|
||||
|
||||
ArrayData* array_setm_ik1_v0(RefData* ref, ArrayData* ad, int64_t key,
|
||||
TypedValue* value) {
|
||||
return array_setm<int64_t, true, false, false>(ref, ad, key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* String keys.
|
||||
*
|
||||
* array_setm_sk1_v --
|
||||
* $a[$keyOfTypeString] = <polymorphic value>;
|
||||
*
|
||||
* array_setm_sk1_v0 --
|
||||
* Like above, but don't count the new reference.
|
||||
*
|
||||
* array_setm_s0k1_v --
|
||||
* array_setm_s0k1_v0 --
|
||||
* As above, but dont decRef the key
|
||||
*
|
||||
* array_setm_s0k1nc_v --
|
||||
* array_setm_s0k1nc_v0 --
|
||||
* Dont decRef the key, and skip the check for
|
||||
* whether the key is really an integer.
|
||||
*/
|
||||
ArrayData* array_setm_sk1_v(RefData* ref, ArrayData* ad, StringData* key,
|
||||
TypedValue* value) {
|
||||
return array_setm<StringData*, false, true, true>(ref, ad, key, value);
|
||||
}
|
||||
|
||||
ArrayData* array_setm_sk1_v0(RefData* ref, ArrayData* ad, StringData* key,
|
||||
TypedValue* value) {
|
||||
return array_setm<StringData*, true, true, true>(ref, ad, key, value);
|
||||
}
|
||||
|
||||
ArrayData* array_setm_s0k1_v(RefData* ref, ArrayData* ad, StringData* key,
|
||||
TypedValue* value) {
|
||||
return array_setm<StringData*, false, true, false>(ref, ad, key, value);
|
||||
}
|
||||
|
||||
ArrayData* array_setm_s0k1_v0(RefData* ref, ArrayData* ad, StringData* key,
|
||||
TypedValue* value) {
|
||||
return array_setm<StringData*, true, true, false>(ref, ad, key, value);
|
||||
}
|
||||
|
||||
ArrayData* array_setm_s0k1nc_v(RefData* ref, ArrayData* ad, StringData* key,
|
||||
TypedValue* value) {
|
||||
return array_setm<StringData*, false, false, false>(ref, ad, key, value);
|
||||
}
|
||||
|
||||
ArrayData* array_setm_s0k1nc_v0(RefData* ref, ArrayData* ad,
|
||||
StringData* key, TypedValue* value) {
|
||||
return array_setm<StringData*, true, false, false>(ref, ad, key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append.
|
||||
*
|
||||
* array_setm_wk1_v0 --
|
||||
* $a[] = <polymorphic value>
|
||||
* ... but don't count the reference to the new value.
|
||||
*/
|
||||
ArrayData* array_setm_wk1_v0(ArrayData* ad, TypedValue* value) {
|
||||
return HphpArray::AddNewElemC(ad, *value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Array runtime helpers. For code-sharing purposes, all of these handle as
|
||||
* much ref-counting machinery as possible. They differ by -arity, type
|
||||
* signature, and necessity of various costly checks.
|
||||
*
|
||||
* They return the array that was just passed in as a convenience to
|
||||
* callers, which may have "lost" the array in volatile registers before
|
||||
* calling.
|
||||
*/
|
||||
|
||||
ArrayData*
|
||||
array_getm_i(void* dptr, int64_t key, TypedValue* out) {
|
||||
assert(dptr);
|
||||
ArrayData* ad = (ArrayData*)dptr;
|
||||
TRACE(2, "array_getm_ik1: (%p) <- %p[%" PRId64 "]\n", out, dptr, key);
|
||||
// Ref-counting the value is the translator's responsibility. We know out
|
||||
// pointed to uninitialized memory, so no need to dec it.
|
||||
TypedValue* ret = ad->nvGetCell(key);
|
||||
tvDup(ret, out);
|
||||
return ad;
|
||||
}
|
||||
|
||||
NEVER_INLINE
|
||||
ArrayData* array_getm_s(ArrayData* ad, StringData* sd, TypedValue* out,
|
||||
int flags) {
|
||||
bool drKey = flags & DecRefKey;
|
||||
bool checkInts = flags & CheckInts;
|
||||
int64_t ikey;
|
||||
TypedValue* ret = checkInts && UNLIKELY(sd->isStrictlyInteger(ikey)) ?
|
||||
ad->nvGetCell(ikey) :
|
||||
ad->nvGetCell(sd);
|
||||
tvDup((ret), (out));
|
||||
if (drKey) decRefStr(sd);
|
||||
TRACE(2, "%s: (%p) <- %p[\"%s\"@sd%p]\n", __FUNCTION__,
|
||||
out, ad, sd->data(), sd);
|
||||
return ad;
|
||||
}
|
||||
|
||||
// issetm's DNA.
|
||||
static bool
|
||||
issetMUnary(const void* dptr, StringData* sd, bool decRefKey, bool checkInt) {
|
||||
const ArrayData* ad = (const ArrayData*)dptr;
|
||||
bool retval;
|
||||
int64_t keyAsInt;
|
||||
|
||||
TypedValue* c;
|
||||
if (checkInt && sd->isStrictlyInteger(keyAsInt)) {
|
||||
c = ad->nvGet(keyAsInt);
|
||||
} else {
|
||||
c = ad->nvGet(sd);
|
||||
}
|
||||
const Variant* cell = &tvAsVariant(c);
|
||||
|
||||
retval = cell && !cell->isNull();
|
||||
TRACE(2, "issetMUnary: %p[\"%s\"@sd%p] -> %d\n",
|
||||
dptr, sd->data(), sd, retval);
|
||||
|
||||
if (decRefKey) decRefStr(sd);
|
||||
return retval;
|
||||
}
|
||||
|
||||
uint64_t array_issetm_s(const void* dptr, StringData* sd)
|
||||
{ return issetMUnary(dptr, sd, true /*decRefKey*/, true /*checkInt*/); }
|
||||
uint64_t array_issetm_s0(const void* dptr, StringData* sd)
|
||||
{ return issetMUnary(dptr, sd, false /*decRefKey*/, true /*checkInt*/); }
|
||||
uint64_t array_issetm_s_fast(const void* dptr, StringData* sd)
|
||||
{ return issetMUnary(dptr, sd, true /*decRefKey*/, false /*checkInt*/); }
|
||||
uint64_t array_issetm_s0_fast(const void* dptr, StringData* sd)
|
||||
{ return issetMUnary(dptr, sd, false /*decRefKey*/, false /*checkInt*/); }
|
||||
|
||||
uint64_t array_issetm_i(const void* dptr, int64_t key) {
|
||||
ArrayData* ad = (ArrayData*)dptr;
|
||||
TypedValue* ret = ad->nvGet(key);
|
||||
// Variant.isNull unboxes ret if its KindOfRef.
|
||||
return ret && !tvAsCVarRef(ret).isNull();
|
||||
}
|
||||
|
||||
ArrayData* array_add(ArrayData* a1, ArrayData* a2) {
|
||||
if (!a2->empty()) {
|
||||
if (a1->empty()) {
|
||||
decRefArr(a1);
|
||||
return a2;
|
||||
}
|
||||
if (a1 != a2) {
|
||||
ArrayData *escalated = a1->append(a2, ArrayData::Plus,
|
||||
a1->getCount() > 1);
|
||||
if (escalated != a1) {
|
||||
escalated->incRefCount();
|
||||
decRefArr(a2);
|
||||
decRefArr(a1);
|
||||
return escalated;
|
||||
}
|
||||
}
|
||||
}
|
||||
decRefArr(a2);
|
||||
return a1;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
ALWAYS_INLINE HphpArray* HphpArray::clone(AllocationMode am) const {
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário