Chip away at ClassInfo::FindClass() and ObjectData cruft

Esse commit está contido em:
andrewparoski
2013-03-14 14:57:22 -07:00
commit de Sara Golemon
commit 5b8111f402
28 arquivos alterados com 220 adições e 672 exclusões
+1
Ver Arquivo
@@ -29,6 +29,7 @@
#include <runtime/base/variable_serializer.h>
#include <runtime/base/program_functions.h>
#include <runtime/eval/runtime/file_repository.h>
#include <runtime/ext_hhvm/ext_hhvm.h>
#include <compiler/builtin_symbols.h>
#include <compiler/analysis/class_scope.h>
+2
Ver Arquivo
@@ -40,6 +40,8 @@ DECLARE_BOOST_TYPES(SimpleFunctionCall);
DECLARE_BOOST_TYPES(SwitchStatement);
DECLARE_BOOST_TYPES(ForEachStatement);
class StaticClassName;
class HhbcExtFuncInfo;
class HhbcExtClassInfo;
namespace Compiler {
///////////////////////////////////////////////////////////////////////////////
-1
Ver Arquivo
@@ -289,7 +289,6 @@ BeginClass(
virtual int64_t o_toInt64() const;
virtual double o_toDouble() const;
virtual Array o_toArray() const;
virtual Variant *___lval(Variant v_name);
private:
xmlXPathContextPtr m_xpath;
EOT
+2 -5
Ver Arquivo
@@ -1031,14 +1031,11 @@ ClassInfo::MethodInfo::~MethodInfo() {
void ClassInfo::GetArray(const ObjectData *obj,
Array &props, GetArrayKind kind) {
HPHP::VM::Instance *inst = static_cast<HPHP::VM::Instance*>(
const_cast<ObjectData*>(obj));
inst->HPHP::VM::Instance::o_getArray(props, !(kind & GetArrayPrivate));
obj->o_getArray(props, !(kind & GetArrayPrivate));
}
void ClassInfo::SetArray(ObjectData *obj, CArrRef props) {
HPHP::VM::Instance *inst = static_cast<HPHP::VM::Instance*>(obj);
inst->HPHP::VM::Instance::o_setArray(props);
obj->o_setArray(props);
}
///////////////////////////////////////////////////////////////////////////////
+1 -1
Ver Arquivo
@@ -50,7 +50,7 @@ UserFile::UserFile(VM::Class *cls, int options /*= 0 */,
}
m_obj = VM::Instance::newInstance(cls);
m_obj.o_setPublic("context", context);
m_obj.o_set("context", context);
Variant ret;
g_vmContext->invokeFunc(ret.asTypedValue(), ctor,
Array::Create(), m_obj.get());
+74 -250
Ver Arquivo
@@ -104,17 +104,6 @@ CStrRef ObjectData::o_getParentName() const {
return *(const String*)(&m_cls->m_preClass->parentRef());
}
CStrRef ObjectData::GetParentName(CStrRef cls) {
const ClassInfo *classInfo = ClassInfo::FindClass(cls);
if (classInfo) {
CStrRef parentClass = classInfo->getParentClass();
if (!parentClass.isNull()) {
return parentClass;
}
}
return empty_string;
}
CStrRef ObjectData::o_getClassNameHook() const {
throw FatalErrorException("Class didnt provide a name");
return empty_string;
@@ -197,10 +186,8 @@ void ObjectData::initProperties(int nProp) {
if (!o_properties.get()) ((HPHP::VM::Instance*)this)->initDynProps(nProp);
}
void *ObjectData::o_realPropTyped(CStrRef propName, int flags,
CStrRef context, DataType *type) const {
*type = KindOfUnknown;
Variant* ObjectData::o_realProp(CStrRef propName, int flags,
CStrRef context /* = null_string */) const {
/*
* Returns a pointer to a place for a property value. This should never
* call the magic methods __get or __set. The flags argument describes the
@@ -219,19 +206,18 @@ void *ObjectData::o_realPropTyped(CStrRef propName, int flags,
accessible, unset)
: thiz->getProp(ctx, propName.get(), visible,
accessible, unset);
if (ret == nullptr) {
if (!ret) {
// Property is not declared, and not dynamically created yet.
if (flags & RealPropCreate) {
assert(!(flags & RealPropNoDynamic));
if (o_properties.get() == nullptr) {
thiz->initDynProps();
}
o_properties.get()->lvalPtr(propName,
*(Variant**)(&ret), false, true);
return (Variant*)ret;
} else {
if (!(flags & RealPropCreate)) {
return nullptr;
}
assert(!(flags & RealPropNoDynamic));
if (!o_properties.get()) {
thiz->initDynProps();
}
o_properties.get()->lvalPtr(propName,
*(Variant**)(&ret), false, true);
return (Variant*)ret;
}
// ret is non-NULL if we reach here
@@ -244,31 +230,6 @@ void *ObjectData::o_realPropTyped(CStrRef propName, int flags,
}
}
Variant *ObjectData::o_realProp(CStrRef propName, int flags,
CStrRef context /* = null_string */) const {
DataType type;
if (void *p = o_realPropTyped(propName, flags, context, &type)) {
if (LIKELY(type == KindOfUnknown)) return (Variant*)p;
if (flags & (RealPropCreate|RealPropWrite)) return nullptr;
SystemGlobals* globals = get_system_globals();
Variant *res = &globals->__realPropProxy;
*res = ClassInfo::GetVariant(type, p);
return res;
}
return nullptr;
}
Variant *ObjectData::o_realPropPublic(CStrRef propName, int flags) const {
return o_realProp(propName, flags, empty_string);
}
bool ObjectData::o_exists(CStrRef propName,
CStrRef context /* = null_string */) const {
const Variant *t = o_realProp(propName, RealPropUnchecked, context);
return t && t->isInitialized();
}
inline Variant ObjectData::o_getImpl(CStrRef propName, int flags,
bool error /* = true */,
CStrRef context /* = null_string */) {
@@ -287,7 +248,8 @@ inline Variant ObjectData::o_getImpl(CStrRef propName, int flags,
}
if (error) {
return o_getError(propName, context);
raise_notice("Undefined property: %s::$%s", o_getClassName().data(),
propName.data());
}
return uninit_null();
@@ -298,33 +260,6 @@ Variant ObjectData::o_get(CStrRef propName, bool error /* = true */,
return o_getImpl(propName, 0, error, context);
}
Variant ObjectData::o_getPublic(CStrRef propName, bool error /* = true */) {
if (UNLIKELY(!*propName.data())) {
throw_invalid_property_name(propName);
}
if (Variant *t = o_realPropPublic(propName, 0)) {
if (t->isInitialized())
return *t;
}
if (getAttribute(UseGet)) {
AttributeClearer a(UseGet, this);
return t___get(propName);
}
if (error) {
return o_getError(propName, null_string);
}
return uninit_null();
}
Variant ObjectData::o_getUnchecked(CStrRef propName,
CStrRef context /* = null_string */) {
return o_getImpl(propName, RealPropUnchecked, true, context);
}
template <class T>
inline ALWAYS_INLINE Variant ObjectData::o_setImpl(CStrRef propName, T v,
bool forInit,
@@ -334,7 +269,7 @@ inline ALWAYS_INLINE Variant ObjectData::o_setImpl(CStrRef propName, T v,
}
bool useSet = !forInit && getAttribute(UseSet);
int flags = useSet ? RealPropWrite : RealPropCreate | RealPropWrite;
int flags = useSet ? 0 : RealPropCreate;
if (forInit) flags |= RealPropUnchecked;
if (Variant *t = o_realProp(propName, flags, context)) {
@@ -350,7 +285,6 @@ inline ALWAYS_INLINE Variant ObjectData::o_setImpl(CStrRef propName, T v,
return variant(v);
}
o_setError(propName, context);
return variant(v);
}
@@ -378,70 +312,64 @@ Variant ObjectData::o_setRef(CStrRef propName, CVarRef v, CStrRef context) {
return o_setImpl<RefResult>(propName, ref(v), false, context);
}
template<typename T>
inline ALWAYS_INLINE Variant ObjectData::o_setPublicImpl(CStrRef propName,
T v,
bool forInit) {
if (UNLIKELY(!*propName.data())) {
throw_invalid_property_name(propName);
}
bool useSet = !forInit && getAttribute(UseSet);
int flags = useSet ? RealPropWrite : RealPropCreate | RealPropWrite;
if (forInit) flags |= RealPropUnchecked;
if (Variant *t = o_realPropPublic(propName, flags)) {
if (!useSet || t->isInitialized()) {
*t = v;
return variant(v);
}
}
if (useSet) {
AttributeClearer a(UseSet, this);
t___set(propName, variant(v));
return variant(v);
}
o_setError(propName, null_string);
return variant(v);
}
Variant ObjectData::o_setPublic(CStrRef propName, CVarRef v) {
return o_setPublicImpl<CVarRef>(propName, v, false);
}
Variant ObjectData::o_setPublic(CStrRef propName, RefResult v) {
return o_setPublicRef(propName, variant(v));
}
Variant ObjectData::o_setPublicRef(CStrRef propName, CVarRef v) {
return o_setPublicImpl<CVarStrongBind>(propName, strongBind(v), false);
}
Variant ObjectData::o_i_setPublicWithRef(CStrRef propName, CVarRef v) {
return o_setPublicImpl<CVarWithRefBind>(propName, withRefBind(v), true);
}
HOT_FUNC
void ObjectData::o_setArray(CArrRef properties) {
auto thiz = static_cast<VM::Instance*>(this);
for (ArrayIter iter(properties); iter; ++iter) {
String key = iter.first().toString();
if (key.empty() || key.charAt(0) != '\0') {
// non-private property
CVarRef secondRef = iter.secondRef();
o_i_setPublicWithRef(key, secondRef);
String k = iter.first().toString();
VM::Class* ctx = nullptr;
// If the key begins with a NUL, it's a private or protected property. Read
// the class name from between the two NUL bytes.
if (!k.empty() && k.charAt(0) == '\0') {
int subLen = k.find('\0', 1) + 1;
String cls = k.substr(1, subLen - 2);
if (cls == "*") {
// Protected.
ctx = m_cls;
} else {
// Private.
ctx = VM::Unit::lookupClass(cls.get());
if (!ctx) continue;
}
k = k.substr(subLen);
}
CVarRef secondRef = iter.secondRef();
thiz->setProp(ctx, k.get(), (TypedValue*)(&secondRef),
secondRef.isReferenced());
}
}
void ObjectData::o_getArray(Array &props, bool pubOnly /* = false */) const {
const Array& arr = o_properties.asArray();
if (!arr.empty()) {
for (ArrayIter it(arr); !it.end(); it.next()) {
// The declared properties in the resultant array should be a permutation of
// propVec. They appear in the following order: go most-to-least-derived in
// the inheritance hierarchy, inserting properties in declaration order (with
// the wrinkle that overridden properties should appear only once, with the
// access level given to it in its most-derived declaration).
// This is needed to keep track of which elements have been inserted. This is
// the smoothest way to get overridden properties right.
std::vector<bool> inserted(m_cls->numDeclProperties(), false);
// Iterate over declared properties and insert {mangled name --> prop} pairs.
const VM::Class* cls = m_cls;
auto thiz = static_cast<const VM::Instance*>(this);
do {
thiz->getProps(cls, pubOnly, cls->m_preClass.get(), props, inserted);
const std::vector<VM::ClassPtr> &usedTraits = cls->m_usedTraits;
for (unsigned t = 0; t < usedTraits.size(); t++) {
const VM::ClassPtr& trait = usedTraits[t];
thiz->getProps(cls, pubOnly, trait->m_preClass.get(), props, inserted);
}
cls = cls->m_parent.get();
} while (cls);
// Iterate over dynamic properties and insert {name --> prop} pairs.
if (o_properties.get() && !o_properties.get()->empty()) {
for (ArrayIter it(o_properties.get()); !it.end(); it.next()) {
Variant key = it.first();
CVarRef value = it.secondRef();
props.lvalAt(key, AccessFlags::Key).setWithRef(value);
props.addLval(key, true).setWithRef(value);
}
}
}
@@ -454,55 +382,6 @@ Object ObjectData::FromArray(ArrayData *properties) {
return ret;
}
CVarRef ObjectData::set(CStrRef s, CVarRef v) {
o_set(s, v);
return v;
}
Variant &ObjectData::o_lval(CStrRef propName, CVarRef tmpForGet,
CStrRef context /* = null_string */) {
if (UNLIKELY(!*propName.data())) {
throw_invalid_property_name(propName);
}
bool useGet = getAttribute(UseGet);
int flags = useGet ? RealPropWrite : RealPropCreate | RealPropWrite;
if (Variant *t = o_realProp(propName, flags, context)) {
if (!useGet || t->isInitialized()) {
return *t;
}
}
Variant &ret = const_cast<Variant&>(tmpForGet);
if (LIKELY(useGet)) {
AttributeClearer a(UseGet, this);
if (getAttribute(HasLval)) {
return *___lval(propName);
}
ret = t___get(propName);
return ret;
}
/* we only get here if its a protected property
under hphpi - and then o_getError fatals
with a suitable message
*/
ret = o_getError(propName, context);
return ret;
}
Variant *ObjectData::o_weakLval(CStrRef propName,
CStrRef context /* = null_string */) {
if (Variant *t = o_realProp(propName, RealPropWrite|RealPropUnchecked,
context)) {
if (t->isInitialized()) {
return t;
}
}
return nullptr;
}
Array ObjectData::o_toArray() const {
Array ret(ArrayData::Create());
ClassInfo::GetArray(this, ret, ClassInfo::GetArrayAll);
@@ -522,7 +401,7 @@ Array ObjectData::o_toIterArray(CStrRef context,
// Get all declared properties first, bottom-to-top in the inheritance
// hierarchy, in declaration order.
const VM::Class* klass = m_cls;
while (klass != nullptr) {
while (klass) {
const VM::PreClass::Prop* props = klass->m_preClass->properties();
const size_t numProps = klass->m_preClass->numProperties();
@@ -670,47 +549,6 @@ Variant ObjectData::o_invoke_few_args(CStrRef s, strhash_t hash, int count,
return o_invoke(s, params, hash);
}
Variant ObjectData::o_invoke_ex(CStrRef clsname, CStrRef s,
CArrRef params, bool fatal /* = true */) {
// TODO This duplicates some logic from vm_decode_function and
// vm_call_user_func, we should refactor this in the near future
ObjectData* this_ = this;
HPHP::VM::Class* cls = VM::Unit::lookupClass(clsname.get());
if (!cls || !getVMClass()->classof(cls)) {
o_invoke_failed(clsname.data(), s.data(), fatal);
return uninit_null();
}
StringData* invName = nullptr;
// XXX The lookup below doesn't take context into account, so it will lead
// to incorrect behavior in some corner cases. o_invoke is gradually being
// removed from the HPHP runtime this should be ok for the short term.
const HPHP::VM::Func* f = cls->lookupMethod(s.get());
if (f && (f->attrs() & HPHP::VM::AttrStatic)) {
// If we found a method and its static, null out this_
this_ = nullptr;
} else if (!f) {
if (this_) {
// If this_ is non-null AND we could not find a method, try
// looking up __call in cls's method table
f = cls->lookupMethod(s___call.get());
}
if (!f) {
// Bail if we couldn't find the method or __call
o_invoke_failed(clsname.data(), s.data(), fatal);
return uninit_null();
}
// We found __call! Stash the original name into invName.
assert(!(f->attrs() & HPHP::VM::AttrStatic));
invName = s.get();
invName->incRefCount();
}
assert(f);
Variant ret;
g_vmContext->invokeFunc((TypedValue*)&ret, f, params, this_, cls,
nullptr, invName);
return ret;
}
bool ObjectData::php_sleep(Variant &ret) {
setAttribute(HasSleep);
ret = t___sleep();
@@ -783,19 +621,24 @@ void ObjectData::serializeImpl(VariableSerializer *serializer) const {
if (UNLIKELY(handleSleep)) {
assert(!isCollection());
if (ret.isArray()) {
const ClassInfo *cls = ClassInfo::FindClass(o_getClassName());
auto thiz = (VM::Instance*)(this);
Array wanted = Array::Create();
Array props = ret.toArray();
for (ArrayIter iter(props); iter; ++iter) {
String name = iter.second().toString();
if (o_exists(name, o_getClassName())) {
ClassInfo::PropertyInfo *p = cls->getPropertyInfo(name);
bool visible, accessible, unset;
thiz->getProp(m_cls, name.get(), visible, accessible, unset);
if (accessible && !unset) {
String propName = name;
if (p && (p->attribute & ClassInfo::IsPrivate)) {
propName = concat4(s_zero, o_getClassName(), s_zero, name);
VM::Slot propInd =
m_cls->getDeclPropIndex(m_cls, name.get(), accessible);
if (accessible && propInd != VM::kInvalidSlot) {
if (m_cls->m_declProperties[propInd].m_attrs & VM::AttrPrivate) {
propName = concat4(s_zero, o_getClassName(), s_zero, name);
}
}
wanted.set(propName, const_cast<ObjectData*>(this)->
o_getUnchecked(name, o_getClassName()));
o_getImpl(name, RealPropUnchecked, true, o_getClassName()));
} else {
raise_warning("\"%s\" returned as member variable from "
"__sleep() but does not exist", name.data());
@@ -859,16 +702,6 @@ ObjectData *ObjectData::clone() {
return instance->cloneImpl();
}
Variant ObjectData::o_getError(CStrRef prop, CStrRef context) {
raise_notice("Undefined property: %s::$%s", o_getClassName().data(),
prop.data());
return uninit_null();
}
Variant ObjectData::o_setError(CStrRef prop, CStrRef context) {
return uninit_null();
}
///////////////////////////////////////////////////////////////////////////////
// magic methods that user classes can override, and these are default handlers
// or actions to take:
@@ -893,10 +726,6 @@ Variant ObjectData::t___get(Variant v_name) {
return uninit_null();
}
Variant *ObjectData::___lval(Variant v_name) {
return nullptr;
}
Variant ObjectData::offsetGet(Variant key) {
assert(instanceof(SystemLib::s_ArrayAccessClass));
const VM::Func* method = m_cls->lookupMethod(s_offsetGet.get());
@@ -919,11 +748,6 @@ Variant ObjectData::t___unset(Variant v_name) {
return uninit_null();
}
bool ObjectData::o_propExists(CStrRef s, CStrRef context /* = null_string */) {
Variant *t = o_realProp(s, RealPropExist, context);
return t;
}
Variant ObjectData::t___sleep() {
clearAttribute(HasSleep);
return uninit_null();
+15 -60
Ver Arquivo
@@ -43,22 +43,13 @@ namespace VM {
extern StaticString ssIterator;
/**
* Base class of all user-defined classes. All data members and methods in
* this class should start with "o_" or "os_" to avoid name conflicts.
* Base class of all PHP objects and PHP resources.
*
* Calling sequence:
*
* 1. Statically resolved properties and methods will be statically called.
* 2. Dynamic properties:
* 1. Properties:
* o_get() -> t___get() as fallback
* o_lval() -> t___get() as fallback (!really)
* o_set() -> t___set() as fallback
* 3. Dynamic methods:
* 2. Methods:
* o_invoke() -> t___call() as fallback
* 4. Auto-generated jump-tables:
* o_realProp()
* o_realPropPublic()
* o_realPropPrivate() # non-virtual, only as needed
*/
class ObjectData : public CountableNF {
public:
@@ -69,7 +60,6 @@ class ObjectData : public CountableNF {
UseGet = 0x0008, // __get()
UseIsset = 0x0010, // __isset()
UseUnset = 0x0020, // __unset()
HasLval = 0x0040, // defines ___lval
HasCall = 0x0080, // defines __call
HasCallStatic = 0x0100, // defines __callStatic
// The top 3 bits of o_attributes are reserved to indicate the
@@ -82,11 +72,10 @@ class ObjectData : public CountableNF {
};
enum {
RealPropCreate = 1, // Property should be created if it doesnt exist
RealPropWrite = 2, // Property could be modified
RealPropNoDynamic = 4,// Dont return dynamic properties
RealPropUnchecked = 8,// Dont check property accessibility
RealPropExist = 16, // For property_exists
RealPropCreate = 1, // Property should be created if it doesnt exist
RealPropNoDynamic = 4, // Dont return dynamic properties
RealPropUnchecked = 8, // Dont check property accessibility
RealPropExist = 16, // For property_exists
};
ObjectData(bool noId, VM::Class* type)
@@ -152,15 +141,14 @@ class ObjectData : public CountableNF {
CStrRef o_getClassName() const;
CStrRef o_getParentName() const;
virtual CStrRef o_getClassNameHook() const;
static CStrRef GetParentName(CStrRef cls);
virtual bool isResource() const { return false;}
bool o_isClass(const char *s) const;
int o_getId() const { return o_id;}
// overridable casting
virtual bool o_toBoolean() const { return true;}
virtual int64_t o_toInt64() const;
virtual double o_toDouble() const { return o_toInt64();}
virtual bool o_toBoolean() const { return true;}
virtual int64_t o_toInt64() const;
virtual double o_toDouble() const { return o_toInt64();}
void destruct();
@@ -172,18 +160,11 @@ class ObjectData : public CountableNF {
return o_properties;
}
Variant *o_realProp(CStrRef s, int flags,
Variant* o_realProp(CStrRef s, int flags,
CStrRef context = null_string) const;
void *o_realPropTyped(CStrRef s, int flags,
CStrRef context, DataType* type) const;
Variant *o_realPropPublic(CStrRef s, int flags) const;
bool o_exists(CStrRef s, CStrRef context = null_string) const;
Variant o_get(CStrRef s, bool error = true,
CStrRef context = null_string);
Variant o_getPublic(CStrRef s, bool error = true);
Variant o_getUnchecked(CStrRef s, CStrRef context = null_string);
Variant o_i_setPublicWithRef(CStrRef s, CVarRef v);
Variant o_set(CStrRef s, CVarRef v);
Variant o_set(CStrRef s, RefResult v);
@@ -192,34 +173,12 @@ class ObjectData : public CountableNF {
Variant o_set(CStrRef s, CVarRef v, CStrRef context);
Variant o_set(CStrRef s, RefResult v, CStrRef context);
Variant o_setRef(CStrRef s, CVarRef v, CStrRef context);
Variant o_setPublic(CStrRef s, CVarRef v);
Variant o_setPublic(CStrRef s, RefResult v);
Variant o_setPublicRef(CStrRef s, CVarRef v);
Variant &o_lval(CStrRef s, CVarRef tmpForGet, CStrRef context = null_string);
Variant *o_weakLval(CStrRef s, CStrRef context = null_string);
virtual void o_setArray(CArrRef properties);
virtual void o_getArray(Array &props, bool pubOnly = false) const;
Variant o_getError(CStrRef prop, CStrRef context);
Variant o_setError(CStrRef prop, CStrRef context);
/**
* This is different from o_exists(), which is isset() semantics. This one
* is property_exists() semantics. ie, accessibility is ignored, and declared
* but unset properties still return true.
*/
bool o_propExists(CStrRef s, CStrRef context = null_string);
void o_setArray(CArrRef properties);
void o_getArray(Array &props, bool pubOnly = false) const;
static Object FromArray(ArrayData *properties);
CVarRef set(CStrRef s, CVarRef v);
// methods
Variant o_invoke_ex(CStrRef clsname, CStrRef s,
CArrRef params, bool fatal = true);
// method invocation with CStrRef
Variant o_invoke(CStrRef s, CArrRef params, strhash_t hash = -1,
bool fatal = true);
@@ -241,7 +200,6 @@ class ObjectData : public CountableNF {
virtual Variant t___call(Variant v_name, Variant v_arguments);
virtual Variant t___set(Variant v_name, Variant v_value);
virtual Variant t___get(Variant v_name);
virtual Variant *___lval(Variant v_name);
virtual bool t___isset(Variant v_name);
virtual Variant t___unset(Variant v_name);
virtual Variant t___sleep();
@@ -256,15 +214,13 @@ class ObjectData : public CountableNF {
CArrRef getProperties() const { return o_properties; }
void initProperties(int nProp);
private:
static DECLARE_THREAD_LOCAL_NO_CHECK(int, os_max_id);
ObjectData(const ObjectData &) { assert(false);}
inline Variant o_getImpl(CStrRef propName, int flags,
bool error = true, CStrRef context = null_string);
static DECLARE_THREAD_LOCAL_NO_CHECK(int, os_max_id);
template <typename T>
inline Variant o_setImpl(CStrRef propName, T v,
bool forInit, CStrRef context);
template <typename T>
inline Variant o_setPublicImpl(CStrRef propName, T v, bool forInit);
public:
static const bool IsResourceClass = false;
@@ -276,7 +232,6 @@ class ObjectData : public CountableNF {
union {
uint16_t u16;
uint8_t u8[2];
} o_subclassData;
protected:
+2 -2
Ver Arquivo
@@ -183,12 +183,12 @@ void tvCastToObjectInPlace(TypedValue* tv) {
case KindOfDouble:
case KindOfStaticString: {
o = SystemLib::AllocStdClassObject();
o->o_lval("scalar", -1) = tvAsVariant(tv);
o->o_set("scalar", tvAsVariant(tv));
break;
}
case KindOfString: {
o = SystemLib::AllocStdClassObject();
o->o_lval("scalar", -1) = tvAsVariant(tv);
o->o_set("scalar", tvAsVariant(tv));
tvDecRefStr(tv);
break;
}
-31
Ver Arquivo
@@ -112,11 +112,6 @@ Variant Object::o_get(CStrRef propName, bool error /* = true */,
return m_px->o_get(propName, error, context);
}
Variant Object::o_getPublic(CStrRef propName, bool error /* = true */) const {
if (UNLIKELY(!m_px)) return warn_non_object();
return m_px->o_getPublic(propName, error);
}
Variant Object::o_set(CStrRef propName, CVarRef val,
CStrRef context /* = null_string */) {
if (!m_px) {
@@ -138,32 +133,6 @@ Variant Object::o_set(CStrRef propName, RefResult val,
return o_setRef(propName, variant(val), context);
}
Variant Object::o_setPublic(CStrRef propName, CVarRef val) {
if (!m_px) {
setToDefaultObject();
}
return m_px->o_setPublic(propName, val);
}
Variant Object::o_setPublicRef(CStrRef propName, CVarRef val) {
if (!m_px) {
setToDefaultObject();
}
return m_px->o_setPublicRef(propName, val);
}
Variant Object::o_setPublic(CStrRef propName, RefResult val) {
return o_setPublicRef(propName, variant(val));
}
Variant &Object::o_lval(CStrRef propName, CVarRef tmpForGet,
CStrRef context /* = null_string */) {
if (!m_px) {
setToDefaultObject();
}
return m_px->o_lval(propName, tmpForGet, context);
}
///////////////////////////////////////////////////////////////////////////////
// output
+1 -6
Ver Arquivo
@@ -183,15 +183,10 @@ public:
*/
Variant o_get(CStrRef propName, bool error = true,
CStrRef context = null_string) const;
Variant o_getPublic(CStrRef propName, bool error = true) const;
Variant o_set(CStrRef s, CVarRef v, CStrRef context = null_string);
Variant o_set(CStrRef s, RefResult v, CStrRef context = null_string);
Variant o_setRef(CStrRef s, CVarRef v, CStrRef context = null_string);
Variant o_setPublic(CStrRef s, CVarRef v);
Variant o_setPublic(CStrRef s, RefResult v);
Variant o_setPublicRef(CStrRef s, CVarRef v);
Variant &o_lval(CStrRef propName, CVarRef tmpForGet,
CStrRef context = null_string);
/**
* Input/Output
*/
+6 -124
Ver Arquivo
@@ -2445,17 +2445,6 @@ Variant Variant::o_get(CStrRef propName, bool error /* = true */,
return null_variant;
}
Variant Variant::o_getPublic(CStrRef propName, bool error /* = true */) const {
if (m_type == KindOfObject) {
return m_data.pobj->o_getPublic(propName, error);
} else if (m_type == KindOfRef) {
return m_data.pref->var()->o_getPublic(propName, error);
} else if (error) {
raise_notice("Trying to get property of non-object");
}
return null_variant;
}
Variant Variant::o_set(CStrRef propName, CVarRef val,
CStrRef context /* = null_string */) {
if (m_type == KindOfObject) {
@@ -2486,34 +2475,6 @@ Variant Variant::o_setRef(CStrRef propName, CVarRef val,
return m_data.pobj->o_setRef(propName, val, context);
}
Variant Variant::o_setPublic(CStrRef propName, CVarRef val) {
if (m_type == KindOfObject) {
} else if (m_type == KindOfRef) {
return m_data.pref->var()->o_setPublic(propName, val);
} else if (isObjectConvertable()) {
setToDefaultObject();
} else {
// Raise a warning
raise_warning("Attempt to assign property of non-object");
return uninit_null();
}
return m_data.pobj->o_setPublic(propName, val);
}
Variant Variant::o_setPublicRef(CStrRef propName, CVarRef val) {
if (m_type == KindOfObject) {
} else if (m_type == KindOfRef) {
return m_data.pref->var()->o_setPublicRef(propName, val);
} else if (isObjectConvertable()) {
setToDefaultObject();
} else {
// Raise a warning
raise_warning("Attempt to assign property of non-object");
return uninit_null();
}
return m_data.pobj->o_setPublicRef(propName, val);
}
Variant Variant::o_invoke(CStrRef s, CArrRef params, int64_t hash /* = -1 */) {
if (m_type == KindOfObject) {
return m_data.pobj->o_invoke(s, params, hash);
@@ -2524,27 +2485,6 @@ Variant Variant::o_invoke(CStrRef s, CArrRef params, int64_t hash /* = -1 */) {
}
}
Variant Variant::o_root_invoke(CStrRef s, CArrRef params,
int64_t hash /* = -1 */) {
if (m_type == KindOfObject) {
return m_data.pobj->o_invoke(s, params, hash);
} else if (m_type == KindOfRef) {
return m_data.pref->var()->o_root_invoke(s, params, hash);
} else {
throw_call_non_object(s);
}
}
Variant Variant::o_invoke_ex(CStrRef clsname, CStrRef s, CArrRef params) {
if (m_type == KindOfObject) {
return m_data.pobj->o_invoke_ex(clsname, s, params);
} else if (m_type == KindOfRef) {
return m_data.pref->var()->o_invoke_ex(clsname, s, params);
} else {
throw_call_non_object(s);
}
}
Variant Variant::o_invoke_few_args(CStrRef s, int64_t hash, int count,
INVOKE_FEW_ARGS_IMPL_ARGS) {
if (m_type == KindOfObject) {
@@ -2558,22 +2498,6 @@ Variant Variant::o_invoke_few_args(CStrRef s, int64_t hash, int count,
}
}
Variant &Variant::o_lval(CStrRef propName, CVarRef tmpForGet,
CStrRef context /* = null_string */) {
if (m_type == KindOfObject) {
return m_data.pobj->o_lval(propName, tmpForGet, context);
} else if (m_type == KindOfRef) {
return m_data.pref->var()->o_lval(propName, tmpForGet, context);
} else if (isObjectConvertable()) {
setToDefaultObject();
return m_data.pobj->o_lval(propName, tmpForGet, context);
} else {
// Raise a warning
raise_warning("Attempt to assign property of non-object");
return const_cast<Variant&>(tmpForGet);
}
}
template <typename T>
inline ALWAYS_INLINE CVarRef Variant::SetImpl(Variant *self, T key,
CVarRef v, bool isKey) {
@@ -3081,68 +3005,26 @@ void Variant::serialize(VariableSerializer *serializer,
}
}
static void setValue(void *addr, DataType type,
VariableUnserializer *uns, Variant &value) {
value.unserialize(uns);
switch (type) {
case KindOfBoolean: *(bool*)addr = value; break;
case KindOfInt64: *(int64_t*)addr = value; break;
case KindOfDouble: *(double*)addr = value; break;
case KindOfString:
*(String*)addr = value.isString() ? value.getStringData() : nullptr;
break;
case KindOfArray:
*(Array*)addr = value.isArray() ? value.getArrayData() : nullptr;
break;
case KindOfObject:
*(Object*)addr = value.isObject() ? value.getObjectData() : nullptr;
break;
default:
raise_error("Internal error in unserialize!");
}
}
static void unserializeProp(VariableUnserializer *uns,
ObjectData *obj, CStrRef key,
CStrRef context, CStrRef realKey,
int nProp) {
// Do a two-step look up
int flags = ObjectData::RealPropWrite;
DataType type;
void *addr = obj->o_realPropTyped(key, flags, context, &type);
if (addr) {
if (UNLIKELY(type != KindOfUnknown)) {
assert(uns->peek() != 'V' && uns->peek() != 'K');
// This is a property which got type inferred.
if (UNLIKELY(uns->peek() == 'O')) {
// an object can be referred to by an 'r', so we
// need to put the variant somewhere it will be available later
// in case an 'r' refers back to it
Variant &value = uns->addVar();
setValue(addr, type, uns, value);
} else {
// we know its not going to be referred to by an 'R', because
// we cant type-infer properties which are referenced, so
// just unserialize to a temporary.
Variant value;
setValue(addr, type, uns, value);
}
return;
}
} else {
int flags = 0;
Variant* t = obj->o_realProp(key, flags, context);
if (!t) {
// Dynamic property. If this is the first, and we're using HphpArray,
// we need to pre-allocate space in the array to ensure the elements
// dont move during unserialization.
obj->initProperties(nProp);
addr = obj->o_realProp(realKey, ObjectData::RealPropCreate, context);
if (!addr) {
t = obj->o_realProp(realKey, ObjectData::RealPropCreate, context);
if (!t) {
// When accessing protected/private property from wrong context,
// we could get NULL for o_realProp.
throw Exception("Error in accessing property");
}
}
((Variant*)addr)->unserialize(uns);
t->unserialize(uns);
}
void Variant::unserialize(VariableUnserializer *uns) {
-12
Ver Arquivo
@@ -885,22 +885,10 @@ class Variant : private VariantBase {
return o_setRef(s, variant(v), context);
}
Variant o_setRef(CStrRef s, CVarRef v, CStrRef context = null_string);
Variant o_getPublic(CStrRef propName, bool error = true) const;
Variant o_setPublic(CStrRef s, CVarRef v);
Variant o_setPublic(CStrRef s, RefResult v) {
return o_setPublicRef(s, variant(v));
}
Variant o_setPublicRef(CStrRef s, CVarRef v);
Variant &o_lval(CStrRef propName, CVarRef tmpForGet,
CStrRef context = null_string);
Variant o_invoke(CStrRef s, CArrRef params, int64_t hash = -1);
Variant o_root_invoke(CStrRef s, CArrRef params, int64_t hash = -1);
Variant o_invoke_ex(CStrRef clsname, CStrRef s, CArrRef params);
Variant o_invoke_few_args(CStrRef s, int64_t hash, int count,
INVOKE_FEW_ARGS_DECL_ARGS);
Variant o_root_invoke_few_args(CStrRef s, int64_t hash, int count,
INVOKE_FEW_ARGS_DECL_ARGS);
template <typename T>
inline ALWAYS_INLINE static CVarRef SetImpl(
+10 -12
Ver Arquivo
@@ -722,19 +722,17 @@ bool BreakPointInfo::MatchClass(const char *fcls, const std::string &bcls,
if (regex || !func || !*func) {
return Match(fcls, 0, bcls, true, true);
}
if (strcasecmp(fcls, bcls.c_str()) == 0) {
return true;
}
const ClassInfo *clsInfo = ClassInfo::FindClass(bcls.c_str());
if (clsInfo) {
ClassInfo *foundClass;
if (clsInfo->hasMethod(func, foundClass) && foundClass) {
const char *name = foundClass->getName();
return strcasecmp(fcls, name) == 0;
}
}
return false;
StackStringData sdBClsName(bcls.c_str());
VM::Class* clsB = VM::Unit::lookupClass(&sdBClsName);
StackStringData sdFClsName(fcls);
VM::Class* clsF = VM::Unit::lookupClass(&sdFClsName);
if (!clsB) return false;
if (clsB == clsF) return true;
StackStringData sdFuncName(func);
VM::Func* f = clsB->lookupMethod(&sdFuncName);
if (!f) return false;
return (f->baseCls() == clsF);
}
bool BreakPointInfo::Match(const char *haystack, int haystack_len,
+4 -4
Ver Arquivo
@@ -436,9 +436,9 @@ static void object_set(Variant &var, StringBuffer &key, CVarRef value,
if (!assoc) {
// We know it is stdClass, and everything is public (and dynamic).
if (data.empty()) {
var.getObjectData()->o_setPublic("_empty_", value);
var.getObjectData()->o_set("_empty_", value);
} else {
var.getObjectData()->o_setPublic(data, value);
var.getObjectData()->o_set(data, value);
}
} else {
var.set(data, value);
@@ -451,9 +451,9 @@ static void object_set(Variant &var, StringBuffer &key, RefResult value,
if (!assoc) {
// We know it is stdClass, and everything is public (and dynamic).
if (data.empty()) {
var.getObjectData()->o_setPublic("_empty_", value);
var.getObjectData()->o_set("_empty_", value);
} else {
var.getObjectData()->o_setPublic(data, value);
var.getObjectData()->o_set(data, value);
}
} else {
var.set(data, value);
+14 -14
Ver Arquivo
@@ -212,9 +212,10 @@ Variant f_get_parent_class(CVarRef object /* = null_variant */) {
} else {
return false;
}
const ClassInfo *classInfo = ClassInfo::FindClass(class_name.toString());
if (classInfo) {
CStrRef parentClass = classInfo->getParentClass();
VM::Class* cls = VM::Unit::lookupClass(class_name.toString().get());
if (cls) {
CStrRef parentClass = *(const String*)(&cls->parentRef());
if (!parentClass.empty()) {
return parentClass;
}
@@ -264,19 +265,18 @@ bool f_method_exists(CVarRef class_or_object, CStrRef method_name) {
bool f_property_exists(CVarRef class_or_object, CStrRef property) {
if (class_or_object.isObject()) {
CStrRef context = ctxClassName();
// Call o_exists for objects, to include dynamic properties.
return class_or_object.toObject()->o_propExists(property, context);
return (bool)class_or_object.toObject()->o_realProp(
property, ObjectData::RealPropExist, context);
}
const ClassInfo *classInfo =
ClassInfo::FindClass(get_classname(class_or_object));
while (classInfo) {
if (classInfo->hasProperty(property)) {
return true;
} else {
classInfo = classInfo->getParentClassInfo();
}
VM::Class* cls = VM::Unit::lookupClass(get_classname(class_or_object).get());
bool accessible;
VM::Slot propInd = cls->getDeclPropIndex(cls, property.get(), accessible);
if (propInd != VM::kInvalidSlot) {
return true;
}
return false;
propInd = cls->lookupSProp(property.get());
return (propInd != VM::kInvalidSlot);
}
Variant f_get_object_vars(CVarRef object) {
+13 -13
Ver Arquivo
@@ -1637,19 +1637,19 @@ Variant f_mysql_fetch_field(CVarRef result, int field /* = -1 */) {
if (!(info = res->fetchFieldInfo())) return false;
Object obj(SystemLib::AllocStdClassObject());
obj->set("name", *(info->name));
obj->set("table", *(info->table));
obj->set("def", *(info->def));
obj->set("max_length", (int)info->max_length);
obj->set("not_null", IS_NOT_NULL(info->flags)? 1 : 0);
obj->set("primary_key", IS_PRI_KEY(info->flags)? 1 : 0);
obj->set("multiple_key", info->flags & MULTIPLE_KEY_FLAG? 1 : 0);
obj->set("unique_key", info->flags & UNIQUE_KEY_FLAG? 1 : 0);
obj->set("numeric", IS_NUM(info->type)? 1 : 0);
obj->set("blob", IS_BLOB(info->flags)? 1 : 0);
obj->set("type", php_mysql_get_field_name(info->type));
obj->set("unsigned", info->flags & UNSIGNED_FLAG? 1 : 0);
obj->set("zerofill", info->flags & ZEROFILL_FLAG? 1 : 0);
obj->o_set("name", *(info->name));
obj->o_set("table", *(info->table));
obj->o_set("def", *(info->def));
obj->o_set("max_length", (int)info->max_length);
obj->o_set("not_null", IS_NOT_NULL(info->flags)? 1 : 0);
obj->o_set("primary_key", IS_PRI_KEY(info->flags)? 1 : 0);
obj->o_set("multiple_key", info->flags & MULTIPLE_KEY_FLAG? 1 : 0);
obj->o_set("unique_key", info->flags & UNIQUE_KEY_FLAG? 1 : 0);
obj->o_set("numeric", IS_NUM(info->type)? 1 : 0);
obj->o_set("blob", IS_BLOB(info->flags)? 1 : 0);
obj->o_set("type", php_mysql_get_field_name(info->type));
obj->o_set("unsigned", info->flags & UNSIGNED_FLAG? 1 : 0);
obj->o_set("zerofill", info->flags & ZEROFILL_FLAG? 1 : 0);
return obj;
}
+3 -3
Ver Arquivo
@@ -578,7 +578,7 @@ static void pdo_stmt_construct(sp_PDOStatement stmt, Object object,
if (!cls) {
return;
}
object->set("queryString", stmt->query_string);
object->o_set("queryString", stmt->query_string);
TypedValue ret;
VM::Instance* inst = static_cast<VM::Instance*>(object.get());
inst->invokeUserMethod(&ret, cls->getCtor(), ctor_args.toArray());
@@ -1930,12 +1930,12 @@ static bool do_fetch(sp_PDOStatement stmt, bool do_bind, Variant &ret,
case PDO_FETCH_OBJ:
case PDO_FETCH_INTO:
ret.toObject()->set(name, val);
ret.toObject()->o_set(name, val);
break;
case PDO_FETCH_CLASS:
if ((flags & PDO_FETCH_SERIALIZE) == 0 || idx) {
ret.toObject()->set(name, val);
ret.toObject()->o_set(name, val);
} else {
#ifdef MBO_0
ret = f_unserialize(val);
+32 -33
Ver Arquivo
@@ -41,10 +41,10 @@ public:
// overriding ResourceData
virtual CStrRef o_getClassNameHook() const { return s_class_name; }
XmlDocWrapper(xmlDocPtr doc, const ClassInfo* cls)
XmlDocWrapper(xmlDocPtr doc, CStrRef cls)
: m_doc(doc), m_cls(cls) { }
const ClassInfo *getClass() { return m_cls; }
CStrRef getClass() { return m_cls; }
void sweep() {
if (m_doc) {
@@ -54,7 +54,7 @@ public:
~XmlDocWrapper() { XmlDocWrapper::sweep(); }
private:
xmlDocPtr m_doc;
const ClassInfo* m_cls;
String m_cls;
};
IMPLEMENT_OBJECT_ALLOCATION_NO_DEFAULT_SWEEP(XmlDocWrapper)
@@ -124,7 +124,7 @@ static Object create_text(CObjRef doc, xmlNodePtr node,
CStrRef value, CStrRef ns,
bool is_prefix, bool free_text) {
Object obj = create_object(doc.getTyped<XmlDocWrapper>()->
getClass()->getName(), Array(), false);
getClass(), Array(), false);
c_SimpleXMLElement *elem = obj.getTyped<c_SimpleXMLElement>();
elem->m_doc = doc;
elem->m_node = node->parent; // assign to parent, not node
@@ -141,7 +141,7 @@ static Array create_children(CObjRef doc, xmlNodePtr root,
static Object create_element(CObjRef doc, xmlNodePtr node,
CStrRef ns, bool is_prefix) {
Object obj = create_object(doc.getTyped<XmlDocWrapper>()->
getClass()->getName(), Array(), false);
getClass(), Array(), false);
c_SimpleXMLElement *elem = obj.getTyped<c_SimpleXMLElement>();
elem->m_doc = doc;
elem->m_node = node;
@@ -244,17 +244,22 @@ Variant f_simplexml_load_string(CStrRef data,
return uninit_null();
}
const ClassInfo *cls = ClassInfo::FindClass(!class_name.empty() ? class_name : s_SimpleXMLElement);
if (cls == NULL) {
throw_invalid_argument("class not found: %s", class_name.data());
return uninit_null();
}
if (!class_name->isame(s_SimpleXMLElement.get()) && !cls->derivesFrom(s_SimpleXMLElement, false)) {
throw_invalid_argument("simplexml_load_string() expects parameter 2 to be a class name derived "
"from SimpleXMLElement, '%s' given",
class_name.data());
return uninit_null();
VM::Class* cls;
if (!class_name.empty()) {
cls = VM::Unit::lookupClass(class_name.get());
if (!cls) {
throw_invalid_argument("class not found: %s", class_name.data());
return uninit_null();
}
if (!cls->classof(c_SimpleXMLElement::s_cls)) {
throw_invalid_argument(
"simplexml_load_string() expects parameter 2 to be a class name "
"derived from SimpleXMLElement, '%s' given",
class_name.data());
return uninit_null();
}
} else {
cls = c_SimpleXMLElement::s_cls;
}
xmlDocPtr doc = xmlReadMemory(data.data(), data.size(), NULL, NULL, options);
@@ -263,7 +268,7 @@ Variant f_simplexml_load_string(CStrRef data,
return false;
}
return create_element(Object(NEWOBJ(XmlDocWrapper)(doc, cls)),
return create_element(Object(NEWOBJ(XmlDocWrapper)(doc, cls->nameRef())),
root, ns, is_prefix);
}
@@ -286,7 +291,6 @@ c_SimpleXMLElement::c_SimpleXMLElement(VM::Class* cb) :
m_node(NULL), m_is_text(false), m_free_text(false),
m_is_attribute(false), m_is_children(false), m_is_property(false),
m_xpath(NULL) {
setAttribute(HasLval);
m_children = Array::Create();
}
@@ -316,8 +320,7 @@ void c_SimpleXMLElement::t___construct(CStrRef data, int64_t options /* = 0 */,
xmlDocPtr doc = xmlReadMemory(xml.data(), xml.size(), NULL, NULL, options);
if (doc) {
m_doc = Object(NEWOBJ(XmlDocWrapper)(doc,
ClassInfo::FindClass(s_SimpleXMLElement)));
m_doc = Object(NEWOBJ(XmlDocWrapper)(doc, s_SimpleXMLElement));
m_node = xmlDocGetRootElement(doc);
if (m_node) {
m_children = create_children(m_doc, m_node, ns, is_prefix);
@@ -480,7 +483,7 @@ Object c_SimpleXMLElement::t_children(CStrRef ns /* = "" */,
}
Object obj = create_object(m_doc.getTyped<XmlDocWrapper>()->
getClass()->getName(), Array(), false);
getClass(), Array(), false);
c_SimpleXMLElement *elem = obj.getTyped<c_SimpleXMLElement>();
elem->m_doc = m_doc;
elem->m_node = m_node;
@@ -542,7 +545,7 @@ Object c_SimpleXMLElement::t_attributes(CStrRef ns /* = "" */,
}
Object obj = create_object(m_doc.getTyped<XmlDocWrapper>()->
getClass()->getName(), Array(), false);
getClass(), Array(), false);
c_SimpleXMLElement *elem = obj.getTyped<c_SimpleXMLElement>();
elem->m_doc = m_doc;
elem->m_node = m_node;
@@ -688,10 +691,6 @@ String c_SimpleXMLElement::t___tostring() {
return "";
}
Variant *c_SimpleXMLElement::___lval(Variant v_name) {
return &m_children.lvalAt(v_name);
}
Variant c_SimpleXMLElement::t___get(Variant name) {
Variant ret = m_children[name];
if (ret.isArray()) {
@@ -700,7 +699,7 @@ Variant c_SimpleXMLElement::t___get(Variant name) {
if (ret.isObject()) {
c_SimpleXMLElement *elem = ret.toObject().getTyped<c_SimpleXMLElement>();
Object obj = create_object(m_doc.getTyped<XmlDocWrapper>()->
getClass()->getName(), Array(), false);
getClass(), Array(), false);
c_SimpleXMLElement *e = obj.getTyped<c_SimpleXMLElement>();
e->m_doc = elem->m_doc;
e->m_node = elem->m_node;
@@ -1189,12 +1188,12 @@ static void libxml_error_handler(void *userData, xmlErrorPtr error) {
static Object create_libxmlerror(xmlError &error) {
Object ret(NEWOBJ(c_LibXMLError)());
ret->o_setPublic("level", error.level);
ret->o_setPublic("code", error.code);
ret->o_setPublic("column", error.int2);
ret->o_setPublic("message", String(error.message, CopyString));
ret->o_setPublic("file", String(error.file, CopyString));
ret->o_setPublic("line", error.line);
ret->o_set("level", error.level);
ret->o_set("code", error.code);
ret->o_set("column", error.int2);
ret->o_set("message", String(error.message, CopyString));
ret->o_set("file", String(error.file, CopyString));
ret->o_set("line", error.line);
return ret;
}
-1
Ver Arquivo
@@ -88,7 +88,6 @@ class c_SimpleXMLElement :
virtual int64_t o_toInt64() const;
virtual double o_toDouble() const;
virtual Array o_toArray() const;
virtual Variant *___lval(Variant v_name);
private:
xmlXPathContextPtr m_xpath;
};
+5 -2
Ver Arquivo
@@ -2714,8 +2714,11 @@ Variant c_SoapClient::t___setcookie(CStrRef name,
CStrRef value /* = null_string */) {
if (!value.isNull()) {
m_cookies.set(name, CREATE_VECTOR1(value));
} else if (o_exists("_cookies")) {
m_cookies.remove(name);
} else {
const Variant* t = o_realProp("_cookies", RealPropUnchecked);
if (t && t->isInitialized()) {
m_cookies.remove(name);
}
}
return uninit_null();
}
+15 -12
Ver Arquivo
@@ -1149,9 +1149,11 @@ static bool get_zval_property(Variant &object, const char* name,
String sname(name);
if (object.isObject()) {
Object obj = object.toObject();
if (Variant *t = obj->o_weakLval(sname)) {
if (ret) ret->assignRef(*t);
return true;
if (Variant* t = obj->o_realProp(sname, ObjectData::RealPropUnchecked)) {
if (t->isInitialized()) {
if (ret) ret->assignRef(*t);
return true;
}
}
return false;
}
@@ -1314,7 +1316,7 @@ static void model_to_zval_object(Variant &ret, sdlContentModelPtr model,
array.append(val);
val = array;
}
ret.toObject()->set(String(model->u_element->name), val);
ret.toObject()->o_set(String(model->u_element->name), val);
}
}
break;
@@ -1376,7 +1378,7 @@ static Variant to_zval_object_ex(encodeTypePtr type, xmlNodePtr data,
return ret;
}
ret = create_object(ce, Array());
ret.toObject()->set("_", master_to_zval_int(enc, data));
ret.toObject()->o_set("_", master_to_zval_int(enc, data));
} else {
FIND_XML_NULL(data, ret);
if (soap_check_xml_ref(ret, data)) {
@@ -1411,13 +1413,13 @@ static Variant to_zval_object_ex(encodeTypePtr type, xmlNodePtr data,
return ret;
}
redo_any = get_zval_property(ret, "any");
ret.toObject()->set("any", uninit_null());
ret.toObject()->o_set("any", uninit_null());
} else {
if (soap_check_xml_ref(ret, data)) {
return ret;
}
ret = create_object(ce, Array());
ret.toObject()->set("_", master_to_zval_int(sdlType->encode, data));
ret.toObject()->o_set("_", master_to_zval_int(sdlType->encode, data));
}
} else {
FIND_XML_NULL(data, ret);
@@ -1428,7 +1430,7 @@ static Variant to_zval_object_ex(encodeTypePtr type, xmlNodePtr data,
}
if (sdlType->model) {
if (redo_any) {
ret.toObject()->set("any", uninit_null());
ret.toObject()->o_set("any", uninit_null());
}
model_to_zval_object(ret, sdlType->model, data, sdl);
if (redo_any) {
@@ -1462,7 +1464,7 @@ static Variant to_zval_object_ex(encodeTypePtr type, xmlNodePtr data,
xmlAddChild(dummy, text);
Variant data = master_to_zval(attr->encode, dummy);
xmlFreeNode(dummy);
ret.toObject()->set(String(attr->name), data);
ret.toObject()->o_set(String(attr->name), data);
}
}
}
@@ -1481,11 +1483,12 @@ static Variant to_zval_object_ex(encodeTypePtr type, xmlNodePtr data,
Variant prop;
if (!get_zval_property(ret, (char*)trav->name, &prop)) {
if (!trav->next || !get_node(trav->next, (char*)trav->name)) {
ret.toObject()->set(String((char*)trav->name, CopyString), tmpVal);
ret.toObject()->o_set(
String((char*)trav->name, CopyString), tmpVal);
} else {
Array arr = Array::Create();
arr.append(tmpVal);
ret.toObject()->set(String((char*)trav->name, CopyString), arr);
ret.toObject()->o_set(String((char*)trav->name, CopyString), arr);
}
} else {
/* Property already exist - make array */
@@ -1493,7 +1496,7 @@ static Variant to_zval_object_ex(encodeTypePtr type, xmlNodePtr data,
/* Convert into array */
Array arr = Array::Create();
arr.append(prop);
ret.toObject()->set(String((char*)trav->name, CopyString), arr);
ret.toObject()->o_set(String((char*)trav->name, CopyString), arr);
prop = arr;
}
/* Add array element */
+2 -3
Ver Arquivo
@@ -22,6 +22,7 @@
#include <algorithm>
#include "runtime/base/base_includes.h"
#include "runtime/base/array/hphp_array.h"
#include "util/util.h"
#include "util/debug.h"
#include "runtime/vm/core_types.h"
@@ -952,7 +953,7 @@ Slot Class::getDeclPropIndex(Class* ctx, const StringData* key,
// We didn't find a visible declared property in this's property map
accessible = false;
}
// If ctx is an ancestor of this, check if ctx has a private method
// If ctx is an ancestor of this, check if ctx has a private property
// with the same name.
if (ctx && classof(ctx)) {
Slot ctxPropInd = ctx->lookupDeclProp(key);
@@ -1728,7 +1729,6 @@ void Class::setODAttributes() {
static StringData* sd__set = StringData::GetStaticString("__set");
static StringData* sd__isset = StringData::GetStaticString("__isset");
static StringData* sd__unset = StringData::GetStaticString("__unset");
static StringData* sd___lval = StringData::GetStaticString("___lval");
static StringData* sd__call = StringData::GetStaticString("__call");
static StringData* sd__callStatic
= StringData::GetStaticString("__callStatic");
@@ -1739,7 +1739,6 @@ void Class::setODAttributes() {
if (lookupMethod(sd__set )) { m_ODAttrs |= ObjectData::UseSet; }
if (lookupMethod(sd__isset )) { m_ODAttrs |= ObjectData::UseIsset; }
if (lookupMethod(sd__unset )) { m_ODAttrs |= ObjectData::UseUnset; }
if (lookupMethod(sd___lval )) { m_ODAttrs |= ObjectData::HasLval; }
if (lookupMethod(sd__call )) { m_ODAttrs |= ObjectData::HasCall; }
if (lookupMethod(sd__callStatic)) { m_ODAttrs |= ObjectData::HasCallStatic; }
}
+6 -7
Ver Arquivo
@@ -26,9 +26,7 @@
#include <runtime/vm/core_types.h>
#include <runtime/vm/repo_helpers.h>
#include <runtime/base/array/hphp_array.h>
#include <runtime/base/runtime_option.h>
#include <runtime/ext_hhvm/ext_hhvm.h>
#include <util/parser/location.h>
#include <util/fixed_vector.h>
#include <util/range.h>
@@ -40,7 +38,9 @@ namespace HPHP {
// Forward declaration.
class ClassInfo;
class ClassInfoVM;
class HphpArray;
class ObjectData;
struct HhbcExtClassInfo;
namespace VM {
@@ -740,6 +740,10 @@ public:
// the trait.
bool declaredMethod(const Func* method);
bool hasConstant(const StringData* clsCnsName) const {
return m_constants.contains(clsCnsName);
}
TypedValue* clsCnsGet(const StringData* clsCnsName) const;
DataType clsCnsType(const StringData* clsCnsName) const;
void initialize() const;
@@ -903,11 +907,6 @@ private:
std::vector<ClassPtr> m_usedTraits;
TraitAliasVec m_traitAliases;
// Methods.
//
// The m_methods map contains an entry for every method that can be
// called in the context of this Class (but no private methods for
// parent classes).
MethodMap m_methods;
Slot m_traitsBeginIdx;
-64
Ver Arquivo
@@ -574,35 +574,6 @@ void Instance::raiseUndefProp(const StringData* key) {
m_cls->name()->data(), key->data());
}
void Instance::o_setArray(CArrRef properties) {
for (ArrayIter iter(properties); iter; ++iter) {
String k = iter.first().toString();
Class* ctx = nullptr;
// If the key begins with a NUL, it's a private or protected property. Read
// the class name from between the two NUL bytes.
if (!k.empty() && k.charAt(0) == '\0') {
int subLen = k.find('\0', 1) + 1;
String cls = k.substr(1, subLen - 2);
if (cls == "*") {
// Protected.
ctx = m_cls;
} else {
// Private.
ctx = Unit::lookupClass(cls.get());
if (!ctx) continue;
}
k = k.substr(subLen);
}
CVarRef secondRef = iter.secondRef();
setProp(ctx, k.get(), (TypedValue*)(&secondRef),
secondRef.isReferenced());
}
// set public properties
ObjectData::o_setArray(properties);
}
void Instance::getProp(const Class* klass, bool pubOnly,
const PreClass::Prop* prop,
Array& props,
@@ -635,41 +606,6 @@ void Instance::getProps(const Class* klass, bool pubOnly,
}
}
void Instance::o_getArray(Array& props, bool pubOnly /* = false */) const {
// The declared properties in the resultant array should be a permutation of
// propVec. They appear in the following order: go most-to-least-derived in
// the inheritance hierarchy, inserting properties in declaration order (with
// the wrinkle that overridden properties should appear only once, with the
// access level given to it in its most-derived declaration).
// This is needed to keep track of which elements have been inserted. This is
// the smoothest way to get overridden properties right.
std::vector<bool> inserted(m_cls->numDeclProperties(), false);
// Iterate over declared properties and insert {mangled name --> prop} pairs.
const Class* klass = m_cls;
while (klass != nullptr) {
getProps(klass, pubOnly, klass->m_preClass.get(), props, inserted);
const std::vector<ClassPtr> &usedTraits = klass->m_usedTraits;
for (unsigned t = 0; t < usedTraits.size(); t++) {
const ClassPtr& trait = usedTraits[t];
getProps(klass, pubOnly, trait->m_preClass.get(), props, inserted);
}
klass = klass->m_parent.get();
}
// Iterate over dynamic properties and insert {name --> prop} pairs.
if (o_properties.get() != nullptr && !o_properties.get()->empty()) {
for (ArrayIter it(o_properties.get()); !it.end(); it.next()) {
Variant key = it.first();
CVarRef value = it.secondRef();
props.addLval(key, true).setWithRef(value);
}
}
}
Variant Instance::t___destruct() {
static StringData* sd__destruct = StringData::GetStaticString("__destruct");
const Func* method = m_cls->lookupMethod(sd__destruct);
+2 -6
Ver Arquivo
@@ -156,9 +156,6 @@ class Instance : public ObjectData {
// Virtual ObjectData methods that we need to override
public:
virtual void o_setArray(CArrRef properties);
virtual void o_getArray(Array& props, bool pubOnly=false) const;
virtual Variant t___destruct();
virtual Variant t___call(Variant v_name, Variant v_arguments);
virtual Variant t___set(Variant v_name, Variant v_value);
@@ -252,6 +249,8 @@ class Instance : public ObjectData {
void unsetProp(Class* ctx, const StringData* key);
void raiseUndefProp(const StringData* name);
friend class ObjectData;
};
inline Instance* instanceFromTv(TypedValue* tv) {
@@ -269,9 +268,6 @@ class ExtObjectData : public HPHP::VM::Instance {
: HPHP::VM::Instance(cls, false) {
assert(!m_cls->callsCustomInstanceInit());
}
virtual void setRoot(ObjectData *r) {}
virtual ObjectData *getRoot() { return this; }
ObjectData *getBuiltinRoot() { return this; }
};
template <int flags> class ExtObjectDataFlags : public ExtObjectData {
+4
Ver Arquivo
@@ -23,6 +23,10 @@
#include <runtime/vm/translator/translator-inline.h>
namespace HPHP {
struct HhbcExtFuncInfo;
struct HhbcExtClassInfo;
namespace VM {
ArrayData* new_array(int capacity);
+5 -5
Ver Arquivo
@@ -1,14 +1,14 @@
// @generated by "php idl.php inc {input.idl.php} {output.inc}"
#if EXT_TYPE == 0
"simplexml_load_string", T(Variant), S(0), "data", T(String), NULL, S(0), NULL, S(0), "class_name", T(String), "s:16:\"SimpleXMLElement\";", S(24), "\"SimpleXMLElement\"", S(0), "options", T(Int64), "i:0;", S(4), "0", S(0), "ns", T(String), "s:0:\"\";", S(7), "\"\"", S(0), "is_prefix", T(Boolean), "b:0;", S(4), "false", S(0), NULL, S(16384), "/**\n * ( excerpt from\n * http://php.net/manual/en/function.simplexml-load-string.php )\n *\n * Takes a well-formed XML string and returns it as an object.\n *\n * @data string A well-formed XML string\n * @class_name string You may use this optional parameter so that\n * simplexml_load_string() will return an object of the\n * specified class. That class should extend the\n * SimpleXMLElement class.\n * @options int Since PHP 5.1.0 and Libxml 2.6.0, you may also use\n * the options parameter to specify additional Libxml\n * parameters.\n * @ns string\n * @is_prefix bool\n *\n * @return mixed Returns an object of class SimpleXMLElement with\n * properties containing the data held within the xml\n * document. On errors, it will return FALSE.\n */",
"simplexml_load_file", T(Variant), S(0), "filename", T(String), NULL, S(0), NULL, S(0), "class_name", T(String), "s:16:\"SimpleXMLElement\";", S(24), "\"SimpleXMLElement\"", S(0), "options", T(Int64), "i:0;", S(4), "0", S(0), "ns", T(String), "s:0:\"\";", S(7), "\"\"", S(0), "is_prefix", T(Boolean), "b:0;", S(4), "false", S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/function.simplexml-load-file.php\n * )\n *\n * Convert the well-formed XML document in the given file to an object.\n *\n * @filename string Path to the XML file\n *\n * Libxml 2 unescapes the URI, so if you want to pass\n * e.g. b&c as the URI parameter a, you have to call\n * simplexml_load_file(rawurlencode('http://example.com/\?a='\n * . urlencode('b&c'))). Since PHP 5.1.0 you don't need\n * to do this because PHP will do it for you.\n * @class_name string You may use this optional parameter so that\n * simplexml_load_file() will return an object of the\n * specified class. That class should extend the\n * SimpleXMLElement class.\n * @options int Since PHP 5.1.0 and Libxml 2.6.0, you may also use\n * the options parameter to specify additional Libxml\n * parameters.\n * @ns string\n * @is_prefix bool\n *\n * @return mixed Returns an object of class SimpleXMLElement with\n * properties containing the data held within the XML\n * document. On errors, it will return FALSE.\n */",
"simplexml_load_string", T(Variant), S(0), "data", T(String), NULL, S(0), NULL, S(0), "class_name", T(String), "s:16:\"SimpleXMLElement\";", S(24), "\"SimpleXMLElement\"", S(0), "options", T(Int64), "i:0;", S(4), "0", S(0), "ns", T(String), "s:0:\"\";", S(7), "\"\"", S(0), "is_prefix", T(Boolean), "b:0;", S(4), "false", S(0), NULL, S(16384), "/**\n * ( excerpt from\n * http://php.net/manual/en/function.simplexml-load-string.php )\n *\n * Takes a well-formed XML string and returns it as an object.\n *\n * @data string A well-formed XML string\n * @class_name string You may use this optional parameter so that\n * simplexml_load_string() will return an object of the\n * specified class. That class should extend the\n * SimpleXMLElement class.\n * @options int Since PHP 5.1.0 and Libxml 2.6.0, you may also use\n * the options parameter to specify additional Libxml\n * parameters.\n * @ns string\n * @is_prefix bool\n *\n * @return mixed Returns an object of class SimpleXMLElement with\n * properties containing the data held within the xml\n * document. On errors, it will return FALSE.\n */",
"simplexml_load_file", T(Variant), S(0), "filename", T(String), NULL, S(0), NULL, S(0), "class_name", T(String), "s:16:\"SimpleXMLElement\";", S(24), "\"SimpleXMLElement\"", S(0), "options", T(Int64), "i:0;", S(4), "0", S(0), "ns", T(String), "s:0:\"\";", S(7), "\"\"", S(0), "is_prefix", T(Boolean), "b:0;", S(4), "false", S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/function.simplexml-load-file.php\n * )\n *\n * Convert the well-formed XML document in the given file to an object.\n *\n * @filename string Path to the XML file\n *\n * Libxml 2 unescapes the URI, so if you want to pass\n * e.g. b&c as the URI parameter a, you have to call\n * simplexml_load_file(rawurlencode('http://example.com/\?a='\n * . urlencode('b&c'))). Since PHP 5.1.0 you don't need\n * to do this because PHP will do it for you.\n * @class_name string You may use this optional parameter so that\n * simplexml_load_file() will return an object of the\n * specified class. That class should extend the\n * SimpleXMLElement class.\n * @options int Since PHP 5.1.0 and Libxml 2.6.0, you may also use\n * the options parameter to specify additional Libxml\n * parameters.\n * @ns string\n * @is_prefix bool\n *\n * @return mixed Returns an object of class SimpleXMLElement with\n * properties containing the data held within the XML\n * document. On errors, it will return FALSE.\n */",
"libxml_get_errors", T(Variant), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/function.libxml-get-errors.php )\n *\n * Retrieve array of errors.\n *\n * @return mixed Returns an array with LibXMLError objects if there\n * are any errors in the buffer, or an empty array\n * otherwise.\n */",
"libxml_get_last_error", T(Variant), S(0), NULL, S(16384), "/**\n * ( excerpt from\n * http://php.net/manual/en/function.libxml-get-last-error.php )\n *\n * Retrieve last error from libxml.\n *\n * @return mixed Returns a LibXMLError object if there is any error\n * in the buffer, FALSE otherwise.\n */",
"libxml_clear_errors", T(Void), S(0), NULL, S(16384), "/**\n * ( excerpt from http://php.net/manual/en/function.libxml-clear-errors.php\n * )\n *\n * libxml_clear_errors() clears the libxml error buffer.\n *\n * @return mixed No value is returned.\n */",
"libxml_use_internal_errors", T(Boolean), S(0), "use_errors", T(Variant), "N;", S(2), "null", S(0), NULL, S(16384), "/**\n * ( excerpt from\n * http://php.net/manual/en/function.libxml-use-internal-errors.php )\n *\n * libxml_use_internal_errors() allows you to disable standard libxml\n * errors and enable user error handling.\n *\n * @use_errors mixed Whether to enable user error handling.\n *\n * @return bool This function returns the previous value of\n * use_errors.\n */",
"libxml_set_streams_context", T(Void), S(0), "streams_context", T(Object), NULL, S(0), NULL, S(0), NULL, S(16384), "/**\n * ( excerpt from\n * http://php.net/manual/en/function.libxml-set-streams-context.php )\n *\n * Sets the streams context for the next libxml document load or write.\n *\n * @streams_context\n * resource\n * The stream context resource (created with\n * stream_context_create())\n *\n * @return mixed No value is returned.\n */",
"libxml_disable_entity_loader", T(Boolean), S(0), "disable", T(Boolean), "b:1;", S(4), "true", S(0), NULL, S(16384), "/**\n * ( excerpt from\n * http://php.net/manual/en/function.libxml-disable-entity-loader.php )\n *\n * Disable/enable the ability to load external entities.\n *\n * @disable bool Disable (TRUE) or enable (FALSE) libxml extensions\n * (such as DOM, XMLWriter and XMLReader) to load\n * external entities.\n *\n * @return bool Returns the previous value.\n */",
"libxml_use_internal_errors", T(Boolean), S(0), "use_errors", T(Variant), "N;", S(2), "null", S(0), NULL, S(16384), "/**\n * ( excerpt from\n * http://php.net/manual/en/function.libxml-use-internal-errors.php )\n *\n * libxml_use_internal_errors() allows you to disable standard libxml\n * errors and enable user error handling.\n *\n * @use_errors mixed Whether to enable user error handling.\n *\n * @return bool This function returns the previous value of\n * use_errors.\n */",
"libxml_set_streams_context", T(Void), S(0), "streams_context", T(Object), NULL, S(0), NULL, S(0), NULL, S(16384), "/**\n * ( excerpt from\n * http://php.net/manual/en/function.libxml-set-streams-context.php )\n *\n * Sets the streams context for the next libxml document load or write.\n *\n * @streams_context\n * resource\n * The stream context resource (created with\n * stream_context_create())\n *\n * @return mixed No value is returned.\n */",
"libxml_disable_entity_loader", T(Boolean), S(0), "disable", T(Boolean), "b:1;", S(4), "true", S(0), NULL, S(16384), "/**\n * ( excerpt from\n * http://php.net/manual/en/function.libxml-disable-entity-loader.php )\n *\n * Disable/enable the ability to load external entities.\n *\n * @disable bool Disable (TRUE) or enable (FALSE) libxml extensions\n * (such as DOM, XMLWriter and XMLReader) to load\n * external entities.\n *\n * @return bool Returns the previous value.\n */",
#elif EXT_TYPE == 1
+1 -1
Ver Arquivo
@@ -12294,7 +12294,7 @@ bool TestCodeRun::TestCompilation() {
// lval on Variant
MVCR("<?php function test() { return array();} reset(test());");
// variant.o_lval() needs lval() wrapper
// obj->prop++ on Variant
MVCR("<?php class A { public $prop = 1;} class B { public $prop = 5;} "
"$a = 1; $a = new A(); $a->prop++; var_dump($a->prop);");