-- RTTypesRemotePrivateImpl.Mesa -- last modified on December 21, 1982 3:17 pm by Paul Rovner DIRECTORY AMBridge USING[WordSequence, WordSequenceRecord, RemotePD, RemoteGlobalFrameHandle, RemoteFrameHandle, RemoteRef, RemoteSED, RemotePointer, TVForRemoteFrame, nilRemotePD, nilRemoteGlobalFrameHandle, nilRemoteFrameHandle], AMTypes USING[Error, TypedVariable, TVType], BcdDefs USING[MTIndex, BCD, FTSelf, SGIndex, SGNull, FTIndex, NameRecord], BcdOps USING[BcdBase, MTHandle, ProcessModules, NameString, FTHandle, ProcessFiles], ConvertUnsafe USING[ToRope], Environment USING[wordsPerPage], LongString USING[AppendChar, AppendOctal, SubStringDescriptor, AppendSubString], PilotLoadStateOps USING[InputLoadState, ReleaseLoadState, GetModule, AcquireBcd], PilotLoadStateFormat USING[LoadState, LoadStateObject, ModuleInfo], PilotLoadStatePrivate USING[InstallLoadState], PrincOps USING[BytePC, ControlLink, CSegPrefix, EntryVectorItem, EPRange, Frame, FrameCodeBase, FrameHandle, GFTIndex, GlobalFrame, GlobalFrameHandle, localbase, NullLink, ProcDesc, SignalDesc, UnboundLink, NullGlobalFrame], PrincOpsRuntime USING[GFT, GFTItem, GetFrame], Rope USING[ROPE, Concat], RTBasic USING[Type, nullType], RTCommon USING[Field, StoreFieldLong], RTQuanta USING[QuantumIndex], RTRefCounts USING[AGCState], RTSD USING[sRTState, sFirstCedarFree], RTSymbolDefs USING[SymbolTableBase, SymbolTableHandle, nullHandle, CallableBodyIndex, BodyIndex, rootBodyIndex, SymbolIdIndex, SymbolRecordIndex, SymbolIndex, nullBodyIndex, nullSymbolIndex], RTSymbolOps USING[AcquireType, EnumerateRecordIseis, AcquireRope], RTSymbols USING[ReleaseSTB, AcquireSTB], RTSymbolsPrivate USING[AcquireSTHFromSTX, GetSTHForModule], RTTypesBasicPrivate USING[TypeDesc, UniqueTypeFinger, STDesc, RMapTiTd, PTypeDesc, FindSTI, PSTDesc, RMapStiStd, SymbolTableIndex, MapStiStd], RTTypesPrivate USING[TypedVariableRec, GetCBTI, ConvertCbti], RTTypesRemotePrivate USING[RemoteErrorType, EVRange], RTZones USING[ZoneFinger, SubZone, SubZoneIndex, TMapQZf, MapPtrQ, NodeHeader, sizeNd, SubZoneRec, RMapQZf, RMapSziSz], SDDefs USING[SD, sSignal, sGFTLength], SafeStorage USING[NewZone], Strings USING[SubStringDescriptor, AppendSubString], Table USING[Base], UnsafeStorage USING[NewUObject, GetSystemUZone], WorldVM USING[Address, CopyRead, CopyWrite, Long, LongRead, LongWrite, Read, ShortAddress, World, Write, Loadstate, Lock, Unlock, CurrentIncarnation]; RTTypesRemotePrivateImpl: MONITOR -- protects the cache of remote BCDs IMPORTS AMBridge, AMTypes, BcdOps, ConvertUnsafe, LongString, PilotLoadStateOps, PilotLoadStatePrivate, PrincOpsRuntime, Rope, RTCommon, RTSymbolOps, RTSymbols, RTSymbolsPrivate, RTTypesBasicPrivate, RTTypesPrivate, RTZones, SafeStorage, Strings, UnsafeStorage, WorldVM EXPORTS RTTypesRemotePrivate = BEGIN OPEN AMBridge, AMTypes, RTBasic, RTSymbolDefs, RTSymbolOps, RTSymbols, RTTypesPrivate, RTTypesRemotePrivate, WorldVM; z: ZONE = SafeStorage.NewZone[prefixed]; -- TYPES RemoteBCDCache: TYPE = LIST OF BCDCacheRec; BCDCacheRec: TYPE = RECORD[world: World _ , remoteBCD: Address _ , localBCD: BcdOps.BcdBase _ , useCount: INT _ ]; -- VARIABLES remoteBCDCache: RemoteBCDCache _ NIL; remoteBCDCacheLength: NAT _ 0; maxRemoteBCDCacheLength: NAT _ 1; -- CONSTANTS SignallerFrameMessageOffset: NAT = 9; SignallerFrameSignalOffset: NAT = 7; -- S I G N A L S RemoteError: PUBLIC ERROR[type: RemoteErrorType, message: LONG POINTER TO TEXT _ NIL] = CODE; -- P R O C E D U R E S --XXX -- raises notImplemented ValidateRemoteRef: PUBLIC PROC[ref: RemoteRef] = {IF FALSE THEN ERROR AMTypes.Error[reason: notImplemented, msg: "ValidateRemoteRef"]; }; SameCode: PUBLIC PROC [f1, f2: RemoteGlobalFrameHandle] RETURNS [BOOL] = { fcb1, fcb2: PrincOps.FrameCodeBase; fcb1 _ GetRemoteGFHeader[f1].code; fcb2 _ GetRemoteGFHeader[f2].code; fcb1.out _ fcb2.out _ FALSE; RETURN[fcb1 = fcb2]}; EnumerateRemoteGlobalFrames: PUBLIC PROC[world: World, proc: PROC[RemoteGlobalFrameHandle] RETURNS[BOOLEAN]] RETURNS[RemoteGlobalFrameHandle] = { gftLength: CARDINAL; { ENABLE UNWIND => Unlock[world]; Lock[world]; gftLength _ Read[world: world, addr: Long[world: world, addr: LOOPHOLE[SDDefs.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]}}; -- MOVE NOTE PROBLEM! AcquireSTBFromRemoteGFH: PUBLIC PROC[gfh: RemoteGlobalFrameHandle] RETURNS[SymbolTableBase] = { mappedBCD: BcdOps.BcdBase; module: PilotLoadStateFormat.ModuleInfo; -- a loadstate.gft entry std: RTTypesBasicPrivate.STDesc; sth: SymbolTableHandle; mth: BcdOps.MTHandle; ftb: Table.Base; sti: RTTypesBasicPrivate.SymbolTableIndex; FindModule: PROC [mth: BcdOps.MTHandle, mti: BcdDefs.MTIndex] RETURNS [BOOLEAN] = {RETURN[module.gfi 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[LOOPHOLE[mappedBCD, LONG POINTER] + mappedBCD.ftOffset, Table.Base]; [mth, ] _ BcdOps.ProcessModules[LOOPHOLE[mappedBCD], FindModule ! UNWIND => ReleaseRemoteBCD[mappedBCD]]; IF mth = NIL THEN 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, moduleNameOnly: TRUE]; sth _ RTSymbolsPrivate.GetSTHForModule[stamp: std.symbolsStamp, moduleName: moduleName, fileName: Rope.Concat[moduleName, ".bcd"]]; IF sth # nullHandle THEN RTTypesBasicPrivate.MapStiStd[sti].sth _ sth; }; IF sth = nullHandle THEN ERROR AMTypes.Error[reason: noSymbols, msg: RemoteGFHToName[gfh]] ELSE RETURN[AcquireSTB[sth]]; }; -- raises Error AcquireRemoteBCDAndModule: PUBLIC PROC[gfh: RemoteGlobalFrameHandle] RETURNS[BcdOps.BcdBase, PilotLoadStateFormat.ModuleInfo] = { bcd: BcdOps.BcdBase; -- remote bcd module: PilotLoadStateFormat.ModuleInfo; -- a loadstate.gft entry world: World = gfh.world; mappedBCD: BcdOps.BcdBase; FindOriginal: PROCEDURE [f: RemoteGlobalFrameHandle] RETURNS [BOOLEAN] = {RETURN[(f.gfh # gfh.gfh) AND (SameCode[gfh, f]) AND (~GetRemoteGFHeader[f].copied)]}; IF gfh.gfh = 0 THEN ERROR AMTypes.Error[reason: noSymbols]; { ENABLE UNWIND => Unlock[world]; loadStateHeld: BOOLEAN _ FALSE; oldState: PilotLoadStateFormat.LoadState; newState: REF PilotLoadStateFormat.LoadStateObject; Lock[world]; { ENABLE ANY => IF loadStateHeld THEN {PilotLoadStateOps.ReleaseLoadState[]; loadStateHeld _ FALSE}; IF GetRemoteGFHeader[gfh].copied THEN gfh _ EnumerateRemoteGlobalFrames[world, FindOriginal]; newState _ Loadstate[gfh.world]; loadStateHeld _ TRUE; [] _ PilotLoadStateOps.InputLoadState[]; oldState _ PilotLoadStatePrivate.InstallLoadState[LOOPHOLE[newState]]; -- no error raised -- now find the bcd and module of interest module _ PilotLoadStateOps.GetModule[GetRemoteGFHeader[gfh].gfi]; IF NOT loadStateHeld THEN {loadStateHeld _ TRUE; [] _ PilotLoadStateOps.InputLoadState[]; [] _ PilotLoadStatePrivate.InstallLoadState[LOOPHOLE[newState]];-- no error raised--}; bcd _ PilotLoadStateOps.AcquireBcd -- NOTE assume that it doesn't need to be released [config: module.config]; IF NOT loadStateHeld THEN {loadStateHeld _ TRUE; [] _ PilotLoadStateOps.InputLoadState[]; [] _ PilotLoadStatePrivate.InstallLoadState[LOOPHOLE[newState]];-- no error raised--}; [] _ PilotLoadStatePrivate.InstallLoadState[oldState]; PilotLoadStateOps.ReleaseLoadState[]; loadStateHeld _ FALSE}; -- end ENABLE ANY mappedBCD _ AcquireRemoteBCD[world: gfh.world, bcd: bcd]; Unlock[world]; }; -- end ENABLE UNWIND RETURN[mappedBCD, module]; }; -- end AcquireRemoteBCDAndModule ReleaseRemoteBCD: PUBLIC ENTRY PROC[bcd: BcdOps.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 {nBCD: BcdOps.BcdBase _ s.first.localBCD; 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: BcdOps.BcdBase _ NIL] = {ENABLE UNWIND => NULL; prev: RemoteBCDCache _ NIL; FOR l: RemoteBCDCache _ remoteBCDCache, l.rest UNTIL l = NIL DO IF l.first.world = world AND l.first.remoteBCD = remoteBCD 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: BcdOps.BcdBase] = {ENABLE UNWIND => NULL; FOR l: RemoteBCDCache _ remoteBCDCache, l.rest UNTIL l = NIL DO IF l.rest = NIL THEN {l.rest _ CONS[[world: world, remoteBCD: remoteBCD, localBCD: localBCD, useCount: 1], NIL]; RETURN; }; ENDLOOP; remoteBCDCache _ CONS[[world: world, remoteBCD: remoteBCD, localBCD: localBCD, useCount: 1], NIL]; }; -- assumes world is locked AcquireRemoteBCD: PUBLIC PROC[world: World, bcd: BcdOps.BcdBase--remote--] RETURNS[mappedBCD: BcdOps.BcdBase _ NIL--local--] = { pages: NAT; mappedBCD _ FindCachedRemoteBCD[world, LOOPHOLE[bcd, Address]]; IF mappedBCD # NIL THEN RETURN[mappedBCD]; mappedBCD _ UnsafeStorage.NewUObject [size: Environment.wordsPerPage, zone: UnsafeStorage.GetSystemUZone[]]; CopyRead[world: world, from: LOOPHOLE[bcd, Address], nwords: SIZE[BcdDefs.BCD], to: LOOPHOLE[mappedBCD, LONG POINTER] ! UNWIND => UnsafeStorage.GetSystemUZone[].FREE[@mappedBCD]]; IF mappedBCD.extended THEN pages _ mappedBCD.nPages - mappedBCD.rtPages.pages ELSE pages _ mappedBCD.nPages; UnsafeStorage.GetSystemUZone[].FREE[@mappedBCD]; mappedBCD _ UnsafeStorage.NewUObject[size: pages*Environment.wordsPerPage, zone: UnsafeStorage.GetSystemUZone[]]; CopyRead[world: world, from: LOOPHOLE[bcd, Address], nwords: pages*Environment.wordsPerPage, to: LOOPHOLE[mappedBCD, LONG POINTER] ! UNWIND => UnsafeStorage.GetSystemUZone[].FREE[@mappedBCD]]; EnterRemoteBCDInCache[world: world, remoteBCD: LOOPHOLE[bcd, Address], localBCD: mappedBCD]; }; RemoteGFHToName: PUBLIC PROC[gfh: RemoteGlobalFrameHandle, moduleNameOnly: BOOL _ FALSE] RETURNS[ans: Rope.ROPE _ NIL] = { s: STRING _ [80]; bcd: BcdOps.BcdBase; module: PilotLoadStateFormat.ModuleInfo; ssb: BcdOps.NameString; AppendBracketed: PROC [s: STRING, value: CARDINAL] = INLINE {IF moduleNameOnly THEN RETURN; LongString.AppendChar[s, '[]; LongString.AppendOctal[s, value]; LongString.AppendChar[s, ']]}; FindModuleString: PROC[mth: BcdOps.MTHandle, mti: BcdDefs.MTIndex] RETURNS [stop: BOOLEAN] = { ssd: LongString.SubStringDescriptor; IF module.gfi IN [mth.gfi..mth.gfi + mth.ngfi) THEN {ssd _ [base: @ssb.string, offset: mth.name, length: ssb.size[mth.name]]; s.length _ 0; LongString.AppendSubString[s, @ssd]; IF GetRemoteGFHeader[gfh].copied THEN AppendBracketed[s, GetRemoteGFHeader[gfh].gfi]; RETURN[TRUE]} ELSE RETURN[FALSE]}; [bcd, module] _ AcquireRemoteBCDAndModule[gfh]; ssb _ LOOPHOLE[bcd + bcd.ssOffset, BcdOps.NameString]; [] _ BcdOps.ProcessModules[bcd, FindModuleString ! ANY => {s.length _ 0; AppendBracketed[s, GetRemoteGFHeader[gfh].gfi]; CONTINUE}]; ReleaseRemoteBCD[bcd]; RETURN[ConvertUnsafe.ToRope[LONG[s]]] }; -- MOVE NOTE PROBLEM! RemoteTypeToLocal: PUBLIC PROC[world: World, remoteType: CARDINAL] RETURNS[type: Type] = {stb: SymbolTableBase; td: RTTypesBasicPrivate.TypeDesc; utf: RTTypesBasicPrivate.UniqueTypeFinger; std: RTTypesBasicPrivate.STDesc; sth: SymbolTableHandle; sti: RTTypesBasicPrivate.SymbolTableIndex; CopyRead[world: world, from: LongRead[world: world, addr: LOOPHOLE[WorldRoot[world].GCStateBasic.mapTiTd + SIZE[RTTypesBasicPrivate.RMapTiTd[0]] + LOOPHOLE[remoteType, CARDINAL] *SIZE[RTTypesBasicPrivate.PTypeDesc], Address]], nwords: SIZE[RTTypesBasicPrivate.TypeDesc], to: @td]; utf _ td.utf; std _ [symbolsStamp: utf.umid]; sti _ RTTypesBasicPrivate.FindSTI[std]; sth _ RTSymbolsPrivate.AcquireSTHFromSTX[sti].sth; IF sth = nullHandle THEN {refRemoteSTD: REF RTTypesBasicPrivate.STDesc = WorldMapStiStdEntry[world: world, sti: td.symbolAccess.sti]; IF refRemoteSTD.bcd # NIL THEN {moduleName: Rope.ROPE; mappedBCD: BcdOps.BcdBase _ AcquireRemoteBCD[world: world, bcd: refRemoteSTD.bcd]; { ENABLE UNWIND => ReleaseRemoteBCD[mappedBCD]; ssb: BcdOps.NameString = LOOPHOLE[mappedBCD + mappedBCD.ssOffset, BcdOps.NameString]; sgi: BcdDefs.SGIndex = refRemoteSTD.sgi; -- maybe SGNull IF sgi = BcdDefs.SGNull -- search the BCD's file table (find a DEFs) THEN { findSymbolFTI: PROC[ffth: BcdOps.FTHandle, ffti: BcdDefs.FTIndex] RETURNS[stop: BOOLEAN] = { IF ffth.version # utf.umid THEN RETURN[FALSE]; moduleName _ GetModuleName[ssb, ffth.name]; RETURN[TRUE]}; [] _ 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[sgi].file; 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 _ RTSymbolsPrivate.GetSTHForModule [stamp: refRemoteSTD.symbolsStamp, moduleName: moduleName, fileName: Rope.Concat[moduleName, ".bcd"]]; IF sth # nullHandle THEN RTTypesBasicPrivate.MapStiStd[sti].sth _ sth; }; -- end refRemoteSTD.bcd # NIL }; -- end sth = nullHandle IF sth = nullHandle THEN ERROR AMTypes.Error[reason: noSymbols]; stb _ AcquireSTB[sth]; type _ AcquireType[stb: stb, seIndex: utf.seIndex ! UNWIND => ReleaseSTB[stb]]; ReleaseSTB[stb]; }; -- end RemoteTypeToLocal GetModuleName: PROC[ssb: BcdOps.NameString, n: BcdDefs.NameRecord] RETURNS[Rope.ROPE] = {nameString: STRING = [100]; ssd: Strings.SubStringDescriptor _ [base: @ssb.string, offset: n, length: MIN[ssb.size[n], 100]]; nameString.length _ 0; Strings.AppendSubString[nameString, @ssd]; FOR i: CARDINAL IN [0..nameString.length) DO IF nameString[i] = '. THEN {nameString.length _ i; EXIT}; ENDLOOP; RETURN[ConvertUnsafe.ToRope[LONG[nameString]]]}; -- raises RemoteError ValidateRemoteFrame: PUBLIC PROC[remoteFH: RemoteFrameHandle] = {frame: rep PrincOps.ControlLink = LOOPHOLE[remoteFH.fh, rep PrincOps.ControlLink]; IF frame.proc OR frame.indirect OR ~ValidRemoteGlobalFrame[[world: remoteFH.world, worldIncarnation: CurrentIncarnation[remoteFH.world], gfh: LOOPHOLE[GetRemoteFrameHeader[remoteFH].accesslink, WorldVM.ShortAddress]]] THEN ERROR RemoteError[invalidFrame]}; ValidRemoteGlobalFrame: PROC[gfh: RemoteGlobalFrameHandle] RETURNS[ans: BOOLEAN _ FALSE] = {h: rep PrincOps.ControlLink = LOOPHOLE[gfh.gfh, rep PrincOps.ControlLink]; ans _ NOT h.proc AND NOT h.indirect AND InRemoteGFT[gfh ! ANY => CONTINUE]}; InRemoteGFT: PROC[gfh: RemoteGlobalFrameHandle] RETURNS[BOOLEAN] = {gftLength: CARDINAL; world: World = gfh.world; { ENABLE UNWIND => Unlock[world]; Lock[world]; gftLength _ Read[world: world, addr: Long[world: world, addr: LOOPHOLE[SDDefs.SD + SDDefs.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]; }}; -- NOTE copies the AGCState (but not MapPiRce and MapOiOe) WorldRoot: PROC[world: World] RETURNS[ans: REF RTRefCounts.AGCState] = {ans _ z.NEW[RTRefCounts.AGCState]; CopyRead[world: world, from: LOOPHOLE[LongRead[world: world, addr: Long[world: world, addr: LOOPHOLE[SDDefs.SD + RTSD.sRTState, ShortAddress]]], Address], nwords: SIZE[RTRefCounts.AGCState], to: LOOPHOLE[ans, LONG POINTER] ]; }; -- NOTE WorldMapStiStdEntry: PROC[world: World, sti: RTTypesBasicPrivate.SymbolTableIndex] RETURNS[ans: REF RTTypesBasicPrivate.STDesc] = {ans _ z.NEW[RTTypesBasicPrivate.STDesc]; CopyRead[ world: world, from: LOOPHOLE [LongRead [world: world, addr: LOOPHOLE[LongRead[world: world, addr: Long[world: world, addr: LOOPHOLE [SDDefs.SD + RTSD.sFirstCedarFree, ShortAddress]]], Address] -- MapStiStd + SIZE[RTTypesBasicPrivate.RMapStiStd[0]] + SIZE[RTTypesBasicPrivate.PSTDesc] * sti], Address], nwords: SIZE[RTTypesBasicPrivate.STDesc], to: LOOPHOLE[ans, LONG POINTER] ]; }; 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: CurrentIncarnation[gfh.world], ptr: LOOPHOLE[c, Address]]]; }; -- raises typeFault UnwindRemoteIndirectProcDesc: PUBLIC PROC[pd: RemotePD] RETURNS[RemotePD] = {icl: PrincOps.ControlLink _ LOOPHOLE[pd.pd, PrincOps.ControlLink]; world: World = pd.world; IF icl = PrincOps.NullLink OR icl = PrincOps.UnboundLink THEN RETURN[nilRemotePD]; { ENABLE UNWIND => Unlock[world]; Lock[world]; UNTIL icl.proc DO IF icl.indirect THEN icl _ LOOPHOLE[Read[world: world, addr: Long[world: world, addr: LOOPHOLE[icl.link, ShortAddress]]], PrincOps.ControlLink] ELSE ERROR Error[reason: typeFault, type: nullType] ENDLOOP; Unlock[world]; RETURN[[world: world, worldIncarnation: CurrentIncarnation[world], pd: icl]]}}; -- break up and MOVE AcquireCBTHandleFromRemotePD: PUBLIC PROC[pd: RemotePD] RETURNS[stb: SymbolTableBase, cbti: CallableBodyIndex] = { item: PrincOpsRuntime.GFTItem; world: World = pd.world; { ENABLE UNWIND => Unlock[world]; Lock[world]; pd _ UnwindRemoteIndirectProcDesc[pd]; CopyRead[world: world, from: Long[world: world, addr: LOOPHOLE[PrincOpsRuntime.GFT + (LOOPHOLE[pd.pd, PrincOps.ProcDesc].gfi * SIZE[PrincOpsRuntime.GFTItem]), ShortAddress]], nwords: SIZE[PrincOpsRuntime.GFTItem], to: @item ]; stb _ AcquireSTBFromRemoteGFH [GetRemoteGFHandle[world: world, gfi: LOOPHOLE[pd.pd, PrincOps.ProcDesc].gfi]]; cbti _ RTTypesPrivate.GetCBTI [stb, item.epbias * PrincOps.EPRange + LOOPHOLE[pd.pd, PrincOps.ProcDesc].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 _ z.NEW[PrincOps.GlobalFrame]; { ENABLE UNWIND => Unlock[world]; Lock[world]; CopyRead[world: world, from: Long[world: world, addr: LOOPHOLE[gfh.gfh, ShortAddress]], nwords: SIZE[PrincOps.GlobalFrame], to: LOOPHOLE[ans, LONG POINTER]]; Unlock[world]; }}; GetRemoteFrameHeader: PUBLIC PROC[fh: RemoteFrameHandle] RETURNS[ans: REF PrincOps.Frame] = {world: World = fh.world; ans _ z.NEW[PrincOps.Frame]; { ENABLE UNWIND => Unlock[world]; Lock[world]; CopyRead[world: world, from: Long[world: world, addr: LOOPHOLE[fh.fh, ShortAddress]], nwords: SIZE[PrincOps.GlobalFrame], to: LOOPHOLE[ans, LONG POINTER]]; Unlock[world]; }}; GetRemoteReferentType: PUBLIC PROC[remoteRef: RemoteRef] RETURNS[type: Type--valid locally--] = { mz: RTZones.ZoneFinger; world: World = remoteRef.world; IF remoteRef.ref = 0 THEN RETURN[nullType]; { ENABLE UNWIND => Unlock[world]; Lock[world]; mz _ RemoteMapRefZf[remoteRef]; WITH mz: mz SELECT FROM prefixed => type _ GetRemotePrefixedType[remoteRef]; sub => type _ GetRemoteSzType[world: world, szi: mz.szi]; ENDCASE => ERROR; Unlock[world]}}; RemoteMapRefZf: PROC[remoteRef: RemoteRef] RETURNS[zf: RTZones.ZoneFinger] = {qi: RTQuanta.QuantumIndex = RTZones.MapPtrQ[LOOPHOLE[remoteRef.ref, LONG POINTER]]; remoteMapQZf: RTZones.TMapQZf = WorldRoot[remoteRef.world].GCStateBasic.mapQZf; CopyRead[world: remoteRef.world, from: LOOPHOLE[remoteMapQZf + SIZE[RTZones.RMapQZf[0]] + qi*SIZE[RTZones.ZoneFinger], Address], nwords: SIZE[RTZones.ZoneFinger], to: @zf]; }; GetRemotePrefixedType: PROC[remoteRef: RemoteRef] RETURNS[Type--valid locally--] = {remoteType: CARDINAL; NHdr: inuse RTZones.NodeHeader; CopyRead[world: remoteRef.world, from: remoteRef.ref - RTZones.sizeNd, nwords: SIZE[inuse RTZones.NodeHeader], to: @NHdr]; remoteType _ NHdr.type; RETURN[RemoteTypeToLocal[world: remoteRef.world, remoteType: remoteType]]; }; GetRemoteSzType: PROC[world: World, szi: RTZones.SubZoneIndex] RETURNS[Type--valid locally--] = {remoteType: CARDINAL; szrp: Address; -- SubZone szRec: RTZones.SubZoneRec; szrp _ LongRead [world: world, addr: LOOPHOLE[WorldRoot[world].GCStateBasic.mapSziSz + SIZE[RTZones.RMapSziSz[0]] + szi*SIZE[RTZones.SubZone], Address]]; CopyRead[world: world, from: szrp, nwords: SIZE[RTZones.SubZoneRec], to: @szRec]; remoteType _ szRec.type; RETURN[RemoteTypeToLocal[world: world, remoteType: remoteType]]; }; -- MOVE GetRemoteProcedureType: PUBLIC PROC[remotePD: RemotePD] RETURNS[type: Type--valid locally--] = { stb: SymbolTableBase; cbti: CallableBodyIndex; [stb, cbti] _ AcquireCBTHandleFromRemotePD[remotePD]; type _ AcquireType[stb, stb.bb[cbti].ioType ! UNWIND => ReleaseSTB[stb]]; ReleaseSTB[stb]}; -- break up and MOVE GetRemoteSignalType: PUBLIC PROC[remoteSED: RemoteSED] RETURNS[type: Type--valid locally--] = { gfh: RemoteGlobalFrameHandle _ nilRemoteGlobalFrameHandle; item: PrincOpsRuntime.GFTItem; stb: SymbolTableBase; world: World = remoteSED.world; proc: PROC[stb: SymbolTableBase, isei: SymbolIdIndex] RETURNS[stop: BOOLEAN] = { tsei: 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 CARDINAL[item.epbias * PrincOps.EPRange + LOOPHOLE[remoteSED.sed, PrincOps.SignalDesc].ep] = STInfoToEPN[LOOPHOLE[stb.seb[isei].idValue, PrincOps.SignalDesc]] THEN {type _ AcquireType[stb, 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]]; { ENABLE UNWIND => Unlock[world]; Lock[world]; gfh _ GetRemoteGFHandle[world: world, gfi: LOOPHOLE[remoteSED.sed, PrincOps.SignalDesc].gfi]; stb _ AcquireSTBFromRemoteGFH[gfh]; CopyRead[world: world, from: Long[world: world, addr: LOOPHOLE[PrincOpsRuntime.GFT + LOOPHOLE[remoteSED.sed, PrincOps.SignalDesc].gfi * SIZE[PrincOpsRuntime.GFTItem], ShortAddress]], nwords: SIZE[PrincOpsRuntime.GFTItem], to: @item ]; type _ nullType; [] _ EnumerateRecordIseis[stb, stb.bb[rootBodyIndex].type, proc ! UNWIND => ReleaseSTB[stb]]; ReleaseSTB[stb]; Unlock[world]}}; -- break up and MOVE IsRemoteCatchFrame: PUBLIC PROC[remoteFrameHandle: RemoteFrameHandle, bti: BodyIndex] RETURNS [isCatchFrame: BOOLEAN _ TRUE, revBti: BodyIndex] = {world: World = remoteFrameHandle.world; { ENABLE UNWIND => Unlock[world]; Lock[world]; revBti _ bti; ValidateRemoteFrame[remoteFrameHandle ! ANY => GOTO notCatch]; { -- return FALSE if input invalid nextFrame: RemoteFrameHandle _ [world: remoteFrameHandle.world, worldIncarnation: CurrentIncarnation[remoteFrameHandle.world], fh: LOOPHOLE[GetRemoteFrameHeader[remoteFrameHandle].returnlink.frame, ShortAddress]]; nextFHdr: REF PrincOps.Frame; ValidateRemoteFrame[nextFrame ! ANY => GOTO notCatch]; -- return FALSE if no valid calling frame nextFHdr _ GetRemoteFrameHeader[nextFrame]; IF nextFHdr.accesslink # RemoteSigGF[remoteFrameHandle.world] THEN GOTO notCatch; { -- return FALSE if caller not signaller L0Frame: RemoteFrameHandle _ [world: remoteFrameHandle.world, worldIncarnation: CurrentIncarnation[remoteFrameHandle.world], fh: LOOPHOLE[GetRemoteFrameHeader[remoteFrameHandle].staticlink - PrincOps.localbase, ShortAddress]]; -- L0Frame is the frame that encloses the catch frame ValidateRemoteFrame[L0Frame ! ANY => GOTO notCatch]; -- return FALSE if static frame not valid (??) IF GetRemoteFrameHeader[remoteFrameHandle].accesslink # GetRemoteFrameHeader[L0Frame].accesslink THEN GOTO notCatch; IF ~nextFHdr.mark THEN GOTO notCatch; -- calling frame not the signaller { -- detect situation where catch frame has no locals, thus no body table. tr: REF TypedVariableRec = NARROW[TVForRemoteFrame[L0Frame], REF TypedVariableRec]; WITH hd: tr.head SELECT FROM remoteFH => IF bti = hd.bti THEN revBti _ nullBodyIndex; ENDCASE => ERROR }; Unlock[world]; } }; EXITS notCatch => {Unlock[world]; isCatchFrame _ FALSE}}}; RemoteSigGF: PROC[world: World] RETURNS[PrincOps.GlobalFrameHandle] = { item: PrincOpsRuntime.GFTItem; pd: PrincOps.ProcDesc = LOOPHOLE[Read[world: world, addr: Long[world: world, addr: LOOPHOLE[SDDefs.SD + SDDefs.sSignal, ShortAddress]]], PrincOps.ProcDesc]; CopyRead[world: world, from: Long[world: world, addr: LOOPHOLE[PrincOpsRuntime.GFT + pd.gfi * SIZE[PrincOpsRuntime.GFTItem], ShortAddress]], nwords: SIZE[PrincOpsRuntime.GFTItem], to: @item ]; RETURN[PrincOpsRuntime.GetFrame[item]]}; -- MOVE AcquireBTIFromRemoteFH: PUBLIC PROC[remoteFrameHandle: RemoteFrameHandle, contextPC: BOOL] RETURNS[bti: BodyIndex] = {stb: SymbolTableBase; world: World = remoteFrameHandle.world; Lock[world]; [stb, bti] _ AcquireBTHandleFromRemoteFH[remoteFrameHandle, contextPC ! ANY => GOTO nope]; Unlock[world]; ReleaseSTB[stb]; EXITS nope => {Unlock[remoteFrameHandle.world]; RETURN[nullBodyIndex]}}; -- MOVE AcquireBTHandleFromRemoteFH: PROC[fh: RemoteFrameHandle, contextPC: BOOL] RETURNS[stb: SymbolTableBase, bti: BodyIndex] = { start: PrincOps.BytePC; epn: CARDINAL; remoteFrame: REF PrincOps.Frame = GetRemoteFrameHeader[fh]; framePC: PrincOps.BytePC = [(remoteFrame.pc - (IF contextPC THEN 0 ELSE 1))]; stb _ AcquireSTBFromRemoteGFH[[world: fh.world, worldIncarnation: CurrentIncarnation[fh.world], gfh: LOOPHOLE[remoteFrame.accesslink, ShortAddress]]]; [epn, start] _ GetRemoteEp[pc: framePC, gf: [world: fh.world, worldIncarnation: CurrentIncarnation[fh.world], gfh: LOOPHOLE[remoteFrame.accesslink, ShortAddress]], stb: stb ! UNWIND => ReleaseSTB[stb]]; bti _ RTTypesPrivate.ConvertCbti[base: stb, pc: framePC, start: start, lastBti: RTTypesPrivate.GetCBTI[stb, epn] ! UNWIND => ReleaseSTB[stb]]; IF bti = rootBodyIndex THEN bti _ nullBodyIndex}; -- MOVE GetRemoteEp: PUBLIC PROC [pc: PrincOps.BytePC, gf: RemoteGlobalFrameHandle, stb: SymbolTableBase] RETURNS [ep: EVRange, start: PrincOps.BytePC] = { FindMaxEI: PROC RETURNS [max: EVRange] = { GetMax: PROC [bti: BodyIndex] RETURNS [stop: BOOLEAN] = {WITH stb.bb[bti] SELECT FROM Callable => IF ~inline THEN max _ MAX[max, entryIndex]; ENDCASE; RETURN[FALSE]}; max _ 0; [] _ stb.EnumerateBodies[rootBodyIndex, GetMax]}; -- body of GetEp begins here diff: CARDINAL _ LAST[CARDINAL]; anyProcedure: BOOLEAN _ FALSE; FOR i: EVRange IN [0..FindMaxEI[]] DO last: PrincOps.BytePC _ GetRemotePc[gf, i]; IF Card[last] > Card[pc] THEN LOOP; IF Card[pc] - Card[last] > diff THEN LOOP; diff _ Card[pc] - Card[last]; ep _ i; start _ last; anyProcedure _ TRUE; ENDLOOP; IF ~anyProcedure THEN ERROR; -- SIGNAL NotInAnyProcedure; RETURN}; -- MOVE RemotePDToName: PUBLIC PROC[pd: RemotePD] RETURNS[ans: Rope.ROPE] = { stb: SymbolTableBase; cbti: CallableBodyIndex; pd _ UnwindRemoteIndirectProcDesc[pd]; IF pd.pd = 0 THEN RETURN[NIL]; [stb, cbti] _ AcquireCBTHandleFromRemotePD[pd]; ans _ AcquireRope[stb, stb.seb[stb.bb[cbti].id].hash ! UNWIND => ReleaseSTB[stb]]; ReleaseSTB[stb]; RETURN[ans]}; -- MOVE RemoteSEDToName: PUBLIC PROC[sed: RemoteSED] RETURNS[ans: Rope.ROPE _ NIL] = { item: PrincOpsRuntime.GFTItem; gfh: RemoteGlobalFrameHandle _ nilRemoteGlobalFrameHandle; stb: SymbolTableBase; world: World = sed.world; proc: PROC[stb: SymbolTableBase, isei: SymbolIdIndex] RETURNS[stop: BOOLEAN] = { tsei: 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 CARDINAL[item.epbias * PrincOps.EPRange + LOOPHOLE[sed.sed, PrincOps.SignalDesc].ep] = STInfoToEPN[LOOPHOLE[stb.seb[isei].idValue, PrincOps.SignalDesc]] THEN {ans _ AcquireRope[stb, stb.seb[isei].hash]; RETURN[TRUE]} ELSE RETURN[FALSE]}; IF sed.sed = PrincOps.NullLink OR sed.sed = PrincOps.UnboundLink THEN RETURN[NIL]; { ENABLE UNWIND => Unlock[world]; sei: SymbolRecordIndex; Lock[world]; gfh _ GetRemoteGFHandle[world: world, gfi: LOOPHOLE[sed.sed, PrincOps.SignalDesc].gfi]; CopyRead[world: world, from: Long[world: world, addr: LOOPHOLE[PrincOpsRuntime.GFT + LOOPHOLE[sed.sed, PrincOps.SignalDesc].gfi * SIZE[PrincOpsRuntime.GFTItem], ShortAddress]], nwords: SIZE[PrincOpsRuntime.GFTItem], to: @item]; stb _ AcquireSTBFromRemoteGFH[gfh]; sei _ stb.bb[rootBodyIndex].type; IF sei # nullSymbolIndex THEN [] _ EnumerateRecordIseis[stb, sei, proc ! UNWIND => ReleaseSTB[stb]]; ReleaseSTB[stb]; Unlock[world]}}; RemoteStoreWords: PUBLIC PROC[from: LONG POINTER, to: RemotePointer, nWords: NAT] = {ENABLE UNWIND => Unlock[to.world]; Lock[to.world]; CopyWrite[world: to.world, from: from, nwords: nWords, to: to.ptr]; Unlock[to.world]}; RemoteStoreWord: PUBLIC PROC[to: RemotePointer, value: CARDINAL] = {ENABLE UNWIND => Unlock[to.world]; Lock[to.world]; Write[world: to.world, addr: to.ptr, value: value]; Unlock[to.world]}; RemoteStoreDoubleWord: PUBLIC PROC[to: RemotePointer, value: LONG CARDINAL] = {ENABLE UNWIND => Unlock[to.world]; Lock[to.world]; LongWrite[world: to.world, addr: to.ptr, value: value]; Unlock[to.world]}; RemoteStoreFieldLong: PUBLIC PROC[ptr: RemotePointer, field: RTCommon.Field, value: LONG CARDINAL] = {ENABLE UNWIND => Unlock[ptr.world]; val: LONG CARDINAL; Lock[ptr.world]; val _ LongRead[world: ptr.world, addr: LOOPHOLE[ptr.ptr, Address]]; RTCommon.StoreFieldLong[ptr: @val, field: field, newValue: value]; LongWrite[world: ptr.world, addr: LOOPHOLE[ptr.ptr, Address], value: val]; Unlock[ptr.world]; }; GetRemoteWord: PUBLIC PROC[remotePointer: RemotePointer] RETURNS[ans: WORD] = {ENABLE UNWIND => Unlock[remotePointer.world]; Lock[remotePointer.world]; ans _ Read[world: remotePointer.world, addr: remotePointer.ptr]; Unlock[remotePointer.world]; }; GetRemoteLC: PUBLIC PROC[remotePointer: RemotePointer] RETURNS[ans: LONG CARDINAL] = {ENABLE UNWIND => Unlock[remotePointer.world]; Lock[remotePointer.world]; ans _ LongRead[world: remotePointer.world, addr: remotePointer.ptr]; Unlock[remotePointer.world]; }; GetRemoteWords: PUBLIC PROC[remotePointer: RemotePointer, nWords: NAT] RETURNS[ans: WordSequence] = {ENABLE UNWIND => Unlock[remotePointer.world]; Lock[remotePointer.world]; ans _ z.NEW[WordSequenceRecord[nWords]]; CopyRead[world: remotePointer.world, from: remotePointer.ptr, nwords: nWords, to: LOOPHOLE[@ans[0], LONG POINTER]]; Unlock[remotePointer.world]; }; -- NOTE RemoteSignalValues: PUBLIC PROC[tv: TypedVariable--catch Frame--] RETURNS [message: CARDINAL, signal: PrincOps.SignalDesc, world: World] = {rtr: REF TypedVariableRec _ NARROW[tv]; WITH th: rtr.head SELECT FROM remoteFH => IF th.isCatchFrame THEN {ENABLE UNWIND => Unlock[th.remoteFrameHandle.world]; remoteSignallerFrameHandle: RemoteFrameHandle _ nilRemoteFrameHandle; Lock[th.remoteFrameHandle.world]; ValidateRemoteFrame[th.remoteFrameHandle]; remoteSignallerFrameHandle _ [world: th.remoteFrameHandle.world, worldIncarnation: CurrentIncarnation[th.remoteFrameHandle.world], fh: LOOPHOLE[GetRemoteFrameHeader [th.remoteFrameHandle].returnlink, ShortAddress]]; message _ Read[world: th.remoteFrameHandle.world, addr: Long[world: th.remoteFrameHandle.world, addr: remoteSignallerFrameHandle.fh + SignallerFrameMessageOffset]]; signal _ LOOPHOLE [Read[world: th.remoteFrameHandle.world, addr: Long[world: th.remoteFrameHandle.world, addr: remoteSignallerFrameHandle.fh + SignallerFrameSignalOffset]], PrincOps.SignalDesc]; Unlock[th.remoteFrameHandle.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.