void ThreadSharedVariant::getStats(SharedVariantStats *stats) { stats->initStats(); stats->variantCount = 1; switch (m_type) { case KindOfBoolean: case KindOfInt64: stats->dataSize = sizeof(m_data.num); stats->dataTotalSize = sizeof(ThreadSharedVariant); break; case KindOfDouble: stats->dataSize = sizeof(m_data.dbl); stats->dataTotalSize = sizeof(ThreadSharedVariant); break; case KindOfString: case KindOfObject: if (m_data.str->isStatic()) { stats->dataSize = 0; stats->dataTotalSize = sizeof(ThreadSharedVariant); break; } stats->dataSize = m_data.str->size(); stats->dataTotalSize = sizeof(ThreadSharedVariant) + sizeof(StringData) + stats->dataSize; break; default: ASSERT(is(KindOfArray)); if (getSerializedArray()) { stats->dataSize = m_data.str->size(); stats->dataTotalSize = sizeof(ThreadSharedVariant) + sizeof(StringData) + stats->dataSize; break; } if (getIsVector()) { stats->dataTotalSize = sizeof(ThreadSharedVariant) + sizeof(VectorData); stats->dataTotalSize += sizeof(ThreadSharedVariant*) * m_data.vec->size; for (size_t i = 0; i < m_data.vec->size; i++) { ThreadSharedVariant *v = m_data.vec->vals[i]; SharedVariantStats childStats; v->getStats(&childStats); stats->addChildStats(&childStats); } } else { ImmutableMap *map = m_data.map; stats->dataTotalSize = sizeof(ThreadSharedVariant) + map->getStructSize(); for (int i = 0; i < map->size(); i++) { SharedVariantStats childStats; map->getKeyIndex(i)->getStats(&childStats); stats->addChildStats(&childStats); map->getValIndex(i)->getStats(&childStats); stats->addChildStats(&childStats); } } break; } }
SharedVariant* ThreadSharedVariant::convertObj(CVarRef var) { if (!var.is(KindOfObject) || getObjAttempted()) { return NULL; } setObjAttempted(); PointerSet seen; ObjectData *obj = var.getObjectData(); CArrRef arr = obj->o_toArray(); if (arr->hasInternalReference(seen, true)) { return NULL; } ThreadSharedVariant *tmp = new ThreadSharedVariant(var, false, true, true); tmp->setObjAttempted(); return tmp; }
void ThreadSharedVariant::getStats(SharedVariantStats *stats) { stats->initStats(); stats->variantCount = 1; switch (m_type) { case KindOfNull: case KindOfBoolean: case KindOfInt64: case KindOfDouble: stats->dataSize = sizeof(m_data.dbl); stats->dataTotalSize = sizeof(ThreadSharedVariant); break; case KindOfObject: if (getIsObj()) { SharedVariantStats childStats; m_data.obj->getSizeStats(&childStats); stats->addChildStats(&childStats); break; } // fall through case KindOfString: if (m_data.str->isStatic()) { stats->dataSize = 0; stats->dataTotalSize = sizeof(ThreadSharedVariant); break; } stats->dataSize = m_data.str->size(); stats->dataTotalSize = sizeof(ThreadSharedVariant) + sizeof(StringData) + stats->dataSize; break; default: ASSERT(is(KindOfArray)); if (getSerializedArray()) { stats->dataSize = m_data.str->size(); stats->dataTotalSize = sizeof(ThreadSharedVariant) + sizeof(StringData) + stats->dataSize; break; } if (getIsVector()) { stats->dataTotalSize = sizeof(ThreadSharedVariant) + sizeof(VectorData); stats->dataTotalSize += sizeof(ThreadSharedVariant*) * m_data.vec->size; for (size_t i = 0; i < m_data.vec->size; i++) { ThreadSharedVariant *v = m_data.vec->vals[i]; SharedVariantStats childStats; v->getStats(&childStats); stats->addChildStats(&childStats); } } else if (RuntimeOption::ApcUseGnuMap) { // There is no way to calculate this accurately, and this should be only // used if ImmutableMap is seriously broken, when profiling is less // important. Just not do basic thing here: stats->dataTotalSize = sizeof(MapData); } else { ImmutableMap *map = m_data.map; stats->dataTotalSize = sizeof(ThreadSharedVariant) + map->getStructSize(); for (int i = 0; i < map->size(); i++) { SharedVariantStats childStats; map->getKeyIndex(i)->getStats(&childStats); stats->addChildStats(&childStats); map->getValIndex(i)->getStats(&childStats); stats->addChildStats(&childStats); } } break; } }
ThreadSharedVariant::ThreadSharedVariant(CVarRef source, bool serialized, bool inner /* = false */, bool unserializeObj /* = false */) { ASSERT(!serialized || source.isString()); setOwner(); m_ref = 1; switch (source.getType()) { case KindOfBoolean: { m_type = KindOfBoolean; m_data.num = source.toBoolean(); break; } case KindOfByte: case KindOfInt16: case KindOfInt32: case KindOfInt64: { m_type = KindOfInt64; m_data.num = source.toInt64(); break; } case KindOfDouble: { m_type = KindOfDouble; m_data.dbl = source.toDouble(); break; } case KindOfStaticString: case KindOfString: { String s = source.toString(); m_type = serialized ? KindOfObject : KindOfString; if (serialized) { // It is priming, and there might not be the right class definitions // for unserialization. s = apc_reserialize(s); } m_data.str = s->copy(true); break; } case KindOfArray: { m_type = KindOfArray; ArrayData *arr = source.getArrayData(); if (!inner) { // only need to call hasInternalReference() on the toplevel array PointerSet seen; if (arr->hasInternalReference(seen)) { setSerializedArray(); setShouldCache(); String s = apc_serialize(source); m_data.str = new StringData(s.data(), s.size(), CopyString); break; } } size_t size = arr->size(); if (arr->isVectorData()) { setIsVector(); m_data.vec = new VectorData(size); uint i = 0; for (ArrayIter it(arr); !it.end(); it.next(), i++) { ThreadSharedVariant* val = Create(it.second(), false, true, unserializeObj); if (val->shouldCache()) setShouldCache(); m_data.vec->vals[i] = val; } } else if (RuntimeOption::ApcUseGnuMap) { // Configured to use old Gnu Map m_data.gnuMap = new MapData(size); uint i = 0; for (ArrayIter it(arr); !it.end(); it.next(), i++) { ThreadSharedVariant* key = Create(it.first(), false, true, unserializeObj); ThreadSharedVariant* val = Create(it.second(), false, true, unserializeObj); if (val->shouldCache()) setShouldCache(); m_data.gnuMap->set(i, key, val); } } else { m_data.map = new ImmutableMap(size); for (ArrayIter it(arr); !it.end(); it.next()) { ThreadSharedVariant* key = Create(it.first(), false, true, unserializeObj); ThreadSharedVariant* val = Create(it.second(), false, true, unserializeObj); if (val->shouldCache()) setShouldCache(); m_data.map->add(key, val); } } break; } case KindOfNull: { m_type = KindOfNull; m_data.num = 0; break; } default: { ASSERT(source.isObject()); m_type = KindOfObject; setShouldCache(); if (unserializeObj) { // This assumes hasInternalReference(seen, true) is false ImmutableObj* obj = new ImmutableObj(source.getObjectData()); m_data.obj = obj; setIsObj(); } else { String s = apc_serialize(source); m_data.str = new StringData(s.data(), s.size(), CopyString); } break; } } }