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; RemoteBCDCache: TYPE = LIST OF BCDCacheRec; BCDCacheRec: TYPE = RECORD[world: World _ , incarnation: Incarnation _ , remoteBCD: Address _ , localBCD: BcdDefs.BcdBase _ , useCount: INT _ ]; remoteBCDCache: RemoteBCDCache _ NIL; remoteBCDCacheLength: NAT _ 0; maxRemoteBCDCacheLength: NAT _ 1; SignallerFrameMessageOffset: NAT = 9; SignallerFrameSignalOffset: NAT = 7; RemoteError: PUBLIC ERROR[type: RemoteErrorType, message: LONG POINTER TO TEXT _ NIL] = CODE; 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]; 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[]; { 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]]; 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]; CopyRead[world: world, from: LOOPHOLE[bcd, Address], nwords: SIZE[BcdDefs.BCD], to: LOOPHOLE[mappedBCD, LONG POINTER] ! UNWIND => VM.Free[interval]]; IF mappedBCD.extended THEN pages _ mappedBCD.nPages - mappedBCD.rtPages.pages ELSE pages _ mappedBCD.nPages; VM.Free[interval]; interval _ VM.Allocate[count: pages]; mappedBCD _ VM.AddressForPageNumber[interval.page]; CopyRead[world: world, from: LOOPHOLE[bcd, Address], nwords: pages*PrincOps.wordsPerPage, to: LOOPHOLE[mappedBCD, LONG POINTER] ! UNWIND => VM.Free[interval]]; 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[]; { 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.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; 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]; 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 { 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] 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] = { 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]}; 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]]]; }; 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]; }; 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]}; 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: BOOL _ TRUE, 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]; 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] ]; ValidateRemoteFrame[L0Frame ! RuntimeError.UNCAUGHT, RemoteError, WorldVM.AddressFault => GOTO notCatch]; 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}; 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}; 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]; }; -- 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. 4RTTypesRemotePrivateImpl.Mesa last modified on January 16, 1984 2:39 pm by Paul Rovner TYPES VARIABLES CONSTANTS S I G N A L S 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]}}; here with the copied remote BCD. Now poke around in the remote bcd to find the version stamp, then get the symboltable now find the bcd and module of interest UnsafeStorage.GetSystemUZone[].FREE[@nBCD]; assumes world is locked UnsafeStorage.NewUObject [size: PrincOps.wordsPerPage, zone: UnsafeStorage.GetSystemUZone[]]; UnsafeStorage.GetSystemUZone[].FREE[@mappedBCD]]; UnsafeStorage.GetSystemUZone[].FREE[@mappedBCD]; UnsafeStorage.NewUObject[ size: pages*PrincOps.wordsPerPage, zone: UnsafeStorage.GetSystemUZone[]]; UnsafeStorage.GetSystemUZone[].FREE[@mappedBCD]]; seIndex must be consistent with sth: either symbols from the UTF or from the Typs's symbol access info first try for the original defining module go again for the defining module, this time with its name (search the BCD's file table) NOTE module name vs file name raises RemoteError 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]; }; raises typeFault 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]]]}; }; START GetRemoteSignalType HERE return FALSE if no valid calling frame L0Frame is the frame that encloses the catch frame return FALSE if static frame not valid (??) body of GetEp begins here Κ$v˜J˜Jšœ™Jšœ8™8J˜šΟk ˜ šœ ˜˜EJ˜7J˜?——Jšœœ ˜!Jšœœ˜,šœ˜ šœ œF˜SJ˜ ——Jšœœ˜+šœ˜J˜H—šœ˜J˜H—Jšœœ˜0šœ ˜˜LJ˜ ——šœ ˜˜BJ˜;J˜HJšœœ ˜——Jšœœ4˜MJšœœœ˜'Jšœ œ˜&Jšœœ˜!šœ ˜šœX˜XJ˜M——Jšœ œ;˜LJšœ œ*˜9Jšœœ˜*šœ˜Jšœu˜u—Jšœœ)˜=Jšœœ˜5Jšœ œœ˜Jšœ œ˜"Jšœœ˜JšœœG˜Ošœ˜ šœ[˜[J˜HJ˜———šœœΟc$˜GšœE˜LJ˜Jšœœ!˜'Jšœœ œœ˜F——J˜—Jšœœ˜+J˜ —Jšœ*™*Jšœž>˜Y˜(J˜?J˜—šœžE˜Zšœ˜!J˜J˜)˜*J˜D—šœ ˜šœœœ˜"˜˜ J˜'J˜——šœœœ ˜/˜Jšœœ5˜?J˜—šœ˜š˜Jšœ9™9šœ™šœœ˜-J˜Jšœœ˜š œœ#œœœ˜:J˜+Jšœœ˜—J˜!J˜3Jšœœœœ˜—J˜——šœž)˜/˜Jšœœ-˜7˜Jšœœ-˜7—J˜+J˜šœ˜šœ2˜6Jšœ™—Jšœ1˜5—————Jšœž˜˜J˜˜˜J˜J˜+——Jšœž˜———Jšœž˜J˜——Jšœœœ"˜@J˜Jšœ0œ˜KJ˜—Jšœž˜J˜—šŸ œœ0˜Cšœ˜J˜SJ˜+šœœœ˜'Jšœœœ˜-Jšœ˜ J˜———Jšœ™šŸœœœ!˜AJšœ"œ(˜Ršœ ˜ Jšœ˜šœ˜Jšœ˜Jšœ-˜-JšœœA˜OJšœ˜—Jšœœ˜%—šœ˜J˜——šŸœœ˜:Jšœœœ˜šœœ$˜KJšœœœœž,˜SJ˜——Jšœ?™?Jšœ™Jšœ™Jšœ ™ Jšœ!™!Jšœ™Jšœ™Jšœ1™1Jšœ™Jšœ$™$Jšœ0™0Jšœ"™"Jšœ#™#Jšœ™Jšœ™Jšœ™Jšœ™Jšœ™˜Iprocš œœœ8œœ˜[—š Πbn œœœœœ˜<šœ˜šœ ž=˜HJ˜ šœžL˜Sšœ ž&˜1Jšœ ˜ šœžH˜OJšœœ œœ˜M—Jšœœœœ˜——J˜—J˜—J˜J˜—šŸœœ?˜XJšœ<˜CJ˜ šœ ž˜J˜ šœ˜šœ ž'˜0J˜ šœžJ˜Ošœ ž+˜6Jšœ ˜ šœžN˜Sšœ˜Jšœ ˜ Jšœœ œœ˜;Jšœ˜——Jšœ˜—Jšœœ#˜)Jšœœ)˜/—Jšœ˜——Jšœœ˜)J˜J˜—Jšœ$˜*J˜J˜—šŸ œœœ)˜AJšœ˜šœž&˜@J˜šœœ˜%šœœ˜%Jšœœ˜Jšœœ˜$——Jšœœ˜+J˜——šŸœœ˜Jšœœ˜Jšœœœœ˜Jšœ˜——šœž˜J˜˜J˜——šŸœœœ˜8Jšœ žœ˜(J˜Jšœœœ ˜+J˜ Jšœ)œ˜BJ˜J˜J˜—šŸœœ˜1Jšœžœ˜"Jšœ œA˜UJšœD˜JJ˜J˜—šŸœœœ˜7Jšœ žœ˜&˜J˜J˜5˜˜šœœ˜Jšœ"œ(˜PJšœ"œ(˜PJšœœ˜——Jšœœ˜—J˜J˜——šŸœœœ˜6Jšœžœ˜1šœœ˜J˜J˜J˜šœœ+˜5Jšœœ˜šœœœ˜Jšœœ œ˜LJšœœ œ˜LJšœœ˜——šœœ1˜œ˜JJšœž˜—J˜šŸ œœœ ˜G˜šœœ˜˜šœœ œ˜.J˜——J˜——Jšœ ˜&J˜—šΟbœ˜Jšœœ2œ˜BJšœ$˜+Jšœ ˜ J˜'J˜ —šœœœ˜!˜ ˜:šœœ2˜IJšœ˜ —Jšœ˜———šœž˜J˜Jšœœ˜'šœ˜J˜——šŸœœ#œ˜IJšœ(˜/˜Jšœœ˜Jšœ œ+˜;Jšœ/œ œœ˜MJ˜˜/Jšœ&˜&Jšœœ)˜6J˜—˜'˜Jšœ&˜&Jšœœ(˜5—J˜Jšœœ˜—˜+J˜ J˜ šœ œ"˜3Jšœœ˜——Jšœœ˜1J˜——šŸ œœœ˜.J˜J˜Jšœ(˜/šœŸ œœœ˜*š œŸœœœœ˜=šœœœ˜˜šœ œ˜Jšœ œ œœ˜7Jšœ˜——Jšœœ˜Jšœœ˜—šŸœœœœ˜;šœœœ˜˜šœ œ˜Jšœ œ œœ˜7Jšœ˜——Jšœœ˜Jšœœ˜——J˜šœœ˜J˜LJ˜LJšœœ˜J˜——Jšœ™Jšœœœœ˜ Jšœœœ˜šœ œ˜%J˜+Jšœœœ˜#Jšœœœ˜*J˜J˜Jšœœ˜Jšœ˜—Jšœœœž˜:Jšœ˜J˜——š Ÿœœœœ œ˜C˜J˜J˜&Jšœ œœœ˜J˜/˜šœœ˜˜Jšœœ*˜B—˜Jšœœ*˜B—Jšœ˜—Jšœœ˜—J˜Jšœ˜ J˜——š Ÿœœœœ œœ˜Lšœœ˜J˜J˜J˜šœœ+˜5Jšœœ˜šœœœ˜Jšœœ œ˜LJšœœ œ˜LJšœœ˜——šœœ1˜˜>Jšœœ!˜)—J˜J˜J˜—š Ÿ œœœœœœ˜VJ˜šœB˜BJšœœ!˜)—J˜J˜J˜—šŸœœœ'œ˜FJšœ˜J˜—šœœœ ˜.Jšœœ˜&˜ J˜J˜J˜Jšœœ œœ˜%——šœž˜J˜J˜J˜—šŸœœœžœ˜AJšœ œ.˜Hšœœœ˜)J˜šœœ˜˜šœ˜šœ-˜1J˜Ešœ œ4˜FJšœœ œ˜—šœ œ3˜GJšœœ˜!—Jšœ˜Jšœœ,˜6———˜ šœ˜šœ˜J˜EJ˜ —šœœœ˜!J˜*˜˜Jšœ9˜9šœœ˜šœ˜J˜Jš œ1˜:—J˜———˜J˜˜ J˜ J˜D——šœ ˜˜˜ J˜ J˜C——J˜——šœž˜J˜Jš˜Jšœ˜Jšœœ,˜6———Jšœœ-˜=J˜———šŸ œœœœ˜>Jšœœ+˜2J˜—šŸœœœœ˜3Jšœœœœ˜!J˜—Jšœ˜J˜J˜—…—}―Ί