/* * The contents of this file are subject to the Mozilla Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Initial Developer of this code is David Baum. * Portions created by David Baum are Copyright (C) 2000 David Baum. * All Rights Reserved. * * Portions created by John Hansen are Copyright (C) 2005 John Hansen. * All Rights Reserved. * */ /* * Allocation Strategy * * fMode Allocation * --------------------------- * kGlobalMode Low Global * * kTaskMode High Local * Low Global * * kSingleSubMode Low Local * Low Global * * kMultiSubMode Low Local * * * In general local variables are prefered to globals. The * only exception is for true global variables (kGlobalMode) * which are not allowed to use the local pool. * * In cases where a single task is known to be in execution * (kTaskMode or kSingleSubMode) allocation is allowed to * overflow from the local pool to the global pool. * * Vars allocated from the global pool may be re-used within the * same Begin()/End() session, but then become permanently * allocated after End(). In contrast, the local pool is refreshed * each time Begin() is called - in the case of tasks this is * justified by the fact that each task has its own local vars. * For subs, this is because the true variable allocation is * done within the calling task, and this is checked for conflicts * by CheckAvailable(). * * This strategy ensures that subs always use the bottom-most * local vars (overflow to globals in the case of a sub called * by only 1 task). Allocations for a task use up locals from * the high end, which means that the only time a call to a sub * will conflict with the presently allocated task vars is if * local space is exhausted. * */ #include "VarAllocator.h" #include "Variable.h" #ifdef DEBUG #include using std::printf; //#define DEBUG_VARS #endif VarAllocator::VarAllocator(int maxGlobals, int maxTaskVars) : fMode(kGlobalMode), fMaxVars(maxGlobals + maxTaskVars), fLocalStart(maxGlobals) { fStates = new VarState[fMaxVars]; for(int i=0; i= kUsed) return false; } } return true; } int VarAllocator::FindUnused(int start, int end, int count) { if (start < end) { // search [start, end) from bottom end -= count; for(int i=start; i<=end; ++i) if (CheckAvailable(i, count)) return i; } else { // search [end, start) from top for(int i=start-count; i>=end; --i) if (CheckAvailable(i, count)) return i; } return kIllegalVar; } bool VarAllocator::CheckAvailable(int first, int count) const { while(count--) { if (fStates[first++] >= kUsed) return false; } return true; }