Remove old HHVM_GC code
This was left over from GC-related experiments, and isn't needed now.
Esse commit está contido em:
@@ -1,289 +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 incl_HPHP_BASE_GC_ROOTS_H_
|
||||
#define incl_HPHP_BASE_GC_ROOTS_H_
|
||||
|
||||
#include <vector>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include "util/base.h"
|
||||
#include "util/util.h"
|
||||
#include "runtime/base/util/smart_ptr.h"
|
||||
#include "runtime/base/types.h"
|
||||
|
||||
namespace HPHP {
|
||||
|
||||
#ifdef HHVM_GC
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* Variants aren't smart pointers and behave a bit differently from
|
||||
* the others. This base is used to change that behavior based on
|
||||
* type.
|
||||
*
|
||||
* TODO: right now we are "over-tracking" Variants, since we still
|
||||
* track the ones allocated inside smart_allocators.
|
||||
*/
|
||||
template<class T> struct GCRootTrackerBase {
|
||||
typedef SmartPtr<T> type;
|
||||
};
|
||||
template<> struct GCRootTrackerBase<Variant> {
|
||||
template<class T>
|
||||
struct EmptyBase {
|
||||
explicit EmptyBase(T* = 0) {}
|
||||
};
|
||||
|
||||
typedef EmptyBase<Variant> type;
|
||||
};
|
||||
|
||||
/*
|
||||
* This is a base class for smart pointers that need to be tracked as
|
||||
* C++ roots for tracing GC.
|
||||
*
|
||||
* The roots are tracked differently depending on whether they live on
|
||||
* the stack or on the heap. For roots on the stack, pointers are
|
||||
* stored in a sorted array, for the heap they currently reside in a
|
||||
* hash set.
|
||||
*/
|
||||
template<class T>
|
||||
class GCRootTracker : protected GCRootTrackerBase<T>::type {
|
||||
typedef typename GCRootTrackerBase<T>::type Base;
|
||||
|
||||
public:
|
||||
BOOST_STATIC_ASSERT((boost::is_same<T,ObjectData>::value ||
|
||||
boost::is_same<T,StringData>::value ||
|
||||
boost::is_same<T,ArrayData>::value ||
|
||||
boost::is_same<T,Variant>::value));
|
||||
|
||||
typedef hphp_hash_set<void*,pointer_hash<void> > HeapSet;
|
||||
|
||||
explicit GCRootTracker(T* t = 0) : Base(t) { track(); }
|
||||
GCRootTracker(const GCRootTracker& o) : Base(o) {
|
||||
track();
|
||||
}
|
||||
~GCRootTracker() { untrack(); }
|
||||
|
||||
GCRootTracker& operator=(const GCRootTracker& o) {
|
||||
Base::operator=(o);
|
||||
return *this;
|
||||
}
|
||||
|
||||
GCRootTracker& operator=(T* t) {
|
||||
Base::operator=(t);
|
||||
return *this;
|
||||
}
|
||||
|
||||
static std::vector<void*>& getStack() {
|
||||
static __thread std::vector<void*>* stack;
|
||||
if (!stack) stack = new std::vector<void*>();
|
||||
return *stack;
|
||||
}
|
||||
|
||||
static HeapSet& getHeap() {
|
||||
static __thread HeapSet* heap;
|
||||
if (!heap) heap = new HeapSet();
|
||||
return *heap;
|
||||
}
|
||||
|
||||
// Discards all pointers below a given address. (This is currently
|
||||
// used in the bridge with ext_hhvm.cpp; see vm/gc.h's
|
||||
// DiscardDeepRoots().)
|
||||
static void discardDeepRoots(char* frontier) {
|
||||
std::vector<void*>& stack = getStack();
|
||||
while (!stack.empty() && stack.back() < frontier) {
|
||||
stack.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Discard all known roots. This is called at sweep() time in
|
||||
* memory_manager, since many String/Array/etc objects will not have
|
||||
* their destructors run.
|
||||
*/
|
||||
static void clear() {
|
||||
getStack().clear();
|
||||
getHeap().clear();
|
||||
}
|
||||
|
||||
private:
|
||||
void track() {
|
||||
if (!is_stack_ptr(this)) return trackHeap();
|
||||
trackStack();
|
||||
}
|
||||
|
||||
void untrack() {
|
||||
if (!is_stack_ptr(this)) return untrackHeap();
|
||||
untrackStack();
|
||||
}
|
||||
|
||||
void trackHeap() {
|
||||
getHeap().insert(this);
|
||||
}
|
||||
|
||||
void untrackHeap() {
|
||||
getHeap().erase(this);
|
||||
}
|
||||
|
||||
private:
|
||||
struct InvariantChecker : boost::noncopyable {
|
||||
explicit InvariantChecker(GCRootTracker* thiz)
|
||||
: m_thiz(thiz)
|
||||
{
|
||||
m_thiz->checkInvariants();
|
||||
}
|
||||
~InvariantChecker()
|
||||
{
|
||||
m_thiz->checkInvariants();
|
||||
}
|
||||
GCRootTracker* m_thiz;
|
||||
};
|
||||
|
||||
void checkInvariants() {
|
||||
if (!debug) return;
|
||||
|
||||
const std::vector<void*>& stack = getStack();
|
||||
std::vector<void*>::const_reverse_iterator it = stack.rbegin();
|
||||
void* last = 0;
|
||||
for (; it != stack.rend(); ++it) {
|
||||
assert(*it > last);
|
||||
last = *it;
|
||||
}
|
||||
}
|
||||
|
||||
void trackStack() {
|
||||
InvariantChecker check(this);
|
||||
|
||||
std::vector<void*>& stack = getStack();
|
||||
if (stack.empty()) {
|
||||
stack.push_back(this);
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<void*>::iterator it = stack.end() - 1;
|
||||
while (it != stack.begin() && *it < this) {
|
||||
--it;
|
||||
}
|
||||
if (it == stack.begin()) {
|
||||
if (*it < this) {
|
||||
stack.insert(stack.begin(), this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
assert(*it > this);
|
||||
++it;
|
||||
assert(it == stack.end() || *it < this);
|
||||
stack.insert(it, this);
|
||||
}
|
||||
|
||||
void untrackStack() {
|
||||
InvariantChecker check(this);
|
||||
|
||||
/*
|
||||
* Note that objects on the C++ stack are not necessarily
|
||||
* destroyed in reverse order of their creation, so this search to
|
||||
* find the correct this pointer is necessary.
|
||||
*
|
||||
* For example, assume NRVO doesn't happen in the following:
|
||||
*
|
||||
* extern String f();
|
||||
* String s(f());
|
||||
*
|
||||
* Then the return value of f is constructed, followed by s being
|
||||
* copy-constructed from it, then ~f happens before ~s.
|
||||
*/
|
||||
std::vector<void*>& stack = getStack();
|
||||
std::vector<void*>::reverse_iterator it = stack.rbegin();
|
||||
while (it != stack.rend() && *it < this) {
|
||||
++it;
|
||||
}
|
||||
if (it != stack.rend() && *it == this) {
|
||||
stack.erase(it.base() - 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* In some cases we want to register roots on the stack without all
|
||||
* the machinery of the smart pointers that use GCRootTracker<> above.
|
||||
* These roots must be popped in the opposite order they are pushed,
|
||||
* so this is mainly appropriate for holding a root for some C++
|
||||
* lexical scope.
|
||||
*
|
||||
* The specific cases where this can be necessary is during creation,
|
||||
* of smart allocated data, where the object has a ref count of zero
|
||||
* and no root yet lives anywhere, but a GC may happen during the
|
||||
* constructor if it makes allocations. (See for e.g. the
|
||||
* VM::Instance constructor.)
|
||||
*
|
||||
* To use this class, use DECLARE_STACK_GC_ROOT() instead of
|
||||
* instantiating it directly.
|
||||
*/
|
||||
template<class T>
|
||||
struct GCRoot : private boost::noncopyable {
|
||||
BOOST_STATIC_ASSERT((boost::is_same<T,ObjectData>::value ||
|
||||
boost::is_same<T,StringData>::value ||
|
||||
boost::is_same<T,ArrayData>::value ||
|
||||
boost::is_same<T,Variant>::value));
|
||||
|
||||
static std::vector<T*>& getStack() {
|
||||
static __thread std::vector<T*>* stack;
|
||||
if (!stack) stack = new std::vector<T*>();
|
||||
return *stack;
|
||||
}
|
||||
|
||||
static void clear() {
|
||||
// Nothing should be left at end of request time or this class is
|
||||
// being misused.
|
||||
assert(getStack().empty());
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
explicit GCRoot(T* t) : m_debugSavedPtr(t) { getStack().push_back(t); }
|
||||
~GCRoot() {
|
||||
assert(!getStack().empty() && getStack().back() == m_debugSavedPtr);
|
||||
getStack().pop_back();
|
||||
}
|
||||
|
||||
private:
|
||||
T* const m_debugSavedPtr;
|
||||
#else
|
||||
// Non debug version:
|
||||
explicit GCRoot(T* t) { getStack().push_back(t); }
|
||||
~GCRoot() { getStack().pop_back(); }
|
||||
#endif
|
||||
};
|
||||
|
||||
#define DECLARE_STACK_GC_ROOT(type, root) \
|
||||
GCRoot<type> gcr##__LINE__((root))
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#else
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define DECLARE_STACK_GC_ROOT(type, root) /* */
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -213,16 +213,6 @@ void MemoryManager::add(SmartAllocatorImpl *allocator) {
|
||||
|
||||
void MemoryManager::sweepAll() {
|
||||
Sweepable::SweepAll();
|
||||
#ifdef HHVM_GC
|
||||
GCRootTracker<StringData>::clear();
|
||||
GCRootTracker<ArrayData>::clear();
|
||||
GCRootTracker<ObjectData>::clear();
|
||||
GCRootTracker<Variant>::clear();
|
||||
GCRoot<StringData>::clear();
|
||||
GCRoot<ArrayData>::clear();
|
||||
GCRoot<ObjectData>::clear();
|
||||
GCRoot<Variant>::clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
struct SmallNode {
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include <runtime/base/array/array_data.h>
|
||||
#include <runtime/base/type_string.h>
|
||||
#include <runtime/base/hphp_value.h>
|
||||
#include <runtime/base/gc_roots.h>
|
||||
|
||||
namespace HPHP {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -42,12 +41,6 @@ inline int64_t ToKey(double d) {
|
||||
class ArrayIter;
|
||||
class StaticArray;
|
||||
|
||||
#ifdef HHVM_GC
|
||||
typedef GCRootTracker<ArrayData> ArrayBase;
|
||||
#else
|
||||
typedef SmartPtr<ArrayData> ArrayBase;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Array type wrapping around ArrayData to implement reference
|
||||
* counting, copy-on-write and ArrayData escalation.
|
||||
@@ -57,7 +50,9 @@ typedef SmartPtr<ArrayData> ArrayBase;
|
||||
* type of ArrayData to accomplish the task. This "upgrade" is called
|
||||
* escalation.
|
||||
*/
|
||||
class Array : protected ArrayBase {
|
||||
class Array : protected SmartPtr<ArrayData> {
|
||||
typedef SmartPtr<ArrayData> ArrayBase;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Create an empty array or an array with one element. Note these are
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#include <runtime/base/object_data.h>
|
||||
#include <runtime/base/type_string.h>
|
||||
#include <runtime/base/hphp_value.h>
|
||||
#include <runtime/base/gc_roots.h>
|
||||
|
||||
namespace HPHP {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -36,16 +35,12 @@ namespace HPHP {
|
||||
class ArrayIter;
|
||||
class MutableArrayIter;
|
||||
|
||||
#ifdef HHVM_GC
|
||||
typedef GCRootTracker<ObjectData> ObjectBase;
|
||||
#else
|
||||
typedef SmartPtr<ObjectData> ObjectBase;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Object type wrapping around ObjectData to implement reference count.
|
||||
*/
|
||||
class Object : protected ObjectBase {
|
||||
class Object : protected SmartPtr<ObjectData> {
|
||||
typedef SmartPtr<ObjectData> ObjectBase;
|
||||
|
||||
public:
|
||||
Object() {}
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include <runtime/base/string_offset.h>
|
||||
#include <runtime/base/types.h>
|
||||
#include <runtime/base/hphp_value.h>
|
||||
#include <runtime/base/gc_roots.h>
|
||||
|
||||
namespace HPHP {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -42,17 +41,13 @@ StringData* buildStringData(int64_t n);
|
||||
StringData* buildStringData(double n);
|
||||
StringData* buildStringData(litstr s);
|
||||
|
||||
#ifdef HHVM_GC
|
||||
typedef GCRootTracker<StringData> StringBase;
|
||||
#else
|
||||
typedef SmartPtr<StringData> StringBase;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* String type wrapping around StringData to implement copy-on-write and
|
||||
* literal string handling (to avoid string copying).
|
||||
*/
|
||||
class String : protected StringBase {
|
||||
class String : protected SmartPtr<StringData> {
|
||||
typedef SmartPtr<StringData> StringBase;
|
||||
|
||||
public:
|
||||
typedef hphp_hash_map<int64_t, const StringData *, int64_hash>
|
||||
IntegerStringDataMap;
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
#include <runtime/base/memory/smart_allocator.h>
|
||||
#include <runtime/base/array/array_data.h>
|
||||
#include <runtime/base/macros.h>
|
||||
#include <runtime/base/gc_roots.h>
|
||||
|
||||
namespace HPHP {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -71,13 +70,7 @@ class MutableArrayIter;
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HHVM_GC
|
||||
typedef GCRootTracker<Variant> VariantBase;
|
||||
#else
|
||||
typedef TypedValue VariantBase;
|
||||
#endif
|
||||
|
||||
class Variant : private VariantBase {
|
||||
class Variant : private TypedValue {
|
||||
public:
|
||||
friend class Array;
|
||||
friend class VariantVectorBase;
|
||||
|
||||
@@ -95,20 +95,6 @@ class Instance : public ObjectData {
|
||||
|
||||
private:
|
||||
void instanceInit(Class* cls) {
|
||||
/*
|
||||
* During the construction of an instance, the instance has a ref
|
||||
* count of zero, and no pointer to it yet exists anywhere the
|
||||
* tracing collector can find it. (I.e., newInstance() hasn't
|
||||
* returned, so it isn't on the execution stack or in an Object
|
||||
* smart pointer yet.)
|
||||
*
|
||||
* However, instance creation can sometimes lead to execution of
|
||||
* arbitrary code (in the form of an autoload handler). Moreover
|
||||
* it can also lead to memory allocations (which may be a point at
|
||||
* which we want to do GC), so we need to register the root for
|
||||
* the duration of construction.
|
||||
*/
|
||||
DECLARE_STACK_GC_ROOT(ObjectData, this);
|
||||
setAttributes(cls->getODAttrs());
|
||||
size_t nProps = cls->numDeclProperties();
|
||||
if (cls->needInitialization()) {
|
||||
|
||||
@@ -127,14 +127,6 @@ static const bool debug =
|
||||
#endif
|
||||
;
|
||||
|
||||
const bool hhvm_gc =
|
||||
#ifdef HHVM_GC
|
||||
true
|
||||
#else
|
||||
false
|
||||
#endif
|
||||
;
|
||||
|
||||
static const bool use_jemalloc =
|
||||
#ifdef USE_JEMALLOC
|
||||
true
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário