Allow different RefData and TypedValue layouts

Fixing various bugs all over the VM that make assumptions about RefData
and TypedValue layout.  Here are the assumptions fixed by this diff:

offsetof(RefData, m_tv) == 0.  Both JIT's assumed this in many subtle
ways, by punning RefData* as TypedValue* without adding an offset.
This assumption also causes RefData._count to overlap TypedValue.m_aux,
which constraints TypedValue layout.

offsetof(TypedValue, m_data) == 0.  gen_ext_hhvm.php assumes you
can cast TypedValue* to Value*; the JITs often weren't using
offsetof(TypedValue, m_data) in their addressing calculations.  HHIR
assumed return-by-value TV's have m_data/m_type in rax/rdx, which
can change when TV layout changes.

offsetof(TypedValue, m_type) > 8 is an assumption baked into the
pass-by-value register assignment logic in HHIR's codegen.cpp; if
the type is in the low word, register assignment is swapped.

sizeof(TypedValue::m_type) == 4.  We used dword-sized operations
in both JIT's when accessing m_type.  Now, we use helper functions
that are sensitive to sizeof(DataType)

Configuration:
DEBUG=: (opt)  same layouts as trunk for RefData & TypedValue
DEBUG=1: (dbg) new RefData layout (m_tv doesn't overlap RefData::_count)
PACKED_TV=1, DEBUG=*:  new RefData and TypedValue layout.
Esse commit está contido em:
smith
2013-03-29 06:07:19 -07:00
commit de Sara Golemon
commit 22058efe41
25 arquivos alterados com 454 adições e 356 exclusões
+20 -23
Ver Arquivo
@@ -1752,7 +1752,7 @@ void setmDecRef(StringData* sd) { decRefStr(sd); }
template<typename Key, bool DecRefValue, bool CheckInt, bool DecRefKey>
static inline
ArrayData*
array_setm(TypedValue* cell, ArrayData* ad, Key key, TypedValue* value) {
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
@@ -1765,12 +1765,9 @@ array_setm(TypedValue* cell, ArrayData* ad, Key key, TypedValue* value) {
// methods that didn't bump up the refcount so that we didn't
// have to decrement it here
if (DecRefValue) tvRefcountedDecRef(value);
if (cell == nullptr) {
return arrayRefShuffle<false>(ad, retval, cell);
} else {
arrayRefShuffle<true>(ad, retval, cell);
return nullptr;
}
if (!ref) return arrayRefShuffle<false>(ad, retval, nullptr);
arrayRefShuffle<true>(ad, retval, ref->tv());
return nullptr;
}
/**
@@ -1781,14 +1778,14 @@ array_setm(TypedValue* cell, ArrayData* ad, Key key, TypedValue* value) {
* array_setm_ik1_v0 --
* Don't count the array's reference to the polymorphic value.
*/
ArrayData* array_setm_ik1_v(TypedValue* cell, ArrayData* ad, int64_t key,
ArrayData* array_setm_ik1_v(RefData* ref, ArrayData* ad, int64_t key,
TypedValue* value) {
return array_setm<int64_t, false, false, false>(cell, ad, key, value);
return array_setm<int64_t, false, false, false>(ref, ad, key, value);
}
ArrayData* array_setm_ik1_v0(TypedValue* cell, ArrayData* ad, int64_t key,
ArrayData* array_setm_ik1_v0(RefData* ref, ArrayData* ad, int64_t key,
TypedValue* value) {
return array_setm<int64_t, true, false, false>(cell, ad, key, value);
return array_setm<int64_t, true, false, false>(ref, ad, key, value);
}
/**
@@ -1809,34 +1806,34 @@ ArrayData* array_setm_ik1_v0(TypedValue* cell, ArrayData* ad, int64_t key,
* Dont decRef the key, and skip the check for
* whether the key is really an integer.
*/
ArrayData* array_setm_sk1_v(TypedValue* cell, ArrayData* ad, StringData* key,
ArrayData* array_setm_sk1_v(RefData* ref, ArrayData* ad, StringData* key,
TypedValue* value) {
return array_setm<StringData*, false, true, true>(cell, ad, key, value);
return array_setm<StringData*, false, true, true>(ref, ad, key, value);
}
ArrayData* array_setm_sk1_v0(TypedValue* cell, ArrayData* ad, StringData* key,
ArrayData* array_setm_sk1_v0(RefData* ref, ArrayData* ad, StringData* key,
TypedValue* value) {
return array_setm<StringData*, true, true, true>(cell, ad, key, value);
return array_setm<StringData*, true, true, true>(ref, ad, key, value);
}
ArrayData* array_setm_s0k1_v(TypedValue* cell, ArrayData* ad, StringData* key,
ArrayData* array_setm_s0k1_v(RefData* ref, ArrayData* ad, StringData* key,
TypedValue* value) {
return array_setm<StringData*, false, true, false>(cell, ad, key, value);
return array_setm<StringData*, false, true, false>(ref, ad, key, value);
}
ArrayData* array_setm_s0k1_v0(TypedValue* cell, ArrayData* ad, StringData* key,
ArrayData* array_setm_s0k1_v0(RefData* ref, ArrayData* ad, StringData* key,
TypedValue* value) {
return array_setm<StringData*, true, true, false>(cell, ad, key, value);
return array_setm<StringData*, true, true, false>(ref, ad, key, value);
}
ArrayData* array_setm_s0k1nc_v(TypedValue* cell, ArrayData* ad, StringData* key,
ArrayData* array_setm_s0k1nc_v(RefData* ref, ArrayData* ad, StringData* key,
TypedValue* value) {
return array_setm<StringData*, false, false, false>(cell, ad, key, value);
return array_setm<StringData*, false, false, false>(ref, ad, key, value);
}
ArrayData* array_setm_s0k1nc_v0(TypedValue* cell, ArrayData* ad,
ArrayData* array_setm_s0k1nc_v0(RefData* ref, ArrayData* ad,
StringData* key, TypedValue* value) {
return array_setm<StringData*, true, false, false>(cell, ad, key, value);
return array_setm<StringData*, true, false, false>(ref, ad, key, value);
}
/**