Arquivos
hhvm/hphp/runtime/base/shared/shared_variant.h
T
smith 6434422e85 Encapsulate access to m_aux in TypedValueAux subclass.
Access to TypedValue.m_aux must now be via TypedValueAux.  For now,
TypedValueAux is an empty subclass with accessors to m_aux, which is
now private.  Once RefData.m_tv is moved out from under RefData._count,
we can move TypedValue.m_aux to TypedValueAux.

Removed unnecessary initialization of m_aux.u_hash from c_Vector.
2013-03-11 21:19:20 -07:00

279 linhas
7.8 KiB
C++

/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#ifndef __HPHP_SHARED_VARIANT_H__
#define __HPHP_SHARED_VARIANT_H__
#include <runtime/base/types.h>
#include <util/lock.h>
#include <util/hash.h>
#include <util/atomic.h>
#include <runtime/base/complex_types.h>
#include <runtime/base/shared/immutable_map.h>
#include <runtime/base/shared/immutable_obj.h>
#if (defined(__APPLE__) || defined(__APPLE_CC__)) && (defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__))
# if defined(__LITTLE_ENDIAN__)
# undef WORDS_BIGENDIAN
# else
# if defined(__BIG_ENDIAN__)
# define WORDS_BIGENDIAN
# endif
# endif
#endif
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
class SharedMap;
class SharedVariantStats;
///////////////////////////////////////////////////////////////////////////////
class SharedVariant {
public:
SharedVariant(CVarRef source, bool serialized, bool inner = false,
bool unserializeObj = false);
~SharedVariant();
// Create will do the wrapped check before creating a SharedVariant
static SharedVariant* Create(CVarRef source, bool serialized,
bool inner = false,
bool unserializeObj = false);
bool is(DataType d) const { return m_type == d; }
DataType getType() const { return (DataType)m_type; }
CVarRef asCVarRef() const {
// Must be non-refcounted types
assert(m_shouldCache == false);
assert(m_flags == 0);
assert(!IS_REFCOUNTED_TYPE(m_tv.m_type));
return tvAsCVarRef(&m_tv);
}
void incRef() {
atomic_inc(m_count);
}
void decRef() {
assert(m_count);
if (atomic_dec(m_count) == 0) {
delete this;
}
}
Variant toLocal();
int64_t intData() const {
assert(is(KindOfInt64));
return m_data.num;
}
const char *stringData() const {
assert(is(KindOfString) || is(KindOfStaticString));
return m_data.str->data();
}
size_t stringLength() const {
assert(is(KindOfString) || is(KindOfStaticString));
return m_data.str->size();
}
strhash_t stringHash() const {
assert(is(KindOfString) || is(KindOfStaticString));
return m_data.str->hash();
}
size_t arrSize() const {
assert(is(KindOfArray));
if (getIsVector()) return m_data.vec->m_size;
return m_data.map->size();
}
size_t arrCap() const {
assert(is(KindOfArray));
if (getIsVector()) return m_data.vec->m_size;
return m_data.map->capacity();
}
int getIndex(int64_t key);
int getIndex(const StringData* key);
void loadElems(ArrayData *&elems, const SharedMap &sharedMap,
bool mapInit = false);
Variant getKey(ssize_t pos) const;
SharedVariant* getValue(ssize_t pos) const;
// implementing LeakDetectable
void dump(std::string &out);
void getStats(SharedVariantStats *stats) const;
int32_t getSpaceUsage() const;
StringData *getStringData() const {
assert(is(KindOfString) || is(KindOfStaticString));
return m_data.str;
}
SharedVariant *convertObj(CVarRef var);
bool isUnserializedObj() { return getIsObj(); }
bool shouldCache() const { return m_shouldCache; }
int countReachable() const;
private:
class VectorData {
public:
union {
size_t m_size;
SharedVariant* m_align_dummy;
};
VectorData() : m_size(0) {}
~VectorData() {
SharedVariant** v = vals();
for (size_t i = 0; i < m_size; i++) {
v[i]->decRef();
}
}
SharedVariant** vals() { return (SharedVariant**)(this + 1); }
void *operator new(size_t sz, int num) {
assert(sz == sizeof(VectorData));
return malloc(sizeof(VectorData) + num * sizeof(SharedVariant*));
}
void operator delete(void* ptr) { free(ptr); }
// just to keep the compiler happy; used if the constructor throws
void operator delete(void* ptr, int num) { free(ptr); }
};
/* This macro is to help making the object layout binary compatible with
* Variant for primitive types. We want to have compile time assertion to
* guard it but still want to have anonymous struct. For non-refcounted
* types, m_shouldCache and m_flags are guaranteed to be 0, and other parts
* of runtime code will not touch the count.*/
#ifdef WORDS_BIGENDIAN
#define SharedVarData \
union {\
int64_t num;\
double dbl;\
StringData *str;\
ImmutableMap* map;\
VectorData* vec;\
ImmutableObj* obj;\
} m_data;\
int m_count;\
bool m_shouldCache;\
uint8_t m_flags;\
uint16_t m_type
#else
#define SharedVarData \
union {\
int64_t num;\
double dbl;\
StringData *str;\
ImmutableMap* map;\
VectorData* vec;\
ImmutableObj* obj;\
} m_data;\
int m_count;\
uint16_t m_type;\
bool m_shouldCache;\
uint8_t m_flags
#endif
struct SharedVar {
SharedVarData;
};
union {
struct {
SharedVarData;
};
TypedValue m_tv;
};
#undef SharedVarData
const static uint8_t SerializedArray = (1<<0);
const static uint8_t IsVector = (1<<1);
const static uint8_t IsObj = (1<<2);
const static uint8_t ObjAttempted = (1<<3);
static void compileTimeAssertions() {
static_assert(offsetof(SharedVar, m_data) == offsetof(TypedValue, m_data),
"Offset of m_data must be equal in SharedVar and TypedValue");
static_assert(offsetof(SharedVar, m_count) == TypedValueAux::auxOffset,
"Offset of m_count must equal offset of TV.m_aux");
static_assert(offsetof(SharedVar, m_type) == offsetof(TypedValue, m_type),
"Offset of m_type must be equal in SharedVar and TypedValue");
}
bool getSerializedArray() const { return (bool)(m_flags & SerializedArray);}
void setSerializedArray() { m_flags |= SerializedArray;}
void clearSerializedArray() { m_flags &= ~SerializedArray;}
bool getIsVector() const { return (bool)(m_flags & IsVector);}
void setIsVector() { m_flags |= IsVector;}
void clearIsVector() { m_flags &= ~IsVector;}
bool getIsObj() const { return (bool)(m_flags & IsObj);}
void setIsObj() { m_flags |= IsObj;}
void clearIsObj() { m_flags &= ~IsObj;}
bool getObjAttempted() const { return (bool)(m_flags & ObjAttempted);}
void setObjAttempted() { m_flags |= ObjAttempted;}
void clearObjAttempted() { m_flags &= ~ObjAttempted;}
};
class SharedVariantStats {
public:
int32_t dataSize;
int32_t dataTotalSize;
int32_t variantCount;
void initStats() {
variantCount = 0;
dataSize = 0;
dataTotalSize = 0;
}
SharedVariantStats() {
initStats();
}
void addChildStats(const SharedVariantStats *childStats) {
dataSize += childStats->dataSize;
dataTotalSize += childStats->dataTotalSize;
variantCount += childStats->variantCount;
}
void removeChildStats(const SharedVariantStats *childStats) {
dataSize -= childStats->dataSize;
dataTotalSize -= childStats->dataTotalSize;
variantCount -= childStats->variantCount;
}
};
///////////////////////////////////////////////////////////////////////////////
}
#endif /* __HPHP_SHARED_VARIANT_H__ */