Implement Tuple

Implement a Tuple class as part of collections.
Esse commit está contido em:
andrewparoski
2013-03-13 02:26:10 -07:00
commit de Sara Golemon
commit a8b6ba6962
23 arquivos alterados com 3357 adições e 1892 exclusões
+2
Ver Arquivo
@@ -2851,6 +2851,8 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) {
cType = Collection::MapType;
} else if (!strcasecmp(clsName->c_str(), "stablemap")) {
cType = Collection::StableMapType;
} else if (!strcasecmp(clsName->c_str(), "tuple")) {
cType = Collection::TupleType;
} else {
throw IncludeTimeFatalException(b,
"Cannot use collection initialization for "
@@ -71,6 +71,8 @@ BinaryOpExpression::BinaryOpExpression
cType = Collection::MapType;
} else if (strcasecmp(s.c_str(), "stablemap") == 0) {
cType = Collection::StableMapType;
} else if (strcasecmp(s.c_str(), "tuple") == 0) {
cType = Collection::TupleType;
}
ExpressionListPtr el = static_pointer_cast<ExpressionList>(m_exp2);
el->setCollectionType(cType);
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+173 -1
Ver Arquivo
@@ -227,7 +227,6 @@ DefineFunction(
),
));
DefineFunction(
array(
'name' => "contains",
@@ -1615,3 +1614,176 @@ DefineFunction(
EndClass(
);
///////////////////////////////////////////////////////////////////////////////
BeginClass(
array(
'name' => "Tuple",
'ifaces' => array('KeyedIterable', 'Countable'),
'desc' => "An ordered fixed-sized container.",
'flags' => IsFinal | HasDocComment,
'footer' => <<<EOT
private:
int size;
int capacity;
EOT
,
));
DefineFunction(
array(
'name' => "__construct",
'return' => array(
'type' => null,
),
));
DefineFunction(
array(
'name' => "isEmpty",
'flags' => HasDocComment,
'desc' => "Returns true if this Tuple is empty, false otherwise.",
'return' => array(
'type' => Boolean,
),
));
DefineFunction(
array(
'name' => "count",
'flags' => HasDocComment,
'desc' => "Returns the number of values in the Tuple.",
'return' => array(
'type' => Int64,
),
));
DefineFunction(
array(
'name' => "toArray",
'flags' => HasDocComment,
'desc' => "Returns an array containing the values from this Tuple.",
'return' => array(
'type' => VariantMap,
),
));
DefineFunction(
array(
'name' => "getIterator",
'flags' => HasDocComment,
'desc' => "Returns an iterator that points to beginning of this ".
"Tuple.",
'return' => array(
'type' => Object,
),
));
DefineFunction(
array(
'name' => "at",
'flags' => HasDocComment,
'desc' => "Returns the value at the specified key. If the key is ".
"not present, an exception is thrown.",
'return' => array(
'type' => Variant,
),
'args' => array(
array(
'name' => "key",
'type' => Variant,
),
),
));
DefineFunction(
array(
'name' => "get",
'flags' => HasDocComment,
'desc' => "Returns the value at the specified key. If the key is ".
"not present, null is returned.",
'return' => array(
'type' => Variant,
),
'args' => array(
array(
'name' => "key",
'type' => Variant,
),
),
));
EndClass(
);
BeginClass(
array(
'name' => "TupleIterator",
'ifaces' => array('KeyedIterator'),
'desc' => "An iterator implementation for iterating over a Tuple.",
'flags' => IsFinal | HasDocComment,
));
DefineFunction(
array(
'name' => "__construct",
'return' => array(
'type' => null,
),
));
DefineFunction(
array(
'name' => "current",
'desc' => "Returns the current value that the iterator points to.",
'flags' => HasDocComment,
'return' => array(
'type' => Variant,
),
));
DefineFunction(
array(
'name' => "key",
'desc' => "Returns the current key that the iterator points to.",
'flags' => HasDocComment,
'return' => array(
'type' => Variant,
),
));
DefineFunction(
array(
'name' => "valid",
'desc' => "Returns true if the iterator points to a valid value, ".
"returns false otherwise.",
'flags' => HasDocComment,
'return' => array(
'type' => Boolean,
),
));
DefineFunction(
array(
'name' => "next",
'desc' => "Advance this iterator forward one position.",
'flags' => HasDocComment,
'return' => array(
'type' => null,
),
));
DefineFunction(
array(
'name' => "rewind",
'desc' => "Move this iterator back to the first position.",
'flags' => HasDocComment,
'return' => array(
'type' => null,
),
));
EndClass(
);
+156 -114
Ver Arquivo
@@ -70,7 +70,7 @@ void ArrayIter::reset() {
if (ad) decRefArr(const_cast<ArrayData*>(ad));
return;
}
ObjectData* obj = getRawObject();
ObjectData* obj = getObject();
m_data = nullptr;
assert(obj);
decRefObj(obj);
@@ -83,24 +83,33 @@ void ArrayIter::objInit(ObjectData *obj) {
if (incRef) {
obj->incRefCount();
}
if (!obj->isCollection()) {
assert(obj->instanceof(SystemLib::s_IteratorClass));
obj->o_invoke(s_rewind, Array());
} else {
if (hasVector()) {
switch (getCollectionType()) {
case Collection::VectorType: {
c_Vector* vec = getVector();
m_versionNumber = vec->getVersionNumber();
m_pos = 0;
} else if (hasMap()) {
break;
}
case Collection::MapType: {
c_Map* mp = getMap();
m_versionNumber = mp->getVersionNumber();
m_pos = mp->iter_begin();
} else if (hasStableMap()) {
break;
}
case Collection::StableMapType: {
c_StableMap* smp = getStableMap();
m_versionNumber = smp->getVersionNumber();
m_pos = smp->iter_begin();
} else {
assert(false);
break;
}
case Collection::TupleType: {
m_pos = 0;
break;
}
default: {
assert(obj->instanceof(SystemLib::s_IteratorClass));
obj->o_invoke(s_rewind, Array());
break;
}
}
}
@@ -129,7 +138,7 @@ ArrayIter::~ArrayIter() {
const ArrayData* ad = getArrayData();
if (ad) decRefArr(const_cast<ArrayData*>(ad));
} else {
ObjectData* obj = getRawObject();
ObjectData* obj = getObject();
assert(obj);
decRefObj(obj);
}
@@ -139,136 +148,169 @@ ArrayIter::~ArrayIter() {
}
bool ArrayIter::endHelper() {
if (hasVector()) {
c_Vector* vec = getVector();
return m_pos >= vec->t_count();
switch (getCollectionType()) {
case Collection::VectorType: {
c_Vector* vec = getVector();
return m_pos >= vec->t_count();
}
case Collection::MapType: {
return m_pos == 0;
}
case Collection::StableMapType: {
return m_pos == 0;
}
case Collection::TupleType: {
c_Tuple* tup = getTuple();
return m_pos >= tup->t_count();
}
default: {
ObjectData* obj = getIteratorObj();
return !obj->o_invoke(s_valid, Array());
}
}
if (hasMap()) {
return m_pos == 0;
}
if (hasStableMap()) {
return m_pos == 0;
}
assert(hasObject());
ObjectData* obj = getObject();
return !obj->o_invoke(s_valid, Array());
}
void ArrayIter::nextHelper() {
if (hasVector()) {
m_pos++;
return;
}
if (hasMap()) {
assert(m_pos != 0);
c_Map* mp = getMap();
if (UNLIKELY(m_versionNumber != mp->getVersionNumber())) {
throw_collection_modified();
switch (getCollectionType()) {
case Collection::VectorType: {
m_pos++;
return;
}
m_pos = mp->iter_next(m_pos);
return;
}
if (hasStableMap()) {
assert(m_pos != 0);
c_StableMap* smp = getStableMap();
if (UNLIKELY(m_versionNumber != smp->getVersionNumber())) {
throw_collection_modified();
case Collection::MapType: {
assert(m_pos != 0);
c_Map* mp = getMap();
if (UNLIKELY(m_versionNumber != mp->getVersionNumber())) {
throw_collection_modified();
}
m_pos = mp->iter_next(m_pos);
return;
}
m_pos = smp->iter_next(m_pos);
return;
case Collection::StableMapType: {
assert(m_pos != 0);
c_StableMap* smp = getStableMap();
if (UNLIKELY(m_versionNumber != smp->getVersionNumber())) {
throw_collection_modified();
}
m_pos = smp->iter_next(m_pos);
return;
}
case Collection::TupleType: {
m_pos++;
return;
}
default:
ObjectData* obj = getIteratorObj();
obj->o_invoke(s_next, Array());
}
assert(hasObject());
ObjectData* obj = getObject();
obj->o_invoke(s_next, Array());
}
Variant ArrayIter::firstHelper() {
if (hasVector()) {
return m_pos;
}
if (hasMap()) {
assert(m_pos != 0);
c_Map* mp = getMap();
if (UNLIKELY(m_versionNumber != mp->getVersionNumber())) {
throw_collection_modified();
switch (getCollectionType()) {
case Collection::VectorType: {
return m_pos;
}
return mp->iter_key(m_pos);
}
if (hasStableMap()) {
assert(m_pos != 0);
c_StableMap* smp = getStableMap();
if (UNLIKELY(m_versionNumber != smp->getVersionNumber())) {
throw_collection_modified();
case Collection::MapType: {
assert(m_pos != 0);
c_Map* mp = getMap();
if (UNLIKELY(m_versionNumber != mp->getVersionNumber())) {
throw_collection_modified();
}
return mp->iter_key(m_pos);
}
case Collection::StableMapType: {
assert(m_pos != 0);
c_StableMap* smp = getStableMap();
if (UNLIKELY(m_versionNumber != smp->getVersionNumber())) {
throw_collection_modified();
}
return smp->iter_key(m_pos);
}
case Collection::TupleType: {
return m_pos;
}
default: {
ObjectData* obj = getIteratorObj();
return obj->o_invoke(s_key, Array());
}
return smp->iter_key(m_pos);
}
assert(hasObject());
ObjectData* obj = getObject();
return obj->o_invoke(s_key, Array());
}
HOT_FUNC
Variant ArrayIter::second() {
if (hasVector()) {
c_Vector* vec = getVector();
if (UNLIKELY(m_versionNumber != vec->getVersionNumber())) {
throw_collection_modified();
if (hasArrayData()) {
assert(m_pos != ArrayData::invalid_index);
const ArrayData* ad = getArrayData();
assert(ad);
return ad->getValue(m_pos);
}
switch (getCollectionType()) {
case Collection::VectorType: {
c_Vector* vec = getVector();
if (UNLIKELY(m_versionNumber != vec->getVersionNumber())) {
throw_collection_modified();
}
return tvAsCVarRef(vec->at(m_pos));
}
return tvAsCVarRef(vec->at(m_pos));
}
if (hasMap()) {
c_Map* mp = getMap();
if (UNLIKELY(m_versionNumber != mp->getVersionNumber())) {
throw_collection_modified();
case Collection::MapType: {
c_Map* mp = getMap();
if (UNLIKELY(m_versionNumber != mp->getVersionNumber())) {
throw_collection_modified();
}
return mp->iter_value(m_pos);
}
return mp->iter_value(m_pos);
}
if (hasStableMap()) {
c_StableMap* smp = getStableMap();
if (UNLIKELY(m_versionNumber != smp->getVersionNumber())) {
throw_collection_modified();
case Collection::StableMapType: {
c_StableMap* smp = getStableMap();
if (UNLIKELY(m_versionNumber != smp->getVersionNumber())) {
throw_collection_modified();
}
return smp->iter_value(m_pos);
}
case Collection::TupleType: {
return tvAsCVarRef(getTuple()->at(m_pos));
}
default: {
ObjectData* obj = getIteratorObj();
return obj->o_invoke(s_current, Array());
}
return smp->iter_value(m_pos);
}
if (hasObject()) {
ObjectData* obj = getObject();
return obj->o_invoke(s_current, Array());
}
assert(hasArrayData());
assert(m_pos != ArrayData::invalid_index);
const ArrayData* ad = getArrayData();
assert(ad);
return ad->getValue(m_pos);
}
void ArrayIter::secondHelper(Variant & v) {
if (hasVector()) {
c_Vector* vec = getVector();
if (UNLIKELY(m_versionNumber != vec->getVersionNumber())) {
throw_collection_modified();
void ArrayIter::secondHelper(Variant& v) {
switch (getCollectionType()) {
case Collection::VectorType: {
c_Vector* vec = getVector();
if (UNLIKELY(m_versionNumber != vec->getVersionNumber())) {
throw_collection_modified();
}
v = tvAsCVarRef(vec->at(m_pos));
break;
}
v = tvAsCVarRef(vec->at(m_pos));
return;
}
if (hasMap()) {
c_Map* mp = getMap();
if (UNLIKELY(m_versionNumber != mp->getVersionNumber())) {
throw_collection_modified();
case Collection::MapType: {
c_Map* mp = getMap();
if (UNLIKELY(m_versionNumber != mp->getVersionNumber())) {
throw_collection_modified();
}
v = mp->iter_value(m_pos);
break;
}
v = mp->iter_value(m_pos);
return;
}
if (hasStableMap()) {
c_StableMap* smp = getStableMap();
if (UNLIKELY(m_versionNumber != smp->getVersionNumber())) {
throw_collection_modified();
case Collection::StableMapType: {
c_StableMap* smp = getStableMap();
if (UNLIKELY(m_versionNumber != smp->getVersionNumber())) {
throw_collection_modified();
}
v = smp->iter_value(m_pos);
break;
}
case Collection::TupleType: {
v = tvAsCVarRef(getTuple()->at(m_pos));
break;
}
default: {
ObjectData* obj = getIteratorObj();
v = obj->o_invoke(s_current, Array());
break;
}
v = smp->iter_value(m_pos);
return;
}
assert(hasObject());
ObjectData* obj = getObject();
v = obj->o_invoke(s_current, Array());
}
HOT_FUNC
+25 -26
Ver Arquivo
@@ -30,6 +30,7 @@ struct TypedValue;
class c_Vector;
class c_Map;
class c_StableMap;
class c_Tuple;
namespace VM {
struct Iter;
}
@@ -129,7 +130,7 @@ class ArrayIter {
return firstHelper();
}
Variant second();
void second(Variant &v) {
void second(Variant& v) {
if (LIKELY(hasArrayData())) {
const ArrayData* ad = getArrayData();
assert(ad);
@@ -155,24 +156,13 @@ class ArrayIter {
bool hasArrayData() {
return !((intptr_t)m_data & 1);
}
bool hasCollection() {
return (!hasArrayData() && getObject()->isCollection());
}
bool hasIteratorObj() {
return (!hasArrayData() && !getObject()->isCollection());
}
private:
bool hasVector() {
return (!hasArrayData() &&
getRawObject()->getCollectionType() == Collection::VectorType);
}
bool hasMap() {
return (!hasArrayData() &&
getRawObject()->getCollectionType() == Collection::MapType);
}
bool hasStableMap() {
return (!hasArrayData() &&
getRawObject()->getCollectionType() == Collection::StableMapType);
}
bool hasObject() {
return (!hasArrayData() &&
getRawObject()->getCollectionType() == Collection::InvalidType);
}
public:
const ArrayData* getArrayData() {
assert(hasArrayData());
@@ -190,27 +180,36 @@ class ArrayIter {
void setIterType(Type iterType) {
m_itype = iterType;
}
private:
c_Vector* getVector() {
assert(hasVector());
assert(hasCollection() && getCollectionType() == Collection::VectorType);
return (c_Vector*)((intptr_t)m_obj & ~1);
}
c_Map* getMap() {
assert(hasMap());
assert(hasCollection() && getCollectionType() == Collection::MapType);
return (c_Map*)((intptr_t)m_obj & ~1);
}
c_StableMap* getStableMap() {
assert(hasStableMap());
assert(hasCollection() && getCollectionType() == Collection::StableMapType);
return (c_StableMap*)((intptr_t)m_obj & ~1);
}
ObjectData* getObject() {
assert(hasObject());
return (ObjectData*)((intptr_t)m_obj & ~1);
c_Tuple* getTuple() {
assert(hasCollection() && getCollectionType() == Collection::TupleType);
return (c_Tuple*)((intptr_t)m_obj & ~1);
}
ObjectData* getRawObject() {
ObjectData* getObject() {
assert(!hasArrayData());
return (ObjectData*)((intptr_t)m_obj & ~1);
}
Collection::Type getCollectionType() {
ObjectData* obj = getObject();
return obj->getCollectionType();
}
ObjectData* getIteratorObj() {
assert(hasIteratorObj());
return getObject();
}
void setArrayData(const ArrayData* ad) {
assert((intptr_t(ad) & 1) == 0);
@@ -224,7 +223,7 @@ class ArrayIter {
bool endHelper();
void nextHelper();
Variant firstHelper();
void secondHelper(Variant &v);
void secondHelper(Variant& v);
union {
const ArrayData* m_data;
+3 -2
Ver Arquivo
@@ -78,6 +78,7 @@ class ObjectData : public CountableNF {
VectorAttrInit = (Collection::VectorType << 13),
MapAttrInit = (Collection::MapType << 13),
StableMapAttrInit = (Collection::StableMapType << 13),
TupleAttrInit = (Collection::TupleType << 13),
};
enum {
@@ -114,9 +115,9 @@ class ObjectData : public CountableNF {
bool isCollection() const {
return getCollectionType() != Collection::InvalidType;
}
int getCollectionType() const {
Collection::Type getCollectionType() const {
// Return the upper 3 bits of o_attribute
return (int)(o_attribute >> 13) & 7;
return (Collection::Type)((uint16_t)(o_attribute >> 13) & 7);
}
bool supportsUnsetElem() const {
return isCollection() || instanceof(SystemLib::s_ArrayAccessClass);
+18 -11
Ver Arquivo
@@ -27,6 +27,7 @@
#include <util/parser/hphp.tab.hpp>
#include <runtime/vm/translator/translator-x64.h>
#include <runtime/vm/runtime.h>
#include <runtime/vm/instance.h>
#include <system/lib/systemlib.h>
#include <runtime/ext/ext_collections.h>
@@ -3260,16 +3261,6 @@ void Variant::unserialize(VariableUnserializer *uns) {
if (sep != ':') {
throw Exception("Expected ':' but got '%c'", sep);
}
Object obj;
try {
obj = create_object_only(clsName);
obj.get()->clearNoDestruct();
} catch (ClassNotFoundException &e) {
obj = create_object_only(s_PHP_Incomplete_Class);
obj->o_set(s_PHP_Incomplete_Class_Name, clsName);
}
operator=(obj);
int64_t size = uns->readInt();
char sep = uns->readChar();
if (sep != ':') {
@@ -3279,9 +3270,25 @@ void Variant::unserialize(VariableUnserializer *uns) {
if (sep != '{') {
throw Exception("Expected '{' but got '%c'", sep);
}
VM::Class* cls = VM::Unit::loadClass(clsName.get());
Object obj;
if (cls) {
if (LIKELY(cls != c_Tuple::s_cls)) {
obj = VM::Instance::newInstance(cls);
} else {
obj = c_Tuple::alloc(size);
}
} else {
obj = VM::Instance::newInstance(
SystemLib::s___PHP_Incomplete_ClassClass);
obj->o_set(s_PHP_Incomplete_Class_Name, clsName);
}
operator=(obj);
if (size > 0) {
if (type == 'O') {
// Collection are not allowed
// Collections are not allowed
if (obj->isCollection()) {
if (size > 0) {
throw Exception("%s does not support the 'O' serialization "
+2 -1
Ver Arquivo
@@ -298,7 +298,8 @@ enum Type {
VectorType = 1,
MapType = 2,
StableMapType = 3,
MaxNumTypes = 4
TupleType = 4,
MaxNumTypes = 5
};
}
+250 -17
Ver Arquivo
@@ -129,10 +129,6 @@ void c_Vector::t___construct(CVarRef iterable /* = null_variant */) {
}
}
Variant c_Vector::t___destruct() {
return uninit_null();
}
void c_Vector::grow() {
if (m_capacity) {
m_capacity += m_capacity;
@@ -882,10 +878,6 @@ void c_Map::t___construct(CVarRef iterable /* = null_variant */) {
}
}
Variant c_Map::t___destruct() {
return uninit_null();
}
Array c_Map::toArrayImpl() const {
ArrayInit ai(m_size);
for (uint i = 0; i <= m_nLastSlot; ++i) {
@@ -1792,10 +1784,6 @@ void c_StableMap::t___construct(CVarRef iterable /* = null_variant */) {
}
}
Variant c_StableMap::t___destruct() {
return uninit_null();
}
Array c_StableMap::toArrayImpl() const {
ArrayInit ai(m_size);
Bucket* p = m_pListHead;
@@ -2726,6 +2714,231 @@ void c_StableMapIterator::t_rewind() {
m_pos = smp->iter_begin();
}
///////////////////////////////////////////////////////////////////////////////
c_Tuple::c_Tuple(VM::Class* cb) :
ExtObjectDataFlags<ObjectData::TupleAttrInit|
ObjectData::UseGet|
ObjectData::UseSet|
ObjectData::UseIsset|
ObjectData::UseUnset>(cb),
m_size(0), m_capacity(0) {
}
c_Tuple::~c_Tuple() {
uint sz = m_size;
for (uint i = 0; i < sz; ++i) {
tvRefcountedDecRef(&getData()[i]);
}
}
void c_Tuple::t___construct() {
Object e(SystemLib::AllocRuntimeExceptionObject(
"Tuples cannot be created using the new operator"));
throw e;
}
Array c_Tuple::toArrayImpl() const {
ArrayInit ai(m_size, ArrayInit::vectorInit);
uint sz = m_size;
for (uint i = 0; i < sz; ++i) {
ai.set(tvAsCVarRef(&getData()[i]));
}
return ai.create();
}
Array c_Tuple::o_toArray() const {
check_collection_cast_to_array();
return toArrayImpl();
}
ObjectData* c_Tuple::clone() {
auto tup = c_Tuple::alloc(m_size);
tup->incRefCount();
uint sz = tup->m_size = m_size;
TypedValue* src = getData();
TypedValue* dst = tup->getData();
for (int i = 0; i < sz; ++i) {
tvDup(&src[i], &dst[i]);
}
return tup;
}
bool c_Tuple::t_isempty() {
return (m_size == 0);
}
int64_t c_Tuple::t_count() {
return m_size;
}
Variant c_Tuple::t_at(CVarRef key) {
if (key.isInteger()) {
return tvAsCVarRef(at(key.toInt64()));
}
throwBadKeyType();
return init_null_variant;
}
Variant c_Tuple::t_get(CVarRef key) {
if (key.isInteger()) {
TypedValue* tv = get(key.toInt64());
if (tv) {
return tvAsCVarRef(tv);
} else {
return init_null_variant;
}
}
throwBadKeyType();
return init_null_variant;
}
Array c_Tuple::t_toarray() {
return toArrayImpl();
}
Object c_Tuple::t_getiterator() {
c_TupleIterator* it = NEWOBJ(c_TupleIterator)();
it->m_obj = this;
it->m_pos = 0;
return it;
}
void c_Tuple::throwOOB(int64_t key) {
throwIntOOB(key, true);
}
void c_Tuple::throwBadKeyType() {
Object e(SystemLib::AllocInvalidArgumentExceptionObject(
"Only integer keys may be used with Tuples"));
throw e;
}
TypedValue* c_Tuple::OffsetGet(ObjectData* obj, TypedValue* key) {
assert(key->m_type != KindOfRef);
auto tup = static_cast<c_Tuple*>(obj);
if (key->m_type == KindOfInt64) {
return tup->at(key->m_data.num);
}
throwBadKeyType();
return NULL;
}
void c_Tuple::OffsetSet(ObjectData* obj, TypedValue* key, TypedValue* val) {
Object e(SystemLib::AllocRuntimeExceptionObject(
"Cannot assign to an element of a Tuple"));
throw e;
}
bool c_Tuple::OffsetIsset(ObjectData* obj, TypedValue* key) {
assert(key->m_type != KindOfRef);
auto tup = static_cast<c_Tuple*>(obj);
TypedValue* result;
if (key->m_type == KindOfInt64) {
result = tup->get(key->m_data.num);
} else {
throwBadKeyType();
result = NULL;
}
return result ? isset(tvAsCVarRef(result)) : false;
}
bool c_Tuple::OffsetEmpty(ObjectData* obj, TypedValue* key) {
assert(key->m_type != KindOfRef);
auto tup = static_cast<c_Tuple*>(obj);
TypedValue* result;
if (key->m_type == KindOfInt64) {
result = tup->get(key->m_data.num);
} else {
throwBadKeyType();
result = NULL;
}
return result ? empty(tvAsCVarRef(result)) : true;
}
bool c_Tuple::OffsetContains(ObjectData* obj, TypedValue* key) {
assert(key->m_type != KindOfRef);
auto tup = static_cast<c_Tuple*>(obj);
if (key->m_type == KindOfInt64) {
return tup->contains(key->m_data.num);
} else {
throwBadKeyType();
return false;
}
}
void c_Tuple::OffsetAppend(ObjectData* obj, TypedValue* val) {
assert(val->m_type != KindOfRef);
auto tup = static_cast<c_Tuple*>(obj);
tup->add(val);
}
void c_Tuple::OffsetUnset(ObjectData* obj, TypedValue* key) {
Object e(SystemLib::AllocRuntimeExceptionObject(
"Cannot unset element of a Tuple"));
throw e;
}
bool c_Tuple::Equals(ObjectData* obj1, ObjectData* obj2) {
auto tup1 = static_cast<c_Tuple*>(obj1);
auto tup2 = static_cast<c_Tuple*>(obj2);
uint sz = tup1->m_size;
if (sz != tup2->m_size) {
return false;
}
TypedValue* data1 = tup1->getData();
TypedValue* data2 = tup2->getData();
for (uint i = 0; i < sz; ++i) {
if (!equal(tvAsCVarRef(&data1[i]),
tvAsCVarRef(&data2[i]))) {
return false;
}
}
return true;
}
c_TupleIterator::c_TupleIterator(VM::Class* cb) :
ExtObjectData(cb) {
}
c_TupleIterator::~c_TupleIterator() {
}
void c_TupleIterator::t___construct() {
}
Variant c_TupleIterator::t_current() {
c_Tuple* tup = m_obj.get();
if (!tup->contains(m_pos)) {
throw_iterator_not_valid();
}
return tvAsCVarRef(&tup->getData()[m_pos]);
}
Variant c_TupleIterator::t_key() {
c_Tuple* tup = m_obj.get();
if (!tup->contains(m_pos)) {
throw_iterator_not_valid();
}
return m_pos;
}
bool c_TupleIterator::t_valid() {
assert(m_pos >= 0);
c_Tuple* tup = m_obj.get();
return tup && (m_pos < (ssize_t)tup->m_size);
}
void c_TupleIterator::t_next() {
m_pos++;
}
void c_TupleIterator::t_rewind() {
m_pos = 0;
}
///////////////////////////////////////////////////////////////////////////////
#define COLLECTION_MAGIC_METHODS(cls) \
String c_##cls::t___tostring() { \
return #cls; \
@@ -2746,13 +2959,15 @@ void c_StableMapIterator::t_rewind() {
COLLECTION_MAGIC_METHODS(Vector)
COLLECTION_MAGIC_METHODS(Map)
COLLECTION_MAGIC_METHODS(StableMap)
COLLECTION_MAGIC_METHODS(Tuple)
#undef COLLECTION_MAGIC_METHODS
void collectionSerialize(ObjectData* obj, VariableSerializer* serializer) {
assert(obj->isCollection());
int64_t sz = collectionSize(obj);
if (obj->getCollectionType() == Collection::VectorType) {
if (obj->getCollectionType() == Collection::VectorType ||
obj->getCollectionType() == Collection::TupleType) {
serializer->setObjectInfo(obj->o_getClassName(), obj->o_getId(), 'V');
serializer->writeArrayHeader(sz, true);
if (serializer->getType() == VariableSerializer::Serialize ||
@@ -2830,6 +3045,9 @@ void collectionDeepCopyTV(TypedValue* tv) {
case Collection::StableMapType:
obj = collectionDeepCopyStableMap(static_cast<c_StableMap*>(obj));
break;
case Collection::TupleType:
obj = collectionDeepCopyTuple(static_cast<c_Tuple*>(obj));
break;
default:
assert(false);
obj = NULL;
@@ -2841,6 +3059,10 @@ void collectionDeepCopyTV(TypedValue* tv) {
tv->m_data.pobj = obj;
break;
}
case KindOfRef: {
assert(false);
break;
}
default: break;
}
}
@@ -2882,18 +3104,29 @@ ObjectData* collectionDeepCopyStableMap(c_StableMap* smp) {
return o.detach();
}
CollectionInit::CollectionInit(int cType, ssize_t nElems) {
ObjectData* collectionDeepCopyTuple(c_Tuple* tup) {
Object o = tup = static_cast<c_Tuple*>(tup->clone());
size_t sz = tup->m_size;
TypedValue* data = tup->getData();
for (size_t i = 0; i < sz; ++i) {
collectionDeepCopyTV(&data[i]);
}
return o.detach();
}
CollectionInit::CollectionInit(int cType, ssize_t nElms) {
switch (cType) {
case Collection::VectorType: m_data = NEWOBJ(c_Vector)(); break;
case Collection::MapType: m_data = NEWOBJ(c_Map)(); break;
case Collection::StableMapType: m_data = NEWOBJ(c_StableMap)(); break;
case Collection::TupleType: m_data = c_Tuple::alloc(nElms); break;
default:
assert(false);
break;
}
// Reserve enough room for nElems elements in advance
if (nElems) {
collectionReserve(m_data, nElems);
// Reserve enough room for nElms elements in advance
if (nElms) {
collectionReserve(m_data, nElms);
}
}
+498
Ver Arquivo
@@ -3952,6 +3952,504 @@ TypedValue* tg_17StableMapIterator_rewind(HPHP::VM::ActRec *ar) {
return &ar->m_r;
}
HPHP::VM::Instance* new_Tuple_Instance(HPHP::VM::Class* cls) {
size_t nProps = cls->numDeclProperties();
size_t builtinPropSize = sizeof(c_Tuple) - sizeof(ObjectData);
size_t size = HPHP::VM::Instance::sizeForNProps(nProps) + builtinPropSize;
HPHP::VM::Instance *inst = (HPHP::VM::Instance*)ALLOCOBJSZ(size);
new ((void *)inst) c_Tuple(cls);
return inst;
}
IMPLEMENT_CLASS(Tuple);
/*
void HPHP::c_Tuple::t___construct()
_ZN4HPHP7c_Tuple13t___constructEv
this_ => rdi
*/
void th_5Tuple___construct(ObjectData* this_) asm("_ZN4HPHP7c_Tuple13t___constructEv");
TypedValue* tg_5Tuple___construct(HPHP::VM::ActRec *ar) {
TypedValue rv;
int64_t count = ar->numArgs();
TypedValue* args UNUSED = ((TypedValue*)ar) - 1;
ObjectData* this_ = (ar->hasThis() ? ar->getThis() : NULL);
if (this_) {
if (count == 0LL) {
rv.m_data.num = 0LL;
rv.m_type = KindOfNull;
th_5Tuple___construct((this_));
frame_free_locals_inl(ar, 0);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
} else {
throw_toomany_arguments_nr("Tuple::__construct", 0, 1);
}
} else {
throw_instance_method_fatal("Tuple::__construct");
}
rv.m_data.num = 0LL;
rv.m_type = KindOfNull;
frame_free_locals_inl(ar, 0);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
return &ar->m_r;
}
/*
bool HPHP::c_Tuple::t_isempty()
_ZN4HPHP7c_Tuple9t_isemptyEv
(return value) => rax
this_ => rdi
*/
bool th_5Tuple_isEmpty(ObjectData* this_) asm("_ZN4HPHP7c_Tuple9t_isemptyEv");
TypedValue* tg_5Tuple_isEmpty(HPHP::VM::ActRec *ar) {
TypedValue rv;
int64_t count = ar->numArgs();
TypedValue* args UNUSED = ((TypedValue*)ar) - 1;
ObjectData* this_ = (ar->hasThis() ? ar->getThis() : NULL);
if (this_) {
if (count == 0LL) {
rv.m_type = KindOfBoolean;
rv.m_data.num = (th_5Tuple_isEmpty((this_))) ? 1LL : 0LL;
frame_free_locals_inl(ar, 0);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
} else {
throw_toomany_arguments_nr("Tuple::isEmpty", 0, 1);
}
} else {
throw_instance_method_fatal("Tuple::isEmpty");
}
rv.m_data.num = 0LL;
rv.m_type = KindOfNull;
frame_free_locals_inl(ar, 0);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
return &ar->m_r;
}
/*
long HPHP::c_Tuple::t_count()
_ZN4HPHP7c_Tuple7t_countEv
(return value) => rax
this_ => rdi
*/
long th_5Tuple_count(ObjectData* this_) asm("_ZN4HPHP7c_Tuple7t_countEv");
TypedValue* tg_5Tuple_count(HPHP::VM::ActRec *ar) {
TypedValue rv;
int64_t count = ar->numArgs();
TypedValue* args UNUSED = ((TypedValue*)ar) - 1;
ObjectData* this_ = (ar->hasThis() ? ar->getThis() : NULL);
if (this_) {
if (count == 0LL) {
rv.m_type = KindOfInt64;
rv.m_data.num = (int64_t)th_5Tuple_count((this_));
frame_free_locals_inl(ar, 0);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
} else {
throw_toomany_arguments_nr("Tuple::count", 0, 1);
}
} else {
throw_instance_method_fatal("Tuple::count");
}
rv.m_data.num = 0LL;
rv.m_type = KindOfNull;
frame_free_locals_inl(ar, 0);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
return &ar->m_r;
}
/*
HPHP::Array HPHP::c_Tuple::t_toarray()
_ZN4HPHP7c_Tuple9t_toarrayEv
(return value) => rax
_rv => rdi
this_ => rsi
*/
Value* th_5Tuple_toArray(Value* _rv, ObjectData* this_) asm("_ZN4HPHP7c_Tuple9t_toarrayEv");
TypedValue* tg_5Tuple_toArray(HPHP::VM::ActRec *ar) {
TypedValue rv;
int64_t count = ar->numArgs();
TypedValue* args UNUSED = ((TypedValue*)ar) - 1;
ObjectData* this_ = (ar->hasThis() ? ar->getThis() : NULL);
if (this_) {
if (count == 0LL) {
rv.m_type = KindOfArray;
th_5Tuple_toArray((Value*)(&(rv)), (this_));
if (rv.m_data.num == 0LL) rv.m_type = KindOfNull;
frame_free_locals_inl(ar, 0);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
} else {
throw_toomany_arguments_nr("Tuple::toArray", 0, 1);
}
} else {
throw_instance_method_fatal("Tuple::toArray");
}
rv.m_data.num = 0LL;
rv.m_type = KindOfNull;
frame_free_locals_inl(ar, 0);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
return &ar->m_r;
}
/*
HPHP::Object HPHP::c_Tuple::t_getiterator()
_ZN4HPHP7c_Tuple13t_getiteratorEv
(return value) => rax
_rv => rdi
this_ => rsi
*/
Value* th_5Tuple_getIterator(Value* _rv, ObjectData* this_) asm("_ZN4HPHP7c_Tuple13t_getiteratorEv");
TypedValue* tg_5Tuple_getIterator(HPHP::VM::ActRec *ar) {
TypedValue rv;
int64_t count = ar->numArgs();
TypedValue* args UNUSED = ((TypedValue*)ar) - 1;
ObjectData* this_ = (ar->hasThis() ? ar->getThis() : NULL);
if (this_) {
if (count == 0LL) {
rv.m_type = KindOfObject;
th_5Tuple_getIterator((Value*)(&(rv)), (this_));
if (rv.m_data.num == 0LL) rv.m_type = KindOfNull;
frame_free_locals_inl(ar, 0);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
} else {
throw_toomany_arguments_nr("Tuple::getIterator", 0, 1);
}
} else {
throw_instance_method_fatal("Tuple::getIterator");
}
rv.m_data.num = 0LL;
rv.m_type = KindOfNull;
frame_free_locals_inl(ar, 0);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
return &ar->m_r;
}
/*
HPHP::Variant HPHP::c_Tuple::t_at(HPHP::Variant const&)
_ZN4HPHP7c_Tuple4t_atERKNS_7VariantE
(return value) => rax
_rv => rdi
this_ => rsi
key => rdx
*/
TypedValue* th_5Tuple_at(TypedValue* _rv, ObjectData* this_, TypedValue* key) asm("_ZN4HPHP7c_Tuple4t_atERKNS_7VariantE");
TypedValue* tg_5Tuple_at(HPHP::VM::ActRec *ar) {
TypedValue rv;
int64_t count = ar->numArgs();
TypedValue* args UNUSED = ((TypedValue*)ar) - 1;
ObjectData* this_ = (ar->hasThis() ? ar->getThis() : NULL);
if (this_) {
if (count == 1LL) {
th_5Tuple_at((&(rv)), (this_), (args-0));
if (rv.m_type == KindOfUninit) rv.m_type = KindOfNull;
frame_free_locals_inl(ar, 1);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
} else {
throw_wrong_arguments_nr("Tuple::at", count, 1, 1, 1);
}
} else {
throw_instance_method_fatal("Tuple::at");
}
rv.m_data.num = 0LL;
rv.m_type = KindOfNull;
frame_free_locals_inl(ar, 1);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
return &ar->m_r;
}
/*
HPHP::Variant HPHP::c_Tuple::t_get(HPHP::Variant const&)
_ZN4HPHP7c_Tuple5t_getERKNS_7VariantE
(return value) => rax
_rv => rdi
this_ => rsi
key => rdx
*/
TypedValue* th_5Tuple_get(TypedValue* _rv, ObjectData* this_, TypedValue* key) asm("_ZN4HPHP7c_Tuple5t_getERKNS_7VariantE");
TypedValue* tg_5Tuple_get(HPHP::VM::ActRec *ar) {
TypedValue rv;
int64_t count = ar->numArgs();
TypedValue* args UNUSED = ((TypedValue*)ar) - 1;
ObjectData* this_ = (ar->hasThis() ? ar->getThis() : NULL);
if (this_) {
if (count == 1LL) {
th_5Tuple_get((&(rv)), (this_), (args-0));
if (rv.m_type == KindOfUninit) rv.m_type = KindOfNull;
frame_free_locals_inl(ar, 1);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
} else {
throw_wrong_arguments_nr("Tuple::get", count, 1, 1, 1);
}
} else {
throw_instance_method_fatal("Tuple::get");
}
rv.m_data.num = 0LL;
rv.m_type = KindOfNull;
frame_free_locals_inl(ar, 1);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
return &ar->m_r;
}
HPHP::VM::Instance* new_TupleIterator_Instance(HPHP::VM::Class* cls) {
size_t nProps = cls->numDeclProperties();
size_t builtinPropSize = sizeof(c_TupleIterator) - sizeof(ObjectData);
size_t size = HPHP::VM::Instance::sizeForNProps(nProps) + builtinPropSize;
HPHP::VM::Instance *inst = (HPHP::VM::Instance*)ALLOCOBJSZ(size);
new ((void *)inst) c_TupleIterator(cls);
return inst;
}
IMPLEMENT_CLASS(TupleIterator);
/*
void HPHP::c_TupleIterator::t___construct()
_ZN4HPHP15c_TupleIterator13t___constructEv
this_ => rdi
*/
void th_13TupleIterator___construct(ObjectData* this_) asm("_ZN4HPHP15c_TupleIterator13t___constructEv");
TypedValue* tg_13TupleIterator___construct(HPHP::VM::ActRec *ar) {
TypedValue rv;
int64_t count = ar->numArgs();
TypedValue* args UNUSED = ((TypedValue*)ar) - 1;
ObjectData* this_ = (ar->hasThis() ? ar->getThis() : NULL);
if (this_) {
if (count == 0LL) {
rv.m_data.num = 0LL;
rv.m_type = KindOfNull;
th_13TupleIterator___construct((this_));
frame_free_locals_inl(ar, 0);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
} else {
throw_toomany_arguments_nr("TupleIterator::__construct", 0, 1);
}
} else {
throw_instance_method_fatal("TupleIterator::__construct");
}
rv.m_data.num = 0LL;
rv.m_type = KindOfNull;
frame_free_locals_inl(ar, 0);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
return &ar->m_r;
}
/*
HPHP::Variant HPHP::c_TupleIterator::t_current()
_ZN4HPHP15c_TupleIterator9t_currentEv
(return value) => rax
_rv => rdi
this_ => rsi
*/
TypedValue* th_13TupleIterator_current(TypedValue* _rv, ObjectData* this_) asm("_ZN4HPHP15c_TupleIterator9t_currentEv");
TypedValue* tg_13TupleIterator_current(HPHP::VM::ActRec *ar) {
TypedValue rv;
int64_t count = ar->numArgs();
TypedValue* args UNUSED = ((TypedValue*)ar) - 1;
ObjectData* this_ = (ar->hasThis() ? ar->getThis() : NULL);
if (this_) {
if (count == 0LL) {
th_13TupleIterator_current((&(rv)), (this_));
if (rv.m_type == KindOfUninit) rv.m_type = KindOfNull;
frame_free_locals_inl(ar, 0);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
} else {
throw_toomany_arguments_nr("TupleIterator::current", 0, 1);
}
} else {
throw_instance_method_fatal("TupleIterator::current");
}
rv.m_data.num = 0LL;
rv.m_type = KindOfNull;
frame_free_locals_inl(ar, 0);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
return &ar->m_r;
}
/*
HPHP::Variant HPHP::c_TupleIterator::t_key()
_ZN4HPHP15c_TupleIterator5t_keyEv
(return value) => rax
_rv => rdi
this_ => rsi
*/
TypedValue* th_13TupleIterator_key(TypedValue* _rv, ObjectData* this_) asm("_ZN4HPHP15c_TupleIterator5t_keyEv");
TypedValue* tg_13TupleIterator_key(HPHP::VM::ActRec *ar) {
TypedValue rv;
int64_t count = ar->numArgs();
TypedValue* args UNUSED = ((TypedValue*)ar) - 1;
ObjectData* this_ = (ar->hasThis() ? ar->getThis() : NULL);
if (this_) {
if (count == 0LL) {
th_13TupleIterator_key((&(rv)), (this_));
if (rv.m_type == KindOfUninit) rv.m_type = KindOfNull;
frame_free_locals_inl(ar, 0);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
} else {
throw_toomany_arguments_nr("TupleIterator::key", 0, 1);
}
} else {
throw_instance_method_fatal("TupleIterator::key");
}
rv.m_data.num = 0LL;
rv.m_type = KindOfNull;
frame_free_locals_inl(ar, 0);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
return &ar->m_r;
}
/*
bool HPHP::c_TupleIterator::t_valid()
_ZN4HPHP15c_TupleIterator7t_validEv
(return value) => rax
this_ => rdi
*/
bool th_13TupleIterator_valid(ObjectData* this_) asm("_ZN4HPHP15c_TupleIterator7t_validEv");
TypedValue* tg_13TupleIterator_valid(HPHP::VM::ActRec *ar) {
TypedValue rv;
int64_t count = ar->numArgs();
TypedValue* args UNUSED = ((TypedValue*)ar) - 1;
ObjectData* this_ = (ar->hasThis() ? ar->getThis() : NULL);
if (this_) {
if (count == 0LL) {
rv.m_type = KindOfBoolean;
rv.m_data.num = (th_13TupleIterator_valid((this_))) ? 1LL : 0LL;
frame_free_locals_inl(ar, 0);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
} else {
throw_toomany_arguments_nr("TupleIterator::valid", 0, 1);
}
} else {
throw_instance_method_fatal("TupleIterator::valid");
}
rv.m_data.num = 0LL;
rv.m_type = KindOfNull;
frame_free_locals_inl(ar, 0);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
return &ar->m_r;
}
/*
void HPHP::c_TupleIterator::t_next()
_ZN4HPHP15c_TupleIterator6t_nextEv
this_ => rdi
*/
void th_13TupleIterator_next(ObjectData* this_) asm("_ZN4HPHP15c_TupleIterator6t_nextEv");
TypedValue* tg_13TupleIterator_next(HPHP::VM::ActRec *ar) {
TypedValue rv;
int64_t count = ar->numArgs();
TypedValue* args UNUSED = ((TypedValue*)ar) - 1;
ObjectData* this_ = (ar->hasThis() ? ar->getThis() : NULL);
if (this_) {
if (count == 0LL) {
rv.m_data.num = 0LL;
rv.m_type = KindOfNull;
th_13TupleIterator_next((this_));
frame_free_locals_inl(ar, 0);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
} else {
throw_toomany_arguments_nr("TupleIterator::next", 0, 1);
}
} else {
throw_instance_method_fatal("TupleIterator::next");
}
rv.m_data.num = 0LL;
rv.m_type = KindOfNull;
frame_free_locals_inl(ar, 0);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
return &ar->m_r;
}
/*
void HPHP::c_TupleIterator::t_rewind()
_ZN4HPHP15c_TupleIterator8t_rewindEv
this_ => rdi
*/
void th_13TupleIterator_rewind(ObjectData* this_) asm("_ZN4HPHP15c_TupleIterator8t_rewindEv");
TypedValue* tg_13TupleIterator_rewind(HPHP::VM::ActRec *ar) {
TypedValue rv;
int64_t count = ar->numArgs();
TypedValue* args UNUSED = ((TypedValue*)ar) - 1;
ObjectData* this_ = (ar->hasThis() ? ar->getThis() : NULL);
if (this_) {
if (count == 0LL) {
rv.m_data.num = 0LL;
rv.m_type = KindOfNull;
th_13TupleIterator_rewind((this_));
frame_free_locals_inl(ar, 0);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
} else {
throw_toomany_arguments_nr("TupleIterator::rewind", 0, 1);
}
} else {
throw_instance_method_fatal("TupleIterator::rewind");
}
rv.m_data.num = 0LL;
rv.m_type = KindOfNull;
frame_free_locals_inl(ar, 0);
memcpy(&ar->m_r, &rv, sizeof(TypedValue));
return &ar->m_r;
return &ar->m_r;
}
} // !HPHP
+411 -195
Ver Arquivo
@@ -46,7 +46,6 @@ class c_Vector : public ExtObjectDataFlags<ObjectData::VectorAttrInit|
public: ~c_Vector();
public: void freeData();
public: void t___construct(CVarRef iterable = null_variant);
public: Variant t___destruct();
public: Object t_add(CVarRef val);
public: Object t_append(CVarRef val);
public: Variant t_pop();
@@ -219,7 +218,6 @@ class c_Map : public ExtObjectDataFlags<ObjectData::MapAttrInit|
public: ~c_Map();
public: void freeData();
public: void t___construct(CVarRef iterable = null_variant);
public: Variant t___destruct();
public: Object t_clear();
public: bool t_isempty();
public: int64_t t_count();
@@ -507,7 +505,6 @@ class c_StableMap : public ExtObjectDataFlags<ObjectData::StableMapAttrInit|
public: ~c_StableMap();
public: void freeData();
public: void t___construct(CVarRef iterable = null_variant);
public: Variant t___destruct();
public: Object t_clear();
public: bool t_isempty();
public: int64_t t_count();
@@ -734,21 +731,153 @@ class c_StableMapIterator : public ExtObjectData {
};
///////////////////////////////////////////////////////////////////////////////
// class Tuple
// Helpers for hhvm
FORWARD_DECLARE_CLASS_BUILTIN(Tuple);
class c_Tuple : public ExtObjectDataFlags<ObjectData::TupleAttrInit|
ObjectData::UseGet|
ObjectData::UseSet|
ObjectData::UseIsset|
ObjectData::UseUnset> {
public:
DECLARE_CLASS_NO_ALLOCATION(Tuple, Tuple, ObjectData)
virtual void sweep();
void operator delete(void* p) {
c_Tuple* this_ = (c_Tuple*)p;
DELETEOBJSZ(sizeForNumElms(this_->m_capacity))(this_);
}
friend class c_TupleIterator;
friend class c_Vector;
friend class c_Map;
friend class c_StableMap;
friend class ArrayIter;
public: c_Tuple(VM::Class* cls = c_Tuple::s_cls);
public: ~c_Tuple();
public: void t___construct();
public: bool t_isempty();
public: int64_t t_count();
public: Variant t_at(CVarRef key);
public: Variant t_get(CVarRef key);
public: Array t_toarray();
public: Object t_getiterator();
public: String t___tostring();
public: Variant t___get(Variant name);
public: Variant t___set(Variant name, Variant value);
public: bool t___isset(Variant name);
public: Variant t___unset(Variant name);
public: static void throwOOB(int64_t key) ATTRIBUTE_COLD;
public: TypedValue* at(int64_t key) {
if (UNLIKELY((uint64_t)key >= (uint64_t)m_size)) {
throwOOB(key);
return NULL;
}
return &getData()[key];
}
public: TypedValue* get(int64_t key) {
if ((uint64_t)key >= (uint64_t)m_size) {
return NULL;
}
return &getData()[key];
}
public: void add(TypedValue* val) {
assert(val->m_type != KindOfRef);
if (m_size == m_capacity) {
Object e(SystemLib::AllocRuntimeExceptionObject(
"Cannot add a new element to a Tuple"));
throw e;
}
tvRefcountedIncRef(val);
TypedValue* tv = &getData()[m_size];
tv->m_data.num = val->m_data.num;
tv->m_type = val->m_type;
++m_size;
}
public: bool contains(int64_t key) {
return ((uint64_t)key < (uint64_t)m_size);
}
public: Array toArrayImpl() const;
public: Array o_toArray() const;
public: ObjectData* clone();
public: static TypedValue* OffsetGet(ObjectData* obj, TypedValue* key);
public: static void OffsetSet(ObjectData* obj, TypedValue* key,
TypedValue* val);
public: static bool OffsetIsset(ObjectData* obj, TypedValue* key);
public: static bool OffsetEmpty(ObjectData* obj, TypedValue* key);
public: static bool OffsetContains(ObjectData* obj, TypedValue* key);
public: static void OffsetUnset(ObjectData* obj, TypedValue* key);
public: static void OffsetAppend(ObjectData* obj, TypedValue* val);
public: static bool Equals(ObjectData* obj1, ObjectData* obj2);
public: static size_t sizeForNumElms(int nElms) {
return sizeof(c_Tuple) + sizeof(TypedValue) * nElms;
}
public: static c_Tuple* alloc(int nElms) {
c_Tuple* tup = (c_Tuple*)ALLOCOBJSZ(sizeForNumElms(nElms));
new ((void *)tup) c_Tuple();
tup->m_capacity = nElms;
return tup;
}
private:
static void throwBadKeyType();
uint m_size;
uint m_capacity;
TypedValue* getData() const {
return (TypedValue*)(this+1);
}
friend ObjectData* collectionDeepCopyTuple(c_Tuple* tup);
} __attribute__((aligned(16)));
///////////////////////////////////////////////////////////////////////////////
// class TupleIterator
FORWARD_DECLARE_CLASS_BUILTIN(TupleIterator);
class c_TupleIterator : public ExtObjectData {
public:
DECLARE_CLASS(TupleIterator, TupleIterator, ObjectData)
friend class c_Tuple;
// need to implement
public: c_TupleIterator(VM::Class* cls = c_TupleIterator::s_cls);
public: ~c_TupleIterator();
public: void t___construct();
public: Variant t_current();
public: Variant t_key();
public: bool t_valid();
public: void t_next();
public: void t_rewind();
private:
SmartPtr<c_Tuple> m_obj;
ssize_t m_pos;
};
///////////////////////////////////////////////////////////////////////////////
inline TypedValue* collectionGet(ObjectData* obj, TypedValue* key) {
assert(key->m_type != KindOfRef);
int ct = obj->getCollectionType();
if (ct == Collection::VectorType) {
return c_Vector::OffsetGet(obj, key);
} else if (ct == Collection::MapType) {
return c_Map::OffsetGet(obj, key);
} else if (ct == Collection::StableMapType) {
return c_StableMap::OffsetGet(obj, key);
} else {
assert(false);
return NULL;
switch (obj->getCollectionType()) {
case Collection::VectorType:
return c_Vector::OffsetGet(obj, key);
case Collection::MapType:
return c_Map::OffsetGet(obj, key);
case Collection::StableMapType:
return c_StableMap::OffsetGet(obj, key);
case Collection::TupleType:
return c_Tuple::OffsetGet(obj, key);
default:
assert(false);
return NULL;
}
}
@@ -756,113 +885,147 @@ inline void collectionSet(ObjectData* obj, TypedValue* key, TypedValue* val) {
assert(key->m_type != KindOfRef);
assert(val->m_type != KindOfRef);
assert(val->m_type != KindOfUninit);
int ct = obj->getCollectionType();
if (ct == Collection::VectorType) {
c_Vector::OffsetSet(obj, key, val);
} else if (ct == Collection::MapType) {
c_Map::OffsetSet(obj, key, val);
} else if (ct == Collection::StableMapType) {
c_StableMap::OffsetSet(obj, key, val);
} else {
assert(false);
switch (obj->getCollectionType()) {
case Collection::VectorType:
c_Vector::OffsetSet(obj, key, val);
break;
case Collection::MapType:
c_Map::OffsetSet(obj, key, val);
break;
case Collection::StableMapType:
c_StableMap::OffsetSet(obj, key, val);
break;
case Collection::TupleType:
c_Tuple::OffsetSet(obj, key, val);
break;
default:
assert(false);
}
}
inline bool collectionIsset(ObjectData* obj, TypedValue* key) {
assert(key->m_type != KindOfRef);
int ct = obj->getCollectionType();
if (ct == Collection::VectorType) {
return c_Vector::OffsetIsset(obj, key);
} else if (ct == Collection::MapType) {
return c_Map::OffsetIsset(obj, key);
} else if (ct == Collection::StableMapType) {
return c_StableMap::OffsetIsset(obj, key);
} else {
assert(false);
return false;
switch (obj->getCollectionType()) {
case Collection::VectorType:
return c_Vector::OffsetIsset(obj, key);
case Collection::MapType:
return c_Map::OffsetIsset(obj, key);
case Collection::StableMapType:
return c_StableMap::OffsetIsset(obj, key);
case Collection::TupleType:
return c_Tuple::OffsetIsset(obj, key);
default:
assert(false);
return false;
}
}
inline bool collectionEmpty(ObjectData* obj, TypedValue* key) {
assert(key->m_type != KindOfRef);
int ct = obj->getCollectionType();
if (ct == Collection::VectorType) {
return c_Vector::OffsetEmpty(obj, key);
} else if (ct == Collection::MapType) {
return c_Map::OffsetEmpty(obj, key);
} else if (ct == Collection::StableMapType) {
return c_StableMap::OffsetEmpty(obj, key);
} else {
assert(false);
return true;
switch (obj->getCollectionType()) {
case Collection::VectorType:
return c_Vector::OffsetEmpty(obj, key);
case Collection::MapType:
return c_Map::OffsetEmpty(obj, key);
case Collection::StableMapType:
return c_StableMap::OffsetEmpty(obj, key);
case Collection::TupleType:
return c_Tuple::OffsetEmpty(obj, key);
default:
assert(false);
return false;
}
}
inline void collectionUnset(ObjectData* obj, TypedValue* key) {
assert(key->m_type != KindOfRef);
int ct = obj->getCollectionType();
if (ct == Collection::VectorType) {
c_Vector::OffsetUnset(obj, key);
} else if (ct == Collection::MapType) {
c_Map::OffsetUnset(obj, key);
} else if (ct == Collection::StableMapType) {
c_StableMap::OffsetUnset(obj, key);
} else {
assert(false);
switch (obj->getCollectionType()) {
case Collection::VectorType:
c_Vector::OffsetUnset(obj, key);
break;
case Collection::MapType:
c_Map::OffsetUnset(obj, key);
break;
case Collection::StableMapType:
c_StableMap::OffsetUnset(obj, key);
break;
case Collection::TupleType:
c_Tuple::OffsetUnset(obj, key);
break;
default:
assert(false);
}
}
inline void collectionAppend(ObjectData* obj, TypedValue* val) {
assert(val->m_type != KindOfRef);
assert(val->m_type != KindOfUninit);
int ct = obj->getCollectionType();
if (ct == Collection::VectorType) {
c_Vector::OffsetAppend(obj, val);
} else if (ct == Collection::MapType) {
c_Map::OffsetAppend(obj, val);
} else if (ct == Collection::StableMapType) {
c_StableMap::OffsetAppend(obj, val);
} else {
assert(false);
switch (obj->getCollectionType()) {
case Collection::VectorType:
c_Vector::OffsetAppend(obj, val);
break;
case Collection::MapType:
c_Map::OffsetAppend(obj, val);
break;
case Collection::StableMapType:
c_StableMap::OffsetAppend(obj, val);
break;
case Collection::TupleType:
c_Tuple::OffsetAppend(obj, val);
break;
default:
assert(false);
}
}
// Helpers for hphpc
inline Variant& collectionOffsetGet(ObjectData* obj, int64_t offset) {
int ct = obj->getCollectionType();
if (ct == Collection::VectorType) {
c_Vector* vec = static_cast<c_Vector*>(obj);
return *(Variant*)(vec->at(offset));
} else if (ct == Collection::MapType) {
c_Map* mp = static_cast<c_Map*>(obj);
return *(Variant*)(mp->at(offset));
} else if (ct == Collection::StableMapType) {
c_StableMap* smp = static_cast<c_StableMap*>(obj);
return *(Variant*)(smp->at(offset));
} else {
assert(false);
return *(Variant*)(NULL);
switch (obj->getCollectionType()) {
case Collection::VectorType: {
c_Vector* vec = static_cast<c_Vector*>(obj);
return *(Variant*)(vec->at(offset));
}
case Collection::MapType: {
c_Map* mp = static_cast<c_Map*>(obj);
return *(Variant*)(mp->at(offset));
}
case Collection::StableMapType: {
c_StableMap* smp = static_cast<c_StableMap*>(obj);
return *(Variant*)(smp->at(offset));
}
case Collection::TupleType: {
c_Tuple* tup = static_cast<c_Tuple*>(obj);
return *(Variant*)(tup->at(offset));
}
default:
assert(false);
return *(Variant*)(NULL);
}
}
inline Variant& collectionOffsetGet(ObjectData* obj, CStrRef offset) {
StringData* key = offset.get();
int ct = obj->getCollectionType();
if (ct == Collection::VectorType) {
Object e(SystemLib::AllocInvalidArgumentExceptionObject(
"Only integer keys may be used with Vectors"));
throw e;
return *(Variant*)(NULL);
} else if (ct == Collection::MapType) {
c_Map* mp = static_cast<c_Map*>(obj);
return *(Variant*)(mp->at(key));
} else if (ct == Collection::StableMapType) {
c_StableMap* smp = static_cast<c_StableMap*>(obj);
return *(Variant*)(smp->at(key));
} else {
assert(false);
return *(Variant*)(NULL);
switch (obj->getCollectionType()) {
case Collection::VectorType: {
Object e(SystemLib::AllocInvalidArgumentExceptionObject(
"Only integer keys may be used with Vectors"));
throw e;
}
case Collection::MapType: {
c_Map* mp = static_cast<c_Map*>(obj);
return *(Variant*)(mp->at(key));
}
case Collection::StableMapType: {
c_StableMap* smp = static_cast<c_StableMap*>(obj);
return *(Variant*)(smp->at(key));
}
case Collection::TupleType: {
Object e(SystemLib::AllocInvalidArgumentExceptionObject(
"Only integer keys may be used with Tuples"));
throw e;
}
default:
assert(false);
return *(Variant*)(NULL);
}
}
@@ -871,16 +1034,18 @@ inline Variant& collectionOffsetGet(ObjectData* obj, CVarRef offset) {
if (key->m_type == KindOfRef) {
key = key->m_data.pref->tv();
}
int ct = obj->getCollectionType();
if (ct == Collection::VectorType) {
return *(Variant*)(c_Vector::OffsetGet(obj, key));
} else if (ct == Collection::MapType) {
return *(Variant*)(c_Map::OffsetGet(obj, key));
} else if (ct == Collection::StableMapType) {
return *(Variant*)(c_StableMap::OffsetGet(obj, key));
} else {
assert(false);
return *(Variant*)(NULL);
switch (obj->getCollectionType()) {
case Collection::VectorType:
return *(Variant*)(c_Vector::OffsetGet(obj, key));
case Collection::MapType:
return *(Variant*)(c_Map::OffsetGet(obj, key));
case Collection::StableMapType:
return *(Variant*)(c_StableMap::OffsetGet(obj, key));
case Collection::TupleType:
return *(Variant*)(c_Tuple::OffsetGet(obj, key));
default:
assert(false);
return *(Variant*)(NULL);
}
}
@@ -904,18 +1069,29 @@ inline void collectionOffsetSet(ObjectData* obj, int64_t offset, CVarRef val) {
if (UNLIKELY(tv->m_type == KindOfUninit)) {
tv = (TypedValue*)(&init_null_variant);
}
int ct = obj->getCollectionType();
if (ct == Collection::VectorType) {
c_Vector* vec = static_cast<c_Vector*>(obj);
vec->put(offset, tv);
} else if (ct == Collection::MapType) {
c_Map* mp = static_cast<c_Map*>(obj);
mp->put(offset, tv);
} else if (ct == Collection::StableMapType) {
c_StableMap* smp = static_cast<c_StableMap*>(obj);
smp->put(offset, tv);
} else {
assert(false);
switch (obj->getCollectionType()) {
case Collection::VectorType: {
c_Vector* vec = static_cast<c_Vector*>(obj);
vec->put(offset, tv);
break;
}
case Collection::MapType: {
c_Map* mp = static_cast<c_Map*>(obj);
mp->put(offset, tv);
break;
}
case Collection::StableMapType: {
c_StableMap* smp = static_cast<c_StableMap*>(obj);
smp->put(offset, tv);
break;
}
case Collection::TupleType: {
Object e(SystemLib::AllocRuntimeExceptionObject(
"Cannot assign to an element of a Tuple"));
throw e;
}
default:
assert(false);
}
}
@@ -928,19 +1104,29 @@ inline void collectionOffsetSet(ObjectData* obj, CStrRef offset, CVarRef val) {
if (UNLIKELY(tv->m_type == KindOfUninit)) {
tv = (TypedValue*)(&init_null_variant);
}
int ct = obj->getCollectionType();
if (ct == Collection::VectorType) {
Object e(SystemLib::AllocInvalidArgumentExceptionObject(
"Only integer keys may be used with Vectors"));
throw e;
} else if (ct == Collection::MapType) {
c_Map* mp = static_cast<c_Map*>(obj);
mp->put(key, tv);
} else if (ct == Collection::StableMapType) {
c_StableMap* smp = static_cast<c_StableMap*>(obj);
smp->put(key, tv);
} else {
assert(false);
switch (obj->getCollectionType()) {
case Collection::VectorType: {
Object e(SystemLib::AllocInvalidArgumentExceptionObject(
"Only integer keys may be used with Vectors"));
throw e;
}
case Collection::MapType: {
c_Map* mp = static_cast<c_Map*>(obj);
mp->put(key, tv);
break;
}
case Collection::StableMapType: {
c_StableMap* smp = static_cast<c_StableMap*>(obj);
smp->put(key, tv);
break;
}
case Collection::TupleType: {
Object e(SystemLib::AllocRuntimeExceptionObject(
"Cannot assign to an element of a Tuple"));
throw e;
}
default:
assert(false);
}
}
@@ -956,15 +1142,25 @@ inline void collectionOffsetSet(ObjectData* obj, CVarRef offset, CVarRef val) {
if (UNLIKELY(tv->m_type == KindOfUninit)) {
tv = (TypedValue*)(&init_null_variant);
}
int ct = obj->getCollectionType();
if (ct == Collection::VectorType) {
c_Vector::OffsetSet(obj, key, tv);
} else if (ct == Collection::MapType) {
c_Map::OffsetSet(obj, key, tv);
} else if (ct == Collection::StableMapType) {
c_StableMap::OffsetSet(obj, key, tv);
} else {
assert(false);
switch (obj->getCollectionType()) {
case Collection::VectorType: {
c_Vector::OffsetSet(obj, key, tv);
break;
}
case Collection::MapType: {
c_Map::OffsetSet(obj, key, tv);
break;
}
case Collection::StableMapType: {
c_StableMap::OffsetSet(obj, key, tv);
break;
}
case Collection::TupleType: {
c_Tuple::OffsetSet(obj, key, tv);
break;
}
default:
assert(false);
}
}
@@ -985,16 +1181,18 @@ inline bool collectionOffsetContains(ObjectData* obj, CVarRef offset) {
if (key->m_type == KindOfRef) {
key = key->m_data.pref->tv();
}
int ct = obj->getCollectionType();
if (ct == Collection::VectorType) {
return c_Vector::OffsetContains(obj, key);
} else if (ct == Collection::MapType) {
return c_Map::OffsetContains(obj, key);
} else if (ct == Collection::StableMapType) {
return c_StableMap::OffsetContains(obj, key);
} else {
assert(false);
return false;
switch (obj->getCollectionType()) {
case Collection::VectorType:
return c_Vector::OffsetContains(obj, key);
case Collection::MapType:
return c_Map::OffsetContains(obj, key);
case Collection::StableMapType:
return c_StableMap::OffsetContains(obj, key);
case Collection::TupleType:
return c_Tuple::OffsetContains(obj, key);
default:
assert(false);
return false;
}
}
@@ -1003,16 +1201,18 @@ inline bool collectionOffsetIsset(ObjectData* obj, CVarRef offset) {
if (key->m_type == KindOfRef) {
key = key->m_data.pref->tv();
}
int ct = obj->getCollectionType();
if (ct == Collection::VectorType) {
return c_Vector::OffsetIsset(obj, key);
} else if (ct == Collection::MapType) {
return c_Map::OffsetIsset(obj, key);
} else if (ct == Collection::StableMapType) {
return c_StableMap::OffsetIsset(obj, key);
} else {
assert(false);
return false;
switch (obj->getCollectionType()) {
case Collection::VectorType:
return c_Vector::OffsetIsset(obj, key);
case Collection::MapType:
return c_Map::OffsetIsset(obj, key);
case Collection::StableMapType:
return c_StableMap::OffsetIsset(obj, key);
case Collection::TupleType:
return c_Tuple::OffsetIsset(obj, key);
default:
assert(false);
return false;
}
}
@@ -1021,16 +1221,18 @@ inline bool collectionOffsetEmpty(ObjectData* obj, CVarRef offset) {
if (key->m_type == KindOfRef) {
key = key->m_data.pref->tv();
}
int ct = obj->getCollectionType();
if (ct == Collection::VectorType) {
return c_Vector::OffsetEmpty(obj, key);
} else if (ct == Collection::MapType) {
return c_Map::OffsetEmpty(obj, key);
} else if (ct == Collection::StableMapType) {
return c_StableMap::OffsetEmpty(obj, key);
} else {
assert(false);
return true;
switch (obj->getCollectionType()) {
case Collection::VectorType:
return c_Vector::OffsetEmpty(obj, key);
case Collection::MapType:
return c_Map::OffsetEmpty(obj, key);
case Collection::StableMapType:
return c_StableMap::OffsetEmpty(obj, key);
case Collection::TupleType:
return c_Tuple::OffsetEmpty(obj, key);
default:
assert(false);
return true;
}
}
@@ -1054,29 +1256,37 @@ inline void collectionOffsetAppend(ObjectData* obj, CVarRef val) {
}
inline int64_t collectionSize(ObjectData* obj) {
int ct = obj->getCollectionType();
if (ct == Collection::VectorType) {
return static_cast<c_Vector*>(obj)->t_count();
} else if (ct == Collection::MapType) {
return static_cast<c_Map*>(obj)->t_count();
} else if (ct == Collection::StableMapType) {
return static_cast<c_StableMap*>(obj)->t_count();
} else {
assert(false);
return 0;
switch (obj->getCollectionType()) {
case Collection::VectorType:
return static_cast<c_Vector*>(obj)->t_count();
case Collection::MapType:
return static_cast<c_Map*>(obj)->t_count();
case Collection::StableMapType:
return static_cast<c_StableMap*>(obj)->t_count();
case Collection::TupleType:
return static_cast<c_Tuple*>(obj)->t_count();
default:
assert(false);
return 0;
}
}
inline void collectionReserve(ObjectData* obj, int64_t sz) {
int ct = obj->getCollectionType();
if (ct == Collection::VectorType) {
static_cast<c_Vector*>(obj)->reserve(sz);
} else if (ct == Collection::MapType) {
static_cast<c_Map*>(obj)->reserve(sz);
} else if (ct == Collection::StableMapType) {
static_cast<c_StableMap*>(obj)->reserve(sz);
} else {
assert(false);
switch (obj->getCollectionType()) {
case Collection::VectorType:
static_cast<c_Vector*>(obj)->reserve(sz);
break;
case Collection::MapType:
static_cast<c_Map*>(obj)->reserve(sz);
break;
case Collection::StableMapType:
static_cast<c_StableMap*>(obj)->reserve(sz);
break;
case Collection::TupleType:
// do nothing
break;
default:
assert(false);
}
}
@@ -1089,26 +1299,31 @@ void collectionUnserialize(ObjectData* obj,
inline bool collectionEquals(ObjectData* obj1, ObjectData* obj2) {
int ct = obj1->getCollectionType();
assert(ct == obj2->getCollectionType());
if (ct == Collection::VectorType) {
return c_Vector::Equals(obj1, obj2);
} else if (ct == Collection::MapType) {
return c_Map::Equals(obj1, obj2);
} else if (ct == Collection::StableMapType) {
return c_StableMap::Equals(obj1, obj2);
switch (ct) {
case Collection::VectorType:
return c_Vector::Equals(obj1, obj2);
case Collection::MapType:
return c_Map::Equals(obj1, obj2);
case Collection::StableMapType:
return c_StableMap::Equals(obj1, obj2);
case Collection::TupleType:
return c_Tuple::Equals(obj1, obj2);
default:
assert(false);
return false;
}
assert(false);
return false;
}
void collectionDeepCopyTV(TypedValue* tv);
ArrayData* collectionDeepCopyArray(ArrayData* arr);
ObjectData* collectionDeepCopyVector(c_Vector* vec);
ObjectData* collectionDeepCopyMap(c_Map* vec);
ObjectData* collectionDeepCopyStableMap(c_StableMap* vec);
ObjectData* collectionDeepCopyMap(c_Map* mp);
ObjectData* collectionDeepCopyStableMap(c_StableMap* smp);
ObjectData* collectionDeepCopyTuple(c_Tuple* tup);
class CollectionInit {
public:
CollectionInit(int cType, ssize_t nElems);
CollectionInit(int cType, ssize_t nElms);
~CollectionInit() {
// In case an exception interrupts the initialization.
if (m_data) m_data->release();
@@ -1174,6 +1389,7 @@ private:
};
///////////////////////////////////////////////////////////////////////////////
}
#endif // __EXT_COLLECTION_H__
+39 -1
Ver Arquivo
@@ -2383,6 +2383,21 @@ TypedValue* tg_17StableMapIterator_key(VM::ActRec *ar);
TypedValue* tg_17StableMapIterator_valid(VM::ActRec *ar);
TypedValue* tg_17StableMapIterator_next(VM::ActRec *ar);
TypedValue* tg_17StableMapIterator_rewind(VM::ActRec *ar);
VM::Instance* new_Tuple_Instance(VM::Class*);
TypedValue* tg_5Tuple___construct(VM::ActRec *ar);
TypedValue* tg_5Tuple_isEmpty(VM::ActRec *ar);
TypedValue* tg_5Tuple_count(VM::ActRec *ar);
TypedValue* tg_5Tuple_toArray(VM::ActRec *ar);
TypedValue* tg_5Tuple_getIterator(VM::ActRec *ar);
TypedValue* tg_5Tuple_at(VM::ActRec *ar);
TypedValue* tg_5Tuple_get(VM::ActRec *ar);
VM::Instance* new_TupleIterator_Instance(VM::Class*);
TypedValue* tg_13TupleIterator___construct(VM::ActRec *ar);
TypedValue* tg_13TupleIterator_current(VM::ActRec *ar);
TypedValue* tg_13TupleIterator_key(VM::ActRec *ar);
TypedValue* tg_13TupleIterator_valid(VM::ActRec *ar);
TypedValue* tg_13TupleIterator_next(VM::ActRec *ar);
TypedValue* tg_13TupleIterator_rewind(VM::ActRec *ar);
VM::Instance* new_Continuation_Instance(VM::Class*);
TypedValue* tg_12Continuation___construct(VM::ActRec *ar);
TypedValue* tg_12Continuation_update(VM::ActRec *ar);
@@ -5427,6 +5442,27 @@ static const HhbcExtMethodInfo hhbc_ext_methods_StableMapIterator[] = {
{ "rewind", tg_17StableMapIterator_rewind }
};
static const long long hhbc_ext_method_count_Tuple = 7;
static const HhbcExtMethodInfo hhbc_ext_methods_Tuple[] = {
{ "__construct", tg_5Tuple___construct },
{ "isEmpty", tg_5Tuple_isEmpty },
{ "count", tg_5Tuple_count },
{ "toArray", tg_5Tuple_toArray },
{ "getIterator", tg_5Tuple_getIterator },
{ "at", tg_5Tuple_at },
{ "get", tg_5Tuple_get }
};
static const long long hhbc_ext_method_count_TupleIterator = 6;
static const HhbcExtMethodInfo hhbc_ext_methods_TupleIterator[] = {
{ "__construct", tg_13TupleIterator___construct },
{ "current", tg_13TupleIterator_current },
{ "key", tg_13TupleIterator_key },
{ "valid", tg_13TupleIterator_valid },
{ "next", tg_13TupleIterator_next },
{ "rewind", tg_13TupleIterator_rewind }
};
static const long long hhbc_ext_method_count_Continuation = 18;
static const HhbcExtMethodInfo hhbc_ext_methods_Continuation[] = {
{ "__construct", tg_12Continuation___construct },
@@ -6207,7 +6243,7 @@ static const HhbcExtMethodInfo hhbc_ext_methods_XMLWriter[] = {
{ "outputMemory", tg_9XMLWriter_outputMemory }
};
const long long hhbc_ext_class_count = 71;
const long long hhbc_ext_class_count = 73;
const HhbcExtClassInfo hhbc_ext_classes[] = {
{ "WaitHandle", nullptr, sizeof(c_WaitHandle), hhbc_ext_method_count_WaitHandle, hhbc_ext_methods_WaitHandle, &c_WaitHandle::s_cls },
{ "StaticWaitHandle", nullptr, sizeof(c_StaticWaitHandle), hhbc_ext_method_count_StaticWaitHandle, hhbc_ext_methods_StaticWaitHandle, &c_StaticWaitHandle::s_cls },
@@ -6227,6 +6263,8 @@ const HhbcExtClassInfo hhbc_ext_classes[] = {
{ "MapIterator", new_MapIterator_Instance, sizeof(c_MapIterator), hhbc_ext_method_count_MapIterator, hhbc_ext_methods_MapIterator, &c_MapIterator::s_cls },
{ "StableMap", new_StableMap_Instance, sizeof(c_StableMap), hhbc_ext_method_count_StableMap, hhbc_ext_methods_StableMap, &c_StableMap::s_cls },
{ "StableMapIterator", new_StableMapIterator_Instance, sizeof(c_StableMapIterator), hhbc_ext_method_count_StableMapIterator, hhbc_ext_methods_StableMapIterator, &c_StableMapIterator::s_cls },
{ "Tuple", new_Tuple_Instance, sizeof(c_Tuple), hhbc_ext_method_count_Tuple, hhbc_ext_methods_Tuple, &c_Tuple::s_cls },
{ "TupleIterator", new_TupleIterator_Instance, sizeof(c_TupleIterator), hhbc_ext_method_count_TupleIterator, hhbc_ext_methods_TupleIterator, &c_TupleIterator::s_cls },
{ "Continuation", new_Continuation_Instance, sizeof(c_Continuation), hhbc_ext_method_count_Continuation, hhbc_ext_methods_Continuation, &c_Continuation::s_cls },
{ "DummyContinuation", new_DummyContinuation_Instance, sizeof(c_DummyContinuation), hhbc_ext_method_count_DummyContinuation, hhbc_ext_methods_DummyContinuation, &c_DummyContinuation::s_cls },
{ "DateTime", new_DateTime_Instance, sizeof(c_DateTime), hhbc_ext_method_count_DateTime, hhbc_ext_methods_DateTime, &c_DateTime::s_cls },
+5 -4
Ver Arquivo
@@ -3942,20 +3942,21 @@ inline void OPTBLD_INLINE VMExecutionContext::iopAddNewElemV(PC& pc) {
inline void OPTBLD_INLINE VMExecutionContext::iopNewCol(PC& pc) {
NEXT();
DECODE_IVA(cType);
DECODE_IVA(nElems);
DECODE_IVA(nElms);
ObjectData* obj;
switch (cType) {
case Collection::VectorType: obj = NEWOBJ(c_Vector)(); break;
case Collection::MapType: obj = NEWOBJ(c_Map)(); break;
case Collection::StableMapType: obj = NEWOBJ(c_StableMap)(); break;
case Collection::TupleType: obj = c_Tuple::alloc(nElms); break;
default:
obj = nullptr;
raise_error("NewCol: Invalid collection type");
break;
}
// Reserve enough room for nElems elements in advance
if (nElems) {
collectionReserve(obj, nElems);
// Reserve enough room for nElms elements in advance
if (nElms) {
collectionReserve(obj, nElms);
}
m_stack.pushObject(obj);
}
+57 -29
Ver Arquivo
@@ -80,19 +80,26 @@ ArrayData* new_tuple(int n, const TypedValue* values) {
#define NEW_COLLECTION_HELPER(name) \
ObjectData* \
new##name##Helper(int nElems) { \
new##name##Helper(int nElms) { \
ObjectData *obj = NEWOBJ(c_##name)(); \
obj->incRefCount(); \
if (nElems) { \
collectionReserve(obj, nElems); \
if (nElms) { \
collectionReserve(obj, nElms); \
} \
TRACE(2, "new" #name "Helper: capacity %d\n", nElems); \
TRACE(2, "new" #name "Helper: capacity %d\n", nElms); \
return obj; \
}
NEW_COLLECTION_HELPER(Vector)
NEW_COLLECTION_HELPER(Map)
NEW_COLLECTION_HELPER(StableMap)
ObjectData* newTupleHelper(int nElms) {
ObjectData *obj = c_Tuple::alloc(nElms);
obj->incRefCount();
TRACE(2, "newTupleHelper: capacity %d\n", nElms);
return obj;
}
#undef NEW_COLLECTION_HELPER
@@ -419,37 +426,58 @@ void collection_setm_wk1_v0(ObjectData* obj, TypedValue* value) {
void collection_setm_ik1_v0(ObjectData* obj, int64_t key, TypedValue* value) {
assert(obj);
int ct = obj->getCollectionType();
if (ct == Collection::VectorType) {
c_Vector* vec = static_cast<c_Vector*>(obj);
vec->put(key, value);
} else if (ct == Collection::MapType) {
c_Map* mp = static_cast<c_Map*>(obj);
mp->put(key, value);
} else if (ct == Collection::StableMapType) {
c_StableMap* smp = static_cast<c_StableMap*>(obj);
smp->put(key, value);
} else {
assert(false);
switch (obj->getCollectionType()) {
case Collection::VectorType: {
c_Vector* vec = static_cast<c_Vector*>(obj);
vec->put(key, value);
break;
}
case Collection::MapType: {
c_Map* mp = static_cast<c_Map*>(obj);
mp->put(key, value);
break;
}
case Collection::StableMapType: {
c_StableMap* smp = static_cast<c_StableMap*>(obj);
smp->put(key, value);
break;
}
case Collection::TupleType: {
Object e(SystemLib::AllocRuntimeExceptionObject(
"Cannot assign to an element of a Tuple"));
throw e;
}
default:
assert(false);
}
tvRefcountedDecRef(value);
}
void collection_setm_sk1_v0(ObjectData* obj, StringData* key,
TypedValue* value) {
int ct = obj->getCollectionType();
if (ct == Collection::VectorType) {
Object e(SystemLib::AllocInvalidArgumentExceptionObject(
"Only integer keys may be used with Vectors"));
throw e;
} else if (ct == Collection::MapType) {
c_Map* mp = static_cast<c_Map*>(obj);
mp->put(key, value);
} else if (ct == Collection::StableMapType) {
c_StableMap* smp = static_cast<c_StableMap*>(obj);
smp->put(key, value);
} else {
assert(false);
switch (obj->getCollectionType()) {
case Collection::VectorType: {
Object e(SystemLib::AllocInvalidArgumentExceptionObject(
"Only integer keys may be used with Vectors"));
throw e;
}
case Collection::MapType: {
c_Map* mp = static_cast<c_Map*>(obj);
mp->put(key, value);
break;
}
case Collection::StableMapType: {
c_StableMap* smp = static_cast<c_StableMap*>(obj);
smp->put(key, value);
break;
}
case Collection::TupleType: {
Object e(SystemLib::AllocRuntimeExceptionObject(
"Cannot assign to an element of a Tuple"));
throw e;
}
default:
assert(false);
}
tvRefcountedDecRef(value);
}
+4 -3
Ver Arquivo
@@ -28,9 +28,10 @@ namespace VM {
ArrayData* new_array(int capacity);
ArrayData* new_tuple(int numArgs, const TypedValue* args);
ObjectData* newVectorHelper(int nElems);
ObjectData* newMapHelper(int nElems);
ObjectData* newStableMapHelper(int nElems);
ObjectData* newVectorHelper(int nElms);
ObjectData* newMapHelper(int nElms);
ObjectData* newStableMapHelper(int nElms);
ObjectData* newTupleHelper(int nElms);
StringData* concat_is(int64_t v1, StringData* v2);
StringData* concat_si(StringData* v1, int64_t v2);
@@ -5374,12 +5374,14 @@ TranslatorX64::translateNewCol(const Tracelet& t,
case Collection::VectorType: fptr = (void*)newVectorHelper; break;
case Collection::MapType: fptr = (void*)newMapHelper; break;
case Collection::StableMapType: fptr = (void*)newStableMapHelper; break;
case Collection::TupleType: fptr = (void*)newTupleHelper; break;
default: assert(false); break;
}
if (false) {
ObjectData* obj1 UNUSED = newVectorHelper(42);
ObjectData* obj2 UNUSED = newMapHelper(42);
ObjectData* obj3 UNUSED = newStableMapHelper(42);
ObjectData* obj4 UNUSED = newTupleHelper(42);
}
EMIT_CALL(a, fptr, IMM(nElems));
m_regMap.bind(rax, i.outStack->location, KindOfObject, RegInfo::DIRTY);
+81
Ver Arquivo
@@ -23009,6 +23009,87 @@ const char *g_class_map[] = {
NULL,
NULL,
NULL,
(const char *)0x10006020, "Tuple", "", "", (const char *)0, (const char *)0,
"/**\n * ( excerpt from http://php.net/manual/en/class.tuple.php )\n *\n * An ordered fixed-sized container.\n *\n */",
"keyediterable", "countable", NULL,
(const char *)0x10006040, "__construct", "", (const char*)0, (const char*)0,
"/**\n * ( excerpt from http://php.net/manual/en/tuple.construct.php )\n *\n *\n */",
(const char *)-1, NULL,
NULL,
NULL,
(const char *)0x10006040, "isEmpty", "", (const char*)0, (const char*)0,
"/**\n * ( excerpt from http://php.net/manual/en/tuple.isempty.php )\n *\n * Returns true if this Tuple is empty, false otherwise.\n *\n * @return bool\n */",
(const char *)0x9, NULL,
NULL,
NULL,
(const char *)0x10006040, "count", "", (const char*)0, (const char*)0,
"/**\n * ( excerpt from http://php.net/manual/en/tuple.count.php )\n *\n * Returns the number of values in the Tuple.\n *\n * @return int\n */",
(const char *)0xa, NULL,
NULL,
NULL,
(const char *)0x10006040, "toArray", "", (const char*)0, (const char*)0,
"/**\n * ( excerpt from http://php.net/manual/en/tuple.toarray.php )\n *\n * Returns an array containing the values from this Tuple.\n *\n * @return map\n */",
(const char *)0x20, NULL,
NULL,
NULL,
(const char *)0x10006040, "getIterator", "", (const char*)0, (const char*)0,
"/**\n * ( excerpt from http://php.net/manual/en/tuple.getiterator.php )\n *\n * Returns an iterator that points to beginning of this Tuple.\n *\n * @return object\n */",
(const char *)0x40, NULL,
NULL,
NULL,
(const char *)0x10006040, "at", "", (const char*)0, (const char*)0,
"/**\n * ( excerpt from http://php.net/manual/en/tuple.at.php )\n *\n * Returns the value at the specified key. If the key is not present, an\n * exception is thrown.\n *\n * @key mixed\n *\n * @return mixed\n */",
(const char *)0xffffffff, (const char *)0x2000, "key", "", (const char *)0xffffffff, "", "", NULL,
NULL,
NULL,
NULL,
(const char *)0x10006040, "get", "", (const char*)0, (const char*)0,
"/**\n * ( excerpt from http://php.net/manual/en/tuple.get.php )\n *\n * Returns the value at the specified key. If the key is not present, null\n * is returned.\n *\n * @key mixed\n *\n * @return mixed\n */",
(const char *)0xffffffff, (const char *)0x2000, "key", "", (const char *)0xffffffff, "", "", NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
(const char *)0x10006020, "TupleIterator", "", "", (const char *)0, (const char *)0,
"/**\n * ( excerpt from http://php.net/manual/en/class.tupleiterator.php )\n *\n * An iterator implementation for iterating over a Tuple.\n *\n */",
"keyediterator", NULL,
(const char *)0x10006040, "__construct", "", (const char*)0, (const char*)0,
"/**\n * ( excerpt from http://php.net/manual/en/tupleiterator.construct.php )\n *\n *\n */",
(const char *)-1, NULL,
NULL,
NULL,
(const char *)0x10006040, "current", "", (const char*)0, (const char*)0,
"/**\n * ( excerpt from http://php.net/manual/en/tupleiterator.current.php )\n *\n * Returns the current value that the iterator points to.\n *\n * @return mixed\n */",
(const char *)0xffffffff, NULL,
NULL,
NULL,
(const char *)0x10006040, "key", "", (const char*)0, (const char*)0,
"/**\n * ( excerpt from http://php.net/manual/en/tupleiterator.key.php )\n *\n * Returns the current key that the iterator points to.\n *\n * @return mixed\n */",
(const char *)0xffffffff, NULL,
NULL,
NULL,
(const char *)0x10006040, "valid", "", (const char*)0, (const char*)0,
"/**\n * ( excerpt from http://php.net/manual/en/tupleiterator.valid.php )\n *\n * Returns true if the iterator points to a valid value, returns false\n * otherwise.\n *\n * @return bool\n */",
(const char *)0x9, NULL,
NULL,
NULL,
(const char *)0x10006040, "next", "", (const char*)0, (const char*)0,
"/**\n * ( excerpt from http://php.net/manual/en/tupleiterator.next.php )\n *\n * Advance this iterator forward one position.\n *\n */",
(const char *)-1, NULL,
NULL,
NULL,
(const char *)0x10006040, "rewind", "", (const char*)0, (const char*)0,
"/**\n * ( excerpt from http://php.net/manual/en/tupleiterator.rewind.php )\n *\n * Move this iterator back to the first position.\n *\n */",
(const char *)-1, NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
(const char *)0x10006000, "PDO", "", "", (const char *)0, (const char *)0,
"/**\n * ( excerpt from http://php.net/manual/en/class.pdo.php )\n *\n * Represents a connection between PHP and a database server.\n *\n */",
NULL,
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
+1
Ver Arquivo
@@ -59,6 +59,7 @@ namespace Eval {
x(JsonSerializable) \
x(Traversable) \
x(Countable) \
x(__PHP_Incomplete_Class) \
class SystemLib {
public:
+135
Ver Arquivo
@@ -9784,6 +9784,141 @@ bool TestCodeRun::TestCollectionClasses() {
" int(72)\n"
"}\n"
);
MVCRO("<?hh\n"
"function g((string,int,string) $t) {}\n"
"class C {\n"
" public $t = Tuple {'foo', 42, '!'};\n"
"}\n"
"function f() {\n"
" $t = Tuple {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\n"
" 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,\n"
" 23, 24, 25, 26, 27, 28, 29, 30, 31, 32};\n"
" var_dump(count($t));\n"
" var_dump($t->count());\n"
" var_dump($t->isEmpty());\n"
" echo \"==========\\n\";\n"
" $c = new C;\n"
" $t = $c->t;\n"
" var_dump(count($t));\n"
" var_dump($t->count());\n"
" var_dump($t->isEmpty());\n"
" g($t);\n"
" echo \"==========\\n\";\n"
" foreach ($t as $k => $v) {\n"
" var_dump($k, $v);\n"
" }\n"
" echo \"==========\\n\";\n"
" var_dump($t[0], $t[1], $t[2]);\n"
" echo \"==========\\n\";\n"
" var_dump($t->at(0), $t->at(1), $t->at(2));\n"
" echo \"==========\\n\";\n"
" var_dump($t->get(0), $t->get(1), $t->get(2), $t->get(3));\n"
" echo \"==========\\n\";\n"
" var_dump((array)$t);\n"
" echo \"==========\\n\";\n"
" var_dump(serialize($t));\n"
" var_dump(unserialize(serialize($t)));\n"
" echo \"==========\\n\";\n"
" var_dump($t->count());\n"
" echo \"==========\\n\";\n"
" var_dump($t->getIterator() instanceof Iterator);\n"
" var_dump($t->getIterator() instanceof KeyedIterator);\n"
" foreach ($t->getIterator() as $k => $v) {\n"
" var_dump($k, $v);\n"
" }\n"
" echo \"==========\\n\";\n"
" var_dump((array)$t);\n"
" var_dump($t->toArray());\n"
" echo \"==========\\n\";\n"
" var_dump(clone $t);\n"
"}\n"
"f();\n"
,
"int(32)\n"
"int(32)\n"
"bool(false)\n"
"==========\n"
"int(3)\n"
"int(3)\n"
"bool(false)\n"
"==========\n"
"int(0)\n"
"string(3) \"foo\"\n"
"int(1)\n"
"int(42)\n"
"int(2)\n"
"string(1) \"!\"\n"
"==========\n"
"string(3) \"foo\"\n"
"int(42)\n"
"string(1) \"!\"\n"
"==========\n"
"string(3) \"foo\"\n"
"int(42)\n"
"string(1) \"!\"\n"
"==========\n"
"string(3) \"foo\"\n"
"int(42)\n"
"string(1) \"!\"\n"
"NULL\n"
"==========\n"
"array(3) {\n"
" [0]=>\n"
" string(3) \"foo\"\n"
" [1]=>\n"
" int(42)\n"
" [2]=>\n"
" string(1) \"!\"\n"
"}\n"
"==========\n"
"string(39) \"V:5:\"Tuple\":3:{s:3:\"foo\";i:42;s:1:\"!\";}\"\n"
"object(Tuple)#6 (3) {\n"
" [0]=>\n"
" string(3) \"foo\"\n"
" [1]=>\n"
" int(42)\n"
" [2]=>\n"
" string(1) \"!\"\n"
"}\n"
"==========\n"
"int(3)\n"
"==========\n"
"bool(true)\n"
"bool(true)\n"
"int(0)\n"
"string(3) \"foo\"\n"
"int(1)\n"
"int(42)\n"
"int(2)\n"
"string(1) \"!\"\n"
"==========\n"
"array(3) {\n"
" [0]=>\n"
" string(3) \"foo\"\n"
" [1]=>\n"
" int(42)\n"
" [2]=>\n"
" string(1) \"!\"\n"
"}\n"
"array(3) {\n"
" [0]=>\n"
" string(3) \"foo\"\n"
" [1]=>\n"
" int(42)\n"
" [2]=>\n"
" string(1) \"!\"\n"
"}\n"
"==========\n"
"object(Tuple)#6 (3) {\n"
" [0]=>\n"
" string(3) \"foo\"\n"
" [1]=>\n"
" int(42)\n"
" [2]=>\n"
" string(1) \"!\"\n"
"}\n"
);
}
return true;
+5 -4
Ver Arquivo
@@ -2532,15 +2532,16 @@ sm_type:
}
| T_ARRAY { $$.setText("array"); }
| T_ARRAY T_TYPELIST_LT sm_type
T_TYPELIST_GT { only_in_strict_mode(_p); $$.setText("array"); }
T_TYPELIST_GT { only_in_strict_mode(_p);
$$.setText("array"); }
| T_ARRAY T_TYPELIST_LT sm_type ','
sm_type T_TYPELIST_GT { only_in_strict_mode(_p); $$.setText("array"); }
sm_type T_TYPELIST_GT { only_in_strict_mode(_p);
$$.setText("array"); }
| T_XHP_LABEL { $1.xhpLabel(); $$ = $1; }
| '(' T_FUNCTION
'(' sm_func_type_list ')'
':' sm_type ')' { only_in_strict_mode(_p); $$.reset(); }
| '(' sm_type_list ',' sm_type ')' { only_in_strict_mode(_p);
$$.setText("array"); }
| '(' sm_type_list ',' sm_type ')' { only_in_strict_mode(_p); $$.reset(); }
;
sm_type_opt:
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff