<> <> DIRECTORY AMBridge USING[ GFHFromTV, IsRemote, RemoteGFHFromTV, GetWorld, TVForGFHReferent, TVForRemoteGFHReferent, RemoteGlobalFrameHandle, nilRemoteGlobalFrameHandle ], AMModel USING[SectionObj, SectionClass, Context], AMModelLocation USING[CodeLocation], AMModelPrivate USING[ SectionRec, EPI, FGIToEPI, FGIToFirstPC, EPIToFirstPC, EPIToLastPC, PCOffset, GetModuleSTB ], AMTypes USING[Error], BcdDefs USING[VersionStamp, MTIndex, FTSelf, BcdBase], LoadState USING[ local, ModuleInfo, ConfigInfo, Acquire, Release, EnumerateAllModules, GlobalFrameToModule, Handle, ConfigID, ModuleIndex ], PrincOps USING[FrameCodeBase, BytePC, GlobalFrameHandle], RTSymbolDefs USING[SymbolTableBase], RTSymbols USING[ReleaseSTB], RTTypesPrivate USING[GetPc], RTTypesRemotePrivate USING[ GetRemoteGFHeader, GetRemotePc, AcquireRemoteBCD, ReleaseRemoteBCD ], Table USING[Base], WorldVM USING[ World, NoWorld, LocalWorld, Lock, Unlock, Loadstate, CurrentIncarnation, ShortAddress ]; AMModelLocationImpl: PROGRAM IMPORTS AMBridge, AMModel, AMModelPrivate, AMTypes, LoadState, RTSymbols, RTTypesPrivate, RTTypesRemotePrivate, WorldVM EXPORTS AMModel, AMModelLocation, AMModelPrivate = { OPEN AMBridge, AMModel, AMModelLocation, AMModelPrivate, AMTypes, RTSymbolDefs, RTSymbols, RTTypesPrivate, RTTypesRemotePrivate, PrincOps, WorldVM; <<>> <> <> Section: TYPE = REF SectionObj; SectionObj: PUBLIC TYPE = SectionRec; EntryLocations: PUBLIC PROC[section: Section] RETURNS[world: World, list: LIST OF CodeLocation _ NIL] = {[world: world, list: list] _ GetLocations[section]}; ExitLocations: PUBLIC PROC[section: Section] RETURNS[world: World, list: LIST OF CodeLocation _ NIL] = {[world: world, list: list] _ GetLocations[section: section, entry: FALSE]}; GetLocations: PROC[section: Section, entry: BOOL _ TRUE] RETURNS[world: World _ NoWorld[], list: LIST OF CodeLocation _ NIL] = { epi: EPI; firstPC: PCOffset; progContexts: LIST OF Context _ NIL; context: Context _ NIL; version: BcdDefs.VersionStamp; SELECT SectionClass[section] FROM statement => { statementSect: REF statement SectionObj = NARROW[section]; context _ statementSect.prog.someGFHTV; IF context = NIL THEN RETURN; -- section is not loaded version _ statementSect.prog.versionStamp; world _ GetWorld[context]; IF world = LocalWorld[] THEN { bcd: BcdDefs.BcdBase = GetLocalBCD[GFHFromTV[context]]; stb: SymbolTableBase _ GetModuleSTB[bcd, statementSect.prog.versionStamp]; { ENABLE UNWIND => ReleaseSTB[stb]; epi _ FGIToEPI[stb, statementSect.fgtIndex]; firstPC _ FGIToFirstPC[stb, statementSect.fgtIndex]; }; -- end ENABLE UNWIND ReleaseSTB[stb]; } -- end IF world = LocalWorld[] ELSE { -- remote world case bcd: BcdDefs.BcdBase = GetRemoteBCD[RemoteGFHFromTV[context]]; stb: SymbolTableBase _ GetModuleSTB[bcd, statementSect.prog.versionStamp ! UNWIND => ReleaseRemoteBCD[bcd]]; ReleaseRemoteBCD[bcd]; { ENABLE UNWIND => ReleaseSTB[stb]; epi _ FGIToEPI[stb, statementSect.fgtIndex]; firstPC _ FGIToFirstPC[stb, statementSect.fgtIndex]; }; -- end ENABLE UNWIND ReleaseSTB[stb]; }; }; proc => { procSect: REF proc SectionObj = NARROW[section]; context _ procSect.prog.someGFHTV; IF context = NIL THEN RETURN; -- section is not loaded version _ procSect.prog.versionStamp; epi _ procSect.entryPointIndex; world _ GetWorld[context]; IF world = LocalWorld[] THEN { bcd: BcdDefs.BcdBase = GetLocalBCD[GFHFromTV[context]]; stb: SymbolTableBase _ GetModuleSTB[bcd, procSect.prog.versionStamp]; { ENABLE UNWIND => ReleaseSTB[stb]; IF entry THEN firstPC _ EPIToFirstPC[stb, epi, TRUE] ELSE firstPC _ EPIToLastPC[stb, epi]; }; -- end ENABLE UNWIND ReleaseSTB[stb]; } ELSE { -- remote world case bcd: BcdDefs.BcdBase = GetRemoteBCD[RemoteGFHFromTV[context]]; stb: SymbolTableBase _ GetModuleSTB[bcd, procSect.prog.versionStamp ! UNWIND => ReleaseRemoteBCD[bcd]]; ReleaseRemoteBCD[bcd]; { ENABLE UNWIND => ReleaseSTB[stb]; IF entry THEN firstPC _ EPIToFirstPC[stb, epi, TRUE] ELSE firstPC _ EPIToLastPC[stb, epi]; }; -- end ENABLE UNWIND ReleaseSTB[stb]; }; }; ENDCASE => ERROR Error[ reason: typeFault, msg: "EntryLocation applied to a section neither for a statement nor a proc"]; progContexts _ ProgContextsForVersion[world: world, version: version]; <> IF progContexts = NIL THEN ERROR; <<>> <> FOR contextList: LIST OF Context _ progContexts, contextList.rest UNTIL contextList = NIL DO codeBase: PrincOps.FrameCodeBase; pc: PrincOps.BytePC; context: Context = contextList.first; found: BOOL _ FALSE; IF IsRemote[context] THEN { codeBase _ GetRemoteGFHeader[RemoteGFHFromTV[context]].code; pc _ [firstPC + GetRemotePc[RemoteGFHFromTV[context], epi]]; } ELSE { codeBase _ GFHFromTV[context].code; pc _ [firstPC + GetPc[GFHFromTV[context], epi]]; }; FOR cll: LIST OF CodeLocation _ list, cll.rest UNTIL cll = NIL DO IF cll.first.codeBase = codeBase THEN {found _ TRUE; EXIT}; ENDLOOP; IF NOT found THEN list _ CONS[[codeBase: codeBase, pc: pc], list]; ENDLOOP; }; -- end GetLocations ProgContextsForVersion: PROC[world: World, version: BcdDefs.VersionStamp] RETURNS[contexts: LIST OF Context _ NIL] = { IF world = LocalWorld[] THEN { forEachModule: PROC[ci: LoadState.ConfigID, mi: LoadState.ModuleIndex] RETURNS[stop: BOOL _ FALSE] = { bcd: BcdDefs.BcdBase = LoadState.local.ConfigInfo[ci].bcd; ftb: Table.Base _ LOOPHOLE[bcd + bcd.ftOffset]; mtb: Table.Base _ LOOPHOLE[bcd + bcd.mtOffset]; gfh: GlobalFrameHandle; mti: BcdDefs.MTIndex; [gfh: gfh, mti: mti] _ LoadState.local.ModuleInfo[ci, mi]; IF NOT loadStateHeld THEN ERROR; IF (IF mtb[mti].file = BcdDefs.FTSelf THEN bcd.version ELSE ftb[mtb[mti].file].version) = version THEN contexts _ CONS[TVForGFHReferent[gfh], contexts]; }; loadStateHeld: BOOL _ FALSE; LoadState.local.Acquire[]; loadStateHeld _ TRUE; [] _ LoadState.local.EnumerateAllModules[newestFirst, forEachModule ! ANY => {LoadState.local.Release[]; loadStateHeld _ FALSE}]; IF loadStateHeld THEN LoadState.local.Release[]; } -- end local case of ProgContextsForVersion ELSE { -- remote world case of ProgContextsForVersion Lock[world]; { ENABLE UNWIND => Unlock[world]; forEachModule: PROC[ci: LoadState.ConfigID, mi: LoadState.ModuleIndex] RETURNS[stop: BOOL _ FALSE] = { bcd: BcdDefs.BcdBase = AcquireRemoteBCD [world, WorldVM.CurrentIncarnation[world], newState.ConfigInfo[ci].bcd]; { ENABLE UNWIND => ReleaseRemoteBCD[bcd]; ftb: Table.Base _ LOOPHOLE[bcd + bcd.ftOffset]; mtb: Table.Base _ LOOPHOLE[bcd + bcd.mtOffset]; gfh: GlobalFrameHandle; rgfh: RemoteGlobalFrameHandle _ nilRemoteGlobalFrameHandle; mti: BcdDefs.MTIndex; [gfh: gfh, mti: mti] _ newState.ModuleInfo[ci, mi]; rgfh _ [world, WorldVM.CurrentIncarnation[world], LOOPHOLE[gfh, WorldVM.ShortAddress]]; IF NOT loadStateHeld THEN ERROR; IF (IF mtb[mti].file = BcdDefs.FTSelf THEN bcd.version ELSE ftb[mtb[mti].file].version) = version THEN contexts _ CONS[TVForRemoteGFHReferent[rgfh], contexts]; }; -- end ENABLE UNWIND => ReleaseRemoteBCD[bcd]; ReleaseRemoteBCD[bcd]; }; -- end forEachModule loadStateHeld: BOOL _ FALSE; newState: LoadState.Handle = WorldVM.Loadstate[world]; newState.Acquire[]; loadStateHeld _ TRUE; [] _ newState.EnumerateAllModules[newestFirst, forEachModule ! ANY => {newState.Release[]; loadStateHeld _ FALSE}]; IF loadStateHeld THEN newState.Release[]; }; -- end ENABLE UNWIND => Unlock[world]; Unlock[world]; }; -- end remote world case of ProgContextsForVersion }; -- end ProgContextsForVersion GetRemoteBCD: PUBLIC PROC[rgfh: RemoteGlobalFrameHandle] RETURNS[bcd: BcdDefs.BcdBase _ NIL] = { h: LoadState.Handle; WorldVM.Lock[rgfh.world]; h _ WorldVM.Loadstate[rgfh.world ! UNWIND => WorldVM.Unlock[rgfh.world]]; h.Acquire[]; { ENABLE UNWIND => {h.Release[]; WorldVM.Unlock[rgfh.world]}; gfh: GlobalFrameHandle = LOOPHOLE[rgfh.gfh]; bcd _ AcquireRemoteBCD[ rgfh.world, WorldVM.CurrentIncarnation[rgfh.world], h.ConfigInfo[h.GlobalFrameToModule[gfh].config].bcd ]; }; -- end ENABLE UNWIND h.Release[]; WorldVM.Unlock[rgfh.world]; }; GetLocalBCD: PUBLIC PROC[gfh: GlobalFrameHandle] RETURNS[bcd: BcdDefs.BcdBase] = { LoadState.local.Acquire[]; { ENABLE UNWIND => LoadState.local.Release[]; bcd _ LoadState.local.ConfigInfo[LoadState.local.GlobalFrameToModule[gfh].config].bcd; }; LoadState.local.Release[]; }; <<>> <> <> <> <> <> <<{ ENABLE UNWIND => Unlock[world];>> <> <> <> <> <<[] _ PilotLoadStateOps.InputLoadState[];>> <> <> <> <> <> <> < {>> <<[] _ PilotLoadStatePrivate.InstallLoadState[oldState];>> <> <> <<}];>> <> <<[] _ PilotLoadStatePrivate.InstallLoadState[oldState];>> <> <> <<};>> <> <<}; end ENABLE UNWIND => Unlock[world];>> <> <<}; end GetRemoteBCD >> }.