RTTypesRemotePrivateImpl.Mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Rovner, January 16, 1984 2:39 pm
Russ Atkinson (RRA) March 22, 1985 10:00:30 am PST
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, RuntimeError, 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;
moduleName: Rope.ROPE = RemoteGFHToName[gfh: gfh];
FindModule: PROC [mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex] RETURNS [BOOL] = {
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 ! AMTypes.Error => CONTINUE].sth;
IF sth = nullHandle THEN {
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]];
};
OuterFromRemoteGFH: PUBLIC PROC [gfh: RemoteGlobalFrameHandle, inner: PROC [stb: SymbolTableBase] ] = {
stb: SymbolTableBase ← AcquireSTBFromRemoteGFH[gfh];
inner[stb ! UNWIND => ReleaseSTB[stb] ];
ReleaseSTB[stb];
};
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];
};
AcquireRemoteBCD: PUBLIC PROC [world: World, incarnation: Incarnation, bcd: BcdDefs.BcdBase] RETURNS [mappedBCD: BcdDefs.BcdBase ← NIL] ={
assumes world is locked
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: BOOL] = {
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 ! UNCAUGHT => 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
THEN {
not easy. Try harder using symbol access info for the remote type.
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: BOOL] = {
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;
};
ValidateRemoteFrame: PUBLIC PROC [remoteFH: RemoteFrameHandle] = {
raises RemoteError
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: BOOLFALSE] = {
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 = GetRemoteEntryTableBase[gf];
LONG POINTER TO PrincOps.CSegPrefix
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]]];
};
UnwindRemoteIndirectProcDesc: PUBLIC PROC [pd: RemotePD] RETURNS [RemotePD] = {
raises typeFault
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: LOOPHOLE[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: BOOL] = {
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: BOOL] = {
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: BOOL] = {
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, LOOPHOLE[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: BOOL] = {
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: BOOL] = {
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: BOOLFALSE;
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: BOOL] = {
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: BOOL] = {
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: BOOL] = {
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]};
SELECT LOOPHOLE[sed.sed, CARDINAL] FROM
LOOPHOLE[PrincOps.NullLink, CARDINAL] => RETURN[NIL];
LOOPHOLE[PrincOps.UnboundLink, CARDINAL] => RETURN[NIL];
177777B => RETURN["ERROR"];
LOOPHOLE[UNWIND, CARDINAL] => RETURN["UNWIND"];
LOOPHOLE[ABORTED, CARDINAL] => RETURN["ABORTED"];
ENDCASE;
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.