void Package::SetName(String* n) { this->name = n; this->dotName = name; WriteBarrier(this->name); if (superPackage) { String* supername = superPackage->dotName; String* superdot = String::Concat(supername, engine->AllocString(".")); this->dotName = String::Concat(superdot, this->name); WriteBarrier(this->dotName); } }
void AddSoftRoot(DObject *obj) { DObject **probe; // Are there any soft roots yet? if (SoftRoots == NULL) { // Create a new object to root the soft roots off of, and stick // it at the end of the object list, so we know that anything // before it is not a soft root. SoftRoots = new DObject; SoftRoots->ObjectFlags |= OF_Fixed; probe = &Root; while (*probe != NULL) { probe = &(*probe)->ObjNext; } Root = SoftRoots->ObjNext; SoftRoots->ObjNext = NULL; *probe = SoftRoots; } // Mark this object as rooted and move it after the SoftRoots marker. probe = &Root; while (*probe != NULL && *probe != obj) { probe = &(*probe)->ObjNext; } *probe = (*probe)->ObjNext; obj->ObjNext = SoftRoots->ObjNext; SoftRoots->ObjNext = obj; obj->ObjectFlags |= OF_Rooted; WriteBarrier(obj); }
void Package::SetSuper(Package* super) { if (super) WriteBarrier(super); superPackage = super; SetName(name); }
bool Package::SetGlobal(const Value& key, Value& val, u4 attr) { if (!CanSetGlobal(key)) { if (!(attr & Slot::ATTR_forcewrite)) { return false; } else { attr &= ~Slot::ATTR_forcewrite; } } if (key.IsCollectible()) WriteBarrier(key); if (val.IsCollectible()) WriteBarrier(val); if (!Members().Set(key, val, attr)) { return false; } return true; }
void Package::Init(Context* ctx) { u2 argc = ctx->GetArgCount(); if (argc == 1) { String* nstr = ctx->GetStringArg(0); SetName(nstr); } else if (argc >= 2) { String* nstr = ctx->GetStringArg(0); Object* super = ctx->IsArgNull(1) ? engine->GetWorld() : ctx->GetObjectArg(1); if (!super->IsDerivedFrom(Package::StaticGetClass())) { RaiseException(Exception::ERROR_type, "Attempt to initialize package: super must be a package"); } superPackage = (Package*)super; WriteBarrier(superPackage); this->SetName(nstr); } }
void Proxy::Init(Context* ctx) { u4 argc = ctx->GetArgCount(); if (argc == 1) { this->property = ctx->GetPropertyArg(0); name.Set(this->property->Name()); WriteBarrier(property); WriteBarrier(name); Function* f = property->Writer() ? property->Writer() : property->Reader(); if (f) { object.Set(f->GetLocation()); WriteBarrier(object); } } else if (argc == 2) { object = ctx->GetArg(0); name = ctx->GetArg(1); WriteBarrier(object); WriteBarrier(name); if (object.tag >= TAG_basic) { Basic* basic = object.val.basic; Value res; if (!basic->GetSlot(name, res)) { } if (res.tag == TAG_property) { this->property = res.val.property; WriteBarrier(property); } else { RaiseException("Attempt to get property %s from object of type %s.", engine->SafeToString(ctx, name), engine->GetTypenameOf(object)); } } } else { ctx->CheckArgCount(2); } }
int __cdecl main(int argc, char* argv[]) { // // Initialize system info // if (!GCToOSInterface::Initialize()) { return -1; } // // Initialize free object methodtable. The GC uses a special array-like methodtable as placeholder // for collected free space. // static MethodTable freeObjectMT; freeObjectMT.InitializeFreeObject(); g_pFreeObjectMethodTable = &freeObjectMT; // // Initialize GC heap // GcDacVars dacVars; IGCHeap *pGCHeap; IGCHandleManager *pGCHandleManager; if (!InitializeGarbageCollector(nullptr, &pGCHeap, &pGCHandleManager, &dacVars)) { return -1; } if (FAILED(pGCHeap->Initialize())) return -1; // // Initialize handle manager // if (!pGCHandleManager->Initialize()) return -1; // // Initialize current thread // ThreadStore::AttachCurrentThread(); // // Create a Methodtable with GCDesc // class My : Object { public: Object * m_pOther1; int dummy_inbetween; Object * m_pOther2; }; static struct My_MethodTable { // GCDesc CGCDescSeries m_series[2]; size_t m_numSeries; // The actual methodtable MethodTable m_MT; } My_MethodTable; // 'My' contains the MethodTable* uint32_t baseSize = sizeof(My); // GC expects the size of ObjHeader (extra void*) to be included in the size. baseSize = baseSize + sizeof(ObjHeader); // Add padding as necessary. GC requires the object size to be at least MIN_OBJECT_SIZE. My_MethodTable.m_MT.m_baseSize = max(baseSize, MIN_OBJECT_SIZE); My_MethodTable.m_MT.m_componentSize = 0; // Array component size My_MethodTable.m_MT.m_flags = MTFlag_ContainsPointers; My_MethodTable.m_numSeries = 2; // The GC walks the series backwards. It expects the offsets to be sorted in descending order. My_MethodTable.m_series[0].SetSeriesOffset(offsetof(My, m_pOther2)); My_MethodTable.m_series[0].SetSeriesCount(1); My_MethodTable.m_series[0].seriessize -= My_MethodTable.m_MT.m_baseSize; My_MethodTable.m_series[1].SetSeriesOffset(offsetof(My, m_pOther1)); My_MethodTable.m_series[1].SetSeriesCount(1); My_MethodTable.m_series[1].seriessize -= My_MethodTable.m_MT.m_baseSize; MethodTable * pMyMethodTable = &My_MethodTable.m_MT; // Allocate instance of MyObject Object * pObj = AllocateObject(pMyMethodTable); if (pObj == NULL) return -1; // Create strong handle and store the object into it OBJECTHANDLE oh = HndCreateHandle(g_HandleTableMap.pBuckets[0]->pTable[GetCurrentThreadHomeHeapNumber()], HNDTYPE_DEFAULT, pObj); if (oh == NULL) return -1; for (int i = 0; i < 1000000; i++) { Object * pBefore = ((My *)HndFetchHandle(oh))->m_pOther1; // Allocate more instances of the same object Object * p = AllocateObject(pMyMethodTable); if (p == NULL) return -1; Object * pAfter = ((My *)HndFetchHandle(oh))->m_pOther1; // Uncomment this assert to see how GC triggered inside AllocateObject moved objects around // assert(pBefore == pAfter); // Store the newly allocated object into a field using WriteBarrier WriteBarrier(&(((My *)HndFetchHandle(oh))->m_pOther1), p); } // Create weak handle that points to our object OBJECTHANDLE ohWeak = HndCreateHandle(g_HandleTableMap.pBuckets[0]->pTable[GetCurrentThreadHomeHeapNumber()], HNDTYPE_WEAK_DEFAULT, HndFetchHandle(oh)); if (ohWeak == NULL) return -1; // Destroy the strong handle so that nothing will be keeping out object alive HndDestroyHandle(HndGetHandleTable(oh), HNDTYPE_DEFAULT, oh); // Explicitly trigger full GC pGCHeap->GarbageCollect(); // Verify that the weak handle got cleared by the GC assert(HndFetchHandle(ohWeak) == NULL); printf("Done\n"); return 0; }
int __cdecl main(int argc, char* argv[]) { // // Initialize system info // if (!GCToOSInterface::Initialize()) { return -1; } // // Initialize free object methodtable. The GC uses a special array-like methodtable as placeholder // for collected free space. // static MethodTable freeObjectMT; freeObjectMT.InitializeFreeObject(); g_pFreeObjectMethodTable = &freeObjectMT; // // Initialize handle table // if (!Ref_Initialize()) return -1; // // Initialize GC heap // GCHeap *pGCHeap = GCHeap::CreateGCHeap(); if (!pGCHeap) return -1; if (FAILED(pGCHeap->Initialize())) return -1; // // Initialize current thread // ThreadStore::AttachCurrentThread(); // // Create a Methodtable with GCDesc // class My : Object { public: Object * m_pOther1; int dummy_inbetween; Object * m_pOther2; }; static struct My_MethodTable { // GCDesc CGCDescSeries m_series[2]; size_t m_numSeries; // The actual methodtable MethodTable m_MT; } My_MethodTable; // 'My' contains the MethodTable* uint32_t baseSize = sizeof(My); // GC expects the size of ObjHeader (extra void*) to be included in the size. baseSize = baseSize + sizeof(ObjHeader); // Add padding as necessary. GC requires the object size to be at least MIN_OBJECT_SIZE. My_MethodTable.m_MT.m_baseSize = max(baseSize, MIN_OBJECT_SIZE); My_MethodTable.m_MT.m_componentSize = 0; // Array component size My_MethodTable.m_MT.m_flags = MTFlag_ContainsPointers; My_MethodTable.m_numSeries = 2; // The GC walks the series backwards. It expects the offsets to be sorted in descending order. My_MethodTable.m_series[0].SetSeriesOffset(offsetof(My, m_pOther2)); My_MethodTable.m_series[0].SetSeriesCount(1); My_MethodTable.m_series[0].seriessize -= My_MethodTable.m_MT.m_baseSize; My_MethodTable.m_series[1].SetSeriesOffset(offsetof(My, m_pOther1)); My_MethodTable.m_series[1].SetSeriesCount(1); My_MethodTable.m_series[1].seriessize -= My_MethodTable.m_MT.m_baseSize; MethodTable * pMyMethodTable = &My_MethodTable.m_MT; // Allocate instance of MyObject Object * pObj = AllocateObject(pMyMethodTable); if (pObj == NULL) return -1; // Create strong handle and store the object into it OBJECTHANDLE oh = CreateGlobalHandle(pObj); if (oh == NULL) return -1; for (int i = 0; i < 1000000; i++) { Object * pBefore = ((My *)ObjectFromHandle(oh))->m_pOther1; // Allocate more instances of the same object Object * p = AllocateObject(pMyMethodTable); if (p == NULL) return -1; Object * pAfter = ((My *)ObjectFromHandle(oh))->m_pOther1; // Uncomment this assert to see how GC triggered inside AllocateObject moved objects around // assert(pBefore == pAfter); if (pBefore != pAfter) { printf("%8i) pBefore = 0x%08x, pAfter = 0x%08x, diff = 0x%08x (%i)\n", i, pBefore, pAfter, pBefore - pAfter, pBefore - pAfter); PrintGCStats(pGCHeap); } // Store the newly allocated object into a field using WriteBarrier WriteBarrier(&(((My *)ObjectFromHandle(oh))->m_pOther1), p); } // Create weak handle that points to our object OBJECTHANDLE ohWeak = CreateGlobalWeakHandle(ObjectFromHandle(oh)); if (ohWeak == NULL) return -1; // Destroy the strong handle so that nothing will be keeping out object alive DestroyGlobalHandle(oh); // Verify that the weak handle has not yet been cleared (i.e. before the GC has run) assert(ObjectFromHandle(ohWeak) != NULL); printf("\nBEFORE Final Call to pGCHeap->GarbageCollect()"); PrintGCStats(pGCHeap); // Explicitly trigger full GC pGCHeap->GarbageCollect(); printf("\nAFTER Final Call to pGCHeap->GarbageCollect()"); PrintGCStats(pGCHeap); // Verify that the weak handle got cleared by the GC assert(ObjectFromHandle(ohWeak) == NULL); printf("Done\n"); return 0; }