AMModelContextImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Russ Atkinson, April 18, 1985 12:24:38 pm PST
"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 [PutFR],
LoadState USING [Acquire, local, ConfigInfo, Release, Handle, nullConfig, GetChangeCount, GlobalFrameToModule, ConfigID, ModuleIndex, EnumerateAllModules, ModuleToGlobalFrame, EnumerateModulesInConfig, EnumerateConfigs, nullModule, CopiesList, ModuleInfo],
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, 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.
IF world = NIL THEN world ← WorldVM.LocalWorld[];
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]];
};
ContextName: PUBLIC PROC [context: Context] RETURNS [ans: ROPENIL] = {
SectionName with instance info
IF context = NIL THEN RETURN[NIL];
WITH context SELECT FROM
sc: StatementContext => {
ans ← IO.PutFR["%g:FGT#%g",
[rope[ContextName[sc.localFrameTV]]],
[cardinal[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 ← IO.PutFR["%g:gfh#%b", [rope[ans]], [cardinal[gfhBits]]];
};
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 ← IO.PutFR["%g:fh#%b", [rope[ans]], [cardinal[fhBits]]];
};
ENDCASE => {
ans ← Cat["Interface:", TypeToName[TVType[tv]]];
}; -- assume an IR
IF GetWorld[tv] # LocalWorld[] THEN
ans ← Cat[ans, ",world:", WorldName[GetWorld[tv]]];
};
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 ← IO.PutFR[
"%g:ConfigIndex#%g",
[rope[BcdNameToRope[bcd, ctHandle.name]]],
[cardinal[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 ← IO.PutFR["%g:ConfigIndex#%g,world:%g",
[rope[BcdNameToRope[bcd, ctHandle.name]]],
[cardinal[LOOPHOLE[mc.configIndex, CARDINAL]]],
[rope[WorldName[mc.world]]] ];
};
ReleaseRemoteBCD[bcd];
};
}; -- end ELSE arm (mc.configIndex # LoadState.nullConfig)
ENDCASE => ERROR AMTypes.Error[reason: notImplemented];
};
MostRecentNamedContext: PUBLIC PROC [name: ROPE, context: --world or model-- Context] RETURNS [ans: Context ← NIL] = {
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.
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 ← LoadState.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
RRA: In all cases where we do not already have the name we should fill in the name. If we get an AMTypes.Error when trying to execute the caller's proc we just go on to the next frame.
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
! AMTypes.Error => LOOP]
THEN RETURN[gfList.first.context];
ENDLOOP;
};
NamedContexts: PUBLIC PROC [name: ROPE, context: Context, proc: PROC [Context] RETURNS [stop: BOOL]] RETURNS [ans: Context ← NIL] = {
an enumerator. Like MostRecentNamedContext, but gets 'em all.
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];
};
ContextSection: PUBLIC PROC [context: Context] RETURNS [ans: Section ← NIL] = {
param to creator of context
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[ LOOPHOLE[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];
};
ParentContext: PUBLIC PROC [context: Context] RETURNS [Context] = {
world => NIL
model => world
prog => model
proc => prog
statement => proc
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 => {
world: World ← GetWorld[tv];
ci: LoadState.ConfigID;
IF NOT IsRemote[tv]
THEN {
gfh: PrincOps.GlobalFrameHandle = GFHFromTV[tv];
LoadState.local.Acquire[];
ci ← LoadState.local.GlobalFrameToModule[gfh].config;
LoadState.local.Release[];
}
ELSE { -- remote case
rgfh: RemoteGlobalFrameHandle = RemoteGFHFromTV[tv];
Lock[world];
{ ENABLE UNWIND => Unlock[world];
h: LoadState.Handle ← WorldVM.Loadstate[world];
h.Acquire[];
ci ← h.GlobalFrameToModule[LOOPHOLE[rgfh.gfh]
! UNWIND => h.Release[]].config;
h.Release[];
}; -- end ENABLE UNWIND => Unlock[world];
Unlock[world];
};
RETURN[NEW[ConfigContextObj ← [
world: 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];
};
ContextChildren: PUBLIC PROC [context: Context, proc: PROC [Context] RETURNS [stop: BOOL]] RETURNS [ans: Context ← NIL--NIL if not stopped--] = {
world -> model or prog (TV for a global frame)
model -> prog
proc -> statement
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];
};
NextSiblingContext: PROC [context: Context] RETURNS [ans: Context ← NIL] = {
model -> model or prog (TV for a global frame)
prog -> model or prog
returns NIL if nomore
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
Imports: PUBLIC PROC [context: Context] RETURNS [ans: LIST OF PartialInterfaceInstance ← NIL] = {
... dealing with PartialInterfaceInstances
Implemented only for loadstate entries and global frames sharing
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;
};
Exports: PUBLIC PROC [context: Context] RETURNS [ans: LIST OF PartialInterfaceInstance ← NIL] = {
Implemented only for loadstate entries and global frames; sharing!
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;
};
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];
};
StatementContextToFGI: PROC [sc: StatementContext] RETURNS [ans: FGIndex ← FGNull] = {
[local frame, PC] => FGIndex (wrt prog module bcd)
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
}.