RTTypesRemotePrivateImpl.Mesa
last modified on December 8, 1983 2:42 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, CallableBodyIndex, BodyIndex,
rootBodyIndex, SymbolIdIndex, SymbolRecordIndex, SymbolIndex, nullBodyIndex],
RTSymbolOps USING[AcquireType, EnumerateRecordIseis, AcquireRope, NullISEI],
RTSymbols USING[ReleaseSTB, AcquireSTB, GetSTHForModule],
RTSymbolsPrivate USING[AcquireSTHFromSTX],
RTTypesBasicPrivate
USING
[TypeDesc, UniqueTypeFinger, STDesc, RMapTiTd, PTypeDesc, FindSTI, PSTDesc,
RMapStiStd, SymbolTableIndex, MapStiStd],
RTTypesPrivate USING[TypedVariableRec, GetCBTI, ConvertCbti],
RTTypesRemotePrivate USING[RemoteErrorType, EVRange],
SafeStorage USING[Type, nullType],
Table USING[Base],
VM USING[Interval, Allocate, Free, PageNumberForAddress, AddressForPageNumber],
WorldVM
USING
[Address, 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, 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 TEXT ← NIL] = CODE;
P R O C E D U R E S
XXX
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]];
};
raises Error
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
[config, module]
← loadState.GlobalFrameToModule[LOOPHOLE[gfh.gfh, PrincOps.GlobalFrameHandle]];
bcd ← loadState.ConfigInfo[config].bcd;
loadState.Release[];
mappedBCD ← AcquireRemoteBCD[world: gfh.world,
incarnation: gfh.worldIncarnation,
bcd: bcd];
Unlock[gfh.world];
};
-- end ENABLE UNWIND
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];
};
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: BOOL ← FALSE] = {
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[];
[config, moduleIndex] ← LoadState.local.GlobalFrameToModule[f];
bcd ← LoadState.local.ConfigInfo[config].bcd;
LoadState.local.Release[];
ssb ← LOOPHOLE[bcd + bcd.ssOffset];
[] ← BcdOps.ProcessModules[bcd, FindModuleString];
};
RemoteGFHToName:
PUBLIC
PROC[gfh: RemoteGlobalFrameHandle]
RETURNS[ans: Rope.ROPE ← NIL] =
{ 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.
ROPE ←
NIL;
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: BOOLEAN ← FALSE] =
{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;
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];
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];
{
ENABLE
UNWIND => Unlock[world];
Lock[world];
CopyRead[world: world,
from: Long[world: world,
addr: LOOPHOLE[gfh.gfh, ShortAddress]],
nwords: SIZE[PrincOps.GlobalFrame],
to: LOOPHOLE[ans, LONG POINTER]];
Unlock[world];
}};
GetRemoteFrameHeader:
PUBLIC
PROC[fh: RemoteFrameHandle]
RETURNS[ans: REF PrincOps.Frame] =
{world: World = fh.world;
ans ← NEW[PrincOps.Frame];
{
ENABLE
UNWIND => Unlock[world];
Lock[world];
CopyRead[world: world,
from: Long[world: world,
addr: LOOPHOLE[fh.fh, ShortAddress]],
nwords: SIZE[PrincOps.Frame],
to: LOOPHOLE[ans, LONG POINTER]];
Unlock[world];
}};
GetRemoteReferentType:
PUBLIC
PROC[remoteRef: RemoteRef]
RETURNS[type: Type--valid locally--] =
{ world: World = remoteRef.world;
IF remoteRef.ref = 0 THEN RETURN[nullType];
{
ENABLE
UNWIND => Unlock[world];
Lock[world];
type ← GetRemotePrefixedType[remoteRef];
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]];
};
MOVE
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]};
break up and MOVE
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];
Unlock[world]}};
break up and MOVE
IsRemoteCatchFrame:
PUBLIC
PROC[remoteFrameHandle: RemoteFrameHandle,
bti: BodyIndex]
RETURNS [isCatchFrame:
BOOLEAN ←
TRUE,
revBti: BodyIndex] =
{world: World = remoteFrameHandle.world;
{
ENABLE
UNWIND => Unlock[world];
Lock[world];
revBti ← bti;
ValidateRemoteFrame[remoteFrameHandle ! ANY => 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 !
ANY =>
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 !
ANY =>
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
};
Unlock[world];
}
};
EXITS
notCatch => {Unlock[world];
isCatchFrame ← FALSE}}};
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]]};
MOVE
AcquireBTIFromRemoteFH:
PUBLIC
PROC[remoteFrameHandle: RemoteFrameHandle,
contextPC: BOOL]
RETURNS[bti: BodyIndex] =
{stb: SymbolTableBase;
world: World = remoteFrameHandle.world;
Lock[world];
[stb, bti] ← AcquireBTHandleFromRemoteFH[remoteFrameHandle, contextPC
! ANY => GOTO nope];
Unlock[world];
ReleaseSTB[stb];
EXITS nope => {Unlock[remoteFrameHandle.world]; RETURN[nullBodyIndex]}};
MOVE
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};
MOVE
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: CARDINAL ← LAST[CARDINAL];
anyProcedure: BOOLEAN ← FALSE;
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};
MOVE
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.
ROPE ←
NIL] =
{ 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];
Unlock[world]}};
RemoteStoreWords:
PUBLIC
PROC[from:
LONG
POINTER,
to: RemotePointer,
nWords: NAT] =
{
ENABLE
UNWIND => Unlock[to.world];
Lock[to.world];
CopyWrite[world: to.world, from: from, nwords: nWords, to: to.ptr];
Unlock[to.world]};
RemoteStoreWord:
PUBLIC
PROC[to: RemotePointer, value:
CARDINAL] =
{
ENABLE
UNWIND => Unlock[to.world];
Lock[to.world];
Write[world: to.world, addr: to.ptr, value: value];
Unlock[to.world]};
RemoteStoreDoubleWord:
PUBLIC
PROC[to: RemotePointer, value:
LONG
CARDINAL] =
{
ENABLE
UNWIND => Unlock[to.world];
Lock[to.world];
LongWrite[world: to.world, addr: to.ptr, value: value];
Unlock[to.world]};
RemoteStoreFieldLong:
PUBLIC
PROC[ptr: RemotePointer,
field: RTCommon.Field,
value: LONG CARDINAL] =
{
ENABLE
UNWIND => Unlock[ptr.world];
val: LONG CARDINAL;
Lock[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];
Unlock[ptr.world];
};
GetRemoteWord:
PUBLIC
PROC[remotePointer: RemotePointer]
RETURNS[ans:
WORD] =
{
ENABLE
UNWIND => Unlock[remotePointer.world];
Lock[remotePointer.world];
ans ← Read[world: remotePointer.world, addr: remotePointer.ptr];
Unlock[remotePointer.world];
};
GetRemoteLC:
PUBLIC
PROC[remotePointer: RemotePointer]
RETURNS[ans:
LONG
CARDINAL] =
{
ENABLE
UNWIND => Unlock[remotePointer.world];
Lock[remotePointer.world];
ans ← LongRead[world: remotePointer.world, addr: remotePointer.ptr];
Unlock[remotePointer.world];
};
GetRemoteWords:
PUBLIC
PROC[remotePointer: RemotePointer, nWords:
NAT]
RETURNS[ans: WordSequence] =
{
ENABLE
UNWIND => Unlock[remotePointer.world];
Lock[remotePointer.world];
ans ← NEW[WordSequenceRecord[nWords]];
CopyRead[world: remotePointer.world,
from: remotePointer.ptr,
nwords: nWords,
to: LOOPHOLE[@ans[0], LONG POINTER]];
Unlock[remotePointer.world];
};
NOTE
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 {
ENABLE
UNWIND => Unlock[world];
remoteSignallerFrameHandle: RemoteFrameHandle ← nilRemoteFrameHandle;
Lock[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];
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.