Some ObjectData/Variant cleanup and dead code removal

This diff eliminates setOpEqual() and appendOpEqual() from Variant, and
it also removes several methods from ObjectData: o_assign_op(), o_argval(),
setDummy(), init(), cloneDynamic(), o_setPublicWithRef(), o_i_set(),
getRedeclaredParent(), and o_propForIteration().

This diff also makes several methods in ObjectData non-virtual: destruct(),
o_toIterArray(), and o_getDynamicProperties(). To achieve this, some of the
logic from Instance was moved to ObjectData.

Finally, this diff gets rid of "hhvm/externals_stubs.cpp" and
"runtime/eval/eval.cpp".
Esse commit está contido em:
andrewparoski
2013-03-09 01:19:38 -08:00
commit de Sara Golemon
commit c1e4c29d0d
23 arquivos alterados com 133 adições e 1134 exclusões
-43
Ver Arquivo
@@ -1,43 +0,0 @@
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "runtime/eval/eval.h"
#include "runtime/base/externals.h"
/*
* HHVM's stubs for various hphpc-style externals.h functions.
*
* These exist for legacy reasons---much of the runtime assumed
* generated versions of some of these functions would exist (as
* output from hphpc).
*
* In the VM, we still fake a few of them while phasing this out.
*/
namespace HPHP {
//////////////////////////////////////////////////////////////////////
Object create_object_only(CStrRef s, ObjectData* root /* = NULL*/) {
ObjectData *obj = eval_create_object_only_hook(s, root);
if (UNLIKELY(!obj)) throw_missing_class(s);
Object r = obj;
obj->init();
return r;
}
//////////////////////////////////////////////////////////////////////
}
+6 -7
Ver Arquivo
@@ -23,7 +23,6 @@
#include <runtime/base/runtime_option.h>
#include <runtime/base/execution_context.h>
#include <runtime/base/strings.h>
#include <runtime/eval/eval.h>
#include <runtime/eval/runtime/file_repository.h>
#include <runtime/eval/debugger/debugger.h>
#include <runtime/ext/ext_process.h>
@@ -519,12 +518,12 @@ void check_collection_cast_to_array() {
}
}
Object create_object(CStrRef s, CArrRef params, bool init /* = true */,
ObjectData *root /* = NULL */) {
assert_not_implemented(root == nullptr);
const StringData* className = StringData::GetStaticString(s.get());
Object o = g_vmContext->createObject((StringData*)className, params, init);
return o;
Object create_object_only(CStrRef s) {
return g_vmContext->createObjectOnly(s.get());
}
Object create_object(CStrRef s, CArrRef params, bool init /* = true */) {
return g_vmContext->createObject(s.get(), params, init);
}
/*
+3
Ver Arquivo
@@ -405,6 +405,9 @@ void check_collection_compare(ObjectData* obj);
void check_collection_compare(ObjectData* obj1, ObjectData* obj2);
void check_collection_cast_to_array();
Object create_object_only(CStrRef s);
Object create_object(CStrRef s, const Array &params, bool init = true);
/**
* Argument count handling.
* - When level is 2, it's from constructors that turn these into fatals
-14
Ver Arquivo
@@ -52,20 +52,6 @@ extern Variant get_class_var_init(CStrRef s, const char *var);
* Class/function meta info entirely encoded here as a const char * array.
*/
extern const char *g_class_map[];
#if 0
extern const char *g_source_root;
extern const char *g_source_info[];
extern const char *g_source_cls2file[];
extern const char *g_source_func2file[];
extern const char *g_paramrtti_map[];
#endif
/**
* Dynamically create an object.
*/
Object create_object(CStrRef s, const Array &params,
bool init = true, ObjectData *root = nullptr);
extern Object create_object_only(CStrRef s, ObjectData *root = nullptr);
/**
* Returns a thread local global variable class pointer.
-1
Ver Arquivo
@@ -29,7 +29,6 @@
#include <runtime/base/base_includes.h>
#include <runtime/base/program_functions.h>
#include <runtime/ext/ext.h>
#include <runtime/eval/eval.h>
///////////////////////////////////////////////////////////////////////////////
+95 -192
Ver Arquivo
@@ -25,6 +25,7 @@
#include <runtime/ext/ext_closure.h>
#include <runtime/ext/ext_continuation.h>
#include <runtime/ext/ext_collection.h>
#include <runtime/vm/class.h>
#include <system/lib/systemlib.h>
@@ -66,13 +67,26 @@ bool ObjectData::instanceof(const HPHP::VM::Class* c) const {
HOT_FUNC
void ObjectData::destruct() {
if (UNLIKELY(RuntimeOption::EnableObjDestructCall)) {
assert(RuntimeOption::EnableObjDestructCall);
g_vmContext->m_liveBCObjs.erase(this);
}
if (!noDestruct()) {
setNoDestruct();
CountableHelper h(this);
try {
t___destruct();
} catch (...) {
handle_destructor_exception();
if (auto meth = m_cls->getDtor()) {
// We raise the refcount around the call to __destruct(). This is to
// prevent the refcount from going to zero when the destructor returns.
CountableHelper h(this);
TypedValue retval;
tvWriteNull(&retval);
try {
// Call the destructor method
g_vmContext->invokeFunc(&retval, meth, null_array, this);
} catch (...) {
// Swallow any exceptions that escape the __destruct method
handle_destructor_exception();
}
tvRefcountedDecRef(&retval);
}
}
}
@@ -405,14 +419,6 @@ Variant ObjectData::o_setPublicRef(CStrRef propName, CVarRef v) {
return o_setPublicImpl<CVarStrongBind>(propName, strongBind(v), false);
}
Variant ObjectData::o_setPublicWithRef(CStrRef propName, CVarRef v) {
return o_setPublicImpl<CVarWithRefBind>(propName, withRefBind(v), false);
}
Variant ObjectData::o_i_set(CStrRef propName, CVarRef v) {
return o_setPublicImpl<CVarRef>(propName, v, true);
}
Variant ObjectData::o_i_setPublicWithRef(CStrRef propName, CVarRef v) {
return o_setPublicImpl<CVarWithRefBind>(propName, withRefBind(v), true);
}
@@ -440,15 +446,6 @@ void ObjectData::o_getArray(Array &props, bool pubOnly /* = false */) const {
}
}
Variant ObjectData::o_argval(bool byRef, CStrRef s,
bool error /* = true */, CStrRef context /* = null_string */) {
if (byRef) {
return strongBind(o_lval(s, context));
} else {
return o_get(s, error, context);
}
}
Object ObjectData::FromArray(ArrayData *properties) {
ObjectData *ret = SystemLib::AllocStdClassObject();
if (!properties->empty()) {
@@ -514,114 +511,81 @@ Array ObjectData::o_toArray() const {
Array ObjectData::o_toIterArray(CStrRef context,
bool getRef /* = false */) {
CStrRef object_class = o_getClassName();
const ClassInfo *classInfo = ClassInfo::FindClass(object_class);
const ClassInfo *contextClassInfo = nullptr;
int category;
if (!classInfo) {
return Array::Create();
size_t size = m_cls->m_declPropNumAccessible +
(o_properties.get() ? o_properties.get()->size() : 0);
HphpArray* retval = NEW(HphpArray)(size);
VM::Class* ctx = nullptr;
if (!context.empty()) {
ctx = VM::Unit::lookupClass(context.get());
}
Array ret(Array::Create());
// Get all declared properties first, bottom-to-top in the inheritance
// hierarchy, in declaration order.
const VM::Class* klass = m_cls;
while (klass != nullptr) {
const VM::PreClass::Prop* props = klass->m_preClass->properties();
const size_t numProps = klass->m_preClass->numProperties();
// There are 3 cases:
// (1) called from standalone function (this_object == null) or
// the object class is not related to the context class;
// (2) the object class is a subclass of the context class or vice versa.
// (3) the object class is the same as the context class
// For (1), only public properties of the object are accessible.
// For (2) and (3), the public/protected properties of the object are
// accessible;
// any property of the context class is also accessible unless it is
// overriden by the object class. (3) is really just an optimization.
if (context.empty()) { // null_string is also empty
category = 1;
} else {
contextClassInfo = ClassInfo::FindClass(context);
assert(contextClassInfo);
if (object_class->isame(context.get())) {
category = 3;
} else if (classInfo->derivesFrom(context, false) ||
contextClassInfo->derivesFrom(object_class, false)) {
category = 2;
} else {
category = 1;
}
}
ClassInfo::PropertyVec properties;
classInfo->getAllProperties(properties);
ClassInfo::PropertyMap contextProperties;
if (category == 2) {
contextClassInfo->getAllProperties(contextProperties);
}
Array dynamics = o_getDynamicProperties();
for (unsigned int i = 0; i < properties.size(); i++) {
ClassInfo::PropertyInfo *prop = properties[i];
if (prop->attribute & ClassInfo::IsStatic) continue;
bool visible = false;
switch (category) {
case 1:
visible = (prop->attribute & ClassInfo::IsPublic);
break;
case 2:
if ((prop->attribute & ClassInfo::IsPrivate) == 0) {
visible = true;
} else {
ClassInfo::PropertyMap::const_iterator iterProp =
contextProperties.find(prop->name);
if (iterProp != contextProperties.end() &&
iterProp->second->owner == contextClassInfo) {
visible = true;
for (size_t i = 0; i < numProps; ++i) {
auto key = const_cast<StringData*>(props[i].name());
bool visible, accessible, unset;
TypedValue* val = ((VM::Instance*)this)->getProp(
ctx, key, visible, accessible, unset);
if (accessible && val->m_type != KindOfUninit && !unset) {
if (getRef) {
if (val->m_type != KindOfRef) {
tvBox(val);
}
retval->nvBind(key, val);
} else {
visible = false;
retval->nvSet(key, val, false);
}
}
break;
case 3:
if ((prop->attribute & ClassInfo::IsPrivate) == 0 ||
prop->owner == classInfo) {
visible = true;
}
break;
default:
assert(false);
}
if (visible && o_propForIteration(prop->name, context)) {
if (getRef) {
Variant tmp;
Variant &ov = o_lval(prop->name, tmp, context);
Variant &av = ret.lvalAt(prop->name, AccessFlags::Key);
av.assignRef(ov);
} else {
ret.set(prop->name, o_getUnchecked(prop->name,
prop->owner->getName()));
}
}
dynamics.remove(prop->name);
klass = klass->m_parent.get();
}
if (!dynamics.empty()) {
if (getRef) {
for (ArrayIter iter(o_getDynamicProperties()); iter; ++iter) {
// Object property names are always strings.
String key = iter.first().toString();
if (dynamics->exists(key)) {
CVarRef value = iter.secondRef();
Variant &av = ret.lvalAt(key, AccessFlags::Key);
av.assignRef(value);
}
}
} else {
ret += dynamics;
}
}
return ret;
}
Array ObjectData::o_getDynamicProperties() const {
return o_properties;
// Now get dynamic properties.
if (o_properties.get()) {
ssize_t iter = o_properties.get()->iter_begin();
while (iter != HphpArray::ElmIndEmpty) {
TypedValue key;
static_cast<HphpArray*>(o_properties.get())->nvGetKey(&key, iter);
iter = o_properties.get()->iter_advance(iter);
// You can get this if you cast an array to object. These properties must
// be dynamic because you can't declare a property with a non-string name.
if (UNLIKELY(!IS_STRING_TYPE(key.m_type))) {
assert(key.m_type == KindOfInt64);
TypedValue* val =
static_cast<HphpArray*>(o_properties.get())->nvGet(key.m_data.num);
if (getRef) {
if (val->m_type != KindOfRef) {
tvBox(val);
}
retval->nvBind(key.m_data.num, val);
} else {
retval->nvSet(key.m_data.num, val, false);
}
continue;
}
StringData* strKey = key.m_data.pstr;
TypedValue* val =
static_cast<HphpArray*>(o_properties.get())->nvGet(strKey);
if (getRef) {
if (val->m_type != KindOfRef) {
tvBox(val);
}
retval->nvBind(strKey, val);
} else {
retval->nvSet(strKey, val, false);
}
decRefStr(strKey);
}
}
return Array(retval);
}
Variant ObjectData::o_invoke(CStrRef s, CArrRef params,
@@ -747,11 +711,6 @@ Variant ObjectData::o_invoke_ex(CStrRef clsname, CStrRef s,
return ret;
}
Variant ObjectData::o_throw_fatal(const char *msg) {
throw_fatal(msg);
return null;
}
bool ObjectData::php_sleep(Variant &ret) {
setAttribute(HasSleep);
ret = t___sleep();
@@ -900,10 +859,6 @@ ObjectData *ObjectData::clone() {
return instance->cloneImpl();
}
void ObjectData::cloneDynamic(ObjectData *orig) {
o_properties.asArray() = orig->o_properties;
}
Variant ObjectData::o_getError(CStrRef prop, CStrRef context) {
raise_notice("Undefined property: %s::$%s", o_getClassName().data(),
prop.data());
@@ -914,52 +869,6 @@ Variant ObjectData::o_setError(CStrRef prop, CStrRef context) {
return null;
}
bool ObjectData::o_isset(CStrRef prop, CStrRef context) {
if (Variant *t = o_realProp(prop, 0, context)) {
if (t->isInitialized()) {
return !t->isNull();
}
}
if (getAttribute(UseIsset)) {
AttributeClearer a(UseIsset, this);
return t___isset(prop);
}
return false;
}
bool ObjectData::o_empty(CStrRef prop, CStrRef context) {
if (Variant *t = o_realProp(prop, 0, context)) {
if (t->isInitialized()) {
return empty(*t);
}
}
if (getAttribute(UseIsset)) {
{
AttributeClearer a(UseIsset, this);
if (!t___isset(prop) || !getAttribute(UseGet)) {
return true;
}
}
AttributeClearer a(UseGet, this);
return empty(t___get(prop));
}
return true;
}
void ObjectData::o_unset(CStrRef prop, CStrRef context) {
if (Variant *t = o_realProp(prop,
RealPropWrite|RealPropNoDynamic, context)) {
unset(*t);
} else if (o_properties.asArray().exists(prop, true)) {
o_properties.asArray().weakRemove(prop, true);
} else if (UNLIKELY(!*prop.data())) {
throw_invalid_property_name(prop);
} else if (getAttribute(UseUnset)) {
AttributeClearer a(UseUnset, this);
t___unset(prop);
}
}
///////////////////////////////////////////////////////////////////////////////
// magic methods that user classes can override, and these are default handlers
// or actions to take:
@@ -988,17 +897,17 @@ Variant *ObjectData::___lval(Variant v_name) {
return nullptr;
}
Variant& ObjectData::___offsetget_lval(Variant key) {
if (isCollection()) {
return collectionOffsetGet(this, key);
} else {
if (!instanceof(SystemLib::s_ArrayAccessClass)) {
throw InvalidOperandException("not ArrayAccess objects");
}
Variant &v = get_system_globals()->__lvalProxy;
v = o_invoke_few_args(s_offsetGet, -1, 1, key);
return v;
Variant ObjectData::offsetGet(Variant key) {
assert(instanceof(SystemLib::s_ArrayAccessClass));
const VM::Func* method = m_cls->lookupMethod(s_offsetGet.get());
assert(method);
if (!method) {
return null;
}
Variant v;
g_vmContext->invokeFunc((TypedValue*)(&v), method,
CREATE_VECTOR1(key), this);
return v;
}
bool ObjectData::t___isset(Variant v_name) {
@@ -1015,12 +924,6 @@ bool ObjectData::o_propExists(CStrRef s, CStrRef context /* = null_string */) {
return t;
}
bool ObjectData::o_propForIteration(CStrRef s,
CStrRef context /* = null_string */) {
Variant *t = o_realProp(s, 0, context);
return t && t->isInitialized();
}
Variant ObjectData::t___sleep() {
clearAttribute(HasSleep);
return null;
+11 -36
Ver Arquivo
@@ -146,7 +146,6 @@ class ObjectData : public CountableNF {
* false for classes that are descendents of ResourceData.
*/
bool o_instanceof(CStrRef s) const;
virtual ObjectData *getRedeclaredParent() const { return 0; }
// class info
CStrRef o_getClassName() const;
@@ -162,15 +161,16 @@ class ObjectData : public CountableNF {
virtual int64_t o_toInt64() const;
virtual double o_toDouble() const { return o_toInt64();}
void setDummy();
virtual void init() {}
virtual void destruct();
void destruct();
// properties
virtual Array o_toArray() const;
virtual Array o_toIterArray(CStrRef context, bool getRef = false);
virtual Array o_getDynamicProperties() const;
Array o_toIterArray(CStrRef context, bool getRef = false);
Array o_getDynamicProperties() const {
return o_properties;
}
Variant *o_realProp(CStrRef s, int flags,
CStrRef context = null_string) const;
void *o_realPropTyped(CStrRef s, int flags,
@@ -182,7 +182,6 @@ class ObjectData : public CountableNF {
Variant o_getPublic(CStrRef s, bool error = true);
Variant o_getUnchecked(CStrRef s, CStrRef context = null_string);
Variant o_i_set(CStrRef s, CVarRef v);
Variant o_i_setPublicWithRef(CStrRef s, CVarRef v);
Variant o_set(CStrRef s, CVarRef v);
@@ -195,24 +194,16 @@ class ObjectData : public CountableNF {
Variant o_setPublic(CStrRef s, CVarRef v);
Variant o_setPublic(CStrRef s, RefResult v);
Variant o_setPublicRef(CStrRef s, CVarRef v);
Variant o_setPublicWithRef(CStrRef s, CVarRef v);
Variant &o_lval(CStrRef s, CVarRef tmpForGet, CStrRef context = null_string);
Variant &o_unsetLval(CStrRef s, CVarRef tmpForGet,
CStrRef context = null_string) {
return o_lval(s, tmpForGet, context);
}
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;
void o_set(const Array properties);
Variant o_argval(bool byRef, CStrRef s, bool error = true,
CStrRef context = null_string);
virtual Variant o_getError(CStrRef prop, CStrRef context);
virtual Variant o_setError(CStrRef prop, CStrRef context);
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
@@ -220,12 +211,6 @@ class ObjectData : public CountableNF {
*/
bool o_propExists(CStrRef s, CStrRef context = null_string);
/**
* This is different from o_exists(), which is isset() semantics; this one
* returns true even if the property is set to null.
*/
bool o_propForIteration(CStrRef s, CStrRef context = null_string);
static Object FromArray(ArrayData *properties);
CVarRef set(CStrRef s, CVarRef v);
@@ -241,16 +226,13 @@ class ObjectData : public CountableNF {
INVOKE_FEW_ARGS_DECL_ARGS);
// misc
Variant o_throw_fatal(const char *msg);
void serialize(VariableSerializer *serializer) const;
virtual void serializeImpl(VariableSerializer *serializer) const;
bool hasInternalReference(PointerSet &vars, bool ds = false) const;
virtual void dump() const;
virtual ObjectData *clone();
bool o_isset(CStrRef prop, CStrRef context = null_string);
bool o_empty(CStrRef prop, CStrRef context = null_string);
void o_unset(CStrRef prop, CStrRef context = null_string);
Variant offsetGet(Variant key);
// magic methods
// __construct is handled in a special way
@@ -259,7 +241,6 @@ class ObjectData : public CountableNF {
virtual Variant t___set(Variant v_name, Variant v_value);
virtual Variant t___get(Variant v_name);
virtual Variant *___lval(Variant v_name);
virtual Variant &___offsetget_lval(Variant key);
virtual bool t___isset(Variant v_name);
virtual Variant t___unset(Variant v_name);
virtual Variant t___sleep();
@@ -267,13 +248,10 @@ class ObjectData : public CountableNF {
virtual String t___tostring();
virtual Variant t___clone();
template<typename T, int op>
T o_assign_op(CStrRef propName, CVarRef val, CStrRef context = null_string);
static int GetMaxId() ATTRIBUTE_COLD;
protected:
virtual bool php_sleep(Variant &ret);
public:
public:
CArrRef getProperties() const { return o_properties; }
void initProperties(int nProp);
private:
@@ -307,9 +285,6 @@ public:
ArrNR o_properties; // dynamic properties (VM and hphpc)
int o_id; // a numeric identifier of this object
protected:
void cloneDynamic(ObjectData *orig);
private:
static void compileTimeAssertions() {
static_assert(offsetof(ObjectData, _count) == FAST_REFCOUNT_OFFSET,
-1
Ver Arquivo
@@ -35,7 +35,6 @@ public:
void operator delete(void* p) { ::operator delete(p); }
// implementing ObjectData
virtual bool o_instanceof(CStrRef s) const { return false;}
virtual bool isResource() const { return true;}
virtual String t___tostring();
virtual int64_t o_toInt64() const { return o_getId();}
+1
Ver Arquivo
@@ -20,6 +20,7 @@
#include <runtime/base/array/array_init.h>
#include <runtime/base/array/array_iterator.h>
#include <runtime/base/class_info.h>
#include <runtime/base/builtin_functions.h>
#include <util/logger.h>
-34
Ver Arquivo
@@ -164,40 +164,6 @@ Variant &Object::o_lval(CStrRef propName, CVarRef tmpForGet,
return m_px->o_lval(propName, tmpForGet, context);
}
Variant &Object::o_unsetLval(CStrRef propName, CVarRef tmpForGet,
CStrRef context /* = null_string */) {
if (!m_px) {
return const_cast<Variant&>(tmpForGet);
}
return m_px->o_lval(propName, tmpForGet, context);
}
bool Object::o_isset(CStrRef propName,
CStrRef context /* = null_string */) const {
if (!m_px) return false;
return m_px->o_isset(propName, context);
}
bool Object::o_empty(CStrRef propName,
CStrRef context /* = null_string */) const {
if (!m_px) return true;
return m_px->o_empty(propName, context);
}
void Object::o_unset(CStrRef propName,
CStrRef context /* = null_string */) const {
if (m_px) m_px->o_unset(propName, context);
}
Variant Object::o_argval(bool byRef, CStrRef propName,
bool error /* = true */, CStrRef context /* = null_string */) {
if (!byRef) {
return o_get(propName, error, context);
} else {
return strongBind(o_lval(propName, context));
}
}
///////////////////////////////////////////////////////////////////////////////
// output
+9 -22
Ver Arquivo
@@ -127,21 +127,17 @@ public:
}
return nullptr;
}
while (true) {
T *px = dynamic_cast<T*>(cur);
if (!px) {
cur = cur->getRedeclaredParent();
if (cur) continue;
if (!badTypeOkay) {
throw InvalidObjectTypeException(m_px->o_getClassName());
}
return nullptr;
T *px = dynamic_cast<T*>(cur);
if (!px) {
if (!badTypeOkay) {
throw InvalidObjectTypeException(m_px->o_getClassName());
}
// Assert that casting does not adjust the 'this' pointer
assert((void*)px == (void*)cur);
return px;
return nullptr;
}
// Assert that casting does not adjust the 'this' pointer
assert((void*)px == (void*)cur);
return px;
}
template<typename T>
bool is() const {
@@ -196,15 +192,6 @@ public:
Variant o_setPublicRef(CStrRef s, CVarRef v);
Variant &o_lval(CStrRef propName, CVarRef tmpForGet,
CStrRef context = null_string);
Variant &o_unsetLval(CStrRef s, CVarRef tmpForGet,
CStrRef context = null_string);
bool o_isset(CStrRef propName, CStrRef context = null_string) const;
bool o_empty(CStrRef propName, CStrRef context = null_string) const;
void o_unset(CStrRef propName, CStrRef context = null_string) const;
template<typename T, int op>
T o_assign_op(CStrRef propName, CVarRef val, CStrRef context = null_string);
Variant o_argval(bool byRef, CStrRef propName, bool error = true,
CStrRef context = null_string);
/**
* Input/Output
*/
+8 -519
Ver Arquivo
@@ -2262,6 +2262,8 @@ public:
static const bool CheckParams = true;
};
DECLARE_THREAD_LOCAL(Variant, __lvalProxy);
template<typename T>
Variant& Variant::LvalAtImpl0(
Variant *self, T key, Variant *tmp, bool blackHole, ACCESSPARAMS_IMPL) {
@@ -2303,12 +2305,13 @@ head:
if (self->m_data.pobj->isCollection()) {
return collectionOffsetGet(self->m_data.pobj, Variant(key));
}
Variant *ret = &(self->getArrayAccess()->___offsetget_lval(key));
if (!blackHole) {
*tmp = *ret;
ret = tmp;
*tmp = self->getArrayAccess()->offsetGet(key);
return *tmp;
}
return *ret;
Variant& retv = *(__lvalProxy.get());
retv = self->getArrayAccess()->offsetGet(key);
return retv;
}
return lvalInvalid();
}
@@ -2432,7 +2435,7 @@ Variant &Variant::lvalInvalid() {
}
Variant &Variant::lvalBlackHole() {
Variant &bh = get_system_globals()->__lvalProxy;
Variant &bh = *(__lvalProxy.get());
bh.unset();
return bh;
}
@@ -2460,57 +2463,6 @@ Variant Variant::o_getPublic(CStrRef propName, bool error /* = true */) const {
return null_variant;
}
bool Variant::o_empty(CStrRef propName,
CStrRef context /* = null_string */) const {
if (m_type == KindOfObject) {
return m_data.pobj->o_empty(propName, context);
}
if (m_type == KindOfRef) {
return m_data.pref->var()->o_empty(propName, context);
}
return true;
}
bool Variant::o_isset(CStrRef propName,
CStrRef context /* = null_string */) const {
if (m_type == KindOfObject) {
return m_data.pobj->o_isset(propName, context);
}
if (m_type == KindOfRef) {
return m_data.pref->var()->o_isset(propName, context);
}
return false;
}
void Variant::o_unset(CStrRef propName, CStrRef context /* = null_string */) {
if (m_type == KindOfObject) {
m_data.pobj->o_unset(propName, context);
}
if (m_type == KindOfRef) {
m_data.pref->var()->o_unset(propName, context);
}
}
Variant Variant::o_argval(bool byRef, CStrRef propName,
bool error /* = true */, CStrRef context /* = null_string */) const {
if (m_type == KindOfObject) {
if (byRef) {
return strongBind(m_data.pobj->o_lval(propName, context));
} else {
return m_data.pobj->o_get(propName, error, context);
}
} else if (m_type == KindOfRef) {
if (byRef) {
return strongBind(m_data.pref->var()->o_lval(propName, context));
} else {
return m_data.pref->var()->o_get(propName, error, context);
}
} 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) {
@@ -2629,91 +2581,6 @@ Variant &Variant::o_lval(CStrRef propName, CVarRef tmpForGet,
}
}
Variant &Variant::o_unsetLval(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_unsetLval(propName, tmpForGet, context);
} else {
return const_cast<Variant&>(tmpForGet);
}
}
#define OPEQUAL(op, l, r) \
switch (op) { \
case T_CONCAT_EQUAL: concat_assign((l), r); break; \
case T_PLUS_EQUAL: ((l) += r); break; \
case T_MINUS_EQUAL: ((l) -= r); break; \
case T_MUL_EQUAL: ((l) *= r); break; \
case T_DIV_EQUAL: ((l) /= r); break; \
case T_MOD_EQUAL: ((l) %= r); break; \
case T_AND_EQUAL: ((l) &= r); break; \
case T_OR_EQUAL: ((l) |= r); break; \
case T_XOR_EQUAL: ((l) ^= r); break; \
case T_SL_EQUAL: ((l) <<= r); break; \
case T_SR_EQUAL: ((l) >>= r); break; \
default: \
throw FatalErrorException(0, "invalid operator %d", op); \
} \
#define IMPLEMENT_SETAT_OPEQUAL \
check_array: \
if (m_type == KindOfArray) { \
Variant *cv = nullptr; \
ArrayData *escalated = \
m_data.parr->lval(ToKey(key), cv, (m_data.parr->getCount() > 1)); \
if (escalated) { \
set(escalated); \
} \
assert(cv); \
OPEQUAL(op, *cv, v); \
return *cv; \
} \
switch (m_type) { \
case KindOfBoolean: \
if (toBoolean()) { \
throw_bad_type_exception("not array objects"); \
break; \
} \
/* Fall through */ \
case KindOfUninit: \
case KindOfNull: \
set(ArrayData::Create(ToKey(key), null)); \
goto check_array; \
case KindOfRef: \
m_data.pref->var()->setOpEqual(op, key, v); \
break; \
case KindOfStaticString: \
case KindOfString: { \
String s = toString(); \
if (s.empty()) { \
set(ArrayData::Create(ToKey(key), null)); \
goto check_array; \
} \
throw_bad_type_exception("not array objects"); \
break; \
} \
case KindOfObject: { \
ObjectData* obj = m_data.pobj; \
if (obj->isCollection()) { \
Variant &cv = collectionOffsetGet(obj, key); \
OPEQUAL(op, cv, v); \
return cv; \
} else { \
ObjectData *aa = getArrayAccess(); \
Variant &cv = aa->___offsetget_lval(key); \
OPEQUAL(op, cv, v); \
aa->o_invoke(s_offsetSet, CREATE_VECTOR2(key, cv), -1); \
return cv; \
} \
} \
default: \
throw_bad_type_exception("not array objects"); \
break; \
} \
return v; \
template <typename T>
inline ALWAYS_INLINE CVarRef Variant::SetImpl(Variant *self, T key,
CVarRef v, bool isKey) {
@@ -2975,235 +2842,6 @@ CVarRef Variant::appendRef(CVarRef v) {
return v;
}
CVarRef Variant::setOpEqual(int op, bool key, CVarRef v) {
IMPLEMENT_SETAT_OPEQUAL;
}
CVarRef Variant::setOpEqual(int op, int64_t key, CVarRef v) {
IMPLEMENT_SETAT_OPEQUAL;
}
CVarRef Variant::setOpEqual(int op, double key, CVarRef v) {
IMPLEMENT_SETAT_OPEQUAL;
}
CVarRef Variant::setOpEqual(int op, CStrRef key, CVarRef v,
bool isString /* = false */) {
check_array:
if (m_type == KindOfArray) {
Variant *cv = nullptr;
ArrayData *escalated;
if (isString) {
escalated =
m_data.parr->lval(key, cv, (m_data.parr->getCount() > 1));
} else {
escalated =
m_data.parr->lval(ToKey(key), cv, (m_data.parr->getCount() > 1));
}
if (escalated) {
set(escalated);
}
assert(cv);
OPEQUAL(op, *cv, v);
return *cv;
}
switch (m_type) {
case KindOfBoolean:
if (toBoolean()) {
throw_bad_type_exception("not array objects");
break;
}
/* Fall through */
case KindOfUninit:
case KindOfNull:
if (isString) {
set(ArrayData::Create(key, null));
} else {
set(ArrayData::Create(ToKey(key), null));
}
goto check_array;
case KindOfRef:
return m_data.pref->var()->setOpEqual(op, key, v, isString);
case KindOfStaticString:
case KindOfString: {
String s = toString();
if (s.empty()) {
if (isString) {
set(ArrayData::Create(key, null));
} else {
set(ArrayData::Create(ToKey(key), null));
}
goto check_array;
}
throw_bad_type_exception("not array objects");
break;
}
case KindOfObject: {
ObjectData* obj = m_data.pobj;
if (obj->isCollection()) {
Variant &cv = collectionOffsetGet(obj, key);
OPEQUAL(op, cv, v);
return cv;
} else {
ObjectData *aa = getArrayAccess();
Variant &cv = aa->___offsetget_lval(key);
OPEQUAL(op, cv, v);
aa->o_invoke(s_offsetSet, CREATE_VECTOR2(key, cv), -1);
return cv;
}
}
default:
throw_bad_type_exception("not array objects");
break;
}
return v;
}
CVarRef Variant::setOpEqual(int op, CVarRef key, CVarRef v) {
check_array:
if (m_type == KindOfArray) {
Variant *cv = nullptr;
VarNR k(ToKey(key));
if (k.isNull()) return lvalBlackHole();
ArrayData *escalated =
m_data.parr->lval(k, cv, (m_data.parr->getCount() > 1));
if (escalated) {
set(escalated);
}
assert(cv);
OPEQUAL(op, *cv, v);
return *cv;
}
switch (m_type) {
case KindOfBoolean:
if (toBoolean()) {
throw_bad_type_exception("not array objects");
break;
}
/* Fall through */
case KindOfUninit:
case KindOfNull: {
VarNR k(ToKey(key));
if (k.isNull()) return lvalBlackHole();
set(ArrayData::Create(k, null));
goto check_array;
}
case KindOfRef:
return m_data.pref->var()->setOpEqual(op, key, v);
case KindOfStaticString:
case KindOfString: {
String s = toString();
if (s.empty()) {
VarNR k(ToKey(key));
if (k.isNull()) return lvalBlackHole();
set(ArrayData::Create(k, null));
goto check_array;
}
throw_bad_type_exception("not array objects");
break;
}
case KindOfObject: {
ObjectData* obj = m_data.pobj;
if (obj->isCollection()) {
Variant &cv = collectionOffsetGet(obj, key);
OPEQUAL(op, cv, v);
return cv;
} else {
ObjectData *aa = getArrayAccess();
Variant &cv = aa->___offsetget_lval(key);
OPEQUAL(op, cv, v);
aa->o_invoke(s_offsetSet, CREATE_VECTOR2(key, cv), -1);
return cv;
}
}
default:
throw_bad_type_exception("not array objects");
break;
}
return v;
}
CVarRef Variant::appendOpEqual(int op, CVarRef v) {
check_array:
if (m_type == KindOfArray) {
Variant *cv = nullptr;
ArrayData *escalated =
m_data.parr->lvalNew(cv, m_data.parr->getCount() > 1);
if (escalated) {
set(escalated);
}
assert(cv);
switch (op) {
case T_CONCAT_EQUAL: return concat_assign((*cv), v);
case T_PLUS_EQUAL: return ((*cv) += v);
case T_MINUS_EQUAL: return ((*cv) -= v);
case T_MUL_EQUAL: return ((*cv) *= v);
case T_DIV_EQUAL: return ((*cv) /= v);
case T_MOD_EQUAL: return ((*cv) %= v);
case T_AND_EQUAL: return ((*cv) &= v);
case T_OR_EQUAL: return ((*cv) |= v);
case T_XOR_EQUAL: return ((*cv) ^= v);
case T_SL_EQUAL: return ((*cv) <<= v);
case T_SR_EQUAL: return ((*cv) >>= v);
default:
throw FatalErrorException(0, "invalid operator %d", op);
}
return v;
}
switch (m_type) {
case KindOfUninit:
case KindOfNull:
set(ArrayData::Create());
goto check_array;
case KindOfBoolean:
if (!toBoolean()) {
set(ArrayData::Create());
goto check_array;
} else {
throw_bad_type_exception("[] operator not supported for this type");
}
break;
case KindOfRef:
m_data.pref->var()->appendOpEqual(op, v);
break;
case KindOfObject: {
if (m_data.pobj->isCollection()) {
raise_error("Cannot use [] for reading");
}
ObjectData *aa = getArrayAccess();
Variant &cv = aa->___offsetget_lval(null_variant);
switch (op) {
case T_CONCAT_EQUAL: concat_assign(cv, v); break;
case T_PLUS_EQUAL: cv += v; break;
case T_MINUS_EQUAL: cv -= v; break;
case T_MUL_EQUAL: cv *= v; break;
case T_DIV_EQUAL: cv /= v; break;
case T_MOD_EQUAL: cv %= v; break;
case T_AND_EQUAL: cv &= v; break;
case T_OR_EQUAL: cv |= v; break;
case T_XOR_EQUAL: cv ^= v; break;
case T_SL_EQUAL: cv <<= v; break;
case T_SR_EQUAL: cv >= v; break;
break;
default:
throw FatalErrorException(0, "invalid operator %d", op);
}
aa->o_invoke(s_offsetSet, CREATE_VECTOR2(null_variant, cv));
return cv;
}
case KindOfStaticString:
case KindOfString:
if (getStringData()->empty()) {
set(ArrayData::Create());
goto check_array;
}
// fall through to throw
default:
throw_bad_type_exception("[] operator not supported for this type");
}
return v;
}
void Variant::removeImpl(double key) {
switch (getType()) {
case KindOfUninit:
@@ -3865,154 +3503,5 @@ VarNR::VarNR(ObjectData *v) {
}
}
template<>
Variant AssignOp<T_CONCAT_EQUAL>::assign(Variant &var, CVarRef val) {
return concat_assign(var, val);
}
template<>
Variant AssignOp<T_PLUS_EQUAL>::assign(Variant &var, CVarRef val) {
return var += val;
}
template<>
Variant AssignOp<T_MINUS_EQUAL>::assign(Variant &var, CVarRef val) {
return var -= val;
}
template<>
Variant AssignOp<T_MUL_EQUAL>::assign(Variant &var, CVarRef val) {
return var *= val;
}
template<>
Variant AssignOp<T_DIV_EQUAL>::assign(Variant &var, CVarRef val) {
return var /= val;
}
template<>
Variant AssignOp<T_MOD_EQUAL>::assign(Variant &var, CVarRef val) {
return var %= val;
}
template<>
Variant AssignOp<T_AND_EQUAL>::assign(Variant &var, CVarRef val) {
return var &= val;
}
template<>
Variant AssignOp<T_OR_EQUAL>::assign(Variant &var, CVarRef val) {
return var |= val;
}
template<>
Variant AssignOp<T_XOR_EQUAL>::assign(Variant &var, CVarRef val) {
return var ^= val;
}
template<>
Variant AssignOp<T_SL_EQUAL>::assign(Variant &var, CVarRef val) {
return var <<= val;
}
template<>
Variant AssignOp<T_SR_EQUAL>::assign(Variant &var, CVarRef val) {
return var >>= val;
}
template<>
Variant AssignOp<T_INC>::assign(Variant &var, CVarRef val) {
return val.isNull() ? ++var : var++;
}
template<>
Variant AssignOp<T_DEC>::assign(Variant &var, CVarRef val) {
return val.isNull() ? --var : var--;
}
template<typename T, int op>
T Variant::o_assign_op(CStrRef propName, CVarRef val,
CStrRef context /* = null_string */) {
if (LIKELY(m_type == KindOfObject)) {
} else if (m_type == KindOfRef) {
return (T)m_data.pref->var()->template o_assign_op<T,op>(propName,
val, context);
} else if (isObjectConvertable()) {
setToDefaultObject();
} else {
// Raise a warning
raise_warning("Attempt to assign property of non-object");
return T();
}
return (T)m_data.pobj->template o_assign_op<T,op>(propName, val, context);
}
template<typename T, int op>
T Object::o_assign_op(CStrRef propName, CVarRef val,
CStrRef context /* = null_string */) {
if (UNLIKELY(!m_px)) {
setToDefaultObject();
}
assert(m_px);
return m_px->template o_assign_op<T,op>(propName, val, context);
}
template<typename T, int op>
T ObjectData::o_assign_op(CStrRef propName, CVarRef val,
CStrRef context /* = null_string */) {
if (UNLIKELY(!*propName.data())) {
throw_invalid_property_name(propName);
}
bool useGet = getAttribute(ObjectData::UseGet);
bool useSet = getAttribute(ObjectData::UseSet);
int flags = useSet ? ObjectData::RealPropWrite :
ObjectData::RealPropCreate | ObjectData::RealPropWrite;
if (Variant *t = o_realProp(propName, flags, context)) {
if (useGet && !t->isInitialized()) {
AttributeClearer a(ObjectData::UseGet, this);
*t = t___get(propName);
}
return (T)AssignOp<op>::assign(*t, val);
}
assert(useSet);
Variant var;
if (useGet) {
AttributeClearer a(ObjectData::UseGet, this);
var = t___get(propName);
}
Variant ret = AssignOp<op>::assign(var, val);
AttributeClearer a(ObjectData::UseSet, this);
t___set(propName, var);
return (T)ret;
}
#define DECLARE_O_ASSIGN_OP_ONE(C,T,op) \
template T \
C::o_assign_op<T,op>(CStrRef propName, CVarRef val, \
CStrRef context /* = null_string */)
#define DECLARE_O_ASSIGN_OP(op) \
DECLARE_O_ASSIGN_OP_ONE(Object,void,op); \
DECLARE_O_ASSIGN_OP_ONE(Object,Variant,op); \
DECLARE_O_ASSIGN_OP_ONE(Variant,void,op); \
DECLARE_O_ASSIGN_OP_ONE(Variant,Variant,op)
DECLARE_O_ASSIGN_OP(T_CONCAT_EQUAL);
DECLARE_O_ASSIGN_OP(T_PLUS_EQUAL);
DECLARE_O_ASSIGN_OP(T_MINUS_EQUAL);
DECLARE_O_ASSIGN_OP(T_MUL_EQUAL);
DECLARE_O_ASSIGN_OP(T_DIV_EQUAL);
DECLARE_O_ASSIGN_OP(T_MOD_EQUAL);
DECLARE_O_ASSIGN_OP(T_AND_EQUAL);
DECLARE_O_ASSIGN_OP(T_OR_EQUAL);
DECLARE_O_ASSIGN_OP(T_XOR_EQUAL);
DECLARE_O_ASSIGN_OP(T_SL_EQUAL);
DECLARE_O_ASSIGN_OP(T_SR_EQUAL);
DECLARE_O_ASSIGN_OP(T_INC);
DECLARE_O_ASSIGN_OP(T_DEC);
///////////////////////////////////////////////////////////////////////////////
}
-28
Ver Arquivo
@@ -909,13 +909,6 @@ class Variant : private VariantBase {
Variant o_setPublicRef(CStrRef s, CVarRef v);
Variant &o_lval(CStrRef propName, CVarRef tmpForGet,
CStrRef context = null_string);
Variant &o_unsetLval(CStrRef s, CVarRef tmpForGet,
CStrRef context = null_string);
Variant o_argval(bool byRef, CStrRef propName, bool error = true,
CStrRef context = null_string) const;
bool o_empty(CStrRef propName, CStrRef context = null_string) const;
bool o_isset(CStrRef propName, CStrRef context = null_string) const;
void o_unset(CStrRef propName, 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);
@@ -970,22 +963,6 @@ class Variant : private VariantBase {
CVarRef appendRef(CVarRef v);
CVarRef append(RefResult v) { return appendRef(variant(v)); }
CVarRef setOpEqual(int op, bool key, CVarRef v);
CVarRef setOpEqual(int op, int key, CVarRef v) {
return setOpEqual(op, (int64_t)key, v);
}
CVarRef setOpEqual(int op, int64_t key, CVarRef v);
CVarRef setOpEqual(int op, double key, CVarRef v);
CVarRef setOpEqual(int op, litstr key, CVarRef v, bool isString = false) {
return setOpEqual(op, String(key), v, isString);
}
CVarRef setOpEqual(int op, CStrRef key, CVarRef v, bool isString = false);
CVarRef setOpEqual(int op, CVarRef key, CVarRef v);
CVarRef appendOpEqual(int op, CVarRef v);
template<typename T, int op>
T o_assign_op(CStrRef propName, CVarRef val, CStrRef context = null_string);
void remove(bool key) { removeImpl(key);}
void remove(int key) { removeImpl((int64_t)key);}
void remove(int64_t key) { removeImpl(key);}
@@ -1480,11 +1457,6 @@ inline VRefParam directRef(CVarRef v) {
class VariantStrongBind { private: Variant m_var; };
class VariantWithRefBind { private: Variant m_var; };
template<int op> class AssignOp {
public:
static Variant assign(Variant &var, CVarRef val);
};
///////////////////////////////////////////////////////////////////////////////
// VarNR
-26
Ver Arquivo
@@ -91,32 +91,6 @@ public:
}
};
template <typename T>
class SmartInterface : public Object {
public:
SmartInterface() {}
SmartInterface(CObjRef obj) : Object(obj) { intf = init(m_px); }
SmartInterface(ObjectData *obj) : Object(obj) { intf = init(m_px); }
SmartInterface(CVarRef obj) : Object(obj.toObject().get()) {
intf = init(m_px);
}
T* operator->() const { return intf; }
CObjRef object() const { return *this; }
private:
T *init(ObjectData *obj) const {
T *t = dynamic_cast<T*>(obj);
if (!t) {
if (ObjectData *parent = obj->getRedeclaredParent()) {
return init(parent);
}
throw InvalidObjectTypeException(m_px->o_getClassName());
}
return t;
}
T *intf;
};
///////////////////////////////////////////////////////////////////////////////
}
@@ -21,7 +21,6 @@
#include <runtime/eval/debugger/cmd/cmd_machine.h>
#include <runtime/eval/debugger/debugger.h>
#include <runtime/base/runtime_option.h>
#include <runtime/eval/eval.h>
#include <runtime/vm/debugger_hook.h>
#include <util/process.h>
#include <util/logger.h>
-33
Ver Arquivo
@@ -1,33 +0,0 @@
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include <runtime/eval/eval.h>
#include <runtime/base/hphp_system.h>
namespace HPHP {
using namespace Eval;
///////////////////////////////////////////////////////////////////////////////
ObjectData *eval_create_object_only_hook(CStrRef s, ObjectData *root) {
assert_not_implemented(root == nullptr);
const StringData* className = StringData::GetStaticString(s.get());
return g_vmContext->createObjectOnly((StringData*)className);
}
///////////////////////////////////////////////////////////////////////////////
}
-30
Ver Arquivo
@@ -1,30 +0,0 @@
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#ifndef __EVAL_EVAL_H__
#define __EVAL_EVAL_H__
#include <runtime/base/base_includes.h>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
ObjectData *eval_create_object_only_hook(CStrRef s, ObjectData *root);
///////////////////////////////////////////////////////////////////////////////
}
#endif // __EVAL_EVAL_H__
-1
Ver Arquivo
@@ -26,7 +26,6 @@
#include <runtime/base/sort_flags.h>
#include <runtime/vm/translator/translator.h>
#include <runtime/vm/translator/translator-inline.h>
#include <runtime/eval/eval.h>
#include <runtime/base/array/hphp_array.h>
#include <util/logger.h>
-1
Ver Arquivo
@@ -26,7 +26,6 @@
#include <runtime/base/util/string_buffer.h>
#include <runtime/base/util/request_local.h>
#include <runtime/base/macros.h>
#include <runtime/eval/eval.h>
#include <system/lib/systemlib.h>
-121
Ver Arquivo
@@ -81,26 +81,6 @@ Instance* Instance::newInstanceRaw(Class* cls, int idx) {
return obj;
}
void Instance::destructHard(const Func* meth) {
static ArrayData* args =
ArrayData::GetScalarArray(HphpArray::GetStaticEmptyArray());
TypedValue retval;
tvWriteNull(&retval);
try {
// Call the destructor method
g_vmContext->invokeFunc(&retval, meth, CArrRef(args), this);
} catch (...) {
// Swallow any exceptions that escape the __destruct method
handle_destructor_exception();
}
tvRefcountedDecRef(&retval);
}
void Instance::forgetSweepable() {
assert(RuntimeOption::EnableObjDestructCall);
g_vmContext->m_liveBCObjs.erase(this);
}
void Instance::invokeUserMethod(TypedValue* retval, const Func* method,
CArrRef params) {
g_vmContext->invokeFunc(retval, method, params, this);
@@ -592,83 +572,6 @@ void Instance::raiseUndefProp(const StringData* key) {
m_cls->name()->data(), key->data());
}
Array Instance::o_toIterArray(CStrRef context, bool getRef /* = false */) {
int size = m_cls->m_declPropNumAccessible +
(o_properties.get() != nullptr ? o_properties.get()->size() : 0);
HphpArray* retval = NEW(HphpArray)(size);
Class* ctx = nullptr;
if (!context.empty()) {
ctx = Unit::lookupClass(context.get());
}
// Get all declared properties first, bottom-to-top in the inheritance
// hierarchy, in declaration order.
const Class* klass = m_cls;
while (klass != nullptr) {
const PreClass::Prop* props = klass->m_preClass->properties();
const size_t numProps = klass->m_preClass->numProperties();
for (size_t i = 0; i < numProps; ++i) {
StringData* key = const_cast<StringData*>(props[i].name());
bool visible, accessible, unset;
TypedValue* val = getProp(ctx, key, visible, accessible, unset);
if (accessible && val->m_type != KindOfUninit && !unset) {
if (getRef) {
if (val->m_type != KindOfRef) {
tvBox(val);
}
retval->nvBind(key, val);
} else {
retval->nvSet(key, val, false);
}
}
}
klass = klass->m_parent.get();
}
// Now get dynamic properties.
if (o_properties.get() != nullptr) {
ssize_t iter = o_properties.get()->iter_begin();
while (iter != HphpArray::ElmIndEmpty) {
TypedValue key;
static_cast<HphpArray*>(o_properties.get())->nvGetKey(&key, iter);
iter = o_properties.get()->iter_advance(iter);
// You can get this if you cast an array to object. These properties must
// be dynamic because you can't declare a property with a non-string name.
if (UNLIKELY(!IS_STRING_TYPE(key.m_type))) {
assert(key.m_type == KindOfInt64);
TypedValue* val =
static_cast<HphpArray*>(o_properties.get())->nvGet(key.m_data.num);
if (getRef) {
if (val->m_type != KindOfRef) {
tvBox(val);
}
retval->nvBind(key.m_data.num, val);
} else {
retval->nvSet(key.m_data.num, val, false);
}
continue;
}
StringData* strKey = key.m_data.pstr;
TypedValue* val =
static_cast<HphpArray*>(o_properties.get())->nvGet(strKey);
if (getRef) {
if (val->m_type != KindOfRef) {
tvBox(val);
}
retval->nvBind(strKey, val);
} else {
retval->nvSet(strKey, val, false);
}
decRefStr(strKey);
}
}
return Array(retval);
}
void Instance::o_setArray(CArrRef properties) {
for (ArrayIter iter(properties); iter; ++iter) {
String k = iter.first().toString();
@@ -839,30 +742,6 @@ Variant Instance::t___unset(Variant v_name) {
}
}
DECLARE_THREAD_LOCAL(Variant, __lvalProxy);
DECLARE_THREAD_LOCAL(Variant, nullProxy);
Variant& Instance::___offsetget_lval(Variant key) {
if (isCollection()) {
return collectionOffsetGet(this, key);
} else {
if (!instanceof(SystemLib::s_ArrayAccessClass)) {
throw InvalidOperandException("not ArrayAccess objects");
}
static StringData* sd__offsetGet = StringData::GetStaticString("offsetGet");
const Func* method = m_cls->lookupMethod(sd__offsetGet);
assert(method);
if (method) {
Variant *v = __lvalProxy.get();
g_vmContext->invokeFunc((TypedValue*)v, method,
CREATE_VECTOR1(key), this);
return *v;
} else {
return *nullProxy.get();
}
}
}
Variant Instance::t___sleep() {
static StringData* sd__sleep = StringData::GetStaticString("__sleep");
const Func *method = m_cls->lookupMethod(sd__sleep);
-22
Ver Arquivo
@@ -152,31 +152,10 @@ class Instance : public ObjectData {
DELETEOBJSZ(sizeForNProps(nProps))(this_);
}
private:
void destructHard(const Func* meth);
void forgetSweepable();
//============================================================================
// Virtual ObjectData methods that we need to override
public:
virtual void destruct() {
if (UNLIKELY(RuntimeOption::EnableObjDestructCall)) {
forgetSweepable();
}
if (!noDestruct()) {
setNoDestruct();
if (const Func* meth = m_cls->getDtor()) {
// We raise the refcount around the call to __destruct(). This is to
// prevent the refcount from going to zero when the destructor returns.
CountableHelper h(this);
destructHard(meth);
}
}
}
virtual Array o_toIterArray(CStrRef context, bool getRef=false);
virtual void o_setArray(CArrRef properties);
virtual void o_getArray(Array& props, bool pubOnly=false) const;
@@ -184,7 +163,6 @@ class Instance : public ObjectData {
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& ___offsetget_lval(Variant key);
virtual bool t___isset(Variant v_name);
virtual Variant t___unset(Variant v_name);
virtual Variant t___sleep();
-1
Ver Arquivo
@@ -165,7 +165,6 @@ class GlobalNameValueTableWrapper : public NameValueTableWrapper {
Variant gvm_http_response_header;
Variant __realPropProxy;
Variant __lvalProxy;
Variant stgv_Variant[1];
#define k_SID stgv_Variant[0]
-1
Ver Arquivo
@@ -10,7 +10,6 @@ auto_sources(files "*.cpp" "")
list(APPEND CXX_SOURCES ${files})
list(REMOVE_ITEM CXX_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/genCmpTest.cpp")
list(APPEND CXX_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/../hhvm/process_init.cpp")
list(APPEND CXX_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/../hhvm/externals_stubs.cpp")
list(APPEND CXX_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/../hhvm/global_variables.cpp")
add_definitions(-DHPHPI_PATH="hphpi/hphpi")