RTTypesRemotePrivateImpl.Mesa
last modified on January 16, 1984 2:39 pm by Paul Rovner
DIRECTORY
AMBridge USING
[WordSequence, WordSequenceRecord, RemotePD, RemoteGlobalFrameHandle,
RemoteFrameHandle, RemoteRef, RemoteSED, RemotePointer,
TVForRemoteFrame, nilRemotePD, nilRemoteFrameHandle, GetWorld],
AMProcessBasic USING[ReturnLink],
AMTypes USING[Error, TypedVariable, TVType],
BcdDefs USING
[MTIndex, BCD, FTSelf, SGIndex, SGNull, FTIndex, NameRecord, VersionStamp, BcdBase,
MTHandle, NameString, FTHandle],
BcdOps USING[ProcessModules, ProcessFiles],
BrandXSymbolDefs USING
[rootBodyIndex, SymbolTableBase, SymbolIdIndex, SymbolIndex, BodyIndex],
BrandYSymbolDefs USING
[rootBodyIndex, SymbolTableBase, SymbolIdIndex, SymbolIndex, BodyIndex],
ConvertUnsafe USING[SubString, SubStringToRope],
LoadState USING
[Acquire, ConfigID, local, GlobalFrameToModule, ConfigInfo, Release, Handle,
ModuleIndex],
PrincOps USING
[BytePC, ControlLink, CSegPrefix, EntryVectorItem, EPRange, Frame,
FrameCodeBase, FrameHandle, GlobalFrame, GlobalFrameHandle,
localbase, NullLink, ProcDesc, SignalDesc, UnboundLink, NullGlobalFrame,
wordsPerPage, SD, sSignal],
RemotePrincOpsUtils USING[RemoteGlobalFrame, RemoteGlobalFrameAndEntryPoint],
Rope USING[ROPE, Concat, Text, Length],
RTCommon USING[Field, StoreFieldLong],
RTSD USING[sGCState, sMapStiStd],
RTSymbolDefs USING
[SymbolTableBase, SymbolTableHandle, nullHandle, nullBase, CallableBodyIndex, BodyIndex,
rootBodyIndex, SymbolIdIndex, SymbolRecordIndex, SymbolIndex, nullBodyIndex],
RTSymbolOps USING[AcquireType, EnumerateRecordIseis, AcquireRope, NullISEI],
RTSymbols USING[ReleaseSTB, AcquireSTB, GetSTHForModule],
RTSymbolsPrivate USING[AcquireSTHFromSTX],
RTTypesBasicPrivate USING
[UniqueTypeFinger, STDesc, FindSTI, PSTDesc, RMapStiStd, SymbolTableIndex, MapStiStd, TypeDesc, RMapTiTd, PTypeDesc],
RTTypesPrivate USING[TypedVariableRec, GetCBTI, ConvertCbti],
RTTypesRemotePrivate USING[RemoteErrorType, EVRange],
RuntimeError USING[UNCAUGHT],
SafeStorage USING[Type, nullType],
Table USING[Base],
VM USING[Interval, Allocate, Free, PageNumberForAddress, AddressForPageNumber],
WorldVM USING
[Address, AddressFault, CopyRead, CopyWrite, Long, LongRead, LongWrite, Read, ShortAddress,
World, Write, Loadstate, Lock, Unlock, CurrentIncarnation, Incarnation];
RTTypesRemotePrivateImpl: MONITOR -- protects the cache of remote BCDs
IMPORTS AMBridge, AMProcessBasic, AMTypes, BcdOps, ConvertUnsafe, LoadState,
RemotePrincOpsUtils, Rope, RTCommon, RTSymbolOps, RTSymbols,
RTSymbolsPrivate, RTTypesBasicPrivate, RTTypesPrivate, RuntimeError, VM, WorldVM
EXPORTS RTTypesPrivate, RTTypesRemotePrivate
SHARES Rope
= BEGIN OPEN AMBridge, AMTypes, bx: BrandXSymbolDefs, by: BrandYSymbolDefs,
RemotePrincOpsUtils, RTSymbolDefs, RTSymbolOps, RTSymbols,
RTTypesPrivate, RTTypesRemotePrivate, SafeStorage, WorldVM;
TYPES
RemoteBCDCache: TYPE = LIST OF BCDCacheRec;
BCDCacheRec: TYPE = RECORD[world: World ← ,
incarnation: Incarnation ← ,
remoteBCD: Address ← ,
localBCD: BcdDefs.BcdBase ← ,
useCount: INT ← ];
VARIABLES
remoteBCDCache: RemoteBCDCache ← NIL;
remoteBCDCacheLength: NAT ← 0;
maxRemoteBCDCacheLength: NAT ← 1;
CONSTANTS
SignallerFrameMessageOffset: NAT = 9;
SignallerFrameSignalOffset: NAT = 7;
S I G N A L S
RemoteError: PUBLIC ERROR[type: RemoteErrorType,
message: LONG POINTER TO TEXTNIL] = CODE;
P R O C E D U R E S
raises notImplemented
ValidateRemoteRef: PUBLIC PROC[ref: RemoteRef] =
{IF FALSE THEN ERROR AMTypes.Error[reason: notImplemented, msg: "ValidateRemoteRef"];
};
SameCode: PUBLIC PROC [f1, f2: RemoteGlobalFrameHandle] RETURNS [BOOL] =
{ fcb1, fcb2: PrincOps.FrameCodeBase;
fcb1 ← GetRemoteGFHeader[f1].code;
fcb2 ← GetRemoteGFHeader[f2].code;
fcb1.out ← fcb2.out ← FALSE;
RETURN[fcb1 = fcb2]};
EnumerateRemoteGlobalFrames: PUBLIC PROC[world: World,
proc: PROC[RemoteGlobalFrameHandle]
RETURNS[BOOLEAN]]
RETURNS[RemoteGlobalFrameHandle] =
{ gftLength: CARDINAL;
{ ENABLE UNWIND => Unlock[world];
Lock[world];
gftLength ← Read[world: world,
addr: Long[world: world,
addr: LOOPHOLE[PrincOps.SD + SDDefs.sGFTLength,
ShortAddress]]];
FOR i: CARDINAL IN [1..gftLength) DO
item: PrincOpsRuntime.GFTItem;
frame: PrincOps.GlobalFrameHandle;
CopyRead[world: world,
from: Long[world: world,
addr: LOOPHOLE[PrincOpsRuntime.GFT
+ i * SIZE[PrincOpsRuntime.GFTItem],
ShortAddress]],
nwords: SIZE[PrincOpsRuntime.GFTItem],
to: @item];
frame ← PrincOpsRuntime.GetFrame[item];
IF frame # PrincOps.NullGlobalFrame AND item.epbias = 0 THEN
{IF proc[[world: world,
worldIncarnation: CurrentIncarnation[world],
gfh: LOOPHOLE[frame, ShortAddress]]]
THEN {Unlock[world]; RETURN[[world: world,
worldIncarnation: CurrentIncarnation[world],
gfh: LOOPHOLE[frame, ShortAddress]]]}};
ENDLOOP;
Unlock[world];
RETURN[nilRemoteGlobalFrameHandle]}};
AcquireSTBFromRemoteGFH: PUBLIC PROC[gfh: RemoteGlobalFrameHandle]
RETURNS[SymbolTableBase] =
{ mappedBCD: BcdDefs.BcdBase;
module: LoadState.ModuleIndex;
std: RTTypesBasicPrivate.STDesc;
sth: SymbolTableHandle ← nullHandle;
mth: BcdDefs.MTHandle;
ftb: Table.Base;
sti: RTTypesBasicPrivate.SymbolTableIndex;
FindModule: PROC [mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex] RETURNS [BOOLEAN] =
{RETURN[module IN [mth.gfi .. mth.gfi + mth.ngfi)]};
[mappedBCD, module] ← AcquireRemoteBCDAndModule[gfh];
here with the copied remote BCD. Now poke around in the remote bcd to find
the version stamp, then get the symboltable
ftb ← LOOPHOLE[mappedBCD + mappedBCD.ftOffset, Table.Base];
[mth, ] ← BcdOps.ProcessModules[mappedBCD, FindModule
! UNWIND => ReleaseRemoteBCD[mappedBCD]];
IF mth = NIL THEN {ReleaseRemoteBCD[mappedBCD]; ERROR};
std ← [symbolsStamp: IF mth.file = BcdDefs.FTSelf
THEN mappedBCD.version
ELSE ftb[mth.file].version];
ReleaseRemoteBCD[mappedBCD];
sti ← RTTypesBasicPrivate.FindSTI[std];
sth ← RTSymbolsPrivate.AcquireSTHFromSTX[sti].sth;
IF sth = nullHandle
THEN {moduleName: Rope.ROPE = RemoteGFHToName[gfh: gfh];
sth ← GetSTHForModule[stamp: std.symbolsStamp,
moduleName: moduleName,
fileName: Rope.Concat[moduleName, ".bcd"]];
IF sth # nullHandle THEN RTTypesBasicPrivate.MapStiStd[sti].sth ← sth;
};
IF sth = nullHandle
THEN ERROR AMTypes.Error[reason: noSymbols,
msg: RemoteGFHToName[gfh]]
ELSE RETURN[AcquireSTB[sth]];
};
AcquireRemoteBCDAndModule: PUBLIC PROC[gfh: RemoteGlobalFrameHandle]
RETURNS[BcdDefs.BcdBase, LoadState.ModuleIndex] =
{ bcd: BcdDefs.BcdBase; -- remote bcd
module: LoadState.ModuleIndex;
mappedBCD: BcdDefs.BcdBase;
IF gfh.gfh = 0 THEN ERROR AMTypes.Error[reason: noSymbols];
Lock[gfh.world];
{ ENABLE UNWIND => Unlock[gfh.world];
loadState: LoadState.Handle ← WorldVM.Loadstate[gfh.world];
config: LoadState.ConfigID;
loadState.Acquire[];
now find the bcd and module of interest
{ ENABLE UNWIND => loadState.Release[];
[config, module]
← loadState.GlobalFrameToModule[LOOPHOLE[gfh.gfh, PrincOps.GlobalFrameHandle]];
bcd ← loadState.ConfigInfo[config].bcd;
}; -- end ENABLE UNWIND
loadState.Release[];
mappedBCD ← AcquireRemoteBCD[
world: gfh.world,
incarnation: gfh.worldIncarnation,
bcd: bcd];
}; -- end ENABLE UNWIND
Unlock[gfh.world];
RETURN[mappedBCD, module];
}; -- end AcquireRemoteBCDAndModule
ReleaseRemoteBCD: PUBLIC ENTRY PROC[bcd: BcdDefs.BcdBase] =
{ENABLE UNWIND => NULL;
FOR l: RemoteBCDCache ← remoteBCDCache, l.rest UNTIL l = NIL
DO IF l.first.localBCD = bcd
THEN {
l.first.useCount ← l.first.useCount - 1;
IF remoteBCDCacheLength > maxRemoteBCDCacheLength
THEN {
prev: RemoteBCDCache ← NIL;
FOR s: RemoteBCDCache ← remoteBCDCache, s.rest UNTIL s = NIL
DO IF s.first.useCount = 0
THEN {
bcdP: BcdDefs.BcdBase = s.first.localBCD;
pages: NAT
IF bcdP.extended
THEN bcdP.nPages - bcdP.rtPages.pages
ELSE bcdP.nPages;
VM.Free[[page: VM.PageNumberForAddress[bcdP], count: pages]];
UnsafeStorage.GetSystemUZone[].FREE[@nBCD];
IF prev = NIL
THEN remoteBCDCache ← s.rest
ELSE prev.rest ← s.rest;
EXIT;
};
prev ← s;
ENDLOOP;
};
RETURN;
};
ENDLOOP;
ERROR;
};
FindCachedRemoteBCD: ENTRY PROC[world: World, remoteBCD: Address]
RETURNS[localBCD: BcdDefs.BcdBase ← NIL] = {
ENABLE UNWIND => NULL;
prev: RemoteBCDCache ← NIL;
incarnation: Incarnation = CurrentIncarnation[world];
FOR l: RemoteBCDCache ← remoteBCDCache, l.rest UNTIL l = NIL
DO IF l.first.world = world
AND l.first.remoteBCD = remoteBCD
AND l.first.incarnation = incarnation
THEN {
l.first.useCount ← l.first.useCount + 1;
IF prev = NIL THEN remoteBCDCache ← l.rest ELSE prev.rest ← l.rest; --unhook it
l.rest ← remoteBCDCache; -- stick it at the beginning (most recent)
remoteBCDCache ← l;
RETURN[l.first.localBCD];
};
prev ← l;
ENDLOOP;
};
EnterRemoteBCDInCache: ENTRY PROC
[world: World, remoteBCD: Address, localBCD: BcdDefs.BcdBase] = {ENABLE UNWIND => NULL;
incarnation: Incarnation = CurrentIncarnation[world];
FOR l: RemoteBCDCache ← remoteBCDCache, l.rest UNTIL l = NIL
DO
IF l.rest = NIL THEN {
l.rest ← CONS[
[world: world,
incarnation: incarnation,
remoteBCD: remoteBCD,
localBCD: localBCD,
useCount: 1],
NIL];
RETURN;
};
ENDLOOP;
remoteBCDCache ← CONS[
[world: world,
incarnation: incarnation,
remoteBCD: remoteBCD,
localBCD: localBCD,
useCount: 1],
NIL];
};
assumes world is locked
AcquireRemoteBCD: PUBLIC PROC
[world: World, incarnation: Incarnation, bcd: BcdDefs.BcdBase--remote--]
RETURNS[mappedBCD: BcdDefs.BcdBase ← NIL--local--] ={
pages: NAT;
interval: VM.Interval;
mappedBCD ← FindCachedRemoteBCD[world, LOOPHOLE[bcd, Address]];
IF mappedBCD # NIL THEN RETURN[mappedBCD];
interval ← VM.Allocate[count: 1];
mappedBCD ← VM.AddressForPageNumber[interval.page];
UnsafeStorage.NewUObject
[size: PrincOps.wordsPerPage, zone: UnsafeStorage.GetSystemUZone[]];
CopyRead[world: world,
from: LOOPHOLE[bcd, Address],
nwords: SIZE[BcdDefs.BCD],
to: LOOPHOLE[mappedBCD, LONG POINTER]
! UNWIND => VM.Free[interval]];
UnsafeStorage.GetSystemUZone[].FREE[@mappedBCD]];
IF mappedBCD.extended
THEN pages ← mappedBCD.nPages - mappedBCD.rtPages.pages
ELSE pages ← mappedBCD.nPages;
VM.Free[interval];
UnsafeStorage.GetSystemUZone[].FREE[@mappedBCD];
interval ← VM.Allocate[count: pages];
mappedBCD ← VM.AddressForPageNumber[interval.page];
UnsafeStorage.NewUObject[
size: pages*PrincOps.wordsPerPage,
zone: UnsafeStorage.GetSystemUZone[]];
CopyRead[world: world,
from: LOOPHOLE[bcd, Address],
nwords: pages*PrincOps.wordsPerPage,
to: LOOPHOLE[mappedBCD, LONG POINTER]
! UNWIND => VM.Free[interval]];
UnsafeStorage.GetSystemUZone[].FREE[@mappedBCD]];
EnterRemoteBCDInCache[
world: world,
remoteBCD: LOOPHOLE[bcd, Address],
localBCD: mappedBCD
];
};
GFHToName: PUBLIC PROC [f: PrincOps.GlobalFrameHandle] RETURNS [name: Rope.ROPE] = {
moduleIndex: LoadState.ModuleIndex;
config: LoadState.ConfigID;
ssb: BcdDefs.NameString;
bcd: BcdDefs.BcdBase;
FindModuleString: PROC
[mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex] RETURNS [ans: BOOLFALSE] = {
ssd: ConvertUnsafe.SubString;
IF moduleIndex IN [mth.gfi..mth.gfi + mth.ngfi) THEN {
ssd ← [base: @ssb.string, offset: mth.name, length: ssb.size[mth.name]];
name ← ConvertUnsafe.SubStringToRope[ssd];
RETURN [TRUE];
};
};
IF f = PrincOps.NullGlobalFrame THEN RETURN[NIL];
LoadState.local.Acquire[];
{ ENABLE UNWIND => LoadState.local.Release[];
[config, moduleIndex] ← LoadState.local.GlobalFrameToModule[f];
bcd ← LoadState.local.ConfigInfo[config].bcd;
}; -- end ENABLE UNWIND
LoadState.local.Release[];
ssb ← LOOPHOLE[bcd + bcd.ssOffset];
[] ← BcdOps.ProcessModules[bcd, FindModuleString];
};
RemoteGFHToName: PUBLIC PROC[gfh: RemoteGlobalFrameHandle]
RETURNS[ans: Rope.ROPENIL] =
{ bcd: BcdDefs.BcdBase;
module: LoadState.ModuleIndex;
ssb: BcdDefs.NameString;
FindModuleString: PROC[mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex]
RETURNS [stop: BOOLEAN] =
{ ssd: ConvertUnsafe.SubString;
IF module IN [mth.gfi..mth.gfi + mth.ngfi)
THEN {ssd ← [base: @ssb.string, offset: mth.name, length: ssb.size[mth.name]];
ans ← ConvertUnsafe.SubStringToRope[ssd];
RETURN[TRUE]}
ELSE RETURN[FALSE]};
[bcd, module] ← AcquireRemoteBCDAndModule[gfh];
ssb ← LOOPHOLE[bcd + bcd.ssOffset, BcdDefs.NameString];
[] ← BcdOps.ProcessModules[bcd, FindModuleString ! ANY => CONTINUE];
ReleaseRemoteBCD[bcd];
};
RemoteTypeToLocal: PUBLIC PROC[world: World, remoteType: CARDINAL]
RETURNS[type: Type] =
{stb: SymbolTableBase;
td: RTTypesBasicPrivate.TypeDesc; -- copied from the remote world. NO REFS.
sth: SymbolTableHandle ← nullHandle;
seIndex: SymbolIndex;
seIndex must be consistent with sth:
either symbols from the UTF or from the Typs's symbol access info
CopyRead[
world: world,
from:
LongRead[
world: world,
addr:
RemoteMapTiTd[world] -- WorldRoot[world].GCStateBasic.mapTiTd
+ SIZE[RTTypesBasicPrivate.RMapTiTd[0]]
+ LOOPHOLE[remoteType, CARDINAL] * SIZE[RTTypesBasicPrivate.PTypeDesc]
],
nwords: SIZE[RTTypesBasicPrivate.TypeDesc],
to: @td];
first try for the original defining module
seIndex ← td.utf.seIndex; -- utf: (umid: original defining module, seIndex: sei therein)
sth ← RTSymbolsPrivate.AcquireSTHFromSTX
[RTTypesBasicPrivate.FindSTI[[symbolsStamp: td.utf.umid]]].sth;
IF sth = nullHandle -- not easy. Try harder using symbol access info for the remote type.
THEN {remoteBCD: BcdDefs.BcdBase;
remoteSGI: BcdDefs.SGIndex;
remoteSymbolsStamp: BcdDefs.VersionStamp;
[remoteBCD, remoteSGI, remoteSymbolsStamp]
← WorldMapStiStdEntry[world: world, remoteSTI: td.symbolAccess.sti];
IF remoteBCD # NIL
THEN {moduleName: Rope.ROPENIL;
mappedBCD: BcdDefs.BcdBase
← AcquireRemoteBCD[world: world,
incarnation: CurrentIncarnation[world],
bcd: remoteBCD];
{ ENABLE UNWIND => ReleaseRemoteBCD[mappedBCD];
ssb: BcdDefs.NameString
= LOOPHOLE[mappedBCD + mappedBCD.ssOffset, BcdDefs.NameString];
IF remoteSGI = BcdDefs.SGNull
THEN
go again for the defining module, this time with its name
(search the BCD's file table)
{ findSymbolFTI: PROC[ffth: BcdDefs.FTHandle,
ffti: BcdDefs.FTIndex]
RETURNS[stop: BOOLEAN] =
{ IF ffth.version # remoteSymbolsStamp THEN RETURN[FALSE];
moduleName ← GetModuleName[ssb, ffth.name];
RETURN[TRUE]};
remoteSymbolsStamp ← td.utf.umid;
[] ← BcdOps.ProcessFiles[mappedBCD, findSymbolFTI];
IF moduleName = NIL THEN ERROR;
}
ELSE -- go for the module specified by the SGI
{sgb: Table.Base
= LOOPHOLE[mappedBCD + mappedBCD.sgOffset, Table.Base];
ftb: Table.Base
= LOOPHOLE[mappedBCD + mappedBCD.ftOffset, Table.Base];
fti: BcdDefs.FTIndex ← sgb[remoteSGI].file;
seIndex ← td.symbolAccess.sei;
IF fti = BcdDefs.FTSelf
THEN moduleName ← GetModuleName[ssb, mappedBCD.source]
NOTE module name vs file name
ELSE moduleName ← GetModuleName[ssb, ftb[fti].name]};
}; -- end ENABLE UNWIND
ReleaseRemoteBCD[mappedBCD];
sth ← GetSTHForModule
[stamp: remoteSymbolsStamp,
moduleName: moduleName,
fileName: Rope.Concat[moduleName, ".bcd"]];
}; -- end remoteBCD # NIL
}; -- end sth = nullHandle
IF sth = nullHandle THEN ERROR AMTypes.Error[reason: noSymbols];
stb ← AcquireSTB[sth];
type ← AcquireType[stb: stb, seIndex: seIndex ! UNWIND => ReleaseSTB[stb]];
ReleaseSTB[stb];
}; -- end RemoteTypeToLocal
GetModuleName: PROC[ssb: BcdDefs.NameString, n: BcdDefs.NameRecord]
RETURNS[name: Rope.Text] = {
ssd: ConvertUnsafe.SubString ← [base: @ssb.string, offset: n, length: ssb.size[n]];
name ← ConvertUnsafe.SubStringToRope[ssd];
FOR i: INT IN [0..Rope.Length[name]) DO
IF name[i] = '. THEN {name.length ← i; EXIT};
ENDLOOP};
raises RemoteError
ValidateRemoteFrame: PUBLIC PROC[remoteFH: RemoteFrameHandle] = {
frame: rep PrincOps.ControlLink = LOOPHOLE[remoteFH.fh, rep PrincOps.ControlLink];
IF frame.proc
OR frame.indirect
OR ~ValidRemoteGlobalFrame[
[world: remoteFH.world,
worldIncarnation: remoteFH.worldIncarnation,
gfh: LOOPHOLE[GetRemoteFrameHeader[remoteFH].accesslink, WorldVM.ShortAddress]
]]
THEN ERROR RemoteError[invalidFrame];
};
ValidRemoteGlobalFrame: PROC[gfh: RemoteGlobalFrameHandle]
RETURNS[ans: BOOLEANFALSE] =
{h: rep PrincOps.ControlLink = LOOPHOLE[gfh.gfh, rep PrincOps.ControlLink];
ans ← NOT h.proc AND NOT h.indirect}; -- AND InRemoteGFT[gfh ! ANY => CONTINUE]};
InRemoteGFT: PROC[gfh: RemoteGlobalFrameHandle] RETURNS[BOOL] =
{gftLength: CARDINAL;
world: World = gfh.world;
Lock[world];
{ ENABLE UNWIND => Unlock[world];
gftLength ← Read[world: world,
addr: Long[world: world,
addr: LOOPHOLE[PrincOps.SD + PrincOps.sGFTLength,
ShortAddress]]];
FOR k: CARDINAL IN [1..gftLength) DO
IF GetRemoteGFHandle[world: world, gfi: k] = gfh
AND GetRemoteGFHeader[gfh].gfi = k
THEN {Unlock[world]; RETURN[TRUE]};
ENDLOOP;
Unlock[world];
};
RETURN[FALSE];
};
Kludge: TYPE = RECORD [ignore1, ignore2, ignore3, ignore4, ignore5, mapTiTd: LONG POINTER];
RemoteMapTiTd: PROC[world: World] RETURNS[LONG CARDINAL] = {
RETURN[
LongRead[ -- gets the remote address of an RTTypesBasicPrivate.RMapTiTd
world: world,
addr: -- the remote address of a cell containing the remote address of an RMapTiTd
LongRead[ -- gets the remote address of a Kludge
world: world,
addr: --the remote address of a cell containing the remote address of a Kludge
Long[world: world, addr: LOOPHOLE[PrincOps.SD + RTSD.sGCState, ShortAddress]]
] + 5 * SIZE[LONG POINTER]
]
];
};
WorldMapStiStdEntry: PROC[world: World, remoteSTI: RTTypesBasicPrivate.SymbolTableIndex]
RETURNS[BcdDefs.BcdBase, BcdDefs.SGIndex, BcdDefs.VersionStamp] = {
ans: RTTypesBasicPrivate.STDesc;
CopyRead[-- gets an STDesc
world: world,
from:
LongRead[-- gets the remote address of an STDesc
world: world,
addr:-- the remote address of a cell containing the remote address of an STDesc
LongRead[ -- gets the remote address of an RMapStiStd
world: world,
addr:-- the remote address of a cell containing the remote address of an RMapStiStd
Long[
world: world,
addr: LOOPHOLE[PrincOps.SD + RTSD.sMapStiStd, ShortAddress]
]
]
+ SIZE[RTTypesBasicPrivate.RMapStiStd[0]]
+ SIZE[RTTypesBasicPrivate.PSTDesc] * remoteSTI
],
nwords: SIZE[RTTypesBasicPrivate.STDesc],
to: @ans
];
RETURN[ans.bcd, ans.sgi, ans.symbolsStamp]
};
GetRemotePc: PUBLIC PROC[gf: RemoteGlobalFrameHandle, i: EVRange]
RETURNS [PrincOps.BytePC] =
{codeBase: RemotePointer -- LONG POINTER TO PrincOps.CSegPrefix
= GetRemoteEntryTableBase[gf];
wpc: CARDINAL ← Read[world: gf.world,
addr: LOOPHOLE[codeBase.ptr, Address]
+ SIZE[PrincOps.CSegPrefix]
+ i*SIZE[PrincOps.EntryVectorItem]];
RETURN[LOOPHOLE[wpc*2, PrincOps.BytePC]]};
GetRemoteEntryTableBase: PROC [gfh: RemoteGlobalFrameHandle]
RETURNS [RemotePointer] =
{c: PrincOps.FrameCodeBase ← GetRemoteGFHeader[gfh].code;
c.out ← FALSE;
RETURN[[world: gfh.world,
worldIncarnation: gfh.worldIncarnation,
ptr: LOOPHOLE[c, Address]]];
};
raises typeFault
UnwindRemoteIndirectProcDesc: PUBLIC PROC[pd: RemotePD] RETURNS[RemotePD] = {
icl: PrincOps.ControlLink ← LOOPHOLE[pd.pd, PrincOps.ControlLink];
world: World = pd.world;
IF icl = PrincOps.NullLink OR icl = PrincOps.UnboundLink THEN RETURN[nilRemotePD];
Lock[world];
{ ENABLE UNWIND => Unlock[world];
UNTIL icl.proc DO
IF icl.indirect
THEN
icl ← LOOPHOLE[
Read[world: world,
 addr: Long[world: world, addr: LOOPHOLE[icl.link, ShortAddress]]],
PrincOps.ControlLink]
ELSE ERROR Error[reason: typeFault, type: nullType]
ENDLOOP;
}; -- end ENABLE UNWIND
Unlock[world];
RETURN[[world: world, worldIncarnation: pd.worldIncarnation, pd: icl]]};
AcquireCBTHandleFromRemotePD: PUBLIC PROC[pd: RemotePD]
RETURNS[stb: SymbolTableBase, cbti: CallableBodyIndex] = {
world: World = pd.world;
Lock[world];
{ ENABLE UNWIND => Unlock[world];
gfh: RemoteGlobalFrameHandle
← [world: world,
worldIncarnation: pd.worldIncarnation,
gfh: LOOPHOLE[RemoteGlobalFrame[world, pd.pd], WorldVM.ShortAddress]];
stb ← AcquireSTBFromRemoteGFH[gfh];
cbti ← RTTypesPrivate.GetCBTI[stb, RemoteGlobalFrameAndEntryPoint[world, pd.pd].ep];
};
Unlock[world];
};
GetRemoteGFHandle: PUBLIC PROC[world: World, gfi: PrincOps.GFTIndex]
RETURNS[RemoteGlobalFrameHandle] =
{item: PrincOpsRuntime.GFTItem;
{ ENABLE UNWIND => Unlock[world];
Lock[world];
CopyRead[world: world,
from: Long[world: world,
addr: LOOPHOLE[PrincOpsRuntime.GFT
+ gfi * SIZE[PrincOpsRuntime.GFTItem],
ShortAddress]],
nwords: SIZE[PrincOpsRuntime.GFTItem],
to: @item
];
Unlock[world];
RETURN[[world: world,
worldIncarnation: CurrentIncarnation[world],
gfh: LOOPHOLE[PrincOpsRuntime.GetFrame[item], ShortAddress]]]};
};
GetRemoteGFHeader: PUBLIC PROC[gfh: RemoteGlobalFrameHandle]
RETURNS[ans: REF PrincOps.GlobalFrame] = {
world: World = gfh.world;
ans ← NEW[PrincOps.GlobalFrame];
Lock[world];
{ ENABLE UNWIND => Unlock[world];
CopyRead[
world: world,
from: Long[world: world, addr: LOOPHOLE[gfh.gfh, ShortAddress]],
nwords: SIZE[PrincOps.GlobalFrame],
to: LOOPHOLE[ans, LONG POINTER]
];
}; -- end ENABLE UNWIND
Unlock[world];
};
GetRemoteFrameHeader: PUBLIC PROC[fh: RemoteFrameHandle]
RETURNS[ans: REF PrincOps.Frame] = {
world: World = fh.world;
ans ← NEW[PrincOps.Frame];
Lock[world];
{ ENABLE UNWIND => Unlock[world];
CopyRead[
world: world,
from: Long[world: world, addr: LOOPHOLE[fh.fh, ShortAddress]],
nwords: SIZE[PrincOps.Frame],
to: LOOPHOLE[ans, LONG POINTER]
];
}; -- end ENABLE UNWIND
Unlock[world];
};
GetRemoteReferentType: PUBLIC PROC[remoteRef: RemoteRef]
RETURNS[type: Type--valid locally--] = {
world: World = remoteRef.world;
IF remoteRef.ref = 0 THEN RETURN[nullType];
Lock[world];
type ← GetRemotePrefixedType[remoteRef ! UNWIND => Unlock[world]];
Unlock[world];
};
GetRemotePrefixedType: PROC[remoteRef: RemoteRef]
RETURNS[Type--valid locally--] = {
remoteType: CARDINAL = WorldVM.Read[world: remoteRef.world, addr: remoteRef.ref - 1];
RETURN[RemoteTypeToLocal[world: remoteRef.world, remoteType: remoteType]];
};
GetRemoteProcedureType: PUBLIC PROC[remotePD: RemotePD]
RETURNS[type: Type--valid locally--] =
{ stb: SymbolTableBase;
cbti: CallableBodyIndex;
[stb, cbti] ← AcquireCBTHandleFromRemotePD[remotePD];
type ← AcquireType
[stb,
WITH stb SELECT FROM
t: SymbolTableBase.x => [x[t.e.bb[NARROW[cbti, CallableBodyIndex.x].e].ioType]],
t: SymbolTableBase.y => [y[t.e.bb[NARROW[cbti, CallableBodyIndex.y].e].ioType]],
ENDCASE => ERROR,
! UNWIND => ReleaseSTB[stb]];
ReleaseSTB[stb]};
GetRemoteSignalType: PUBLIC PROC[remoteSED: RemoteSED]
RETURNS[type: Type ← nullType--valid locally--] =
{ ep: CARDINAL;
stb: SymbolTableBase;
world: World = remoteSED.world;
proc: PROC[stb: SymbolTableBase, isei: SymbolIdIndex]
RETURNS[stop: BOOLEAN] =
{WITH stb SELECT FROM
t: SymbolTableBase.x => RETURN[procX[t.e, NARROW[isei, SymbolIdIndex.x].e]];
t: SymbolTableBase.y => RETURN[procY[t.e, NARROW[isei, SymbolIdIndex.y].e]];
ENDCASE => ERROR};
procX: PROC[stb: bx.SymbolTableBase, isei: bx.SymbolIdIndex]
RETURNS[stop: BOOLEAN] =
{ tsei: bx.SymbolIndex;
IF stb.seb[isei].constant
AND stb.seb[tsei ← stb.UnderType[stb.seb[isei].idType]].typeTag = transfer
AND (SELECT stb.XferMode[tsei] FROM
error, signal => TRUE,
ENDCASE => FALSE)
AND ep = STInfoToEPN[LOOPHOLE[stb.seb[isei].idValue, PrincOps.SignalDesc]]
THEN {type ← AcquireType[[x[stb]], [x[stb.seb[isei].idType]]]; RETURN[TRUE]}
ELSE RETURN[FALSE]};
procY: PROC[stb: by.SymbolTableBase, isei: by.SymbolIdIndex]
RETURNS[stop: BOOLEAN] =
{ tsei: by.SymbolIndex;
IF stb.seb[isei].constant
AND stb.seb[tsei ← stb.UnderType[stb.seb[isei].idType]].typeTag = transfer
AND (SELECT stb.XferMode[tsei] FROM
error, signal => TRUE,
ENDCASE => FALSE)
AND ep = STInfoToEPN[LOOPHOLE[stb.seb[isei].idValue, PrincOps.SignalDesc]]
THEN {type ← AcquireType[[y[stb]], [y[stb.seb[isei].idType]]]; RETURN[TRUE]}
ELSE RETURN[FALSE]};
START GetRemoteSignalType HERE
IF LOOPHOLE[remoteSED.sed, CARDINAL] = 177777B -- ERROR
OR LOOPHOLE[remoteSED.sed, CARDINAL] = LOOPHOLE[UNWIND, CARDINAL]
OR LOOPHOLE[remoteSED.sed, CARDINAL] = LOOPHOLE[ABORTED, CARDINAL]
THEN RETURN[CODE[ERROR]];
Lock[world];
{ ENABLE UNWIND => Unlock[world];
gfh: PrincOps.GlobalFrameHandle;
[gfh, ep] ← RemoteGlobalFrameAndEntryPoint[world, remoteSED.sed];
stb ← AcquireSTBFromRemoteGFH[[world, remoteSED.worldIncarnation, LOOPHOLE[gfh]]];
[] ← EnumerateRecordIseis
[stb,
WITH stb SELECT FROM
t: SymbolTableBase.x => [x[t.e.bb[bx.rootBodyIndex].type]],
t: SymbolTableBase.y => [y[t.e.bb[by.rootBodyIndex].type]],
ENDCASE => ERROR,
proc
! UNWIND => ReleaseSTB[stb]];
ReleaseSTB[stb];
}; -- end ENABLE UNWIND
Unlock[world];
};
IsRemoteCatchFrame: PUBLIC PROC[remoteFrameHandle: RemoteFrameHandle, bti: BodyIndex]
RETURNS [isCatchFrame: BOOLTRUE, revBti: BodyIndex] = {
world: World = remoteFrameHandle.world;
Lock[world];
{ ENABLE UNWIND => Unlock[world];
revBti ← bti;
ValidateRemoteFrame[remoteFrameHandle
! RuntimeError.UNCAUGHT, RemoteError, WorldVM.AddressFault => GOTO notCatch];
{ -- return FALSE if input invalid
nextFrame: RemoteFrameHandle
← [world: remoteFrameHandle.world,
worldIncarnation: remoteFrameHandle.worldIncarnation,
fh: LOOPHOLE[AMProcessBasic.ReturnLink
[world,
LOOPHOLE[remoteFrameHandle.fh, PrincOps.FrameHandle]],
ShortAddress]];
nextFHdr: REF PrincOps.Frame;
ValidateRemoteFrame[nextFrame
! RuntimeError.UNCAUGHT, RemoteError, WorldVM.AddressFault => GOTO notCatch];
return FALSE if no valid calling frame
nextFHdr ← GetRemoteFrameHeader[nextFrame];
IF nextFHdr.accesslink # RemoteSigGF[remoteFrameHandle.world]
THEN GOTO notCatch;
{ -- return FALSE if caller not signaller
sl: CARDINAL = LOOPHOLE[GetRemoteFrameHeader[remoteFrameHandle].staticlink];
L0Frame: RemoteFrameHandle
← [world: remoteFrameHandle.world,
worldIncarnation: remoteFrameHandle.worldIncarnation,
fh: 0];
IF sl = 0 THEN GOTO notCatch;
L0Frame ← [
world: remoteFrameHandle.world,
worldIncarnation: remoteFrameHandle.worldIncarnation,
fh: LOOPHOLE[sl - PrincOps.localbase, ShortAddress]
];
L0Frame is the frame that encloses the catch frame
ValidateRemoteFrame[L0Frame
! RuntimeError.UNCAUGHT, RemoteError, WorldVM.AddressFault => GOTO notCatch];
return FALSE if static frame not valid (??)
IF GetRemoteFrameHeader[remoteFrameHandle].accesslink
# GetRemoteFrameHeader[L0Frame].accesslink
THEN GOTO notCatch;
IF ~nextFHdr.mark THEN GOTO notCatch; -- calling frame not the signaller
{ -- detect situation where catch frame has no locals, thus no body table.
tr: REF TypedVariableRec
= NARROW[TVForRemoteFrame[L0Frame], REF TypedVariableRec];
WITH hd: tr.head SELECT FROM
remoteFH => IF bti = hd.bti THEN revBti ← nullBodyIndex;
ENDCASE => ERROR
}; -- end detect situation where ...
}; -- end return FALSE if caller not signaller
}; -- end return FALSE if input invalid
}; -- end ENABLE UNWIND
Unlock[world];
EXITS notCatch => {Unlock[remoteFrameHandle.world]; isCatchFrame ← FALSE};
}; -- end IsRemoteCatchFrame
RemoteSigGF: PROC[world: World] RETURNS[PrincOps.GlobalFrameHandle] = {
pd: PrincOps.ProcDesc
= LOOPHOLE[Read[world: world,
addr: Long[world: world,
addr: LOOPHOLE[PrincOps.SD + PrincOps.sSignal,
ShortAddress]]],
PrincOps.ProcDesc];
RETURN[RemoteGlobalFrame[world, pd]]};
AcquireBTIFromRemoteFH:
PUBLIC PROC[remoteFrameHandle: RemoteFrameHandle, contextPC: BOOL]
RETURNS[bti: BodyIndex ← nullBodyIndex] = {
stb: SymbolTableBase ← nullBase;
world: World = remoteFrameHandle.world;
Lock[world];
{ ENABLE UNWIND => Unlock[world];
[stb, bti]
← AcquireBTHandleFromRemoteFH[remoteFrameHandle, contextPC
! RuntimeError.UNCAUGHT, RemoteError, WorldVM.AddressFault, AMTypes.Error
=> CONTINUE
];
}; -- end ENABLE UNWIND
Unlock[world];
IF stb # nullBase THEN ReleaseSTB[stb];
};
AcquireBTHandleFromRemoteFH: PROC[fh: RemoteFrameHandle, contextPC: BOOL]
RETURNS[stb: SymbolTableBase, bti: BodyIndex] =
{ start: PrincOps.BytePC;
epn: CARDINAL;
remoteFrame: REF PrincOps.Frame = GetRemoteFrameHeader[fh];
framePC: PrincOps.BytePC = [(remoteFrame.pc - (IF contextPC THEN 0 ELSE 1))];
stb ← AcquireSTBFromRemoteGFH[[world: fh.world,
worldIncarnation: fh.worldIncarnation,
gfh: LOOPHOLE[remoteFrame.accesslink, ShortAddress]]];
[epn, start] ← GetRemoteEp[pc: framePC,
gf: [world: fh.world,
worldIncarnation: fh.worldIncarnation,
gfh: LOOPHOLE[remoteFrame.accesslink, ShortAddress]],
stb: stb
! UNWIND => ReleaseSTB[stb]];
bti ← RTTypesPrivate.ConvertCbti[base: stb,
pc: framePC,
start: start,
lastBti: LOOPHOLE[RTTypesPrivate.GetCBTI[stb, epn]]
! UNWIND => ReleaseSTB[stb]];
IF bti = rootBodyIndex THEN bti ← nullBodyIndex};
GetRemoteEp: PUBLIC PROC [pc: PrincOps.BytePC,
gf: RemoteGlobalFrameHandle,
stb: SymbolTableBase]
RETURNS [ep: EVRange, start: PrincOps.BytePC] =
{ FindMaxEI: PROC RETURNS [max: EVRange] =
{ GetMaxX: PROC [bti: bx.BodyIndex] RETURNS [stop: BOOLEAN] =
{WITH stb SELECT FROM
t: SymbolTableBase.x =>
WITH t.e.bb[bti] SELECT FROM
Callable => IF ~inline THEN max ← MAX[max, entryIndex];
ENDCASE;
ENDCASE => ERROR;
RETURN[FALSE]};
GetMaxY: PROC [bti: by.BodyIndex] RETURNS [stop: BOOLEAN] =
{WITH stb SELECT FROM
t: SymbolTableBase.y =>
WITH t.e.bb[bti] SELECT FROM
Callable => IF ~inline THEN max ← MAX[max, entryIndex];
ENDCASE;
ENDCASE => ERROR;
RETURN[FALSE]};
max ← 0;
WITH stb SELECT FROM
t: SymbolTableBase.x => [] ← t.e.EnumerateBodies[bx.rootBodyIndex, GetMaxX];
t: SymbolTableBase.y => [] ← t.e.EnumerateBodies[by.rootBodyIndex, GetMaxY];
ENDCASE => ERROR};
body of GetEp begins here
diff: CARDINALLAST[CARDINAL];
anyProcedure: BOOLEANFALSE;
FOR i: EVRange IN [0..FindMaxEI[]] DO
last: PrincOps.BytePC ← GetRemotePc[gf, i];
IF Card[last] > Card[pc] THEN LOOP;
IF Card[pc] - Card[last] > diff THEN LOOP;
diff ← Card[pc] - Card[last];
ep ← i; start ← last;
anyProcedure ← TRUE;
ENDLOOP;
IF ~anyProcedure THEN ERROR; -- SIGNAL NotInAnyProcedure;
RETURN};
RemotePDToName: PUBLIC PROC[pd: RemotePD] RETURNS[ans: Rope.ROPE] =
{ stb: SymbolTableBase;
cbti: CallableBodyIndex;
pd ← UnwindRemoteIndirectProcDesc[pd];
IF pd.pd = 0 THEN RETURN[NIL];
[stb, cbti] ← AcquireCBTHandleFromRemotePD[pd];
ans ← AcquireRope[stb,
WITH stb SELECT FROM
t: SymbolTableBase.x =>
[x[t.e.seb[t.e.bb[NARROW[cbti, CallableBodyIndex.x].e].id].hash]],
t: SymbolTableBase.y =>
[y[t.e.seb[t.e.bb[NARROW[cbti, CallableBodyIndex.y].e].id].hash]],
ENDCASE => ERROR
! UNWIND => ReleaseSTB[stb]];
ReleaseSTB[stb];
RETURN[ans]};
RemoteSEDToName: PUBLIC PROC[sed: RemoteSED] RETURNS[ans: Rope.ROPENIL] =
{ ep: CARDINAL;
stb: SymbolTableBase;
world: World = sed.world;
proc: PROC[stb: SymbolTableBase, isei: SymbolIdIndex]
RETURNS[stop: BOOLEAN] =
{WITH stb SELECT FROM
t: SymbolTableBase.x => RETURN[procX[t.e, NARROW[isei, SymbolIdIndex.x].e]];
t: SymbolTableBase.y => RETURN[procY[t.e, NARROW[isei, SymbolIdIndex.y].e]];
ENDCASE => ERROR};
procX: PROC[stb: bx.SymbolTableBase, isei: bx.SymbolIdIndex]
RETURNS[stop: BOOLEAN] =
{ tsei: bx.SymbolIndex;
IF stb.seb[isei].constant
AND stb.seb[tsei ← stb.UnderType[stb.seb[isei].idType]].typeTag = transfer
AND (SELECT stb.XferMode[tsei] FROM
error, signal => TRUE,
ENDCASE => FALSE)
AND ep = STInfoToEPN[LOOPHOLE[stb.seb[isei].idValue, PrincOps.SignalDesc]]
THEN {ans ← AcquireRope[[x[stb]], [x[stb.seb[isei].hash]]]; RETURN[TRUE]}
ELSE RETURN[FALSE]};
procY: PROC[stb: by.SymbolTableBase, isei: by.SymbolIdIndex]
RETURNS[stop: BOOLEAN] =
{ tsei: by.SymbolIndex;
IF stb.seb[isei].constant
AND stb.seb[tsei ← stb.UnderType[stb.seb[isei].idType]].typeTag = transfer
AND (SELECT stb.XferMode[tsei] FROM
error, signal => TRUE,
ENDCASE => FALSE)
AND ep = STInfoToEPN[LOOPHOLE[stb.seb[isei].idValue, PrincOps.SignalDesc]]
THEN {ans ← AcquireRope[[y[stb]], [y[stb.seb[isei].hash]]]; RETURN[TRUE]}
ELSE RETURN[FALSE]};
IF sed.sed = PrincOps.NullLink OR sed.sed = PrincOps.UnboundLink
THEN RETURN[NIL];
IF LOOPHOLE[sed.sed, CARDINAL] = 177777B
THEN RETURN["ERROR"];
IF LOOPHOLE[sed.sed, CARDINAL] = LOOPHOLE[UNWIND, CARDINAL]
THEN RETURN["UNWIND"];
IF LOOPHOLE[sed.sed, CARDINAL] = LOOPHOLE[ABORTED, CARDINAL]
THEN RETURN["ABORTED"];
Lock[world];
{ ENABLE UNWIND => Unlock[world];
sei: SymbolRecordIndex;
gfh: PrincOps.GlobalFrameHandle;
[gfh, ep] ← RemoteGlobalFrameAndEntryPoint[world, sed.sed];
stb ← AcquireSTBFromRemoteGFH[[world, sed.worldIncarnation, LOOPHOLE[gfh]]];
sei ← WITH stb SELECT FROM
t: SymbolTableBase.x => [x[t.e.bb[bx.rootBodyIndex].type]],
t: SymbolTableBase.y => [y[t.e.bb[by.rootBodyIndex].type]],
ENDCASE => ERROR;
IF NOT NullISEI[LOOPHOLE[sei]] THEN
[] ← EnumerateRecordIseis[stb, sei, proc ! UNWIND => ReleaseSTB[stb]];
ReleaseSTB[stb];
}; -- end ENABLE UNWIND
Unlock[world];
};
RemoteStoreWords:
PUBLIC PROC[from: LONG POINTER, to: RemotePointer, nWords: NAT] = {
Lock[to.world];
CopyWrite[world: to.world, from: from, nwords: nWords, to: to.ptr
! UNWIND => Unlock[to.world]];
Unlock[to.world];
};
RemoteStoreWord: PUBLIC PROC[to: RemotePointer, value: CARDINAL] = {
Lock[to.world];
Write[world: to.world, addr: to.ptr, value: value ! UNWIND => Unlock[to.world]];
Unlock[to.world];
};
RemoteStoreDoubleWord: PUBLIC PROC[to: RemotePointer, value: LONG CARDINAL] = {
Lock[to.world];
LongWrite[world: to.world, addr: to.ptr, value: value ! UNWIND => Unlock[to.world]];
Unlock[to.world];
};
RemoteStoreFieldLong:
PUBLIC PROC[ptr: RemotePointer, field: RTCommon.Field, value: LONG CARDINAL] = {
val: LONG CARDINAL;
Lock[ptr.world];
{ENABLE UNWIND => Unlock[ptr.world];
val ← LongRead[world: ptr.world, addr: LOOPHOLE[ptr.ptr, Address]];
RTCommon.StoreFieldLong[ptr: @val, field: field, newValue: value];
LongWrite[world: ptr.world, addr: LOOPHOLE[ptr.ptr, Address], value: val];
}; -- end ENABLE UNWIND
Unlock[ptr.world];
};
GetRemoteWord: PUBLIC PROC[remotePointer: RemotePointer] RETURNS[ans: WORD] = {
Lock[remotePointer.world];
ans ← Read[world: remotePointer.world, addr: remotePointer.ptr
! UNWIND => Unlock[remotePointer.world]];
Unlock[remotePointer.world];
};
GetRemoteLC: PUBLIC PROC[remotePointer: RemotePointer] RETURNS[ans: LONG CARDINAL] = {
Lock[remotePointer.world];
ans ← LongRead[world: remotePointer.world, addr: remotePointer.ptr
! UNWIND => Unlock[remotePointer.world]];
Unlock[remotePointer.world];
};
GetRemoteWords: PUBLIC PROC[remotePointer: RemotePointer, nWords: NAT]
RETURNS[ans: WordSequence] = {
Lock[remotePointer.world];
{ENABLE UNWIND => Unlock[remotePointer.world];
ans ← NEW[WordSequenceRecord[nWords]];
CopyRead[
world: remotePointer.world,
from: remotePointer.ptr,
nwords: nWords,
to: LOOPHOLE[@ans[0], LONG POINTER]];
}; -- end ENABLE UNWIND
Unlock[remotePointer.world];
};
RemoteSignalValues: PUBLIC PROC[tv: TypedVariable--catch Frame--]
RETURNS [message: CARDINAL, signal: PrincOps.SignalDesc, world: World] =
{rtr: REF TypedVariableRec ← NARROW[tv];
world ← GetWorld[tv];
WITH th: rtr.head SELECT FROM
fh =>
IF th.isCatchFrame
THEN {signallerFrameHandle: PrincOps.FrameHandle;
signallerFrameHandle ← AMProcessBasic.ReturnLink[world, th.fh].frame;
message ← LOOPHOLE[signallerFrameHandle + SignallerFrameMessageOffset,
POINTER TO UNSPECIFIED]^;
signal ← LOOPHOLE[signallerFrameHandle + SignallerFrameSignalOffset,
POINTER TO PrincOps.SignalDesc]^;
RETURN}
ELSE ERROR Error[reason: typeFault, type: TVType[tv]];
remoteFH =>
IF th.isCatchFrame
THEN {
remoteSignallerFrameHandle: RemoteFrameHandle ← nilRemoteFrameHandle;
Lock[world];
{ ENABLE UNWIND => Unlock[world];
ValidateRemoteFrame[th.remoteFrameHandle];
remoteSignallerFrameHandle
← [world: world,
worldIncarnation: th.remoteFrameHandle.worldIncarnation,
fh: LOOPHOLE[
AMProcessBasic.ReturnLink
[world,
LOOPHOLE[th.remoteFrameHandle.fh, PrincOps.FrameHandle]],
ShortAddress]];
message ← Read[
world: world,
addr: Long[
world: world,
addr: remoteSignallerFrameHandle.fh + SignallerFrameMessageOffset]];
signal ← LOOPHOLE
[Read[world: world,
addr: Long[
world: world,
addr: remoteSignallerFrameHandle.fh + SignallerFrameSignalOffset]],
PrincOps.SignalDesc];
}; -- end ENABLE UNWIND
Unlock[world];
RETURN;
}
ELSE ERROR Error[reason: typeFault, type: TVType[tv]];
ENDCASE => ERROR Error[reason: typeFault, type: TVType[tv]]};
STInfoToEPN: PROC[cl: PrincOps.SignalDesc] RETURNS[CARDINAL] =
{RETURN[(cl.gfi - 1) * PrincOps.EPRange + cl.ep]};
Card: PROC[pc: PrincOps.BytePC] RETURNS[CARDINAL] =
{RETURN[LOOPHOLE[pc, CARDINAL]]};
END.