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:
@@ -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;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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 ¶ms, bool init = true);
|
||||
|
||||
/**
|
||||
* Argument count handling.
|
||||
* - When level is 2, it's from constructors that turn these into fatals
|
||||
|
||||
@@ -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 ¶ms,
|
||||
bool init = true, ObjectData *root = nullptr);
|
||||
extern Object create_object_only(CStrRef s, ObjectData *root = nullptr);
|
||||
|
||||
/**
|
||||
* Returns a thread local global variable class pointer.
|
||||
|
||||
@@ -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>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();}
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
@@ -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__
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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")
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário