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;
TYPEs
either binder output bundle for a config, or compiler output bundle for a prog module, DEFs module, proc, or statement
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 misapplied"];
progContexts ← ProgContextsForVersion[world: world, version: version];
was: progContexts ← SourceSection[SectionSource[section], RootContext[world]].contexts; could be (restrict to one gf): progContexts ← CONS[context, NIL]; want to find all gf's for the indicated section
IF progContexts = NIL THEN ERROR;
Here with epi, firstPC and all progContext loadings of the section in the specified world
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[];
};
}.