<> <> <> <> 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; <> 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; <

> <> <> <<{IF FALSE THEN ERROR AMTypes.Error[reason: notImplemented, msg: "ValidateRemoteRef"];>> <<};>> <> <<{ fcb1, fcb2: PrincOps.FrameCodeBase;>> <> <> <> <> <> <> <> <> <<{ gftLength: CARDINAL;>> <<{ ENABLE UNWIND => Unlock[world];>> <> <> <> <> <> <> <> <> <> <> <> <<+ i * SIZE[PrincOpsRuntime.GFTItem],>> <> <> <> <> <> <<{IF proc[[world: world,>> <> <> <> <> <> <> <> <> 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]; <> 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[]; <> { 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] RETURNS [mappedBCD: BcdDefs.BcdBase _ NIL] ={ <> 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]; <> <<[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]]; <> 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: 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; <> <> 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 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 { <> <<(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 { <> 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: BOOL _ FALSE] = { h: rep PrincOps.ControlLink = LOOPHOLE[gfh.gfh, rep PrincOps.ControlLink]; ans _ NOT h.proc AND NOT h.indirect; }; -- AND InRemoteGFT[gfh ! ANY => CONTINUE]}; <> <<{gftLength: CARDINAL;>> <> <> <<{ ENABLE UNWIND => Unlock[world];>> <> <> <> <> <> <> <> <> <> <> <<};>> <> <<};>> 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]; <> 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: 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]; }; <> <> <<{item: PrincOpsRuntime.GFTItem;>> <<{ ENABLE UNWIND => Unlock[world];>> <> <> <> <> <<+ gfi * SIZE[PrincOpsRuntime.GFTItem],>> <> <> <> <<];>> <> <> <> <> <<};>> 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]}; <> 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, 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}; <> diff: CARDINAL _ LAST[CARDINAL]; anyProcedure: BOOL _ 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: 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.