DIRECTORY BasicLoadState, BasicLoadStateFormat, BasicLoadStateFormatExtension, PrincOps, LoadState, LoadStateFormat, WorldVM, 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 = BasicLoadStateFormatExtension.Extension; ExtensionEntry: TYPE = BasicLoadStateFormatExtension.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]]; 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[Extension] ]; 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; }; }; }. šWVMLoadState.mesa Cedar Remote Debugging: cache of client pages Andrew Birrell December 2, 1983 3:08 pm Russ Atkinson, May 15, 1984 5:07:14 pm PDT Types and things The world we are examining has no "real" load state, so check its version, then copy the basic load state. The world we are exmining claims to have a "real" load state. RRA: This routine was written nearly from scratch to transform a basic load state into a real live Cedar load state. It is used whenever there is a basic load state and no real Cedar load state, which is true during the initialization of the world. Once things start to get loaded from Basic.Loadees, the load state is just fine. Copy the first part of the basic load state to determine the real length Copy the basic load state, which maps gft: gfi -> bcds: ConfigIndex -> BcdInfo Copy the load state extension, which maps gfi -> Copy the GFT, which maps gfi -> Allocate the load state Now initialize the load state, using the GFT and the extension We MAY have a new config! We have a new config, sports fans! Allocate the new config object Place the config info into the config table Initialize the new config info Ensure no garbage in the bcd. Unfortunately, I don't know where this info gets used in the new load state (if at all)! Fill in the entries for multi-gfi modules Now place the new gfh info into the hash table as well ʘšœ™Jšœ-™-Jšœ(™(J™*—J˜šÏk ˜ Jšœ˜Jšœ˜Jšœ˜Jšœ ˜ Jšœ ˜ Jšœ˜Jšœ˜Jšœ œ˜!—J˜šœ˜Jšœ˜Jšœ Ïcœ žœ˜H—J˜šœ™Jšœ œ˜ Jšœ œ ˜-šœœ˜&Jšœœ ˜2—Jšœ œ˜1šœ œ$˜5Jšœ:˜:—Jšœ œ˜0Jšœœ"˜6Jšœœ'˜@Jšœ œ˜,Jšœœ˜$Jšœ œ+˜:Jšœœ0˜DJšœ œ#˜3Jšœœœ ˜J˜Jšœ œ˜#Jšœ œ˜!Jšœ œœ œ ˜+J˜Jšœ œœ˜2J˜—šÏn œœœ)˜BJšœ œœ*˜@šœ œ˜Jšœ2œ˜R—Jš œœœœœ˜9šœ ˜ šœ˜Jšœj™jJšœ œœ(œ ˜MJšœL˜LJšœ8œœ˜RJšœ!˜!J˜—šœ˜Jšœ=™=Jšœ œœœ ˜>JšœK˜KJšœ˜Jšœ˜——Jšœ˜J˜—Jšœœœ˜J˜Jšžœœœ˜;J˜šŸœœ!˜8Jšœ œ œ ˜$Jšœ˜šœœ˜2J˜ Jšœœ!œ˜SJ˜—šœ(˜(J˜ šœ˜Jšœ œ!œ˜O—J˜—šœ$˜$J˜ šœ˜Jšœ œœ˜M—J˜—šœ.˜.J˜ šœ˜Jšœ œ$œ˜R—J˜—˜J˜ Jšœœœ˜MJšœ˜Jšœœœœ˜FJ˜—J˜Jšœ˜—J˜šŸœœœœ˜UJšœ œœ!˜9Jšœœœœ˜!Jšœœœœ˜@˜J˜ Jšœ ˜ Jšœ ˜ Jšœ˜—Jšœœ,˜4Jšœ˜Jšœœœ˜šœ˜J˜ šœ˜Jšœ œœ˜8—J˜—Jšœ˜Jšœ˜—J˜šŸ œ˜Jšœœœ˜MJšœ œœ˜7Jšœœœœ˜!Jšœœœœ˜>˜J˜ Jšœ ˜ Jšœ ˜ Jšœ˜—Jšœœ*˜2Jšœ˜šœœœ˜ šœœ˜+Jšœ œœ˜A—šœ˜J˜ šœ˜Jšœ œœ˜?—J˜—Jšœ˜—Jšœ˜—J˜šŸœ˜Jšœœœ$˜RJšœ œœ$˜——J˜—Jšœ˜Jšœ˜—J˜šŸ œ˜Jšœœœ"˜PJšœ œœ"˜:Jšœœœœ˜!Jšœœœ œ˜A˜J˜ Jšœ ˜ Jšœ ˜ Jšœ˜—Jšœœ-˜5Jšœ˜Jšœ œ˜ Jšœ˜šœ˜˜J˜ Jšœœœ˜=Jšœ ˜ Jšœœ˜7Jšœ˜——Jšœ˜—J˜šŸœ˜Jš œœœœœ˜XJšœ˜Jšœœœœ˜0Jš œœœœœœ˜Išœ œ˜Jšœœ˜7—šœ œ˜Jšœœ˜6—šœ ž˜Jšœ#œ-˜XJš œœœœœ˜GJšœœœ œ˜0Jšœ ˜ Jšœ8˜8—Jšœ˜Jšœ˜—J˜šŸœ˜Jš œœœœœ˜SJšœ˜Jšœœœœ˜+Jš œœœœœœ˜Dšœ œ˜Jšœœ˜7—šœ œ˜Jšœœ˜6—šœ ž˜Jšœ˜Jšœœœ˜#˜J˜ Jšœ˜J˜ Jšœœ˜%—Jšœœœ˜#Jšœœœ œ˜0Jšœ ˜ Jšœ8˜8—Jšœ˜Jšœ˜—J˜šŸœœ"˜;JšœË™ËJšœ œœ*˜BJšœœœœ˜!Jšœœœ(œ˜IJšœ œ˜Jšœ œ˜$Jšœ œ œ ˜*Jšœœ œ ˜"Jšœœ=˜PJ˜JšœH™H˜Jšœ ˜ J˜ Jšœ˜—šœœœ&˜Dšœ'˜'Jšœ5˜8——J˜šœ%™%Jšœ*™*Jšœ™—˜Jšœœœœ˜+J˜ Jšœœ4˜@Jšœ˜J˜—Jšœ=™=˜Jšœœ œœ˜&Jšœ œ5˜EJšœœ ˜Jšœ˜J˜—J™*˜Jšœœœœ˜ Jšœœ œ˜2Jšœœ ˜Jšœ˜—J˜Jšœ™Jšœ ˜ šœœ˜8Jšœ ˜ Jš œ œ œœœ˜HJšœ œ˜Jšœœ˜(Jšœœ ˜Jšœ˜J˜—JšœB˜BJšœž˜:J˜Jšœ>™>šœœ ˜%šœœ˜ Jšœœ™Jšœ7˜7J˜šœœœœ˜;Jšœ"™"Jšœ œ˜Jšœ'˜'Jšœœ˜Jšœœž2˜?šœœ ˜ Jšœ/˜/Jšœœ˜.Jšœ˜—J˜Jšœ™Jšœœ˜J˜Jšœ+™+Jšœ˜Jšœ"œ"˜JJ˜Jšœ™šœ)œ˜/Jšœw™w—Jšœ˜Jšœœ˜ Jšœ˜šœœ ˜ Jšœ)™)Jšœ.˜.šœœ˜Jšœ$˜$Jšœ˜Jšœœ œ˜4šœ)˜)Jšœ)˜)Jšœ˜Jšœ˜—Jšœ1˜1Jšœž˜1J˜Jšœ˜Jšœ œ ž!˜AJ˜ Jšœ6™6šœ œ˜Jšœ ˜ šœ ˜ šœ)˜)Jšœ1˜5——šœ˜ Jšœœ'˜.Jšœ˜šœœ˜ Jšœœœœ˜%š˜šœ˜ šœœ˜$Jšœœœ ˜?Jšœ#˜#šœœ˜8Jšœ)˜)Jšœ˜—Jšœ"˜"J˜—Jšœ˜Jšœ œ˜%J˜——Jšœ˜—Jšœœœœ˜;Jšœ'˜'Jšœ˜——J˜—Jšœ˜J˜—J˜—J˜—Jšœ˜J˜—šœ œœ˜Jšœ œ˜J˜—J™Jšœ˜J˜—Jšœ˜J˜J˜—…—*~>