<> <> <> <> <> DIRECTORY BasicLoadState USING [], BasicLoadStateFormat USING [BcdInfo, ConfigIndex, Extension, ExtensionEntry, LoadStateObject, ModuleInfo, nullConfig, versionID], LoadState USING [Handle, Object], LoadStateFormat USING [CollisionTable, CollisionTableIndex, Config, ConfigID, ConfigObject, ConfigTable, CopyTable, Entry, Handle, HashIndex, htSize, ModuleEntry, nullCopyIndex, Object], PrincOps USING [GFT, GFTIndex, GFTItem, GlobalFrameHandle], WorldVM USING [Address, CopyRead, Long, LongRead, Read, WorldObject], WVMPrivate USING [WorldObject]; WVMLoadState: MONITOR IMPORTS WorldVM EXPORTS LoadState--opaque type--, WorldVM--opaque type--, WVMPrivate = { <> Address: TYPE = WorldVM.Address; BcdInfo: TYPE = BasicLoadStateFormat.BcdInfo; Config: TYPE = LoadStateFormat.Config; ConfigObject: TYPE = LoadStateFormat.ConfigObject; ConfigID: PUBLIC TYPE = LoadStateFormat.ConfigID; ConfigIndex: TYPE = BasicLoadStateFormat.ConfigIndex; nullConfig: ConfigIndex = BasicLoadStateFormat.nullConfig; ConfigTable: TYPE = LoadStateFormat.ConfigTable; CollisionTable: TYPE = LoadStateFormat.CollisionTable; CollisionTableIndex: TYPE = LoadStateFormat.CollisionTableIndex; CopyTable: TYPE = LoadStateFormat.CopyTable; Entry: TYPE = LoadStateFormat.Entry; Extension: TYPE = BasicLoadStateFormat.Extension; ExtensionEntry: TYPE = BasicLoadStateFormat.ExtensionEntry; ModuleInfo: TYPE = BasicLoadStateFormat.ModuleInfo; World: TYPE = REF WorldObject; GFTIndex: TYPE = PrincOps.GFTIndex; GFTItem: TYPE = PrincOps.GFTItem; GFTArray: TYPE = ARRAY GFTIndex OF GFTItem; WorldObject: PUBLIC TYPE = WVMPrivate.WorldObject; GetLoadState: PUBLIC PROC [world: World, basic, real: Address] = { basicWords: NAT = SIZE[BasicLoadStateFormat.LoadStateObject[0]]; realWords: NAT = SIZE[LoadStateFormat.Object] - LoadStateFormat.htSize*SIZE[LoadStateFormat.Entry]; cheat: ARRAY [0..MAX[basicWords, realWords]) OF CARDINAL; IF real = 0 THEN { <> basicPtr: POINTER TO BasicLoadStateFormat.LoadStateObject = LOOPHOLE[@cheat]; WorldVM.CopyRead[world: world, to: @cheat, from: basic, nwords: basicWords]; IF basicPtr.versionident # BasicLoadStateFormat.versionID THEN ERROR BadLoadState; CopyBasicLoadState[world, basic]; } ELSE { <> realPtr: POINTER TO LoadStateFormat.Object = LOOPHOLE[@cheat]; WorldVM.CopyRead[world: world, to: @cheat, from: basic, nwords: realWords]; CopyRealLoadState[world, real]; }; }; BadLoadState: ERROR = CODE; --LoadState.--Object: PUBLIC TYPE = LoadStateFormat.Object; CopyRealLoadState: PROC[world: World, real: Address] = { loadState: REF Object = NEW[Object]; loadState.useCount _ 0; loadState.changeCount _ LOOPHOLE[WorldVM.LongRead[ world: world, addr: real + (LOOPHOLE[@loadState.changeCount,Address]-LOOPHOLE[loadState,Address]) ]]; loadState.configTable _ CopyConfigTable[ world: world, from: WorldVM.LongRead[world, real + (LOOPHOLE[@loadState.configTable,Address]-LOOPHOLE[loadState,Address])] ]; loadState.copyTable _ CopyCopyTable[ world: world, from: WorldVM.LongRead[world, real + (LOOPHOLE[@loadState.copyTable,Address]-LOOPHOLE[loadState,Address])] ]; loadState.collisionTable _ CopyCollisionTable[ world: world, from: WorldVM.LongRead[world, real + (LOOPHOLE[@loadState.collisionTable,Address]-LOOPHOLE[loadState,Address])] ]; WorldVM.CopyRead[ world: world, from: real + (LOOPHOLE[@loadState.gfht,Address]-LOOPHOLE[loadState,Address]), to: @loadState.gfht, nwords: SIZE[ARRAY LoadStateFormat.HashIndex OF LoadStateFormat.Entry] ]; world.loadState _ loadState; }; CopyConfigTable: PROC [world: World, from: Address] RETURNS [to: REF ConfigTable] = { minSize: CARDINAL = SIZE[LoadStateFormat.ConfigTable[0]]; temp: ARRAY [0..minSize) OF WORD; cheat: POINTER TO LoadStateFormat.ConfigTable = LOOPHOLE[@temp]; WorldVM.CopyRead[ world: world, from: from, to: @temp, nwords: minSize]; to _ NEW[LoadStateFormat.ConfigTable[cheat.length]]; to.nConfigs _ cheat.nConfigs; FOR i: NAT IN [0..to.nConfigs) DO to[i] _ CopyConfig[ world: world, from: WorldVM.LongRead[world, from + (LOOPHOLE[@to[i],Address]-LOOPHOLE[to,Address])] ]; ENDLOOP; }; CopyCopyTable: PROC [world: World, from: Address] RETURNS [to: REF LoadStateFormat.CopyTable] = { minSize: CARDINAL = SIZE[LoadStateFormat.CopyTable[0]]; temp: ARRAY [0..minSize) OF WORD; cheat: POINTER TO LoadStateFormat.CopyTable = LOOPHOLE[@temp]; WorldVM.CopyRead[ world: world, from: from, to: @temp, nwords: minSize]; to _ NEW[LoadStateFormat.CopyTable[cheat.length]]; to.nCopies _ cheat.nCopies; FOR i: NAT IN [0..to.nCopies) DO to[i].parent _ LOOPHOLE[WorldVM.Read[world, from + (LOOPHOLE[@to[i].parent,Address]-LOOPHOLE[to,Address])]]; to[i].copies _ CopyCopiesList[ world: world, from: WorldVM.LongRead[world, from + (LOOPHOLE[@to[i].copies,Address]-LOOPHOLE[to,Address])] ]; ENDLOOP; }; CopyCollisionTable: PROC [world: World, from: Address] RETURNS [to: REF LoadStateFormat.CollisionTable] = { minSize: CARDINAL = SIZE[LoadStateFormat.CollisionTable[0]]; temp: ARRAY [0..minSize) OF WORD; cheat: POINTER TO LoadStateFormat.CollisionTable = LOOPHOLE[@temp]; WorldVM.CopyRead[ world: world, from: from, to: @temp, nwords: minSize]; to _ NEW[LoadStateFormat.CollisionTable[cheat.length]]; to.nCollisions _ cheat.nCollisions; FOR i: NAT IN [0..to.nCollisions) DO to[i] _ CopyCollisionList[ world: world, from: WorldVM.LongRead[ world, from + (LOOPHOLE[@to[i],Address]-LOOPHOLE[to,Address])] ]; ENDLOOP; }; CopyConfig: PROC [world: World, from: Address] RETURNS [to: REF LoadStateFormat.ConfigObject] = { minSize: CARDINAL = SIZE[LoadStateFormat.ConfigObject[0]]; temp: ARRAY [0..minSize) OF WORD; cheat: POINTER TO LoadStateFormat.ConfigObject = LOOPHOLE[@temp]; WorldVM.CopyRead[ world: world, from: from, to: @temp, nwords: minSize]; to _ NEW[LoadStateFormat.ConfigObject[cheat.length]]; to.bcd _ cheat.bcd; to.ref _ NIL; to.nModules _ cheat.nModules; IF to.nModules > 0 THEN WorldVM.CopyRead[ world: world, from: from + (LOOPHOLE[@to[0],Address]-LOOPHOLE[to,Address]), to: @to[0], nwords: to.nModules * SIZE[LoadStateFormat.ModuleEntry] ]; }; CopyCopiesList: PROC [world: World, from: Address] RETURNS [to: LIST OF PrincOps.GlobalFrameHandle _ NIL] = { fromPos: Address _ from; toPos: LIST OF PrincOps.GlobalFrameHandle _ NIL; dummy: LIST OF PrincOps.GlobalFrameHandle = CONS[first: NULL, rest: NIL]; firstOffset: CARDINAL = LOOPHOLE[@dummy.first,Address]-LOOPHOLE[dummy,Address]; restOffset: CARDINAL = LOOPHOLE[@dummy.rest,Address]-LOOPHOLE[dummy,Address]; UNTIL fromPos = 0--NIL-- DO this: PrincOps.GlobalFrameHandle = LOOPHOLE[WorldVM.Read[world, fromPos + firstOffset]]; new: LIST OF PrincOps.GlobalFrameHandle = CONS[first: this, rest: NIL]; IF to = NIL THEN to _ new ELSE toPos.rest _ new; toPos _ new; fromPos _ WorldVM.LongRead[world, fromPos + restOffset]; ENDLOOP; }; CopyCollisionList: PROC [world: World, from: Address] RETURNS [to: LIST OF LoadStateFormat.Entry _ NIL] = { fromPos: Address _ from; toPos: LIST OF LoadStateFormat.Entry _ NIL; dummy: LIST OF LoadStateFormat.Entry = CONS[first: NULL, rest: NIL]; firstOffset: CARDINAL = LOOPHOLE[@dummy.first,Address]-LOOPHOLE[dummy,Address]; restOffset: CARDINAL = LOOPHOLE[@dummy.rest,Address]-LOOPHOLE[dummy,Address]; UNTIL fromPos = 0--NIL-- DO this: LoadStateFormat.Entry; new: LIST OF LoadStateFormat.Entry; WorldVM.CopyRead[ world: world, from: fromPos + firstOffset, to: @this, nwords: SIZE[LoadStateFormat.Entry]]; new _ CONS[first: this, rest: NIL]; IF to = NIL THEN to _ new ELSE toPos.rest _ new; toPos _ new; fromPos _ WorldVM.LongRead[world, fromPos + restOffset]; ENDLOOP; }; CopyBasicLoadState: PROC [world: World, basic: Address] = { <> minSize: CARDINAL = SIZE[BasicLoadStateFormat.LoadStateObject[0]]; temp: ARRAY [0..minSize) OF WORD; cheat: POINTER TO BasicLoadStateFormat.LoadStateObject = LOOPHOLE[@temp]; nConfigs: CARDINAL _ 0; local: LoadStateFormat.Handle _ NIL; extension: REF Extension = NEW[Extension]; gft: REF GFTArray = NEW[GFTArray]; basicLoadState: REF BasicLoadStateFormat.LoadStateObject _ world.basicLoadState; <> WorldVM.CopyRead[world: world, to: @temp, from: basic, nwords: minSize]; IF basicLoadState = NIL OR cheat.length # basicLoadState.length THEN world.basicLoadState _ basicLoadState _ NEW[BasicLoadStateFormat.LoadStateObject[cheat.length]]; <> < >> < BcdInfo>> WorldVM.CopyRead[world: world, to: LOOPHOLE[basicLoadState, LONG POINTER], from: basic, nwords: SIZE[BasicLoadStateFormat.LoadStateObject[cheat.length]] ]; < >> WorldVM.CopyRead[world: world, to: LOOPHOLE[extension, LONG POINTER], from: basic+SIZE[BasicLoadStateFormat.LoadStateObject[cheat.length]], nwords: SIZE[Extension] ]; < >> WorldVM.CopyRead[world: world, to: LOOPHOLE[gft, LONG POINTER], from: WorldVM.Long[world, LOOPHOLE[PrincOps.GFT]], nwords: SIZE[GFTArray] ]; <> nConfigs _ basicLoadState.nBcds; world.loadState _ local _ NEW[LoadStateFormat.Object _ [ useCount: 0, configTable: NEW[ConfigTable[MIN[MAX[3*nConfigs/2, 2], ConfigID.LAST]]], copyTable: NEW[CopyTable[5]], collisionTable: NEW[CollisionTable[10]], gfht: ALL[[empty[]]] ]]; local.configTable.nConfigs _ local.collisionTable.nCollisions _ 0; local.copyTable.nCopies _ 1; -- because slot 0 isn't used <> FOR outerGfi: GFTIndex IN GFTIndex DO IF gft[outerGfi].data # 0 THEN { <> cfi: ConfigIndex = basicLoadState.gft[outerGfi].config; IF cfi # nullConfig AND local.configTable[cfi] = NIL THEN { <> c: Config _ NIL; bcdInfo: BcdInfo _ basicLoadState[cfi]; nMod: NAT _ 1; i: NAT _ 1; -- first index is not used (inscrutable, but true) FOR gfi: GFTIndex IN GFTIndex DO nmodinfo: ModuleInfo = basicLoadState.gft[gfi]; IF cfi = nmodinfo.config THEN nMod _ nMod + 1; ENDLOOP; <> c _ NEW[ConfigObject[nMod]]; <> local.configTable[cfi] _ c; IF cfi > local.configTable.nConfigs THEN local.configTable.nConfigs _ cfi; <> bcdInfo.exports _ bcdInfo.typeExported _ FALSE; <> c.bcd _ bcdInfo.bcd; c.ref _ NIL; c.nModules _ nMod; FOR gfi: GFTIndex IN GFTIndex DO <> modInfo: ModuleInfo = basicLoadState.gft[gfi]; IF cfi = modInfo.config THEN { ee: ExtensionEntry = extension[gfi]; item: GFTItem _ gft[gfi]; hi: CARDINAL = item.data MOD LoadStateFormat.htSize; entry: LoadStateFormat.Entry _ [original[ copyIndex: LoadStateFormat.nullCopyIndex, configID: cfi, module: modInfo.module]]; oldEntry: LoadStateFormat.Entry = local.gfht[hi]; item.epbias _ 0; -- to make the frame pointer OK c[i].mti _ ee.mti; c[i].gfh _ item.framePtr; c[i].type _ LOOPHOLE[ee.type]; -- is this really the same thing? i _ i + 1; <> WITH e: oldEntry SELECT FROM empty => local.gfht[hi] _ entry; collision => local.collisionTable.collisions[e.list] _ CONS[entry, local.collisionTable.collisions[e.list]]; ENDCASE => { ct: REF CollisionTable _ local.collisionTable; ci: CollisionTableIndex; FOR ci IN [0..ct.nCollisions) DO IF ct.collisions[ci] = NIL THEN EXIT; REPEAT FINISHED => { IF ct.nCollisions = ct.length THEN { newCT: REF CollisionTable = NEW[CollisionTable[3*ct.length/2]]; newCT.nCollisions _ ct.nCollisions; FOR ci: CollisionTableIndex IN [0..newCT.nCollisions) DO newCT.collisions[ci] _ ct.collisions[ci]; ENDLOOP; local.collisionTable _ ct _ newCT; }; ci _ ct.nCollisions; ct.nCollisions _ ct.nCollisions.SUCC; }; ENDLOOP; ct.collisions[ci] _ CONS[entry, CONS[local.gfht[hi], NIL]]; local.gfht[hi] _ [collision[list: ci]]; }; }; ENDLOOP; }; }; ENDLOOP; {exitCrock: BOOL _ TRUE; exitCrock _ FALSE; }; <<>> }; }.