TypedValue HHVM_FUNCTION(serialize_memoize_param, TypedValue param) { // Memoize throws in the emitter if any function parameters are references, so // we can just assert that the param is cell here assertx(param.m_type != KindOfRef); auto const type = param.m_type; if (isStringType(type)) { auto const str = param.m_data.pstr; if (str->empty()) { return make_tv<KindOfPersistentString>(s_emptyStrMemoKey.get()); } else if ((unsigned char)str->data()[0] < '~') { // fb_compact_serialize always returns a string with the high-bit set in // the first character. Furthermore, we use ~ to begin all our special // constants, so anything less than ~ can't collide. There's no worry // about int-like strings because we use dicts (which don't perform key // coercion) to store the memoized values. str->incRefCount(); return param; } } else if (isContainer(param) && getContainerSize(param) == 0) { return make_tv<KindOfPersistentString>(s_emptyArrMemoKey.get()); } else if (type == KindOfUninit || type == KindOfNull) { return make_tv<KindOfPersistentString>(s_nullMemoKey.get()); } else if (type == KindOfBoolean) { return make_tv<KindOfPersistentString>( param.m_data.num ? s_trueMemoKey.get() : s_falseMemoKey.get() ); } else if (type == KindOfInt64) { return param; } return tvReturn( fb_compact_serialize(tvAsCVarRef(¶m), FBCompactSerializeBehavior::MemoizeParam)); }
Variant HHVM_FUNCTION(serialize_memoize_param, const Variant& param) { // Memoize throws in the emitter if any function parameters are references, so // we can just assert that the param is cell here const auto& cell_param = *tvAssertCell(param.asTypedValue()); auto type = param.getType(); if (type == KindOfInt64) { return param; } else if (type == KindOfUninit || type == KindOfNull) { return s_empty; } else if (type == KindOfBoolean) { return param.asBooleanVal() ? s_true : s_false; } else if (type == KindOfString) { auto str = param.asCStrRef(); if (str.empty()) { return s_emptyStr; } else if (str.charAt(0) > '9') { // If it doesn't start with a number, then we know it can never collide // with an int or any of our constants, so it's fine as is return param; } } else if (isContainer(cell_param) && getContainerSize(cell_param) == 0) { return s_emptyArr; } return fb_compact_serialize(param, FBCompactSerializeBehavior::MemoizeParam); }