From d0ae3caca5828675335d3b19ab5dd987e7369b23 Mon Sep 17 00:00:00 2001 From: Tim Blechmann Date: Wed, 14 Jul 2004 16:21:44 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r1857, which included commits to RCS files with non-trunk default branches. svn path=/trunk/externals/tb/; revision=1858 --- sc4pd/headers/lang/GC.h | 263 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 263 insertions(+) create mode 100755 sc4pd/headers/lang/GC.h (limited to 'sc4pd/headers/lang/GC.h') diff --git a/sc4pd/headers/lang/GC.h b/sc4pd/headers/lang/GC.h new file mode 100755 index 0000000..4dc162a --- /dev/null +++ b/sc4pd/headers/lang/GC.h @@ -0,0 +1,263 @@ +/* + SuperCollider real time audio synthesis system + Copyright (c) 2002 James McCartney. All rights reserved. + http://www.audiosynth.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/* + +The garbage collector for SuperCollider. +Based on Wilson and Johnstone's real time collector and the Baker treadmill. + +*/ + +#ifndef _GC_ +#define _GC_ + +#include "PyrObject.h" +#include "VMGlobals.h" +#include "AdvancingAllocPool.h" + +void DumpSimpleBackTrace(VMGlobals *g); + +const int kMaxPoolSet = 7; +const int kNumGCSizeClasses = 28; +const int kFinalizerSet = kNumGCSizeClasses; +const int kNumGCSets = kNumGCSizeClasses + 1; + +class GCSet +{ +public: + GCSet() {} + void Init(int inSizeClass); + + bool HasFree() { return mFree != &mBlack; } + +private: + friend class PyrGC; + + void MoveWhiteToFree(); + + PyrObjectHdr mBlack; + PyrObjectHdr mWhite; + PyrObjectHdr* mFree; +}; + +struct SlotRef { + SlotRef(PyrObject* inObj, int32 inIndex) : obj(inObj), slotIndex(inIndex) {} + + PyrObject *obj; + int32 slotIndex; +}; + +class PyrGC +{ +public: + PyrGC(VMGlobals *g, AllocPool *inPool, PyrClass *mainProcessClass, long poolSize); + + PyrObject* New(size_t inNumBytes, long inFlags, long inFormat, bool inCollect); + + static PyrObject* NewPermanent(size_t inNumBytes, + long inFlags, long inFormat); + + PyrObject* NewFinalizer(ObjFuncPtr finalizeFunc, PyrObject *inObject, bool inCollect); + + int32 ProcessID() { return mProcessID; } + +#if 0 +// Codewarrior is not inlining these.. why? + bool IsBlack(PyrObjectHdr* inObj) { return inObj->gc_color == mBlackColor; } + bool IsWhite(PyrObjectHdr* inObj) { return inObj->gc_color == mWhiteColor; } + bool IsGrey(PyrObjectHdr* inObj) { return inObj->gc_color == mGreyColor; } + bool IsMarker(PyrObjectHdr* inObj) { return inObj->gc_color == obj_gcmarker; } +#else + +#define IsBlack(inObj) ((inObj)->gc_color == mBlackColor) +#define IsWhite(inObj) ((inObj)->gc_color == mWhiteColor) +#define IsGrey(inObj) ((inObj)->gc_color == mGreyColor) +#define IsFree(inObj) (!(IsMarker(inObj) || inObj->IsPermanent() || \ + IsBlack(inObj) || IsWhite(inObj) || IsGrey(inObj))) +#define IsMarker(inObj) ((inObj)->gc_color == obj_gcmarker) +#endif + + bool ObjIsBlack(PyrObjectHdr* inObj) { return IsBlack(inObj); } + bool ObjIsGrey(PyrObjectHdr* inObj) { return IsGrey(inObj); } + bool ObjIsFree(PyrObjectHdr* inObj) { return IsFree(inObj); } + + + // general purpose write barriers: + void GCWrite(PyrObjectHdr* inParent, PyrSlot* inSlot) + { + if (IsBlack(inParent) && IsObj(inSlot) && IsWhite(inSlot->uo)) { + ToGrey(inSlot->uo); + } + } + void GCWrite(PyrObjectHdr* inParent, PyrObjectHdr* inChild) + { + if (IsBlack(inParent) && IsWhite(inChild)) { + ToGrey(inChild); + } + } + // when you know the parent is black: + void GCWriteBlack(PyrSlot* inSlot) + { + if (IsObj(inSlot)) { + if (IsWhite(inSlot->uo)) { + ToGrey(inSlot->uo); + } + } + } + void GCWriteBlack(PyrObjectHdr* inChild) + { + if (IsWhite(inChild)) { + ToGrey(inChild); + } + } + // when you know the child is white + void GCWriteNew(PyrObjectHdr* inParent, PyrObjectHdr* inChild) + { + if (IsBlack(inParent)) { + ToGrey(inChild); + } + } + +// users should not call anything below. + + void Collect(); + void Collect(int32 inNumToScan); + void FullCollection(); + void ScanFinalizers(); + GCSet* GetGCSet(PyrObjectHdr* inObj); + void CompletePartialScan(PyrObject *obj); + + void ToGrey(PyrObjectHdr* inObj); + void ToGrey2(PyrObjectHdr* inObj); + void ToBlack(PyrObjectHdr* inObj); + void ToWhite(PyrObjectHdr *obj); + + int32 StackDepth() { return mVMGlobals->sp - mStack->slots + 1; } + PyrObject* Stack() { return mStack; } + void SetStack(PyrObject* inStack) { mStack = inStack; } + + bool SanityCheck(); + bool SanityCheck2(); + bool LinkSanity(); + bool ListSanity(); + bool BlackToWhiteCheck(PyrObject *objA); + bool SanityMarkObj(PyrObject *objA, PyrObject *fromObj, int level); + bool SanityClearObj(PyrObject *objA, int level); + void DumpInfo(); + void DumpEverything(); + + void BecomePermanent(PyrObject *inObject); + void BecomeImmutable(PyrObject *inObject); + +private: + void Free(PyrObject* inObj); + void ScanSlots(PyrSlot *inSlots, long inNumToScan); + void SweepBigObjects(); + void DoPartialScan(int32 inObjSize); + bool ScanOneObj(); + void Flip(); + void ScanStack(); + void DLRemove(PyrObjectHdr *obj); + void DLInsertAfter(PyrObjectHdr *after, PyrObjectHdr *obj); + void DLInsertBefore(PyrObjectHdr *before, PyrObjectHdr *obj); + + void ClearMarks(); + void Finalize(PyrObject *obj); + + VMGlobals *mVMGlobals; + AllocPool *mPool; + AdvancingAllocPool mNewPool; + GCSet mSets[kNumGCSets]; + PyrProcess *mProcess; // the root is the pyrprocess which contains this struct + PyrObject *mStack; + PyrObject *mPartialScanObj; + PyrObjectHdr mGrey; + + GCSet *mPartialScanSet; + int32 mPartialScanSlot; + int32 mNumToScan; + int32 mNumGrey; + int32 mCurSet; + + int32 mFlips, mCollects, mAllocTotal, mScans, mNumAllocs; + + unsigned char mBlackColor, mGreyColor, mWhiteColor, mFreeColor; + int8 mProcessID; + bool mCanSweep; + bool mRunning; +}; + +inline void PyrGC::DLRemove(PyrObjectHdr *obj) +{ + obj->next->prev = obj->prev; + obj->prev->next = obj->next; +} + +inline void PyrGC::DLInsertAfter(PyrObjectHdr *after, PyrObjectHdr *obj) +{ + obj->next = after->next; + obj->prev = after; + after->next->prev = obj; + after->next = obj; +} + +inline void PyrGC::DLInsertBefore(PyrObjectHdr *before, PyrObjectHdr *obj) +{ + obj->prev = before->prev; + obj->next = before; + before->prev->next = obj; + before->prev = obj; +} + +inline GCSet* PyrGC::GetGCSet(PyrObjectHdr* inObj) +{ + return mSets + (inObj->classptr == class_finalizer ? kFinalizerSet : inObj->obj_sizeclass); +} + +inline void PyrGC::ToBlack(PyrObjectHdr *obj) +{ + if (IsGrey(obj)) { + mNumGrey--; + //post("ToBlack %d\n", mNumGrey); + } + + DLRemove(obj); + + GCSet *gcs = GetGCSet(obj); + DLInsertAfter(&gcs->mBlack, obj); + + obj->gc_color = mBlackColor; +} + +inline void PyrGC::ToWhite(PyrObjectHdr *obj) +{ + if (IsGrey(obj)) { + mNumGrey--; + //post("ToWhite %d\n", mNumGrey); + } + + DLRemove(obj); + + GCSet *gcs = GetGCSet(obj); + DLInsertAfter(&gcs->mWhite, obj); + + obj->gc_color = mWhiteColor; +} + +#endif -- cgit v1.2.1 From 6c03ffeef182c00462a6d0375ed81dc0d9983124 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Thu, 19 Jun 2008 13:50:58 +0000 Subject: removed the svn:executable bit for code, patches and text svn path=/trunk/externals/tb/; revision=10048 --- sc4pd/headers/lang/GC.h | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 sc4pd/headers/lang/GC.h (limited to 'sc4pd/headers/lang/GC.h') diff --git a/sc4pd/headers/lang/GC.h b/sc4pd/headers/lang/GC.h old mode 100755 new mode 100644 -- cgit v1.2.1