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]]; 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; }; }; }. φWVMLoadState.mesa - cache of client pages Copyright c 1985 by Xerox Corporation. All rights reserved. Andrew Birrell December 2, 1983 3:08 pm Russ Atkinson, February 6, 1985 9:23:50 pm PST Russ Atkinson (RRA) May 14, 1985 10:38:11 am 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 Κ+˜codešœ)™)Kšœ Οmœ1™KšœK˜KKšœ˜Kšœ˜——Kšœ˜K˜—Kšœžœžœ˜K˜KšŸœžœžœ˜;K˜š œžœ!˜8Kšœ žœ žœ ˜$Kšœ˜šœžœ˜2K˜ Kšœžœ!žœ˜SK˜—šœ(˜(K˜ šœ˜Kšœ žœ!žœ˜O—K˜—šœ$˜$K˜ šœ˜Kšœ žœžœ˜M—K˜—šœ.˜.K˜ šœ˜Kšœ žœ$žœ˜R—K˜—˜K˜ Kšœžœžœ˜MKšœ˜Kšœžœžœžœ˜FK˜—K˜Kšœ˜—K˜š œžœžœžœ˜UKšœ žœžœ!˜9Kšœžœžœžœ˜!Kšœžœžœžœ˜@˜K˜ Kšœ ˜ Kšœ ˜ Kšœ˜—Kšœžœ,˜4Kšœ˜Kšžœžœžœ˜šžœ˜K˜ šœ˜Kšœ žœžœ˜8—K˜—Kšžœ˜Kšœ˜—K˜š  œž˜Kšœžœžœ˜MKšœ žœžœ˜7Kšœžœžœžœ˜!Kšœžœžœžœ˜>˜K˜ Kšœ ˜ Kšœ ˜ Kšœ˜—Kšœžœ*˜2Kšœ˜šžœžœžœž˜ šœžœ˜+Kšœ žœžœ˜A—šœ˜K˜ šœ˜Kšœ žœžœ˜?—K˜—Kšžœ˜—Kšœ˜—K˜š œž˜Kšœžœžœ$˜RKšœ žœžœ$˜——K˜—Kšžœ˜Kšœ˜—K˜š  œž˜Kšœžœžœ"˜PKšœ žœžœ"˜:Kšœžœžœžœ˜!Kšœžœžœ žœ˜A˜K˜ Kšœ ˜ Kšœ ˜ Kšœ˜—Kšœžœ-˜5Kšœ˜Kšœ žœ˜ Kšœ˜šžœž˜˜K˜ Kšœžœžœ˜=Kšœ ˜ Kšœžœ˜7Kšœ˜——Kšœ˜—K˜š œž˜Kš œžœžœžœžœ˜XKšœ˜Kšœžœžœžœ˜0Kš œžœžœžœžœžœ˜Išœ žœ˜Kšžœžœ˜7—šœ žœ˜Kšžœžœ˜6—šžœ Ÿž˜Kšœ#žœ-˜XKš œžœžœžœžœ˜GKšžœžœžœ žœ˜0Kšœ ˜ Kšœ8˜8—Kšžœ˜Kšœ˜—K˜š œž˜Kš œžœžœžœžœ˜SKšœ˜Kšœžœžœžœ˜+Kš œžœžœžœžœžœ˜Dšœ žœ˜Kšžœžœ˜7—šœ žœ˜Kšžœžœ˜6—šžœ Ÿž˜Kšœ˜Kšœžœžœ˜#˜K˜ Kšœ˜K˜ Kšœžœ˜%—Kšœžœžœ˜#Kšžœžœžœ žœ˜0Kšœ ˜ Kšœ8˜8—Kšžœ˜Kšœ˜—K˜š œžœ"˜;KšœΛ™ΛKšœ žœžœ*˜BKšœžœžœžœ˜!Kšœžœžœ(žœ˜IKšœ žœ˜Kšœ žœ˜$Kšœ žœ žœ ˜*Kšœžœ žœ ˜"Kšœžœ=˜PK˜KšœH™H˜Kšœ ˜ K˜ Kšœ˜—šžœžœžœ&ž˜Dšœ'˜'Kšžœ5˜8——K˜šœ%™%Kšœ*™*Kšœ™—˜Kšœžœžœžœ˜+K˜ Kšœžœ4˜@Kšœ˜K˜—Kšœ=™=˜Kšœžœ žœžœ˜&Kšœ žœ5˜EKšœžœ ˜Kšœ˜K˜—K™*˜Kšœžœžœžœ˜ Kšœžœ žœ˜2Kšœžœ ˜Kšœ˜—K˜Kšœ™Kšœ ˜ šœžœ˜8Kšœ ˜ Kš œ žœ žœžœžœ˜HKšœ žœ˜Kšœžœ˜(Kšœžœ ˜Kšœ˜K˜—KšœB˜BKšœŸ˜:K˜Kšœ>™>šžœžœ ž˜%šžœžœ˜ Kšœžœ™Kšœ7˜7K˜šžœžœžœžœ˜;Kšœ"™"Kšœ žœ˜Kšœ'˜'Kšœžœ˜KšœžœŸ2˜?šžœžœ ž˜ Kšœ/˜/Kšžœžœ˜.Kšžœ˜—K˜Kšœ™Kšœžœ˜K˜Kšœ+™+Kšœ˜Kšžœ"žœ"˜JK˜Kšœ™šœ)žœ˜/Kšœw™w—Kšœ˜Kšœžœ˜ Kšœ˜šžœžœ ž˜ Kšœ)™)Kšœ.˜.šžœžœ˜Kšœ$˜$Kšœ˜Kšœžœ žœ˜4šœ)˜)Kšœ)˜)Kšœ˜Kšœ˜—Kšœ1˜1KšœŸ˜1K˜Kšœ˜Kšœ žœ Ÿ!˜AK˜ Kšœ6™6šžœ žœž˜Kšœ ˜ šœ ˜ šœ)˜)Kšžœ1˜5——šžœ˜ Kšœžœ'˜.Kšœ˜šžœžœž˜ Kšžœžœžœžœ˜%šž˜šžœ˜ šžœžœ˜$Kšœžœžœ ˜?Kšœ#˜#šžœžœž˜8Kšœ)˜)Kšžœ˜—Kšœ"˜"K˜—Kšœ˜Kšœ žœ˜%K˜——Kšžœ˜—Kšœžœžœžœ˜;Kšœ'˜'Kšœ˜——K˜—Kšžœ˜K˜—K˜—K˜—Kšžœ˜K˜—šœ žœžœ˜Kšœ žœ˜K˜—K™Kšœ˜K˜—Kšœ˜K˜K˜—…—+ξ@