bool MemMgr::GrowOrShrinkStack(StackSpace *space, POLYUNSIGNED newSize) { size_t iSpace = newSize*sizeof(PolyWord); PolyWord *newSpace = (PolyWord*)osMemoryManager->Allocate(iSpace, PERMISSION_READ|PERMISSION_WRITE); if (newSpace == 0) { if (debugOptions & DEBUG_MEMMGR) Log("MMGR: Unable to change size of stack %p from %lu to %lu: insufficient space\n", space, space->spaceSize(), newSize); return false; } // The size may have been rounded up to a block boundary. newSize = iSpace/sizeof(PolyWord); try { AddTree(space, newSpace, newSpace+newSize); } catch (std::bad_alloc a) { RemoveTree(space, newSpace, newSpace+newSize); delete space; return 0; } CopyStackFrame(space->stack(), space->spaceSize(), (StackObject*)newSpace, newSize); if (debugOptions & DEBUG_MEMMGR) Log("MMGR: Size of stack %p changed from %lu to %lu at %p\n", space, space->spaceSize(), newSize, newSpace); RemoveTree(space); // Remove it BEFORE freeing the space - another thread may allocate it osMemoryManager->Free(space->bottom, (char*)space->top - (char*)space->bottom); space->bottom = newSpace; space->top = newSpace+newSize; return true; }
// Delete a local space and remove it from the table. bool MemMgr::DeleteLocalSpace(LocalMemSpace *sp) { for (unsigned i = 0; i < nlSpaces; i++) { if (lSpaces[i] == sp) { if (debugOptions & DEBUG_MEMMGR) Log("MMGR: Deleted local %s space %p\n", sp->spaceTypeString(), sp); currentHeapSize -= sp->spaceSize(); globalStats.setSize(PSS_TOTAL_HEAP, currentHeapSize * sizeof(PolyWord)); if (sp->allocationSpace) currentAllocSpace -= sp->spaceSize(); RemoveTree(sp); delete sp; nlSpaces--; while (i < nlSpaces) { lSpaces[i] = lSpaces[i+1]; i++; } return true; } } ASSERT(false); // It should always be in the table. return false; }
StackSpace *MemMgr::NewStackSpace(POLYUNSIGNED size) { PLocker lock(&stackSpaceLock); try { StackSpace *space = new StackSpace; size_t iSpace = size*sizeof(PolyWord); space->bottom = (PolyWord*)osMemoryManager->Allocate(iSpace, PERMISSION_READ|PERMISSION_WRITE); if (space->bottom == 0) { if (debugOptions & DEBUG_MEMMGR) Log("MMGR: New stack space: insufficient space\n"); delete space; return 0; } // The size may have been rounded up to a block boundary. size = iSpace/sizeof(PolyWord); space->top = space->bottom + size; space->spaceType = ST_STACK; space->isMutable = true; // Extend the permanent memory table and add this space to it. StackSpace **table = (StackSpace **)realloc(sSpaces, (nsSpaces+1) * sizeof(StackSpace *)); if (table == 0) { if (debugOptions & DEBUG_MEMMGR) Log("MMGR: New stack space: table realloc failed\n"); delete space; return 0; } sSpaces = table; // Add the stack space to the tree. This ensures that operations such as // LocalSpaceForAddress will work for addresses within the stack. We can // get them in the RTS with functions such as quot_rem and exception stack. // It's not clear whether they really appear in the GC. try { AddTree(space); } catch (std::bad_alloc a) { RemoveTree(space); delete space; return 0; } sSpaces[nsSpaces++] = space; if (debugOptions & DEBUG_MEMMGR) Log("MMGR: New stack space %p allocated at %p size %lu\n", space, space->bottom, space->spaceSize()); return space; } catch (std::bad_alloc a) { if (debugOptions & DEBUG_MEMMGR) Log("MMGR: New stack space: \"new\" failed\n"); return 0; } }
void MemMgr::DeleteExportSpaces(void) { while (neSpaces > 0) { PermanentMemSpace *space = eSpaces[--neSpaces]; RemoveTree(space); delete(space); } }
// If we have saved the state rather than exported a function we turn the exported // spaces into permanent ones, removing existing permanent spaces at the same or // lower level. bool MemMgr::PromoteExportSpaces(unsigned hierarchy) { // Create a new table big enough to hold all the permanent and export spaces PermanentMemSpace **pTable = (PermanentMemSpace **)calloc(npSpaces+neSpaces, sizeof(PermanentMemSpace *)); if (pTable == 0) return false; unsigned newSpaces = 0; // Save permanent spaces at a lower hierarchy. Others are converted into // local spaces. Most or all items will have been copied from these spaces // into an export space but there could be items reachable only from the stack. for (unsigned i = 0; i < npSpaces; i++) { PermanentMemSpace *pSpace = pSpaces[i]; if (pSpace->hierarchy < hierarchy) pTable[newSpaces++] = pSpace; else { try { // Turn this into a local space. // Remove this from the tree - AddLocalSpace will make an entry for the local version. RemoveTree(pSpace); LocalMemSpace *space = new LocalMemSpace; space->top = space->fullGCLowerLimit = pSpace->top; space->bottom = space->upperAllocPtr = space->lowerAllocPtr = pSpace->bottom; space->isMutable = pSpace->isMutable; space->isOwnSpace = true; if (! space->bitmap.Create(space->top-space->bottom) || ! AddLocalSpace(space)) return false; currentHeapSize += space->spaceSize(); globalStats.setSize(PSS_TOTAL_HEAP, currentHeapSize * sizeof(PolyWord)); } catch (std::bad_alloc a) { return false; } } } // Save newly exported spaces. for (unsigned j = 0; j < neSpaces; j++) { PermanentMemSpace *space = eSpaces[j]; space->hierarchy = hierarchy; // Set the hierarchy of the new spaces. space->spaceType = ST_PERMANENT; // Put a dummy object to fill up the unused space. if (space->topPointer != space->top) FillUnusedSpace(space->topPointer, space->top - space->topPointer); // Put in a dummy object to fill the rest of the space. pTable[newSpaces++] = space; } neSpaces = 0; npSpaces = newSpaces; free(pSpaces); pSpaces = pTable; return true; }
// Before we import a hierarchical saved state we need to turn any previously imported // spaces into local spaces. bool MemMgr::DemoteImportSpaces() { // Create a new permanent space table. PermanentMemSpace **table = (PermanentMemSpace **)calloc(npSpaces, sizeof(PermanentMemSpace *)); if (table == NULL) return false; unsigned newSpaces = 0; for (unsigned i = 0; i < npSpaces; i++) { PermanentMemSpace *pSpace = pSpaces[i]; if (pSpace->hierarchy == 0) // Leave truly permanent spaces table[newSpaces++] = pSpace; else { try { // Turn this into a local space. // Remove this from the tree - AddLocalSpace will make an entry for the local version. RemoveTree(pSpace); LocalMemSpace *space = new LocalMemSpace; space->top = pSpace->top; // Space is allocated in local areas from the top down. This area is full and // all data is in the old generation. The area can be recovered by a full GC. space->bottom = space->upperAllocPtr = space->lowerAllocPtr = space->fullGCLowerLimit = pSpace->bottom; space->isMutable = pSpace->isMutable; space->isOwnSpace = true; if (! space->bitmap.Create(space->top-space->bottom) || ! AddLocalSpace(space)) { if (debugOptions & DEBUG_MEMMGR) Log("MMGR: Unable to convert saved state space %p into local space\n", pSpace); return false; } if (debugOptions & DEBUG_MEMMGR) Log("MMGR: Converted saved state space %p into local %smutable space %p\n", pSpace, pSpace->isMutable ? "im": "", space); currentHeapSize += space->spaceSize(); globalStats.setSize(PSS_TOTAL_HEAP, currentHeapSize * sizeof(PolyWord)); } catch (std::bad_alloc a) { if (debugOptions & DEBUG_MEMMGR) Log("MMGR: Unable to convert saved state space %p into local space (\"new\" failed)\n", pSpace); return false; } } } npSpaces = newSpaces; free(pSpaces); pSpaces = table; return true; }
// Create and initialise a new export space and add it to the table. PermanentMemSpace* MemMgr::NewExportSpace(POLYUNSIGNED size, bool mut, bool noOv) { try { PermanentMemSpace *space = new PermanentMemSpace; space->spaceType = ST_EXPORT; space->isMutable = mut; space->noOverwrite = noOv; space->index = nextIndex++; // Allocate the memory itself. size_t iSpace = size*sizeof(PolyWord); space->bottom = (PolyWord*)osMemoryManager->Allocate(iSpace, PERMISSION_READ|PERMISSION_WRITE|PERMISSION_EXEC); if (space->bottom == 0) { delete space; return 0; } space->isOwnSpace = true; // The size may have been rounded up to a block boundary. size = iSpace/sizeof(PolyWord); space->top = space->bottom + size; space->topPointer = space->bottom; // Add to the table. PermanentMemSpace **table = (PermanentMemSpace **)realloc(eSpaces, (neSpaces+1) * sizeof(PermanentMemSpace *)); if (table == 0) { delete space; return 0; } eSpaces = table; try { AddTree(space); } catch (std::bad_alloc a) { RemoveTree(space); delete space; return 0; } eSpaces[neSpaces++] = space; return space; } catch (std::bad_alloc a) { return 0; } }
// Create an entry for a permanent space. PermanentMemSpace* MemMgr::NewPermanentSpace(PolyWord *base, POLYUNSIGNED words, unsigned flags, unsigned index, unsigned hierarchy /*= 0*/) { try { PermanentMemSpace *space = new PermanentMemSpace; space->bottom = base; space->topPointer = space->top = space->bottom + words; space->spaceType = ST_PERMANENT; space->isMutable = flags & MTF_WRITEABLE ? true : false; space->noOverwrite = flags & MTF_NO_OVERWRITE ? true : false; space->byteOnly = flags & MTF_BYTES ? true : false; space->index = index; space->hierarchy = hierarchy; if (index >= nextIndex) nextIndex = index+1; // Extend the permanent memory table and add this space to it. PermanentMemSpace **table = (PermanentMemSpace **)realloc(pSpaces, (npSpaces+1) * sizeof(PermanentMemSpace *)); if (table == 0) { delete space; return 0; } pSpaces = table; try { AddTree(space); } catch (std::bad_alloc a) { RemoveTree(space); delete space; return 0; } pSpaces[npSpaces++] = space; return space; } catch (std::bad_alloc a) { return 0; } }
// Add a local memory space to the table. bool MemMgr::AddLocalSpace(LocalMemSpace *space) { // Add to the table. LocalMemSpace **table = (LocalMemSpace **)realloc(lSpaces, (nlSpaces+1) * sizeof(LocalMemSpace *)); if (table == 0) return false; lSpaces = table; // Update the B-tree. try { AddTree(space); } catch (std::bad_alloc a) { RemoveTree(space); return false; } // The entries in the local table are ordered so that the copy phase of the full // GC simply has to copy to an entry earlier in the table. Immutable spaces come // first, followed by mutable spaces and finally allocation spaces. if (space->allocationSpace) lSpaces[nlSpaces++] = space; // Just add at the end else if (space->isMutable) { // Add before the allocation spaces unsigned s; for (s = nlSpaces; s > 0 && lSpaces[s-1]->allocationSpace; s--) lSpaces[s] = lSpaces[s-1]; lSpaces[s] = space; nlSpaces++; } else { // Immutable space: Add before the mutable spaces unsigned s; for (s = nlSpaces; s > 0 && lSpaces[s-1]->isMutable; s--) lSpaces[s] = lSpaces[s-1]; lSpaces[s] = space; nlSpaces++; } return true; }
// // This file contains the C++ code from Program 11.20 of // "Data Structures and Algorithms // with Object-Oriented Design Patterns in C++" // by Bruno R. Preiss. // // Copyright (c) 1998 by Bruno R. Preiss, P.Eng. All rights reserved. // // http://www.pads.uwaterloo.ca/Bruno.Preiss/books/opus4/programs/pgm11_20.cpp // Object& BinomialQueue::DequeueMin () { if (count == 0) throw domain_error ("priority queue is empty"); BinomialTree& minTree = FindMinTree (); RemoveTree (minTree); BinomialQueue queue; while (minTree.Degree () > 0) { BinomialTree& child = minTree.Subtree (0); minTree.DetachSubtree (child); queue.AddTree (child); } Merge (queue); Object& result = minTree.Key (); minTree.RescindOwnership (); delete &minTree; return result; }
// Delete a stack when a thread has finished. // This can be called by an ML thread so needs an interlock. bool MemMgr::DeleteStackSpace(StackSpace *space) { PLocker lock(&stackSpaceLock); for (unsigned i = 0; i < nsSpaces; i++) { if (sSpaces[i] == space) { RemoveTree(space); delete space; nsSpaces--; while (i < nsSpaces) { sSpaces[i] = sSpaces[i+1]; i++; } if (debugOptions & DEBUG_MEMMGR) Log("MMGR: Deleted stack space %p\n", space); return true; } } ASSERT(false); // It should always be in the table. return false; }
void TreeViewWidget::keyPressEvent(QKeyEvent *e) { ActionNode x; switch (e->key()) { case Qt::Key_Left: if (!onmove && (mode == Mode::MOVE || mode == Mode::ROTATE || mode == Mode::ZOOM)) { x.operation = ActionNode::ALTER; for (int i = 0; i < selectedList.size(); i++) { QString path = DBManager::Instance()->FindPathByTreeName(selectedList[i]->GetModelName()); TreeInfo info(selectedList[i]->GetModelName(), path); x.changedTrees.push_back(TreeNode(selectedList[i]->GetName(), info, selectedList[i]->GetPosition(), selectedList[i]->GetEulerAngles(), selectedList[i]->GetScale())); } thestack.PushToUndo(x); emit Pushed(); onmove = true; } if (mode == Mode::MOVE) { for (int i = 0; i < selectedList.size(); i++) selectedList[i]->Translate(QVector3D(-0.5, 0.0, 0.0)); } else if (mode == Mode::ROTATE) { for (int i = 0; i < selectedList.size(); i++) selectedList[i]->Rotate(-15, QVector3D(0.0, 1.0, 0.0)); } else if (mode == Mode::ZOOM) { for (int i = 0; i < selectedList.size(); i++) selectedList[i]->Scale(QVector2D(0.9, 1.0)); } break; case Qt::Key_Right: if (!onmove && (mode == Mode::MOVE || mode == Mode::ROTATE || mode == Mode::ZOOM)) { x.operation = ActionNode::ALTER; for (int i = 0; i < selectedList.size(); i++) { QString path = DBManager::Instance()->FindPathByTreeName(selectedList[i]->GetModelName()); TreeInfo info(selectedList[i]->GetModelName(), path); x.changedTrees.push_back(TreeNode(selectedList[i]->GetName(), info, selectedList[i]->GetPosition(), selectedList[i]->GetEulerAngles(), selectedList[i]->GetScale())); } thestack.PushToUndo(x); emit Pushed(); onmove = true; } if (mode == Mode::MOVE) { for (int i = 0; i < selectedList.size(); i++) selectedList[i]->Translate(QVector3D(0.5, 0.0, 0.0)); } else if (mode == Mode::ROTATE) { for (int i = 0; i < selectedList.size(); i++) selectedList[i]->Rotate(15, QVector3D(0.0, 1.0, 0.0)); } else if (mode == Mode::ZOOM) { for (int i = 0; i < selectedList.size(); i++) selectedList[i]->Scale(QVector2D(1.1, 1.0)); } break; case Qt::Key_Up: if (!onmove && (mode == Mode::MOVE || mode == Mode::ROTATE || mode == Mode::ZOOM)) { x.operation = ActionNode::ALTER; for (int i = 0; i < selectedList.size(); i++) { QString path = DBManager::Instance()->FindPathByTreeName(selectedList[i]->GetModelName()); TreeInfo info(selectedList[i]->GetModelName(), path); x.changedTrees.push_back(TreeNode(selectedList[i]->GetName(), info, selectedList[i]->GetPosition(), selectedList[i]->GetEulerAngles(), selectedList[i]->GetScale())); } thestack.PushToUndo(x); emit Pushed(); onmove = true; } if (mode == Mode::MOVE) { for (int i = 0; i < selectedList.size(); i++) selectedList[i]->Translate(QVector3D(0.0, 0.5, 0.0)); } else if (mode == Mode::ROTATE) { for (int i = 0; i < selectedList.size(); i++) selectedList[i]->Rotate(-15, QVector3D(1.0, 0.0, 0.0)); } else if (mode == Mode::ZOOM) { for (int i = 0; i < selectedList.size(); i++) selectedList[i]->Scale(QVector2D(1.0, 0.9)); } break; case Qt::Key_Down: if (!onmove && (mode == Mode::MOVE || mode == Mode::ROTATE || mode == Mode::ZOOM)) { x.operation = ActionNode::ALTER; for (int i = 0; i < selectedList.size(); i++) { QString path = DBManager::Instance()->FindPathByTreeName(selectedList[i]->GetModelName()); TreeInfo info(selectedList[i]->GetModelName(), path); x.changedTrees.push_back(TreeNode(selectedList[i]->GetName(), info, selectedList[i]->GetPosition(), selectedList[i]->GetEulerAngles(), selectedList[i]->GetScale())); } thestack.PushToUndo(x); emit Pushed(); onmove = true; } if (mode == Mode::MOVE) { for (int i = 0; i < selectedList.size(); i++) selectedList[i]->Translate(QVector3D(0.0, -0.5, 0.0)); } else if (mode == Mode::ROTATE) { for (int i = 0; i < selectedList.size(); i++) selectedList[i]->Rotate(15, QVector3D(1.0, 0.0, 0.0)); } else if (mode == Mode::ZOOM) { for (int i = 0; i < selectedList.size(); i++) selectedList[i]->Scale(QVector2D(1.0, 1.1)); } break; case Qt::Key_Comma: if (!onmove && (mode == Mode::MOVE || mode == Mode::ROTATE || mode == Mode::ZOOM)) { x.operation = ActionNode::ALTER; for (int i = 0; i < selectedList.size(); i++) { QString path = DBManager::Instance()->FindPathByTreeName(selectedList[i]->GetModelName()); TreeInfo info(selectedList[i]->GetModelName(), path); x.changedTrees.push_back(TreeNode(selectedList[i]->GetName(), info, selectedList[i]->GetPosition(), selectedList[i]->GetEulerAngles(), selectedList[i]->GetScale())); } thestack.PushToUndo(x); emit Pushed(); onmove = true; } for (int i = 0; i < selectedList.size(); i++) selectedList[i]->Translate(QVector3D(0.0, 0.0, -0.5)); break; case Qt::Key_Period: if (!onmove && (mode == Mode::MOVE || mode == Mode::ROTATE || mode == Mode::ZOOM)) { x.operation = ActionNode::ALTER; for (int i = 0; i < selectedList.size(); i++) { QString path = DBManager::Instance()->FindPathByTreeName(selectedList[i]->GetModelName()); TreeInfo info(selectedList[i]->GetModelName(), path); x.changedTrees.push_back(TreeNode(selectedList[i]->GetName(), info, selectedList[i]->GetPosition(), selectedList[i]->GetEulerAngles(), selectedList[i]->GetScale())); } thestack.PushToUndo(x); emit Pushed(); onmove = true; } for (int i = 0; i < selectedList.size(); i++) selectedList[i]->Translate(QVector3D(0.0, 0.0, 0.5)); break; case Qt::Key_G: LoadBGImage("bg2.jpg"); break; case Qt::Key_Control: groupSelecting = true; break; case Qt::Key_Shift: shiftdown = true; break; case Qt::Key_Delete: x.operation = ActionNode::REMOVE; for(int i=0;i<selectedList.size();i++) { QString path = DBManager::Instance()->FindPathByTreeName(selectedList[i]->GetModelName()); TreeInfo info(selectedList[i]->GetModelName(), path); x.changedTrees.push_back(TreeNode(selectedList[i]->GetName(), info, selectedList[i]->GetPosition(), selectedList[i]->GetEulerAngles(), selectedList[i]->GetScale())); RemoveTree(selectedList[i]->Name()); } thestack.PushToUndo(x); emit Pushed(); selectedList.clear(); break; case Qt::Key_X: /*debug*/ ClearAllTrees(); /*debug*/ break; } update(); }