AMModelContextImpl.mesa
Russ Atkinson, October 13, 1983 11:44 am
"h.EnumerateAllModules[oldestFirst," ← "h.EnumerateAllModules[newestFirst,"
Last Modified On October 18, 1983 2:12 pm By Paul Rovner
"h.EnumerateAllModules[newestFirst," ← "h.EnumerateAllModules[oldestFirst,"
Last Modified On December 8, 1983 8:38 am By Paul Rovner
DIRECTORY
AMBridge USING [TVForGFHReferent, GFHFromTV, TVToProc, FHFromTV, ContextPC, GetWorld, RemoteGlobalFrameHandle, IsRemote, RemoteGFHFromTV, RemoteFHFromTV, TVToRemoteProc, GetWorldIncarnation, nilRemoteGlobalFrameHandle, TVForRemoteGFHReferent, RemotePD],
AMMiniModel USING [GetInterfaceRecordFromType, GetInterfaceRecordNames, GetInterfaceRecord],
AMModel USING [Class, Context, PartialInterfaceInstance],
AMModelPrivate USING [FGIndex, FGNull, EPI, PCToFGI, SectionRec, RefTVRec, ConfigContext, ConfigContextObj, StatementContext, StatementContextObj, GetLocalBCD, GetRemoteBCD],
AMTypes USING [GlobalParent, Procedure, TVType, Error, TVToName, TypeToName, TV],
BcdDefs USING [NullVersion, VersionStamp, MTIndex, FTSelf, NameRecord, IMPIndex, EXPIndex, CTIndex, CTNull, BcdBase, MTHandle, NameString, IMPHandle, EXPHandle, CTHandle],
BcdOps USING [ProcessModules, ProcessImports, ProcessExports, ProcessConfigs],
ConvertUnsafe USING [SubString, SubStringToRope],
IO USING [PutR, card, PutFR],
LoadState USING [Acquire, local, ConfigInfo, Release, Handle, nullConfig, GlobalFrameToModule, ConfigID, ModuleIndex, EnumerateAllModules, ModuleToGlobalFrame, EnumerateModulesInConfig, EnumerateConfigs, nullModule, CopiesList, ModuleInfo],
LoadStateExtra USING [GetChangeCount],
PrincOps USING [GlobalFrameHandle, BytePC],
PrincOpsUtils USING [GlobalFrameAndEntryPoint],
RemotePrincOpsUtils USING [RemoteGlobalFrameAndEntryPoint],
Rope USING [ROPE, Concat, Substr, SkipTo, Index, Length, Match, Cat],
RTSymbolDefs USING [SymbolTableBase, SymbolTableHandle, SymbolIndex, SymbolIdIndex, SymbolConstructorIndex],
RTSymbolOps USING [EnumerateCtxIseis, STBToModuleName, AcquireType, SEUnderType, STBDirectoryCtx, ISEPublic, ISEType],
RTSymbols USING [GetTypeSymbols, AcquireSTB, ReleaseSTB, AcquireSTBFromSGI, AcquireSTBFromGFH, GetSTHForModule],
RTSymbolsPrivate USING [AcquireBCDFromVersion, ReleaseBCD],
RTTypesPrivate USING [GetEp],
RTTypesRemotePrivate USING [AcquireRemoteBCD, GetRemoteEp, AcquireSTBFromRemoteGFH, ReleaseRemoteBCD],
SafeStorage USING [Type, fhType, gfhType],
Table USING [Base],
WorldVM USING [LocalWorld, World, WorldName, CurrentIncarnation, Lock, Unlock, Loadstate, Incarnation, Read, Address];
AMModelContextImpl: MONITOR -- protects WorldGFNameLists
IMPORTS AMBridge, AMModelPrivate, AMTypes, BcdOps, IO, ConvertUnsafe, LoadState, LoadStateExtra, PrincOpsUtils, RemotePrincOpsUtils, Rope, AMMiniModel, RTSymbolOps, RTSymbols, RTSymbolsPrivate, RTTypesPrivate, RTTypesRemotePrivate, WorldVM
EXPORTS AMModel, AMModelPrivate
= { OPEN AMBridge, AMMiniModel, AMModel, AMModelPrivate, AMTypes, PrincOps, RemotePrincOpsUtils, Rope, RTSymbolDefs, RTSymbolOps, RTSymbols, RTTypesPrivate, RTTypesRemotePrivate, SafeStorage, 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;
WorldGFNameList: TYPE = LIST OF WorldGFNames;
WorldGFNames: TYPE = REF WorldGFNameListRec;
WorldGFNameListRec: TYPE = RECORD[
   world: World,
   incarnation: Incarnation,
   loadStateChangeCount: INT,
   gfList: LIST OF GFContextRec
   ];
GFContextRec: TYPE = RECORD[name: ROPE, context: Context];
worldGFNameList: WorldGFNameList ← NIL;
PROCs dealing with Contexts (loadstate entries, global or local frames, statements, IR instances)
RootContext: PUBLIC PROC[world: World] RETURNS[Context] = {
a "rootContext" represents a Loadstate. Immediate children are the Contexts of loadstate configs for individually loaded program modules and bound configs.
RETURN[NEW[ConfigContextObj
← [world: world,
worldIncarnation: CurrentIncarnation[world],
configIndex: LoadState.nullConfig]]];
};
ContextClass: PUBLIC PROC[context: Context] RETURNS[Class] = {
WITH context SELECT FROM
sc: StatementContext => RETURN[statement];
mc: ConfigContext =>
IF mc.configIndex = LoadState.nullConfig
THEN RETURN[world]
ELSE RETURN[model];
tv: RefTVRec => {
SELECT TVType[tv] FROM
gfhType => RETURN[prog];
fhType => RETURN[proc];
ENDCASE => RETURN[interface];
};
ENDCASE => ERROR AMTypes.Error[reason: notImplemented];
};
ContextWorld: PUBLIC PROC[context: Context] RETURNS[World] = {
WITH context SELECT FROM
sc: StatementContext => RETURN[GetWorld[sc.localFrameTV]];
cc: ConfigContext => RETURN[cc.world];
ENDCASE => RETURN[GetWorld[context]];
};
SectionName with instance info
ContextName: PUBLIC PROC[context: Context] RETURNS[ans: ROPENIL] = {
IF context = NIL THEN RETURN[NIL];
WITH context SELECT FROM
sc: StatementContext => {
ans ← Rope.Cat[
ContextName[sc.localFrameTV], ":FGT#",
IO.PutR
[IO.card[NARROW[ContextSection[context],
     REF statement SectionObj].fgtIndex.fgCard]]];
};
tv: RefTVRec => {
SELECT TVType[tv] FROM
gfhType => {
gfhBits: CARDINAL =
IF GetWorld[tv] # LocalWorld[]
THEN LOOPHOLE[RemoteGFHFromTV[tv].gfh, CARDINAL]
ELSE LOOPHOLE[GFHFromTV[tv], CARDINAL];
ans ← TVToName[tv ! AMTypes.Error => CONTINUE];
ans ← Cat[ans, ":gfh#", IO.PutFR["%b", IO.card[gfhBits]]];
IF GetWorld[tv] # LocalWorld[]
THEN ans ← Cat[ans, ",world:", WorldName[GetWorld[tv]]];
};
fhType => {
fhBits: CARDINAL =
IF GetWorld[tv] # LocalWorld[]
THEN LOOPHOLE[RemoteFHFromTV[tv].fh, CARDINAL]
ELSE LOOPHOLE[FHFromTV[tv], CARDINAL];
ans ← TVToName[Procedure[tv ! AMTypes.Error => CONTINUE]
! AMTypes.Error => CONTINUE];
ans ← Cat[ans, ":fh#", IO.PutFR["%b", IO.card[fhBits]]];
IF GetWorld[tv] # LocalWorld[]
THEN ans ← Cat[ans, ",world:", WorldName[GetWorld[tv]]];
};
ENDCASE => {
ans ← TypeToName[TVType[tv]];
ans ← Cat["Interface:", ans];
IF GetWorld[tv] # LocalWorld[]
THEN ans ← Cat[Cat[ans, ",world:"], WorldName[GetWorld[tv]]];
}; -- assume an IR
};
mc: ConfigContext =>
IF mc.configIndex = LoadState.nullConfig
THEN ans ← Rope.Cat["World:", WorldName[mc.world]]
ELSE {
FindRootConfig: PROC[cth: BcdDefs.CTHandle, cti: BcdDefs.CTIndex]
RETURNS[stop: BOOLFALSE] =
{IF cth.config = BcdDefs.CTNull THEN RETURN[TRUE]};
IF mc.world = LocalWorld[]
THEN {
bcd: BcdDefs.BcdBase;
ctHandle: BcdDefs.CTHandle;
LoadState.local.Acquire[];
bcd ← LoadState.local.ConfigInfo[mc.configIndex
! UNWIND => LoadState.local.Release[]].bcd;
LoadState.local.Release[];
IF bcd = NIL THEN ERROR;
[ctHandle,] ← BcdOps.ProcessConfigs[bcd, FindRootConfig];
ans ← Rope.Cat[
BcdNameToRope[bcd, ctHandle.name],
":ConfigIndex#",
IO.PutR[IO.card[LOOPHOLE[mc.configIndex, CARDINAL]]]
];
}
ELSE {
bcd: BcdDefs.BcdBase;
ctHandle: BcdDefs.CTHandle;
Lock[mc.world];
{ ENABLE UNWIND => Unlock[mc.world];
h: LoadState.Handle = WorldVM.Loadstate[mc.world];
h.Acquire[];
{ ENABLE UNWIND => h.Release[];
bcd ← AcquireRemoteBCD
[mc.world, mc.worldIncarnation, h.ConfigInfo[mc.configIndex].bcd];
};
h.Release[];
};
Unlock[mc.world];
IF bcd = NIL THEN ERROR;
{ ENABLE UNWIND => ReleaseRemoteBCD[bcd];
[ctHandle,] ← BcdOps.ProcessConfigs[bcd, FindRootConfig];
ans ← Rope.Cat[
BcdNameToRope[bcd, ctHandle.name],
":ConfigIndex#",
IO.PutR[IO.card[LOOPHOLE[mc.configIndex, CARDINAL]]],
",world:",
WorldName[mc.world]
];
};
ReleaseRemoteBCD[bcd];
};
}; -- end ELSE arm (mc.configIndex # LoadState.nullConfig)
ENDCASE => ERROR AMTypes.Error[reason: notImplemented];
}; -- end ContextName
EXAMPLE USAGE: given a module name and a world context, this returns a Context for the most recently loaded global frame for a program with that name. name must identify a model or prog (someday interface) if context identifies a world, or a prog (someday interface) if context identifies a model. The format of the name should be the same as that produced by ContextName, with elided fields meaning "don't care". The result will be either a model or prog (someday interface) context.
MostRecentNamedContext: PUBLIC PROC[name: ROPE, context: --world or model-- Context]
RETURNS[ans: Context ← NIL] = {
WITH context SELECT FROM
mc: ConfigContext => {
IF mc.configIndex = LoadState.nullConfig -- the model of a world
THEN {
p: PROC[name: ROPE, gf: TV] RETURNS[stop: BOOLTRUE] = {NULL};
ans ← FindMatchingGlobalFrames[ContextWorld[context], name, p];
IF ans # NIL THEN RETURN;
};
here to look for a named config or a module of a config
{
p: PROC[c: Context] RETURNS[stop: BOOLFALSE] = {
n: ROPE = ContextName[c];
len: INT ← Rope.Index[s1: n, s2: ":"];
nPart: ROPEIF len = Rope.Length[n] THEN n ELSE Rope.Substr[base: n, len: len];
IF name.Match[nPart, FALSE] THEN {ans ← c; stop ← TRUE};
};
[] ← ContextChildren[context, p];
};
};
ENDCASE =>
ERROR AMTypes.Error
[reason: notImplemented,
msg: "MostRecentNamedContext for other than a world or model Context"];
};
LoadStateChangeCount:
INTERNAL PROC[world: World] RETURNS[ans: INT] = {
h: LoadState.Handle = WorldVM.Loadstate[world];
h.Acquire[];
ans ← LoadStateExtra.GetChangeCount[h];
h.Release[];
};
FindWorldGFNames:
INTERNAL PROC[world: World] RETURNS[WorldGFNames] = {
FOR wgfnl: WorldGFNameList ← worldGFNameList, wgfnl.rest UNTIL wgfnl = NIL
DO
IF world = wgfnl.first.world
THEN {
IF (CurrentIncarnation[world] # wgfnl.first.incarnation)
OR (LoadStateChangeCount[world] # wgfnl.first.loadStateChangeCount)
THEN {
wgfnl.first.gfList ← NIL;
wgfnl.first.incarnation ← CurrentIncarnation[world];
wgfnl.first.loadStateChangeCount ← LoadStateChangeCount[world];
};
RETURN[wgfnl.first];
};
ENDLOOP;
worldGFNameList ← CONS[NEW[WorldGFNameListRec
← [world: world,
incarnation: CurrentIncarnation[world],
loadStateChangeCount: LoadStateChangeCount[world],
gfList: NIL]],
worldGFNameList];
RETURN[worldGFNameList.first];
};
FindMatchingGlobalFrames:
PUBLIC ENTRY PROC[
world: World,
name: ROPE,
proc: PROC[ROPE, Context] RETURNS[--stop:-- BOOL]
]
RETURNS[ans: Context ← NIL] = { ENABLE UNWIND => NULL;
gfNames: WorldGFNames;
WorldVM.Lock[world];
{ ENABLE UNWIND => WorldVM.Unlock[world];
gfNames ← FindWorldGFNames[world];
IF gfNames.gfList = NIL THEN {
h: LoadState.Handle = WorldVM.Loadstate[world];
p: PROC [ci: LoadState.ConfigID, mx: LoadState.ModuleIndex]
RETURNS [stop: BOOLFALSE] = {
rgfh: RemoteGlobalFrameHandle
= [world: world,
worldIncarnation: CurrentIncarnation[world],
gfh: LOOPHOLE[h.ModuleToGlobalFrame[ci, mx]]];
gfNames.gfList
CONS[[name: NIL, context: TVForRemoteGFHReferent[rgfh]], gfNames.gfList];
};
h.Acquire[];
[] ← h.EnumerateAllModules[oldestFirst, p ! UNWIND => h.Release[]];
h.Release[];
};
}; -- ENABLE UNWIND => WorldVM.Unlock[world];
WorldVM.Unlock[world];
FOR gfList: LIST OF GFContextRec ← gfNames.gfList, gfList.rest UNTIL gfList = NIL
DO
IF gfList.first.name = NIL
THEN gfList.first.name ← AMTypes.TVToName[gfList.first.context];
IF name.Match[gfList.first.name, FALSE]
AND proc[gfList.first.name, gfList.first.context]
THEN RETURN[gfList.first.context];
ENDLOOP;
};
an enumerator. Like MostRecentNamedContext, but gets 'em all.
NamedContexts: PUBLIC PROC[
name: ROPE,
context: --worldRoot or model--Context,
proc: PROC[Context] RETURNS[stop: BOOL]]
RETURNS[ans: Context ← NIL--NIL if not stopped--] = {
lookForNamedContext: PROC[c: Context] RETURNS[stop: BOOLFALSE] = {
n: ROPE = ContextName[c];
len: INT ← Rope.Index[s1: n, s2: ":"];
nPart: ROPEIF len = Rope.Length[n] THEN n ELSE Rope.Substr[base: n, len: len];
IF name.Match[nPart, FALSE] --Rope.Equal[name, nPart]
THEN {stop ← proc[c]; IF stop THEN ans ← c}
ELSE
SELECT ContextClass[c] FROM
model => {ans ← NamedContexts[name, c, proc]; IF ans # NIL THEN stop ← TRUE};
ENDCASE;
};
start HERE
[] ← ContextChildren[context, lookForNamedContext];
};
param to creator of context
ContextSection: PUBLIC PROC[context: Context] RETURNS[ans: Section ← NIL] = {
WITH context SELECT FROM
sc: StatementContext => {
parentContext: Context ← ParentContext[context];
UNTIL ContextClass[parentContext] = prog
DO parentContext ← ParentContext[parentContext]; ENDLOOP;
RETURN[NEW[SectionObj
← [statement[prog: NARROW[ContextSection[parentContext], REF prog SectionObj],
   fgtIndex: StatementContextToFGI[sc]]]]];
};
tv: RefTVRec => {
SELECT TVType[tv] FROM
gfhType => -- program module
RETURN[NEW[SectionObj
← [prog
[moduleName: TVToName[tv],
versionStamp: IF IsRemote[tv]
THEN RemoteGFHToVersionStamp[RemoteGFHFromTV[tv]]
ELSE GFHToVersionStamp[GFHFromTV[tv]],
someGFHTV: tv]]]];
fhType => {
procTV: RefTVRec = NARROW[Procedure[tv]]; -- procedure
ep: CARDINAL;
IF IsRemote[procTV] THEN {
rpd: AMBridge.RemotePD = AMBridge.TVToRemoteProc[procTV];
ep ← RemoteGlobalFrameAndEntryPoint[rpd.world, rpd.pd].ep;
}
ELSE ep ← PrincOpsUtils.GlobalFrameAndEntryPoint[TVToProc[procTV]].ep;
RETURN[NEW[SectionObj
← [proc[prog: NARROW[ContextSection[GlobalParent[tv]]],
  entryPointIndex: ep,
  procTV: procTV]]]];
};
ENDCASE => { -- better be a TV for an interface record
type: Type = TVType[tv];
stb: SymbolTableBase;
sei: SymbolIndex;
mn: ROPE;
vs: BcdDefs.VersionStamp;
[stb, sei] ← GetTypeSymbols[type];
{ ENABLE UNWIND => ReleaseSTB[stb];
csei: SymbolConstructorIndex = SEUnderType[stb, sei];
WITH stb SELECT FROM
t: SymbolTableBase.x =>
WITH ser: t.e.seb[NARROW[csei, SymbolConstructorIndex.x].e] SELECT FROM
definition => vs ← t.e.stHandle.version;
ENDCASE => ERROR;
t: SymbolTableBase.y =>
WITH ser: t.e.seb[NARROW[csei, SymbolConstructorIndex.y].e] SELECT FROM
definition => vs ← t.e.stHandle.version;
ENDCASE => ERROR;
ENDCASE => ERROR;
mn ← STBToModuleName[stb];
};
ReleaseSTB[stb];
RETURN[NEW[SectionObj ← [interface[moduleName: mn, versionStamp: vs]]]];
};
};
mc: ConfigContext =>
IF mc.world = LocalWorld[]
THEN {
bcd: BcdDefs.BcdBase;
IF mc.configIndex = LoadState.nullConfig THEN RETURN[NIL];
LoadState.local.Acquire[];
bcd ← LoadState.local.ConfigInfo[mc.configIndex
! UNWIND => LoadState.local.Release[]].bcd;
LoadState.local.Release[];
IF bcd = NIL THEN ERROR;
ans ← NEW[SectionObj ←
[model[configName: StripExtension[BcdNameToRope[bcd, bcd.source]],
  versionStamp: bcd.version,
  configContext: mc]]];
}
ELSE {
bcd: BcdDefs.BcdBase;
IF mc.configIndex = LoadState.nullConfig THEN RETURN[NIL];
Lock[mc.world];
{ ENABLE UNWIND => Unlock[mc.world];
h: LoadState.Handle = WorldVM.Loadstate[mc.world];
h.Acquire[];
{ ENABLE UNWIND => h.Release[];
bcd ← AcquireRemoteBCD
[mc.world, mc.worldIncarnation, h.ConfigInfo[mc.configIndex].bcd];
};
h.Release[];
};
Unlock[mc.world];
IF bcd = NIL THEN ERROR;
{ ENABLE UNWIND => ReleaseRemoteBCD[bcd];
ans ← NEW[SectionObj ←
[model[configName: StripExtension[BcdNameToRope[bcd, bcd.source]],
  versionStamp: bcd.version,
  configContext: mc]]];
};
ReleaseRemoteBCD[bcd];
};
ENDCASE => ERROR AMTypes.Error[reason: notImplemented];
}; -- end ContextSection
world => NIL
model => world
prog => model
proc => prog
statement => proc
ParentContext: PUBLIC PROC[context: Context] RETURNS[Context] = {
WITH context SELECT FROM
sc: StatementContext => RETURN[sc.localFrameTV];
mc: ConfigContext =>
IF mc.configIndex = LoadState.nullConfig
THEN RETURN[NIL]
ELSE -- the loadstate has only one level of structure
RETURN[NEW[ConfigContextObj ←
[world: mc.world, worldIncarnation: mc.worldIncarnation, configIndex: LoadState.nullConfig]]];
tv: RefTVRec => {
SELECT TVType[tv] FROM
gfhType =>
IF NOT IsRemote[tv]
THEN {
ci: LoadState.ConfigID;
gfh: PrincOps.GlobalFrameHandle = GFHFromTV[tv];
LoadState.local.Acquire[];
ci ← LoadState.local.GlobalFrameToModule[gfh].config;
LoadState.local.Release[];
RETURN[NEW[ConfigContextObj ←
[world: LocalWorld[],
worldIncarnation: GetWorldIncarnation[tv],
configIndex: ci]]];
}
ELSE { -- remote case
ci: LoadState.ConfigID;
rgfh: RemoteGlobalFrameHandle = RemoteGFHFromTV[tv];
Lock[rgfh.world];
{ ENABLE UNWIND => Unlock[rgfh.world];
h: LoadState.Handle ← WorldVM.Loadstate[rgfh.world];
h.Acquire[];
ci ← h.GlobalFrameToModule[LOOPHOLE[rgfh.gfh]
! UNWIND => h.Release[]].config;
h.Release[];
}; -- end ENABLE UNWIND => Unlock[world];
Unlock[rgfh.world];
RETURN[NEW[ConfigContextObj ←
[world: rgfh.world,
worldIncarnation: GetWorldIncarnation[tv],
configIndex: ci]]];
};
fhType => RETURN[GlobalParent[tv]];
ENDCASE => ERROR AMTypes.Error[reason: typeFault, type: TVType[tv]];
};
ENDCASE => ERROR AMTypes.Error[reason: notImplemented];
}; -- end ParentContext
world -> model or prog (TV for a global frame)
model -> prog
proc -> statement
ContextChildren: PUBLIC PROC[context: Context, proc: PROC[Context] RETURNS[stop: BOOL]]
RETURNS[ans: Context ← NIL--NIL if not stopped--] = {
FOR c: Context ← FirstChildContext[context], NextSiblingContext[c]
UNTIL c = NIL DO IF proc[c] THEN RETURN[c]; ENDLOOP;
};
FirstChildContext: PROC[context: Context] RETURNS[ans: Context] = {
WITH context SELECT FROM
sc: StatementContext => RETURN[NIL]; -- do statements have substructure?
tv: RefTVRec =>
SELECT TVType[tv] FROM
fhType => RETURN[NEW[StatementContextObj ← [localFrameTV: tv]]];
gfhType => RETURN[NIL];
ENDCASE => ERROR AMTypes.Error[reason: typeFault, type: TVType[tv]];
mc: ConfigContext =>
IF mc.configIndex = LoadState.nullConfig
THEN {
IF mc.world = LocalWorld[]
THEN {
config: LoadState.ConfigID;
gfh: GlobalFrameHandle;
composite: BOOL;
LoadState.local.Acquire[];
{ ENABLE UNWIND => LoadState.local.Release[];
mx: LoadState.ModuleIndex;
p: PROC[LoadState.ConfigID, LoadState.ModuleIndex] RETURNS[BOOL] = {RETURN[TRUE]};
[config, mx] ← LoadState.local.EnumerateAllModules[newestFirst, p];
composite ← IsComposite[LoadState.local.ConfigInfo[config].bcd];
gfh ← LoadState.local.ModuleToGlobalFrame[config, mx];
IF gfh = NIL THEN ERROR;
}; -- ENABLE UNWIND => LoadState.local.Release[];
LoadState.local.Release[];
IF composite
THEN
RETURN[NEW[ConfigContextObj ←
[world: mc.world,
worldIncarnation: mc.worldIncarnation,
configIndex: config]]]
ELSE RETURN[TVForGFHReferent[gfh]];
}
ELSE { -- remote world
config: LoadState.ConfigID;
gfh: GlobalFrameHandle;
rgfh: RemoteGlobalFrameHandle ← nilRemoteGlobalFrameHandle;
composite: BOOL;
Lock[mc.world];
{ ENABLE UNWIND => Unlock[mc.world];
h: LoadState.Handle = WorldVM.Loadstate[mc.world];
h.Acquire[];
{ ENABLE UNWIND => h.Release[];
mx: LoadState.ModuleIndex;
p: PROC[LoadState.ConfigID, LoadState.ModuleIndex] RETURNS[BOOL] = {RETURN[TRUE]};
[config, mx] ← h.EnumerateAllModules[newestFirst, p];
composite ← IsRemoteBCDComposite[mc.world, h.ConfigInfo[config].bcd];
gfh ← h.ModuleToGlobalFrame[config, mx];
IF gfh = NIL THEN ERROR;
rgfh ← [mc.world, mc.worldIncarnation, LOOPHOLE[gfh]];
}; -- ENABLE UNWIND => h.Release[];
h.Release[];
}; -- end ENABLE UNWIND => Unlock[mc.world];
Unlock[mc.world];
IF composite
THEN RETURN[NEW[ConfigContextObj ←
[world: mc.world,
worldIncarnation: mc.worldIncarnation,
configIndex: config]]]
ELSE RETURN[TVForRemoteGFHReferent[rgfh]];
};
} -- end world config case
ELSE {
IF mc.world = LocalWorld[]
THEN {
gfh: GlobalFrameHandle;
p: PROC[LoadState.ModuleIndex] RETURNS[BOOL] = {RETURN[TRUE]};
LoadState.local.Acquire[];
[gfh: gfh] ← LoadState.local.EnumerateModulesInConfig[mc.configIndex, p
! UNWIND => LoadState.local.Release[]];
LoadState.local.Release[];
RETURN[TVForGFHReferent[gfh]];
}
ELSE {
gfh: GlobalFrameHandle;
rgfh: RemoteGlobalFrameHandle ← nilRemoteGlobalFrameHandle;
Lock[mc.world];
{ ENABLE UNWIND => Unlock[mc.world];
h: LoadState.Handle = WorldVM.Loadstate[mc.world];
p: PROC[LoadState.ModuleIndex] RETURNS[BOOL] = {RETURN[TRUE]};
h.Acquire[];
[gfh: gfh] ← h.EnumerateModulesInConfig[mc.configIndex, p
! UNWIND => h.Release[]];
h.Release[];
}; -- end ENABLE UNWIND => Unlock[mc.world];
Unlock[mc.world];
rgfh ← [mc.world, mc.worldIncarnation, LOOPHOLE[gfh]];
RETURN[TVForRemoteGFHReferent[rgfh]];
};
};
ENDCASE => ERROR AMTypes.Error[reason: notImplemented];
}; -- end FirstChildContext
model -> model or prog (TV for a global frame)
prog -> model or prog
returns NIL if nomore
NextSiblingContext: PROC[context: Context] RETURNS[ans: Context ← NIL] = {
IF context = NIL THEN RETURN[NIL];
WITH context SELECT FROM
sc: StatementContext => RETURN[NIL]; -- substructure?
mc: ConfigContext => {
IF mc.configIndex = LoadState.nullConfig THEN RETURN[NIL];
IF mc.world = LocalWorld[]
THEN {
nextIsIt: BOOLFALSE;
composite: BOOL;
config: LoadState.ConfigID;
gfh: GlobalFrameHandle;
LoadState.local.Acquire[];
{ ENABLE UNWIND => LoadState.local.Release[];
p: PROC[config: LoadState.ConfigID] RETURNS[BOOL] = {
IF nextIsIt THEN RETURN[TRUE];
IF config = mc.configIndex THEN nextIsIt ← TRUE;
RETURN[FALSE];
};
q: PROC[LoadState.ModuleIndex] RETURNS[BOOL] = {RETURN[TRUE]};
config ← LoadState.local.EnumerateConfigs[newestFirst, p];
IF config = LoadState.nullConfig
THEN {LoadState.local.Release[]; RETURN[NIL]};
composite ← IsComposite[LoadState.local.ConfigInfo[config].bcd];
[gfh: gfh] ← LoadState.local.EnumerateModulesInConfig[config, q];
};
LoadState.local.Release[];
IF composite
THEN RETURN[NEW[ConfigContextObj ←
[world: mc.world,
worldIncarnation: mc.worldIncarnation,
configIndex: config]]]
ELSE RETURN[TVForGFHReferent[gfh]];
}
ELSE {
nextIsIt: BOOLFALSE;
composite: BOOL;
config: LoadState.ConfigID;
gfh: GlobalFrameHandle;
Lock[mc.world];
{ ENABLE UNWIND => Unlock[mc.world];
h: LoadState.Handle = WorldVM.Loadstate[mc.world];
h.Acquire[];
{ ENABLE UNWIND => h.Release[];
p: PROC[config: LoadState.ConfigID] RETURNS[BOOL] = {
IF nextIsIt THEN RETURN[TRUE];
IF config = mc.configIndex THEN nextIsIt ← TRUE;
RETURN[FALSE];
};
q: PROC[LoadState.ModuleIndex] RETURNS[BOOL] = {RETURN[TRUE]};
config ← h.EnumerateConfigs[newestFirst, p];
IF config = LoadState.nullConfig
THEN {h.Release[]; WorldVM.Unlock[mc.world]; RETURN[NIL]};
composite ← IsRemoteBCDComposite[mc.world, h.ConfigInfo[config].bcd];
IF NOT composite THEN [gfh: gfh] ← h.EnumerateModulesInConfig[config, q];
};
h.Release[];
}; -- end ENABLE UNWIND => Unlock[mc.world];
Unlock[mc.world];
IF composite
THEN RETURN[NEW[ConfigContextObj ←
[world: mc.world,
worldIncarnation: mc.worldIncarnation,
configIndex: config]]]
ELSE {
rgfh: RemoteGlobalFrameHandle
← [mc.world, mc.worldIncarnation, LOOPHOLE[gfh]];
RETURN[TVForRemoteGFHReferent[rgfh]];
};
};
};
tv: RefTVRec => {
SELECT TVType[tv] FROM
gfhType =>
IF IsRemote[tv]
THEN { -- remote case
world: World = GetWorld[tv];
WorldVM.Lock[world];
{ ENABLE UNWIND => WorldVM.Unlock[world];
h: LoadState.Handle = WorldVM.Loadstate[world];
h.Acquire[];
{ ENABLE UNWIND => h.Release[];
gfh: GlobalFrameHandle = LOOPHOLE[RemoteGFHFromTV[tv].gfh];
config: LoadState.ConfigID ← h.GlobalFrameToModule[gfh].config;
IF IsRemoteBCDComposite[world, h.ConfigInfo[config].bcd] THEN {
nextGFH: GlobalFrameHandle;
rgfh: RemoteGlobalFrameHandle ← nilRemoteGlobalFrameHandle;
lastWasIt: BOOLFALSE;
q: PROC[mx: LoadState.ModuleIndex] RETURNS[stop: BOOLFALSE] = {
mgfh: GlobalFrameHandle;
copies: LoadState.CopiesList;
[gfh: mgfh, copies: copies]h.ModuleInfo[config, mx];
IF lastWasIt THEN {nextGFHmgfh; RETURN[TRUE]};
IF gfh = mgfh THEN
{IF copies = NIL
THEN {lastWasIt ← TRUE; RETURN[FALSE]}
ELSE {nextGFH ← copies.first; RETURN[TRUE]}}
ELSE IF copies # NIL THEN {
FOR x: LoadState.CopiesList ← copies, x.rest UNTIL x = NIL
DO
IF lastWasIt THEN {nextGFHx.first; RETURN[TRUE]};
IF x.first = gfh THEN lastWasIt ← TRUE;
ENDLOOP;
};
};
nextModule: LoadState.ModuleIndex ←
h.EnumerateModulesInConfig[config, q].module;
rgfh ← [world, CurrentIncarnation[world], LOOPHOLE[nextGFH]];
ans ← IF nextModule = LoadState.nullModule THEN NIL
ELSE TVForRemoteGFHReferent[rgfh];
}
ELSE { -- not a composite config
lastWasIt: BOOLFALSE;
p: PROC[ci: LoadState.ConfigID] RETURNS[BOOL] = {
IF lastWasIt THEN RETURN[TRUE];
IF ci = config THEN lastWasIt ← TRUE;
RETURN[FALSE];
};
nextConfig: LoadState.ConfigID ←
h.EnumerateConfigs[newestFirst, p];
IF nextConfig = LoadState.nullConfig THEN ans ← NIL
ELSE {
r: PROC[LoadState.ModuleIndex] RETURNS[BOOL] =
{RETURN[TRUE]};
IF IsRemoteBCDComposite[world, h.ConfigInfo[nextConfig].bcd] THEN {
ans ← NEW[ConfigContextObj ←
[world: world,
worldIncarnation: CurrentIncarnation[world],
configIndex: nextConfig]];
}
ELSE ans ← TVForRemoteGFHReferent
[[ world,
CurrentIncarnation[world],
LOOPHOLE[h.EnumerateModulesInConfig[nextConfig, r].gfh]]];
};
};
}; -- end ENABLE UNWIND => h.Release[]
h.Release[];
}; -- end ENABLE UNWIND => WorldVM.Unlock[world];
WorldVM.Unlock[world];
}
ELSE { -- local case
LoadState.local.Acquire[];
{ ENABLE UNWIND => LoadState.local.Release[];
gfh: GlobalFrameHandle = GFHFromTV[tv];
config: LoadState.ConfigID ← LoadState.local.GlobalFrameToModule[gfh].config;
IF IsComposite[LoadState.local.ConfigInfo[config].bcd] THEN {
nextGFH: GlobalFrameHandle;
lastWasIt: BOOLFALSE;
q: PROC[mx: LoadState.ModuleIndex] RETURNS[stop: BOOLFALSE] = {
mgfh: GlobalFrameHandle;
copies: LoadState.CopiesList;
[gfh: mgfh, copies: copies]LoadState.local.ModuleInfo[config, mx];
IF lastWasIt THEN {nextGFHmgfh; RETURN[TRUE]};
IF gfh = mgfh THEN
{IF copies = NIL
THEN {lastWasIt ← TRUE; RETURN[FALSE]}
ELSE {nextGFH ← copies.first; RETURN[TRUE]}}
ELSE IF copies # NIL THEN {
FOR x: LoadState.CopiesList ← copies, x.rest UNTIL x = NIL
DO
IF lastWasIt THEN {nextGFHx.first; RETURN[TRUE]};
IF x.first = gfh THEN lastWasIt ← TRUE;
ENDLOOP;
};
};
nextModule: LoadState.ModuleIndex ←
LoadState.local.EnumerateModulesInConfig[config, q].module;
ans ← IF nextModule = LoadState.nullModule THEN NIL
ELSE TVForGFHReferent[nextGFH];
}
ELSE { -- not a composite config
lastWasIt: BOOLFALSE;
p: PROC[ci: LoadState.ConfigID] RETURNS[BOOL] = {
IF lastWasIt THEN RETURN[TRUE];
IF ci = config THEN lastWasIt ← TRUE;
RETURN[FALSE];
};
nextConfig: LoadState.ConfigID ←
LoadState.local.EnumerateConfigs[newestFirst, p];
IF nextConfig = LoadState.nullConfig THEN ans ← NIL
ELSE {
r: PROC[LoadState.ModuleIndex] RETURNS[BOOL] =
{RETURN[TRUE]};
IF IsComposite[LoadState.local.ConfigInfo[nextConfig].bcd] THEN {
ans ← NEW[ConfigContextObj ←
[world: LocalWorld[],
worldIncarnation: CurrentIncarnation[LocalWorld[]],
configIndex: nextConfig]];
}
ELSE ans ← TVForGFHReferent
[LoadState.local.EnumerateModulesInConfig[nextConfig, r].gfh];
};
};
}; -- end ENABLE UNWIND => LoadState.local.Release[]
LoadState.local.Release[];
};
ENDCASE => ERROR AMTypes.Error[reason: typeFault, type: TVType[tv]];
};
ENDCASE => ERROR;
}; -- end NextSiblingContext
... dealing with PartialInterfaceInstances
Implemented only for loadstate entries and global frames sharing
Imports: PUBLIC PROC[context: Context]
RETURNS[ans: LIST OF PartialInterfaceInstance ← NIL] = {
WITH context SELECT FROM
mc: ConfigContext => {
bcd: BcdDefs.BcdBase;
ftb: Table.Base;
AcquireIR: PROC [imph: BcdDefs.IMPHandle, impi: BcdDefs.IMPIndex]
RETURNS [stop: BOOLFALSE] = {
type: Type;
seIndex: SymbolIndex;
stb: SymbolTableBase
← AcquireSTB[
GetSTHForModule
[stamp: ftb[imph.file].version,
fileName: BcdNameToRope[bcd, ftb[imph.file].name],
moduleName: BcdNameToRope[bcd, imph.name]]];
p: PROC[stb: SymbolTableBase, isei: SymbolIdIndex] RETURNS[stop: BOOL] = {
IF ISEPublic[stb, isei]
THEN {seIndex ← ISEType[stb, isei]; RETURN[TRUE]} ELSE RETURN[FALSE];
};
IF NOT EnumerateCtxIseis[stb: stb, ctx: STBDirectoryCtx[stb], proc: p
! UNWIND => ReleaseSTB[stb]]
THEN {ReleaseSTB[stb]; ERROR};
type ← AcquireType[stb: stb, seIndex: seIndex ! UNWIND => ReleaseSTB[stb]];
ReleaseSTB[stb];
ans ← CONS[[ir: GetInterfaceRecordFromType[type, mc.world], usingList: NIL], ans]; -- NOTE
};
IF mc.configIndex = LoadState.nullConfig THEN RETURN[NIL];
IF mc.world # LocalWorld[] THEN {
Lock[mc.world];
{ ENABLE UNWIND => Unlock[mc.world];
h: LoadState.Handle = WorldVM.Loadstate[mc.world];
h.Acquire[];
{ ENABLE UNWIND => h.Release[];
bcd ← h.ConfigInfo[mc.configIndex].bcd;
IF bcd = NIL THEN ERROR;
bcd ← AcquireRemoteBCD[mc.world, mc.worldIncarnation, bcd];
IF bcd = NIL THEN ERROR;
}; -- end ENABLE UNWIND => h.Release[];
h.Release[];
{ ENABLE UNWIND => ReleaseRemoteBCD[bcd];
ftb ← LOOPHOLE[bcd + bcd.ftOffset];
IF NOT IsComposite[bcd] THEN ERROR; -- single module loadstate entry
[] ← BcdOps.ProcessImports[bcd, AcquireIR];
}; -- end ENABLE UNWIND => ... ReleaseRemoteBCD ...
ReleaseRemoteBCD[bcd];
}; -- end ENABLE UNWIND => Unlock[mc.world];
Unlock[mc.world];
}
ELSE { -- local case
LoadState.local.Acquire[];
bcd ← LoadState.local.ConfigInfo[mc.configIndex].bcd;
LoadState.local.Release[];
ftb ← LOOPHOLE[bcd + bcd.ftOffset];
IF NOT IsComposite[bcd] THEN ERROR; -- single module loadstate entry
[] ← BcdOps.ProcessImports[bcd, AcquireIR];
};
};
tv: RefTVRec => {
SELECT TVType[tv] FROM
gfhType => {
gets top level imports from the loadstate, via the minimodel. Encapsulation awaits the modeller.
bcd: BcdDefs.BcdBase = RTSymbolsPrivate.AcquireBCDFromVersion
[versionStamp:
IF IsRemote[tv] THEN RemoteGFHToVersionStamp[RemoteGFHFromTV[tv]]
ELSE GFHToVersionStamp[GFHFromTV[tv]],
shortFileNameHint: Rope.Concat[TVToName[tv], ".bcd"]
];
ftb: Table.Base = LOOPHOLE[bcd + bcd.ftOffset];
AcquireIR: PROC[imph: BcdDefs.IMPHandle, impi: BcdDefs.IMPIndex]
RETURNS [stop: BOOLFALSE] = {
type: Type;
seIndex: SymbolIndex;
stb: SymbolTableBase ← AcquireSTB
[GetSTHForModule
[stamp: ftb[imph.file].version,
fileName: BcdNameToRope[bcd, ftb[imph.file].name],
moduleName: BcdNameToRope[bcd, imph.name]
]
];
p: PROC[stb: SymbolTableBase, isei: SymbolIdIndex] RETURNS[stop: BOOL] = {
IF ISEPublic[stb, isei]
THEN {seIndex ← ISEType[stb, isei]; RETURN[TRUE]}
ELSE RETURN[FALSE];
};
IF NOT EnumerateCtxIseis[stb: stb, ctx: STBDirectoryCtx[stb], proc: p
! UNWIND => ReleaseSTB[stb]]
THEN {ReleaseSTB[stb]; ERROR};
type ← AcquireType[stb: stb, seIndex: seIndex ! UNWIND => ReleaseSTB[stb]];
ReleaseSTB[stb];
ans ← CONS[[ir: GetInterfaceRecordFromType[type, GetWorld[tv]], usingList: NIL], ans];
};
IF IsComposite[bcd] THEN {RTSymbolsPrivate.ReleaseBCD[bcd]; ERROR};--disaster
single module bcd
[] ← BcdOps.ProcessImports[bcd, AcquireIR
! UNWIND => RTSymbolsPrivate.ReleaseBCD[bcd]];
RTSymbolsPrivate.ReleaseBCD[bcd];
};
ENDCASE => ERROR AMTypes.Error[reason: typeFault, type: TVType[tv]];
NOTE interface modules import stuff.
};
ENDCASE => ERROR;
}; -- end Imports
Implemented only for loadstate entries and global frames; sharing!
Exports: PUBLIC PROC[context: Context]
RETURNS[ans: LIST OF PartialInterfaceInstance ← NIL] = {
WITH context SELECT FROM
mc: ConfigContext => {
bcd: BcdDefs.BcdBase;
ftb: Table.Base;
AcquireIR: PROC [exph: BcdDefs.EXPHandle, expi: BcdDefs.EXPIndex]
RETURNS [stop: BOOLFALSE] = {
type: Type;
seIndex: SymbolIndex;
stb: SymbolTableBase ← AcquireSTB
[GetSTHForModule
[stamp: ftb[exph.file].version,
fileName: BcdNameToRope[bcd, ftb[exph.file].name],
moduleName: BcdNameToRope[bcd, exph.name]]];
p: PROC[stb: SymbolTableBase, isei: SymbolIdIndex] RETURNS[stop: BOOL] = {
IF ISEPublic[stb, isei]
THEN {seIndex ← ISEType[stb, isei]; RETURN[TRUE]}
ELSE RETURN[FALSE];
};
IF NOT EnumerateCtxIseis[stb: stb, ctx: STBDirectoryCtx[stb], proc: p
! UNWIND => ReleaseSTB[stb]]
THEN {ReleaseSTB[stb]; ERROR};
type ← AcquireType[stb: stb, seIndex: seIndex ! UNWIND => ReleaseSTB[stb]];
ReleaseSTB[stb];
ans ← CONS[[ir: GetInterfaceRecordFromType[type, mc.world], usingList: NIL], ans];
};
IF mc.configIndex = LoadState.nullConfig
THEN {
FOR irNames: LIST OF ROPE ← GetInterfaceRecordNames[mc.world], irNames.rest
UNTIL irNames = NIL DO
ans ← CONS[[ir: GetInterfaceRecord[irNames.first, mc.world], usingList: NIL],
   ans];
ENDLOOP;
RETURN;
};
IF mc.world # LocalWorld[] THEN {
Lock[mc.world];
{ ENABLE UNWIND => Unlock[mc.world];
h: LoadState.Handle = WorldVM.Loadstate[mc.world];
h.Acquire[];
{ ENABLE UNWIND => h.Release[];
bcd ← h.ConfigInfo[mc.configIndex].bcd;
IF bcd = NIL THEN ERROR;
bcd ← AcquireRemoteBCD[mc.world, mc.worldIncarnation, bcd];
IF bcd = NIL THEN ERROR;
}; -- end ENABLE UNWIND => h.Release[];
h.Release[];
{ ENABLE UNWIND => ReleaseRemoteBCD[bcd];
ftb ← LOOPHOLE[bcd + bcd.ftOffset];
IF NOT IsComposite[bcd] THEN ERROR; -- single module loadstate entry
[] ← BcdOps.ProcessExports[bcd, AcquireIR];
}; -- end ENABLE UNWIND => ... ReleaseRemoteBCD ...
ReleaseRemoteBCD[bcd];
}; -- end ENABLE UNWIND => Unlock[mc.world];
Unlock[mc.world];
}
ELSE { -- local case
LoadState.local.Acquire[];
bcd ← LoadState.local.ConfigInfo[mc.configIndex].bcd;
LoadState.local.Release[];
ftb ← LOOPHOLE[bcd + bcd.ftOffset];
IF NOT IsComposite[bcd] THEN ERROR; -- single module loadstate entry
[] ← BcdOps.ProcessExports[bcd, AcquireIR];
};
};
tv: RefTVRec => {
SELECT TVType[tv] FROM
gfhType => {
gets top level imports from the loadstate, via the minimodel; Encapsulation awaits the modeller.
bcd: BcdDefs.BcdBase = RTSymbolsPrivate.AcquireBCDFromVersion
[versionStamp:
IF IsRemote[tv]
THEN RemoteGFHToVersionStamp[RemoteGFHFromTV[tv]]
ELSE GFHToVersionStamp[GFHFromTV[tv]],
shortFileNameHint: Rope.Concat[TVToName[tv], ".bcd"]];
ftb: Table.Base = LOOPHOLE[bcd + bcd.ftOffset];
AcquireIR: PROC[exph: BcdDefs.EXPHandle, expi: BcdDefs.EXPIndex]
RETURNS [stop: BOOLFALSE] = {
type: Type;
seIndex: SymbolIndex;
stb: SymbolTableBase ← AcquireSTB
[GetSTHForModule
[stamp: ftb[exph.file].version,
fileName: BcdNameToRope[bcd, ftb[exph.file].name],
moduleName: BcdNameToRope[bcd, exph.name]]];
p: PROC[stb: SymbolTableBase, isei: SymbolIdIndex]
RETURNS[stop: BOOL] = {
IF ISEPublic[stb, isei]
THEN {seIndex ← ISEType[stb, isei]; RETURN[TRUE]}
ELSE RETURN[FALSE];
};
IF NOT EnumerateCtxIseis[stb: stb, ctx: STBDirectoryCtx[stb], proc: p
! UNWIND => ReleaseSTB[stb]]
THEN {ReleaseSTB[stb]; ERROR};
type ← AcquireType[stb: stb, seIndex: seIndex ! UNWIND => ReleaseSTB[stb]];
ReleaseSTB[stb];
ans ← CONS[[ir: GetInterfaceRecordFromType[type, GetWorld[tv]], usingList: NIL], ans];
};
IF IsComposite[bcd] THEN {RTSymbolsPrivate.ReleaseBCD[bcd]; ERROR};--disaster
single module bcd
[] ← BcdOps.ProcessExports[bcd, AcquireIR
! UNWIND => RTSymbolsPrivate.ReleaseBCD[bcd]];
RTSymbolsPrivate.ReleaseBCD[bcd];
};
ENDCASE => ERROR AMTypes.Error[reason: typeFault, type: TVType[tv]];
};
ENDCASE => ERROR;
}; -- end Exports
Private Procedures
StripExtension: PROC[name: ROPE] RETURNS[ROPE] =
{RETURN[Rope.Substr[base: name, start: 0, len: Rope.SkipTo[s: name, pos: 0, skip: "."]]]};
IsComposite: PROC[bcd: BcdDefs.BcdBase] RETURNS[BOOL] = {RETURN[bcd.nConfigs # 0]};
IsRemoteBCDComposite: PROC[world: World, bcd: BcdDefs.BcdBase] RETURNS[BOOL] = {
RETURN[WorldVM.Read[world, LOOPHOLE[@bcd.nConfigs, WorldVM.Address]] # 0];
};
BcdNameToRope: PROC[bcd: BcdDefs.BcdBase, n: BcdDefs.NameRecord] RETURNS[ROPE] = {
ssb: BcdDefs.NameString = LOOPHOLE[bcd + bcd.ssOffset];
ssd: ConvertUnsafe.SubString ← [base: @ssb.string, offset: n, length: ssb.size[n]];
RETURN[ConvertUnsafe.SubStringToRope[ssd]];
};
RemoteGFHToVersionStamp: PROC[gfh: RemoteGlobalFrameHandle]
RETURNS[version: BcdDefs.VersionStamp ← BcdDefs.NullVersion] = {
mx: LoadState.ModuleIndex;
config: LoadState.ConfigID;
bcd: BcdDefs.BcdBase;
ftb: Table.Base;
h: LoadState.Handle;
FindModuleVersion: PROC[mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex]
RETURNS[stop: BOOLFALSE] = {
IF mx IN [mth.gfi .. mth.gfi + mth.ngfi)
THEN {
version ← IF mth.file = BcdDefs.FTSelf THEN bcd.version ELSE ftb[mth.file].version;
RETURN[TRUE];
};
};
start RemoteGFHToVersionStamp here
IF gfh = nilRemoteGlobalFrameHandle THEN RETURN;
h ← WorldVM.Loadstate[gfh.world];
h.Acquire[];
{ ENABLE UNWIND => h.Release[];
[config, mx] ← h.GlobalFrameToModule[LOOPHOLE[gfh.gfh]];
IF config = LoadState.nullConfig THEN {h.Release[]; RETURN};
bcd ← AcquireRemoteBCD[gfh.world, gfh.worldIncarnation, h.ConfigInfo[config].bcd];
{ ENABLE UNWIND => ReleaseRemoteBCD[bcd];
ftb ← LOOPHOLE[bcd + bcd.ftOffset];
[] ← BcdOps.ProcessModules[bcd, FindModuleVersion];
}; -- end ENABLE UNWIND => ReleaseRemoteBCD[bcd];
ReleaseRemoteBCD[bcd];
}; -- end ENABLE UNWIND => h.Release[];
h.Release[];
};
GFHToVersionStamp: PROC[gfh: PrincOps.GlobalFrameHandle]
RETURNS[version: BcdDefs.VersionStamp ← BcdDefs.NullVersion] = {
mx: LoadState.ModuleIndex;
config: LoadState.ConfigID;
bcd: BcdDefs.BcdBase;
ftb: Table.Base;
FindModuleVersion: PROC[mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex]
RETURNS[stop: BOOLFALSE] = {
IF mx IN [mth.gfi .. mth.gfi + mth.ngfi)
THEN {
version ← IF mth.file = BcdDefs.FTSelf THEN bcd.version ELSE ftb[mth.file].version;
RETURN[TRUE];
};
};
start GFHToVersionStamp here
IF gfh = NIL THEN RETURN;
LoadState.local.Acquire[];
{ ENABLE UNWIND => LoadState.local.Release[];
[config, mx] ← LoadState.local.GlobalFrameToModule[gfh];
IF config = LoadState.nullConfig THEN {LoadState.local.Release[]; RETURN};
bcd ← LoadState.local.ConfigInfo[config].bcd;
ftb ← LOOPHOLE[bcd + bcd.ftOffset];
[] ← BcdOps.ProcessModules[bcd, FindModuleVersion];
}; -- end ENABLE UNWIND => LoadState.local.Release[];
LoadState.local.Release[];
};
ProgPCToFGI: PUBLIC PROC[prog: AMTypes.TV--globalFrame--, pc: PrincOps.BytePC]
RETURNS[ans: FGIndex ← FGNull] = {
stb: SymbolTableBase;
IF IsRemote[prog]
THEN stb ← AcquireSTBFromRemoteGFH[RemoteGFHFromTV[prog]]
ELSE stb ← AcquireSTBFromGFH[GFHFromTV[prog]];
{ ENABLE UNWIND => ReleaseSTB[stb];
now compute the epi and the relative pc
epi: EPI;
startPC: PrincOps.BytePC;
IF IsRemote[prog]
THEN [epi, startPC] ← RTTypesRemotePrivate.GetRemoteEp
[pc: pc, gf: RemoteGFHFromTV[prog], stb: stb]
ELSE [epi, startPC] ← RTTypesPrivate.GetEp
[pc: pc, gf: GFHFromTV[prog], stb: stb];
ans ← PCToFGI[stb, epi, pc - startPC];
}; -- end ENABLE UNWIND => ReleaseSTB[stb];
ReleaseSTB[stb];
};
[local frame, PC] => FGIndex (wrt prog module bcd)
StatementContextToFGI: PROC[sc: StatementContext] RETURNS[ans: FGIndex ← FGNull] = {
prog: REF prog SectionObj ← NIL;
bcd: BcdDefs.BcdBase;
c: Context ← sc;
world: World;
local: BOOLFALSE;
UNTIL ContextClass[c] = prog DO c ← ParentContext[c]; ENDLOOP;
world ← GetWorld[c];
prog ← NARROW[ContextSection[c]];
local ← (world = LocalWorld[]);
IF local
THEN bcd ← GetLocalBCD[GFHFromTV[c]]
ELSE bcd ← GetRemoteBCD[RemoteGFHFromTV[c]];
{ ENABLE UNWIND => IF NOT local THEN ReleaseRemoteBCD[bcd];
mth: BcdDefs.MTHandle;
stb: SymbolTableBase;
GetModule: PROC[mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex] RETURNS[BOOL] =
{RETURN[TRUE]};
[mth,] ← BcdOps.ProcessModules[bcd, GetModule];
IF mth = NIL THEN ERROR;
stb ← AcquireSTBFromSGI[bcd: bcd, sgi: mth.sseg];
{ ENABLE UNWIND => ReleaseSTB[stb];
now compute the epi and the relative pc
pc: PrincOps.BytePC = AMBridge.ContextPC[sc.localFrameTV];
epi: EPI;
startPC: PrincOps.BytePC;
IF IsRemote[sc.localFrameTV]
THEN [epi, startPC] ← RTTypesRemotePrivate.GetRemoteEp
[pc: pc, gf: RemoteGFHFromTV[GlobalParent[sc.localFrameTV]], stb: stb]
ELSE [epi, startPC] ← RTTypesPrivate.GetEp
[pc: pc, gf: FHFromTV[sc.localFrameTV].accesslink, stb: stb];
ans ← PCToFGI[stb, epi, pc - startPC];
}; -- end ENABLE UNWIND => ReleaseSTB[stb];
ReleaseSTB[stb];
}; -- end ENABLE UNWIND => ... ReleaseRemoteBCD;
IF NOT local THEN ReleaseRemoteBCD[bcd];
}; -- end StatementContextToFGI
}.